commit
cca43f0b5b
|
@ -0,0 +1,29 @@
|
||||||
|
name: GithHub Pages
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
github-pages:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP, with composer and extensions
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 7.4
|
||||||
|
coverage: none # remove xdebug
|
||||||
|
|
||||||
|
- name: Build API documentation
|
||||||
|
run: |
|
||||||
|
curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0-rc/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
|
|
@ -0,0 +1,150 @@
|
||||||
|
name: Build
|
||||||
|
on: [ push, pull_request ]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php-version:
|
||||||
|
- '7.2'
|
||||||
|
- '7.3'
|
||||||
|
- '7.4'
|
||||||
|
- '8.0'
|
||||||
|
|
||||||
|
name: PHP ${{ matrix.php-version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- 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 "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache composer dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
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 == '8.0' }}
|
||||||
|
run: |
|
||||||
|
rm composer.lock
|
||||||
|
echo "::set-output name=flags::--ignore-platform-reqs"
|
||||||
|
|
||||||
|
- 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: Test with PHPUnit
|
||||||
|
run: ./vendor/bin/phpunit
|
||||||
|
|
||||||
|
php-cs-fixer:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP, with composer and extensions
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 7.4
|
||||||
|
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 "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache composer dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
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 --format=checkstyle | cs2pr
|
||||||
|
|
||||||
|
phpcs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP, with composer and extensions
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 7.4
|
||||||
|
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 "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache composer dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
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
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup PHP, with composer and extensions
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 7.4
|
||||||
|
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 "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache composer dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
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
|
||||||
|
curl -LO https://scrutinizer-ci.com/ocular.phar
|
||||||
|
php ocular.phar code-coverage:upload --format=php-clover coverage-clover.xml
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PHP_CodeSniffer"
|
||||||
|
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||||
|
|
||||||
|
<file>samples</file>
|
||||||
|
<file>src</file>
|
||||||
|
<file>tests</file>
|
||||||
|
|
||||||
|
<exclude-pattern>samples/Header.php</exclude-pattern>
|
||||||
|
<exclude-pattern>*/tests/Core/*/*Test\.(inc|css|js)$</exclude-pattern>
|
||||||
|
|
||||||
|
<arg name="report-width" value="200"/>
|
||||||
|
<arg name="parallel" value="80"/>
|
||||||
|
<arg name="cache" value="/tmp/.phpspreadsheet.phpcs-cache"/>
|
||||||
|
<arg name="colors"/>
|
||||||
|
<arg value="np"/>
|
||||||
|
|
||||||
|
<!-- Include the whole PSR12 standard -->
|
||||||
|
<rule ref="PSR12">
|
||||||
|
<exclude name="PSR2.Methods.MethodDeclaration.Underscore"/>
|
||||||
|
</rule>
|
||||||
|
</ruleset>
|
33
.travis.yml
33
.travis.yml
|
@ -5,6 +5,7 @@ php:
|
||||||
- 7.2
|
- 7.2
|
||||||
- 7.3
|
- 7.3
|
||||||
- 7.4
|
- 7.4
|
||||||
|
- nightly
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
@ -13,11 +14,15 @@ cache:
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
# Deactivate xdebug
|
# Deactivate xdebug
|
||||||
- phpenv config-rm xdebug.ini
|
- if [[ $TRAVIS_PHP_VERSION != nightly ]]; then phpenv config-rm xdebug.ini; fi
|
||||||
|
- if [[ $TRAVIS_PHP_VERSION == nightly ]]; then rm composer.lock; fi
|
||||||
- composer install --ignore-platform-reqs
|
- composer install --ignore-platform-reqs
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- ./vendor/bin/phpunit
|
- ./vendor/bin/phpunit --color=always --coverage-text
|
||||||
|
|
||||||
|
allow_failures:
|
||||||
|
- php: nightly
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
|
@ -26,26 +31,4 @@ jobs:
|
||||||
php: 7.4
|
php: 7.4
|
||||||
script:
|
script:
|
||||||
- ./vendor/bin/php-cs-fixer fix --diff --verbose --dry-run
|
- ./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
|
- ./vendor/bin/phpcs
|
||||||
|
|
||||||
- stage: Coverage
|
|
||||||
php: 7.4
|
|
||||||
script:
|
|
||||||
- pecl install pcov
|
|
||||||
- ./vendor/bin/phpunit --coverage-clover coverage-clover.xml
|
|
||||||
after_script:
|
|
||||||
- wget https://scrutinizer-ci.com/ocular.phar
|
|
||||||
- php ocular.phar code-coverage:upload --format=php-clover tests/coverage-clover.xml
|
|
||||||
|
|
||||||
- stage: API documentations
|
|
||||||
if: tag is present AND branch = master
|
|
||||||
php: 7.4
|
|
||||||
before_script:
|
|
||||||
- curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0-rc/phpDocumentor.phar
|
|
||||||
script:
|
|
||||||
- php phpDocumentor.phar --directory src/ --target docs/api
|
|
||||||
deploy:
|
|
||||||
provider: pages
|
|
||||||
skip-cleanup: true
|
|
||||||
local-dir: docs/api
|
|
||||||
github-token: $GITHUB_TOKEN
|
|
||||||
|
|
164
CHANGELOG.md
164
CHANGELOG.md
|
@ -5,12 +5,125 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com)
|
The format is based on [Keep a Changelog](https://keepachangelog.com)
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org).
|
and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
## [Unreleased]
|
## Unreleased - TBD
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Nothing.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Nothing.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
- Nothing.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Nothing.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 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)
|
||||||
|
|
||||||
|
## 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
|
### Added
|
||||||
|
|
||||||
- Support writing to streams in all writers [#1292](https://github.com/PHPOffice/PhpSpreadsheet/issues/1292)
|
- 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 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
|
### Fixed
|
||||||
|
|
||||||
|
@ -21,6 +134,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Several improvements in HTML writer [#1464](https://github.com/PHPOffice/PhpSpreadsheet/pull/1464)
|
- Several improvements in HTML writer [#1464](https://github.com/PHPOffice/PhpSpreadsheet/pull/1464)
|
||||||
- Fix incorrect behaviour when saving XLSX file with drawings [#1462](https://github.com/PHPOffice/PhpSpreadsheet/pull/1462),
|
- Fix 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)
|
- 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
|
### Changed
|
||||||
|
|
||||||
|
@ -28,7 +143,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Drop partial migration tool in favor of complete migration via RectorPHP [#1445](https://github.com/PHPOffice/PhpSpreadsheet/issues/1445)
|
- 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)
|
- Limit composer package to `src/` [#1424](https://github.com/PHPOffice/PhpSpreadsheet/pull/1424)
|
||||||
|
|
||||||
## [1.12.0] - 2020-04-27
|
## 1.12.0 - 2020-04-27
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -44,7 +159,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- 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)
|
- 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)
|
- Fix Xlsx Reader's handling of undefined fill color [#1353](https://github.com/PHPOffice/PhpSpreadsheet/pull/1353)
|
||||||
|
|
||||||
## [1.11.0] - 2020-03-02
|
## 1.11.0 - 2020-03-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -63,7 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Fix XLSX file loading with autofilter containing '$' [#1326](https://github.com/PHPOffice/PhpSpreadsheet/pull/1326)
|
- 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)
|
- PHPDoc - Use `@return $this` for fluent methods [#1362](https://github.com/PHPOffice/PhpSpreadsheet/pull/1362)
|
||||||
|
|
||||||
## [1.10.1] - 2019-12-02
|
## 1.10.1 - 2019-12-02
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -78,7 +193,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- ODS writer prevent invalid numeric value if locale decimal separator is comma [#1268](https://github.com/PHPOffice/PhpSpreadsheet/pull/1268)
|
- 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)
|
- Xlsx writer actually writes plotVisOnly and dispBlanksAs from chart properties [#1266](https://github.com/PHPOffice/PhpSpreadsheet/pull/1266)
|
||||||
|
|
||||||
## [1.10.0] - 2019-11-18
|
## 1.10.0 - 2019-11-18
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -103,7 +218,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Validate XIRR inputs and return correct error values [#1120](https://github.com/PHPOffice/PhpSpreadsheet/issues/1120)
|
- 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)
|
- 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
|
## 1.9.0 - 2019-08-17
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -134,20 +249,20 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Fix `getCalculatedValue()` error with more than two INDIRECT [#1115](https://github.com/PHPOffice/PhpSpreadsheet/pull/1115)
|
- 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)
|
- Writer\Html did not hide columns [#985](https://github.com/PHPOffice/PhpSpreadsheet/pull/985)
|
||||||
|
|
||||||
## [1.8.2] - 2019-07-08
|
## 1.8.2 - 2019-07-08
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Uncaught error when opening ods file and properties aren't defined [#1047](https://github.com/PHPOffice/PhpSpreadsheet/issues/1047)
|
- 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)
|
- Xlsx Reader Cell datavalidations bug [#1052](https://github.com/PHPOffice/PhpSpreadsheet/pull/1052)
|
||||||
|
|
||||||
## [1.8.1] - 2019-07-02
|
## 1.8.1 - 2019-07-02
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Allow nullable theme for Xlsx Style Reader class [#1043](https://github.com/PHPOffice/PhpSpreadsheet/issues/1043)
|
- Allow nullable theme for Xlsx Style Reader class [#1043](https://github.com/PHPOffice/PhpSpreadsheet/issues/1043)
|
||||||
|
|
||||||
## [1.8.0] - 2019-07-01
|
## 1.8.0 - 2019-07-01
|
||||||
|
|
||||||
### Security Fix (CVE-2019-12331)
|
### Security Fix (CVE-2019-12331)
|
||||||
|
|
||||||
|
@ -170,7 +285,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- 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 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
|
- Fix incorrectly handled backslash-escaped space characters in number format
|
||||||
|
|
||||||
## [1.7.0] - 2019-05-26
|
## 1.7.0 - 2019-05-26
|
||||||
|
|
||||||
- Added support for inline styles in Html reader (borders, alignment, width, height)
|
- 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 `=`
|
- QuotedText cells no longer treated as formulae if the content begins with a `=`
|
||||||
|
@ -184,7 +299,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Fix VLOOKUP
|
- Fix VLOOKUP
|
||||||
- Fix return type hint
|
- Fix return type hint
|
||||||
|
|
||||||
## [1.6.0] - 2019-01-02
|
## 1.6.0 - 2019-01-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -212,13 +327,13 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
- `master` is the new default branch, `develop` does not exist anymore
|
- `master` is the new default branch, `develop` does not exist anymore
|
||||||
|
|
||||||
## [1.5.2] - 2018-11-25
|
## 1.5.2 - 2018-11-25
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Improvements to the design of the XML Security Scanner [#771](https://github.com/PHPOffice/PhpSpreadsheet/issues/771)
|
- Improvements to the design of the XML Security Scanner [#771](https://github.com/PHPOffice/PhpSpreadsheet/issues/771)
|
||||||
|
|
||||||
## [1.5.1] - 2018-11-20
|
## 1.5.1 - 2018-11-20
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
@ -238,7 +353,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Mpdf export can exceed pcre.backtrack_limit [#637](https://github.com/PHPOffice/PhpSpreadsheet/issues/637)
|
- 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)
|
- Fix index overflow on data values array [#748](https://github.com/PHPOffice/PhpSpreadsheet/pull/748)
|
||||||
|
|
||||||
## [1.5.0] - 2018-10-21
|
## 1.5.0 - 2018-10-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -253,7 +368,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- OFFSET should allow omitted height and width [#561](https://github.com/PHPOffice/PhpSpreadsheet/issues/561)
|
- 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)
|
- Correctly determine delimiter when CSV contains line breaks inside enclosures [#716](https://github.com/PHPOffice/PhpSpreadsheet/issues/716)
|
||||||
|
|
||||||
## [1.4.1] - 2018-09-30
|
## 1.4.1 - 2018-09-30
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -262,7 +377,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Fix warning when reading xlsx without styles [#631](https://github.com/PHPOffice/PhpSpreadsheet/pull/631)
|
- 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)
|
- 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
|
### Added
|
||||||
|
|
||||||
|
@ -326,13 +441,13 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Migration tool keep variables containing $PHPExcel untouched [#598](https://github.com/PHPOffice/PhpSpreadsheet/issues/598)
|
- 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)
|
- 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
|
### 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
|
### Added
|
||||||
|
|
||||||
|
@ -351,13 +466,13 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Fixed parsing of conditionals in COUNTIF functions [#526](https://github.com/PHPOffice/PhpSpreadsheet/issues/526)
|
- 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)
|
- 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
|
### 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
|
### Added
|
||||||
|
|
||||||
|
@ -375,7 +490,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Select correct cell when calling freezePane [#389](https://github.com/PHPOffice/PhpSpreadsheet/issues/389)
|
- 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)
|
- `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
|
### Added
|
||||||
|
|
||||||
|
@ -393,7 +508,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Support XML file without styles [#331](https://github.com/PHPOffice/PhpSpreadsheet/pull/331)
|
- 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)
|
- 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
|
### Added
|
||||||
|
|
||||||
|
@ -412,7 +527,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
- Constant `TYPE_DOUGHTNUTCHART` is now `TYPE_DOUGHNUTCHART`.
|
- Constant `TYPE_DOUGHTNUTCHART` is now `TYPE_DOUGHNUTCHART`.
|
||||||
|
|
||||||
## [1.0.0-beta2] - 2017-11-26
|
## 1.0.0-beta2 - 2017-11-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -450,7 +565,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- `PhpSpreadsheet\Style` => `PhpSpreadsheet\Style\Style`
|
- `PhpSpreadsheet\Style` => `PhpSpreadsheet\Style\Style`
|
||||||
- `PhpSpreadsheet\Worksheet` => `PhpSpreadsheet\Worksheet\Worksheet`
|
- `PhpSpreadsheet\Worksheet` => `PhpSpreadsheet\Worksheet\Worksheet`
|
||||||
|
|
||||||
## [1.0.0-beta] - 2017-08-17
|
## 1.0.0-beta - 2017-08-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -470,6 +585,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Ignore inlineStr type if formula element exists - @ncrypthic [#570](https://github.com/PHPOffice/PHPExcel/issues/570)
|
- 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)
|
- 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)
|
- 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
|
### General
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
[![Build Status](https://travis-ci.org/PHPOffice/PhpSpreadsheet.svg?branch=master)](https://travis-ci.org/PHPOffice/PhpSpreadsheet)
|
[![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 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)
|
[![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://poser.pugx.org/phpoffice/phpspreadsheet/downloads.png)](https://packagist.org/packages/phpoffice/phpspreadsheet)
|
[![Total Downloads](https://img.shields.io/packagist/dt/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet)
|
||||||
[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpspreadsheet/v/stable.png)](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://poser.pugx.org/phpoffice/phpspreadsheet/license.png)](https://packagist.org/packages/phpoffice/phpspreadsheet)
|
[![License](https://img.shields.io/github/license/PHPOffice/PhpSpreadsheet)](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)
|
[![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 providing a set of classes that allow you to read from and to write to different spreadsheet file formats, like Excel and LibreOffice Calc.
|
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.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"check": [
|
"check": [
|
||||||
"php-cs-fixer fix --ansi --dry-run --diff",
|
"php-cs-fixer fix --ansi --dry-run --diff",
|
||||||
"phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n",
|
"phpcs",
|
||||||
"phpunit --color=always"
|
"phpunit --color=always"
|
||||||
],
|
],
|
||||||
"fix": [
|
"fix": [
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2",
|
"php": "^7.2|^8.0",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
|
@ -53,10 +53,12 @@
|
||||||
"ext-xmlwriter": "*",
|
"ext-xmlwriter": "*",
|
||||||
"ext-zip": "*",
|
"ext-zip": "*",
|
||||||
"ext-zlib": "*",
|
"ext-zlib": "*",
|
||||||
"markbaker/complex": "^1.4",
|
"maennchen/zipstream-php": "^2.1",
|
||||||
"markbaker/matrix": "^1.2",
|
"markbaker/complex": "^1.5|^2.0",
|
||||||
|
"markbaker/matrix": "^1.2|^2.0",
|
||||||
"psr/simple-cache": "^1.0",
|
"psr/simple-cache": "^1.0",
|
||||||
"maennchen/zipstream-php": "^2.0"
|
"psr/http-client": "^1.0",
|
||||||
|
"psr/http-factory": "^1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"dompdf/dompdf": "^0.8.5",
|
"dompdf/dompdf": "^0.8.5",
|
||||||
|
@ -64,14 +66,14 @@
|
||||||
"jpgraph/jpgraph": "^4.0",
|
"jpgraph/jpgraph": "^4.0",
|
||||||
"mpdf/mpdf": "^8.0",
|
"mpdf/mpdf": "^8.0",
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
"phpcompatibility/php-compatibility": "^9.3",
|
||||||
"phpunit/phpunit": "^8.5",
|
"phpunit/phpunit": "^8.5|^9.3",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"squizlabs/php_codesniffer": "^3.5",
|
||||||
"tecnickcom/tcpdf": "^6.3"
|
"tecnickcom/tcpdf": "^6.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
||||||
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
|
"dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
|
||||||
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer",
|
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
|
||||||
"jpgraph/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": {
|
"autoload": {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
range protection, prohibiting deleting rows, ...), make sure you enable
|
||||||
worksheet security. This can for example be done like this:
|
worksheet security. This can for example be done like this:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getProtection()->setSheet(true);
|
$spreadsheet->getActiveSheet()->getProtection()->setSheet(true);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
![Logo](./assets/logo.svg)
|
![Logo](./assets/logo.svg)
|
||||||
|
|
||||||
PhpSpreadsheet is a library written in pure PHP and providing a set of
|
PhpSpreadsheet is a library written in pure PHP and offers a set of classes that
|
||||||
classes that allow you to read from and to write to different
|
allow you to read and write various spreadsheet file formats such as Excel and LibreOffice Calc.
|
||||||
spreadsheet file formats, like Excel and LibreOffice Calc.
|
|
||||||
|
|
||||||
## File formats supported
|
## File formats supported
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ FALSE | \PhpOffice\PhpSpreadsheet\Calculation\Logical::FALSE
|
||||||
IF | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementIf
|
IF | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementIf
|
||||||
IFERROR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR
|
IFERROR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR
|
||||||
IFNA | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFNA
|
IFNA | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFNA
|
||||||
IFS | **Not yet Implemented**
|
IFS | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFS
|
||||||
NOT | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT
|
NOT | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT
|
||||||
OR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalOr
|
OR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalOr
|
||||||
SWITCH | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementSwitch
|
SWITCH | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementSwitch
|
||||||
|
@ -229,6 +229,7 @@ AREAS | **Not yet Implemented**
|
||||||
CHOOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CHOOSE
|
CHOOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CHOOSE
|
||||||
COLUMN | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMN
|
COLUMN | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMN
|
||||||
COLUMNS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMNS
|
COLUMNS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMNS
|
||||||
|
FILTER | **Not yet Implemented**
|
||||||
FORMULATEXT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT
|
FORMULATEXT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT
|
||||||
GETPIVOTDATA | **Not yet Implemented**
|
GETPIVOTDATA | **Not yet Implemented**
|
||||||
HLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::HLOOKUP
|
HLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::HLOOKUP
|
||||||
|
@ -241,8 +242,13 @@ OFFSET | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::OFFSET
|
||||||
ROW | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROW
|
ROW | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROW
|
||||||
ROWS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROWS
|
ROWS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROWS
|
||||||
RTD | **Not yet Implemented**
|
RTD | **Not yet Implemented**
|
||||||
|
SORT | **Not yet Implemented**
|
||||||
|
SORTBY | **Not yet Implemented**
|
||||||
TRANSPOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::TRANSPOSE
|
TRANSPOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::TRANSPOSE
|
||||||
|
UNIQUE | **Not yet Implemented**
|
||||||
VLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::VLOOKUP
|
VLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::VLOOKUP
|
||||||
|
XLOOKUP | **Not yet Implemented**
|
||||||
|
XMATCH | **Not yet Implemented**
|
||||||
|
|
||||||
## CATEGORY_MATH_AND_TRIG
|
## CATEGORY_MATH_AND_TRIG
|
||||||
|
|
||||||
|
@ -253,6 +259,7 @@ ACOS | acos
|
||||||
ACOSH | acosh
|
ACOSH | acosh
|
||||||
ACOT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOT
|
ACOT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOT
|
||||||
ACOTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOTH
|
ACOTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOTH
|
||||||
|
AGGREGATE | **Not yet Implemented**
|
||||||
ARABIC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ARABIC
|
ARABIC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ARABIC
|
||||||
ASIN | asin
|
ASIN | asin
|
||||||
ASINH | asinh
|
ASINH | asinh
|
||||||
|
@ -261,13 +268,17 @@ ATAN2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ATAN2
|
||||||
ATANH | atanh
|
ATANH | atanh
|
||||||
BASE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::BASE
|
BASE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::BASE
|
||||||
CEILING | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CEILING
|
CEILING | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CEILING
|
||||||
|
CEILING.MATH | **Not yet Implemented**
|
||||||
|
CEILING.PRECISE | **Not yet Implemented**
|
||||||
COMBIN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COMBIN
|
COMBIN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COMBIN
|
||||||
|
COMBINA | **Not yet Implemented**
|
||||||
COS | cos
|
COS | cos
|
||||||
COSH | cosh
|
COSH | cosh
|
||||||
COT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COT
|
COT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COT
|
||||||
COTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COTH
|
COTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COTH
|
||||||
CSC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSC
|
CSC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSC
|
||||||
CSCH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSCH
|
CSCH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSCH
|
||||||
|
DECIMAL | **Not yet Implemented**
|
||||||
DEGREES | rad2deg
|
DEGREES | rad2deg
|
||||||
EVEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::EVEN
|
EVEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::EVEN
|
||||||
EXP | exp
|
EXP | exp
|
||||||
|
@ -278,6 +289,7 @@ FLOOR.MATH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORMATH
|
||||||
FLOOR.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORPRECISE
|
FLOOR.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORPRECISE
|
||||||
GCD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD
|
GCD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD
|
||||||
INT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::INT
|
INT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::INT
|
||||||
|
ISO.CEILING | **Not yet Implemented**
|
||||||
LCM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM
|
LCM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM
|
||||||
LN | log
|
LN | log
|
||||||
LOG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::logBase
|
LOG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::logBase
|
||||||
|
@ -288,6 +300,7 @@ MMULT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MMULT
|
||||||
MOD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MOD
|
MOD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MOD
|
||||||
MROUND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MROUND
|
MROUND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MROUND
|
||||||
MULTINOMIAL | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MULTINOMIAL
|
MULTINOMIAL | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MULTINOMIAL
|
||||||
|
MUNIT | **Not yet Implemented**
|
||||||
ODD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ODD
|
ODD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ODD
|
||||||
PI | pi
|
PI | pi
|
||||||
POWER | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::POWER
|
POWER | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::POWER
|
||||||
|
@ -295,6 +308,7 @@ PRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::PRODUCT
|
||||||
QUOTIENT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::QUOTIENT
|
QUOTIENT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::QUOTIENT
|
||||||
RADIANS | deg2rad
|
RADIANS | deg2rad
|
||||||
RAND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND
|
RAND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND
|
||||||
|
RANDARRAY | **Not yet Implemented**
|
||||||
RANDBETWEEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND
|
RANDBETWEEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND
|
||||||
ROMAN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROMAN
|
ROMAN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROMAN
|
||||||
ROUND | round
|
ROUND | round
|
||||||
|
@ -303,6 +317,7 @@ ROUNDUP | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROUNDUP
|
||||||
SEC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SEC
|
SEC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SEC
|
||||||
SECH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SECH
|
SECH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SECH
|
||||||
SERIESSUM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SERIESSUM
|
SERIESSUM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SERIESSUM
|
||||||
|
SEQUENCE | **Not yet Implemented**
|
||||||
SIGN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SIGN
|
SIGN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SIGN
|
||||||
SIN | sin
|
SIN | sin
|
||||||
SINH | sinh
|
SINH | sinh
|
||||||
|
@ -324,19 +339,31 @@ TRUNC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::TRUNC
|
||||||
## CATEGORY_STATISTICAL
|
## CATEGORY_STATISTICAL
|
||||||
|
|
||||||
Excel Function | PhpSpreadsheet Function
|
Excel Function | PhpSpreadsheet Function
|
||||||
--------------------|-------------------------------------------
|
-------------------------|-------------------------------------------
|
||||||
AVEDEV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVEDEV
|
AVEDEV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVEDEV
|
||||||
AVERAGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGE
|
AVERAGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGE
|
||||||
AVERAGEA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEA
|
AVERAGEA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEA
|
||||||
AVERAGEIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEIF
|
AVERAGEIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEIF
|
||||||
AVERAGEIFS | **Not yet Implemented**
|
AVERAGEIFS | **Not yet Implemented**
|
||||||
BETADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST
|
BETADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST
|
||||||
|
BETA.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST
|
||||||
BETAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV
|
BETAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV
|
||||||
|
BETA.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV
|
||||||
BINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST
|
BINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST
|
||||||
|
BINOM.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST
|
||||||
|
BINOM.DIST.RANGE | **Not yet Implemented**
|
||||||
|
BINOM.INV | **Not yet Implemented**
|
||||||
CHIDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST
|
CHIDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST
|
||||||
|
CHISQ.DIST | **Not yet Implemented**
|
||||||
|
CHISQ.DIST.RT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST
|
||||||
CHIINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV
|
CHIINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV
|
||||||
|
CHISQ.INV | **Not yet Implemented**
|
||||||
|
CHISQ.INV.RT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV
|
||||||
CHITEST | **Not yet Implemented**
|
CHITEST | **Not yet Implemented**
|
||||||
|
CHISQ.TEST | **Not yet Implemented**
|
||||||
CONFIDENCE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE
|
CONFIDENCE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE
|
||||||
|
CONFIDENCE.NORM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE
|
||||||
|
CONFIDENCE.T | **Not yet Implemented**
|
||||||
CORREL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
CORREL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
||||||
COUNT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNT
|
COUNT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNT
|
||||||
COUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTA
|
COUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTA
|
||||||
|
@ -344,19 +371,37 @@ COUNTBLANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTBL
|
||||||
COUNTIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIF
|
COUNTIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIF
|
||||||
COUNTIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIFS
|
COUNTIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIFS
|
||||||
COVAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
|
COVAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
|
||||||
|
COVARIANCE.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
|
||||||
|
COVARIANCE.S | **Not yet Implemented**
|
||||||
CRITBINOM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM
|
CRITBINOM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM
|
||||||
DEVSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ
|
DEVSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ
|
||||||
EXPONDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST
|
EXPONDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST
|
||||||
|
EXPON.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST
|
||||||
FDIST | **Not yet Implemented**
|
FDIST | **Not yet Implemented**
|
||||||
|
F.DIST | **Not yet Implemented**
|
||||||
|
F.DIST.RT | **Not yet Implemented**
|
||||||
FINV | **Not yet Implemented**
|
FINV | **Not yet Implemented**
|
||||||
|
F.INV | **Not yet Implemented**
|
||||||
|
F.INV.RT | **Not yet Implemented**
|
||||||
|
F.TEST | **Not yet Implemented**
|
||||||
FISHER | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHER
|
FISHER | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHER
|
||||||
FISHERINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHERINV
|
FISHERINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHERINV
|
||||||
FORECAST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FORECAST
|
FORECAST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::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::FORECAST
|
||||||
FREQUENCY | **Not yet Implemented**
|
FREQUENCY | **Not yet Implemented**
|
||||||
FTEST | **Not yet Implemented**
|
FTEST | **Not yet Implemented**
|
||||||
|
GAMMA | **Not yet Implemented**
|
||||||
GAMMADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST
|
GAMMADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST
|
||||||
|
GAMMA.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST
|
||||||
GAMMAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV
|
GAMMAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV
|
||||||
|
GAMMA.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV
|
||||||
GAMMALN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN
|
GAMMALN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN
|
||||||
|
GAMMALN.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN
|
||||||
|
GAUSS | **Not yet Implemented**
|
||||||
GEOMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GEOMEAN
|
GEOMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GEOMEAN
|
||||||
GROWTH | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GROWTH
|
GROWTH | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GROWTH
|
||||||
HARMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HARMEAN
|
HARMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HARMEAN
|
||||||
|
@ -368,6 +413,8 @@ LINEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LINEST
|
||||||
LOGEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGEST
|
LOGEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGEST
|
||||||
LOGINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
|
LOGINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
|
||||||
LOGNORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST
|
LOGNORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST
|
||||||
|
LOGNORM.DIST | **Not yet Implemented**
|
||||||
|
LOGNORM.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
|
||||||
MAX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX
|
MAX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX
|
||||||
MAXA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA
|
MAXA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA
|
||||||
MAXIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIFS
|
MAXIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIFS
|
||||||
|
@ -377,22 +424,40 @@ MIN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MIN
|
||||||
MINA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINA
|
MINA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINA
|
||||||
MINIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIFS
|
MINIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIFS
|
||||||
MODE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
|
MODE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
|
||||||
|
MODE.MULT | **Not yet Implemented**
|
||||||
MODE.SNGL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
|
MODE.SNGL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
|
||||||
NEGBINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST
|
NEGBINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST
|
||||||
|
NEGBINOM.DIST | **Not yet Implemented**
|
||||||
NORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST
|
NORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST
|
||||||
|
NORM.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST
|
||||||
NORMINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV
|
NORMINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV
|
||||||
|
NORM.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV
|
||||||
NORMSDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSDIST
|
NORMSDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSDIST
|
||||||
|
NORM.S.DIST | **Not yet Implemented**
|
||||||
NORMSINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV
|
NORMSINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV
|
||||||
|
NORM.S.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV
|
||||||
PEARSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
PEARSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
||||||
PERCENTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE
|
PERCENTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE
|
||||||
|
PERCENTILE.EXC | **Not yet Implemented**
|
||||||
|
PERCENTILE.INC | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE
|
||||||
PERCENTRANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK
|
PERCENTRANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK
|
||||||
|
PERCENTRANK.EXC | **Not yet Implemented**
|
||||||
|
PERCENTRANK.INC | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK
|
||||||
PERMUT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERMUT
|
PERMUT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERMUT
|
||||||
|
PERMUTATIONA | **Not yet Implemented**
|
||||||
|
PHI | **Not yet Implemented**
|
||||||
POISSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON
|
POISSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON
|
||||||
|
POISSON.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON
|
||||||
PROB | **Not yet Implemented**
|
PROB | **Not yet Implemented**
|
||||||
QUARTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE
|
QUARTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE
|
||||||
|
QUARTILE.EXC | **Not yet Implemented**
|
||||||
|
QUARTILE.INC | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE
|
||||||
RANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK
|
RANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK
|
||||||
|
RANK.AVG | **Not yet Implemented**
|
||||||
|
RANK.EQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK
|
||||||
RSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RSQ
|
RSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RSQ
|
||||||
SKEW | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SKEW
|
SKEW | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SKEW
|
||||||
|
SKEW.P | **Not yet Implemented**
|
||||||
SLOPE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SLOPE
|
SLOPE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SLOPE
|
||||||
SMALL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SMALL
|
SMALL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SMALL
|
||||||
STANDARDIZE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STANDARDIZE
|
STANDARDIZE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STANDARDIZE
|
||||||
|
@ -404,10 +469,16 @@ STDEVP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP
|
||||||
STDEVPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVPA
|
STDEVPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVPA
|
||||||
STEYX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STEYX
|
STEYX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STEYX
|
||||||
TDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TDIST
|
TDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TDIST
|
||||||
|
T.DIST | **Not yet Implemented**
|
||||||
|
T.DIST.2T | **Not yet Implemented**
|
||||||
|
T.DIST.RT | **Not yet Implemented**
|
||||||
TINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV
|
TINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV
|
||||||
|
T.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV
|
||||||
|
T.INV.2T | **Not yet Implemented**
|
||||||
TREND | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TREND
|
TREND | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TREND
|
||||||
TRIMMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TRIMMEAN
|
TRIMMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TRIMMEAN
|
||||||
TTEST | **Not yet Implemented**
|
TTEST | **Not yet Implemented**
|
||||||
|
T.TEST | **Not yet Implemented**
|
||||||
VAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc
|
VAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc
|
||||||
VAR.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
VAR.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
||||||
VAR.S | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc
|
VAR.S | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc
|
||||||
|
@ -415,7 +486,9 @@ VARA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARA
|
||||||
VARP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
VARP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
||||||
VARPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARPA
|
VARPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARPA
|
||||||
WEIBULL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL
|
WEIBULL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL
|
||||||
|
WEIBULL.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL
|
||||||
ZTEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST
|
ZTEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST
|
||||||
|
Z.TEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST
|
||||||
|
|
||||||
## CATEGORY_TEXT_AND_DATA
|
## CATEGORY_TEXT_AND_DATA
|
||||||
|
|
||||||
|
@ -428,6 +501,7 @@ CLEAN | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMNONPRI
|
||||||
CODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE
|
CODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE
|
||||||
CONCAT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE
|
CONCAT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE
|
||||||
CONCATENATE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE
|
CONCATENATE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE
|
||||||
|
DBCS | **Not yet Implemented**
|
||||||
DOLLAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData::DOLLAR
|
DOLLAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData::DOLLAR
|
||||||
EXACT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::EXACT
|
EXACT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::EXACT
|
||||||
FIND | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE
|
FIND | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE
|
||||||
|
@ -460,3 +534,11 @@ UNICHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER
|
||||||
UNICODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE
|
UNICODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE
|
||||||
UPPER | \PhpOffice\PhpSpreadsheet\Calculation\TextData::UPPERCASE
|
UPPER | \PhpOffice\PhpSpreadsheet\Calculation\TextData::UPPERCASE
|
||||||
VALUE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::VALUE
|
VALUE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::VALUE
|
||||||
|
|
||||||
|
## CATEGORY_WEB
|
||||||
|
|
||||||
|
Excel Function | PhpSpreadsheet Function
|
||||||
|
--------------------|-------------------------------------------
|
||||||
|
ENCODEURL | **Not yet Implemented**
|
||||||
|
FILTERXML | **Not yet Implemented**
|
||||||
|
WEBSERVICE | \PhpOffice\PhpSpreadsheet\Calculation\Web::WEBSERVICE
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
## A
|
## A
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
ABS | CATEGORY_MATH_AND_TRIG | abs
|
ABS | CATEGORY_MATH_AND_TRIG | abs
|
||||||
ACCRINT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINT
|
ACCRINT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINT
|
||||||
ACCRINTM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINTM
|
ACCRINTM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINTM
|
||||||
|
@ -12,6 +12,7 @@ ACOSH | CATEGORY_MATH_AND_TRIG | acosh
|
||||||
ACOT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOT
|
ACOT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOT
|
||||||
ACOTH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOTH
|
ACOTH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOTH
|
||||||
ADDRESS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::cellAddress
|
ADDRESS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::cellAddress
|
||||||
|
AGGREGATE | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
AMORDEGRC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORDEGRC
|
AMORDEGRC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORDEGRC
|
||||||
AMORLINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORLINC
|
AMORLINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORLINC
|
||||||
AND | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalAnd
|
AND | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalAnd
|
||||||
|
@ -32,7 +33,7 @@ AVERAGEIFS | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
## B
|
## B
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
BAHTTEXT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
BAHTTEXT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
||||||
BASE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::BASE
|
BASE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::BASE
|
||||||
BESSELI | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELI
|
BESSELI | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELI
|
||||||
|
@ -40,11 +41,16 @@ BESSELJ | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet
|
||||||
BESSELK | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELK
|
BESSELK | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELK
|
||||||
BESSELY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELY
|
BESSELY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELY
|
||||||
BETADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST
|
BETADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST
|
||||||
|
BETA.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST
|
||||||
BETAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV
|
BETAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV
|
||||||
|
BETA.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV
|
||||||
BIN2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTODEC
|
BIN2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTODEC
|
||||||
BIN2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOHEX
|
BIN2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOHEX
|
||||||
BIN2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOOCT
|
BIN2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOOCT
|
||||||
BINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST
|
BINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST
|
||||||
|
BINOM.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST
|
||||||
|
BINOM.DIST.RANGE | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
BINOM.INV | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
BITAND | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BITAND
|
BITAND | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BITAND
|
||||||
BITLSHIFT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BITLSHIFT
|
BITLSHIFT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BITLSHIFT
|
||||||
BITOR | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BITOR
|
BITOR | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BITOR
|
||||||
|
@ -54,12 +60,19 @@ BITXOR | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet
|
||||||
## C
|
## C
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
CEILING | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CEILING
|
CEILING | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CEILING
|
||||||
|
CEILING.MATH | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
|
CEILING.PRECISE | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
CELL | CATEGORY_INFORMATION | **Not yet Implemented**
|
CELL | CATEGORY_INFORMATION | **Not yet Implemented**
|
||||||
CHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER
|
CHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER
|
||||||
CHIDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST
|
CHIDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST
|
||||||
CHIINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV
|
CHIINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV
|
||||||
|
CHISQ.DIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
CHISQ.DIST.RT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST
|
||||||
|
CHISQ.INV | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
CHISQ.INV.RT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV
|
||||||
|
CHISQ.TEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
CHITEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
CHITEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
CHOOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CHOOSE
|
CHOOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CHOOSE
|
||||||
CLEAN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMNONPRINTABLE
|
CLEAN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMNONPRINTABLE
|
||||||
|
@ -67,10 +80,13 @@ CODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet
|
||||||
COLUMN | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMN
|
COLUMN | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMN
|
||||||
COLUMNS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMNS
|
COLUMNS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMNS
|
||||||
COMBIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COMBIN
|
COMBIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COMBIN
|
||||||
|
COMBINA | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
COMPLEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::COMPLEX
|
COMPLEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::COMPLEX
|
||||||
CONCAT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE
|
CONCAT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE
|
||||||
CONCATENATE | 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
|
CONFIDENCE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE
|
||||||
|
CONFIDENCE.NORM | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE
|
||||||
|
CONFIDENCE.T | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
CONVERT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::CONVERTUOM
|
CONVERT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::CONVERTUOM
|
||||||
CORREL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
CORREL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
||||||
COS | CATEGORY_MATH_AND_TRIG | cos
|
COS | CATEGORY_MATH_AND_TRIG | cos
|
||||||
|
@ -89,6 +105,8 @@ COUPNCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
COUPNUM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPNUM
|
COUPNUM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPNUM
|
||||||
COUPPCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPPCD
|
COUPPCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPPCD
|
||||||
COVAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
|
COVAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
|
||||||
|
COVARIANCE.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
|
||||||
|
COVARIANCE.S | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
CRITBINOM | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM
|
CRITBINOM | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM
|
||||||
CSC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSC
|
CSC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSC
|
||||||
CSCH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSCH
|
CSCH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSCH
|
||||||
|
@ -105,7 +123,7 @@ CUMPRINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
## D
|
## D
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
DATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATE
|
DATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATE
|
||||||
DATEDIF | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEDIF
|
DATEDIF | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEDIF
|
||||||
DATEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEVALUE
|
DATEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEVALUE
|
||||||
|
@ -114,12 +132,14 @@ DAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet
|
||||||
DAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYS
|
DAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYS
|
||||||
DAYS360 | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYS360
|
DAYS360 | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYS360
|
||||||
DB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DB
|
DB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DB
|
||||||
|
DBCS | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
||||||
DCOUNT | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNT
|
DCOUNT | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNT
|
||||||
DCOUNTA | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNTA
|
DCOUNTA | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNTA
|
||||||
DDB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DDB
|
DDB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DDB
|
||||||
DEC2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOBIN
|
DEC2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOBIN
|
||||||
DEC2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOHEX
|
DEC2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOHEX
|
||||||
DEC2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOOCT
|
DEC2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOOCT
|
||||||
|
DECIMAL | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
DEGREES | CATEGORY_MATH_AND_TRIG | rad2deg
|
DEGREES | CATEGORY_MATH_AND_TRIG | rad2deg
|
||||||
DELTA | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DELTA
|
DELTA | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DELTA
|
||||||
DEVSQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ
|
DEVSQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ
|
||||||
|
@ -141,31 +161,39 @@ DVARP | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet
|
||||||
## E
|
## E
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
EDATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EDATE
|
EDATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EDATE
|
||||||
EFFECT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::EFFECT
|
EFFECT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::EFFECT
|
||||||
|
ENCODEURL | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
||||||
EOMONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EOMONTH
|
EOMONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EOMONTH
|
||||||
ERF | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERF
|
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 | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC
|
||||||
ERFC.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC
|
ERFC.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC
|
||||||
|
ERF.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFPRECISE
|
||||||
ERROR.TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::errorType
|
ERROR.TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::errorType
|
||||||
EVEN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::EVEN
|
EVEN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::EVEN
|
||||||
EXACT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::EXACT
|
EXACT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::EXACT
|
||||||
EXP | CATEGORY_MATH_AND_TRIG | exp
|
EXP | CATEGORY_MATH_AND_TRIG | exp
|
||||||
EXPONDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST
|
EXPONDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST
|
||||||
|
EXPON.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST
|
||||||
|
|
||||||
## F
|
## F
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
FACT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACT
|
FACT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACT
|
||||||
FACTDOUBLE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACTDOUBLE
|
FACTDOUBLE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACTDOUBLE
|
||||||
FALSE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::FALSE
|
FALSE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::FALSE
|
||||||
FDIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
FDIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
F.DIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
F.DIST.RT | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
FILTER | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
|
FILTERXML | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
||||||
FIND | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE
|
FIND | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE
|
||||||
FINDB | 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**
|
FINV | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
F.INV | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
F.INV.RT | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
FISHER | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHER
|
FISHER | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHER
|
||||||
FISHERINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHERINV
|
FISHERINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHERINV
|
||||||
FIXED | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::FIXEDFORMAT
|
FIXED | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::FIXEDFORMAT
|
||||||
|
@ -173,19 +201,30 @@ FLOOR | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet
|
||||||
FLOOR.MATH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORMATH
|
FLOOR.MATH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORMATH
|
||||||
FLOOR.PRECISE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORPRECISE
|
FLOOR.PRECISE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORPRECISE
|
||||||
FORECAST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FORECAST
|
FORECAST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::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::FORECAST
|
||||||
FORMULATEXT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT
|
FORMULATEXT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT
|
||||||
FREQUENCY | CATEGORY_STATISTICAL | **Not yet Implemented**
|
FREQUENCY | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
FTEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
FTEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
F.TEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
FV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FV
|
FV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FV
|
||||||
FVSCHEDULE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FVSCHEDULE
|
FVSCHEDULE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FVSCHEDULE
|
||||||
|
|
||||||
## G
|
## G
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
|
GAMMA | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
GAMMADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST
|
GAMMADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST
|
||||||
|
GAMMA.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST
|
||||||
GAMMAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV
|
GAMMAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV
|
||||||
|
GAMMA.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV
|
||||||
GAMMALN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN
|
GAMMALN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN
|
||||||
|
GAMMALN.PRECISE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN
|
||||||
|
GAUSS | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
GCD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD
|
GCD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD
|
||||||
GEOMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GEOMEAN
|
GEOMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GEOMEAN
|
||||||
GESTEP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::GESTEP
|
GESTEP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::GESTEP
|
||||||
|
@ -195,7 +234,7 @@ GROWTH | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet
|
||||||
## H
|
## H
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
HARMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HARMEAN
|
HARMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HARMEAN
|
||||||
HEX2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTOBIN
|
HEX2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTOBIN
|
||||||
HEX2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTODEC
|
HEX2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTODEC
|
||||||
|
@ -208,11 +247,11 @@ HYPGEOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet
|
||||||
## I
|
## I
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
IF | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementIf
|
IF | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementIf
|
||||||
IFERROR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR
|
IFERROR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR
|
||||||
IFNA | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFNA
|
IFNA | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFNA
|
||||||
IFS | CATEGORY_LOGICAL | **Not yet Implemented**
|
IFS | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFS
|
||||||
IMABS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMABS
|
IMABS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMABS
|
||||||
IMAGINARY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMAGINARY
|
IMAGINARY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMAGINARY
|
||||||
IMARGUMENT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT
|
IMARGUMENT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT
|
||||||
|
@ -255,6 +294,7 @@ ISLOGICAL | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet
|
||||||
ISNA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isNa
|
ISNA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isNa
|
||||||
ISNONTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isNonText
|
ISNONTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isNonText
|
||||||
ISNUMBER | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isNumber
|
ISNUMBER | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isNumber
|
||||||
|
ISO.CEILING | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
ISODD | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isOdd
|
ISODD | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isOdd
|
||||||
ISOWEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::ISOWEEKNUM
|
ISOWEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::ISOWEEKNUM
|
||||||
ISPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ISPMT
|
ISPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ISPMT
|
||||||
|
@ -264,19 +304,19 @@ ISTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet
|
||||||
## J
|
## J
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
JIS | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
JIS | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
||||||
|
|
||||||
## K
|
## K
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
KURT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::KURT
|
KURT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::KURT
|
||||||
|
|
||||||
## L
|
## L
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
LARGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LARGE
|
LARGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LARGE
|
||||||
LCM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM
|
LCM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM
|
||||||
LEFT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LEFT
|
LEFT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LEFT
|
||||||
|
@ -290,13 +330,15 @@ LOG10 | CATEGORY_MATH_AND_TRIG | log10
|
||||||
LOGEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGEST
|
LOGEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGEST
|
||||||
LOGINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
|
LOGINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
|
||||||
LOGNORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST
|
LOGNORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST
|
||||||
|
LOGNORM.DIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
LOGNORM.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
|
||||||
LOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::LOOKUP
|
LOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::LOOKUP
|
||||||
LOWER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LOWERCASE
|
LOWER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LOWERCASE
|
||||||
|
|
||||||
## M
|
## M
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
MATCH | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::MATCH
|
MATCH | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::MATCH
|
||||||
MAX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX
|
MAX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX
|
||||||
MAXA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA
|
MAXA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA
|
||||||
|
@ -316,25 +358,32 @@ MIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
MMULT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MMULT
|
MMULT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MMULT
|
||||||
MOD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MOD
|
MOD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MOD
|
||||||
MODE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
|
MODE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
|
||||||
|
MODE.MULT | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
MODE.SNGL | 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
|
MONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::MONTHOFYEAR
|
||||||
MROUND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MROUND
|
MROUND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MROUND
|
||||||
MULTINOMIAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MULTINOMIAL
|
MULTINOMIAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MULTINOMIAL
|
||||||
|
MUNIT | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
|
|
||||||
## N
|
## N
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
N | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::n
|
N | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::n
|
||||||
NA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::NA
|
NA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::NA
|
||||||
NEGBINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST
|
NEGBINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST
|
||||||
|
NEGBINOM.DIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
NETWORKDAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::NETWORKDAYS
|
NETWORKDAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::NETWORKDAYS
|
||||||
NETWORKDAYS.INTL | CATEGORY_DATE_AND_TIME | **Not yet Implemented**
|
NETWORKDAYS.INTL | CATEGORY_DATE_AND_TIME | **Not yet Implemented**
|
||||||
NOMINAL | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NOMINAL
|
NOMINAL | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NOMINAL
|
||||||
NORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST
|
NORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST
|
||||||
|
NORM.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST
|
||||||
NORMINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV
|
NORMINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV
|
||||||
|
NORM.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV
|
||||||
NORMSDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSDIST
|
NORMSDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSDIST
|
||||||
|
NORM.S.DIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
NORMSINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV
|
NORMSINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV
|
||||||
|
NORM.S.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV
|
||||||
NOT | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT
|
NOT | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT
|
||||||
NOW | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATETIMENOW
|
NOW | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATETIMENOW
|
||||||
NPER | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NPER
|
NPER | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NPER
|
||||||
|
@ -344,7 +393,7 @@ NUMBERVALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet
|
||||||
## O
|
## O
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
OCT2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOBIN
|
OCT2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOBIN
|
||||||
OCT2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTODEC
|
OCT2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTODEC
|
||||||
OCT2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOHEX
|
OCT2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOHEX
|
||||||
|
@ -359,16 +408,23 @@ OR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet
|
||||||
## P
|
## P
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
PDURATION | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PDURATION
|
PDURATION | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PDURATION
|
||||||
PEARSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
PEARSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL
|
||||||
PERCENTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE
|
PERCENTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE
|
||||||
|
PERCENTILE.EXC | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
PERCENTILE.INC | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE
|
||||||
PERCENTRANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK
|
PERCENTRANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK
|
||||||
|
PERCENTRANK.EXC | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
PERCENTRANK.INC | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK
|
||||||
PERMUT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERMUT
|
PERMUT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERMUT
|
||||||
|
PERMUTATIONA | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
PHI | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
PHONETIC | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
PHONETIC | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
|
||||||
PI | CATEGORY_MATH_AND_TRIG | pi
|
PI | CATEGORY_MATH_AND_TRIG | pi
|
||||||
PMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PMT
|
PMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PMT
|
||||||
POISSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON
|
POISSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON
|
||||||
|
POISSON.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON
|
||||||
POWER | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::POWER
|
POWER | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::POWER
|
||||||
PPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PPMT
|
PPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PPMT
|
||||||
PRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICE
|
PRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICE
|
||||||
|
@ -382,18 +438,23 @@ PV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
## Q
|
## Q
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
QUARTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE
|
QUARTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE
|
||||||
|
QUARTILE.EXC | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
QUARTILE.INC | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE
|
||||||
QUOTIENT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::QUOTIENT
|
QUOTIENT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::QUOTIENT
|
||||||
|
|
||||||
## R
|
## R
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
RADIANS | CATEGORY_MATH_AND_TRIG | deg2rad
|
RADIANS | CATEGORY_MATH_AND_TRIG | deg2rad
|
||||||
RAND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND
|
RAND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND
|
||||||
|
RANDARRAY | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
RANDBETWEEN | 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
|
RANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK
|
||||||
|
RANK.AVG | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
RANK.EQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK
|
||||||
RATE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RATE
|
RATE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RATE
|
||||||
RECEIVED | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RECEIVED
|
RECEIVED | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RECEIVED
|
||||||
REPLACE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::REPLACE
|
REPLACE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::REPLACE
|
||||||
|
@ -414,12 +475,13 @@ RTD | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
## S
|
## S
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
SEARCH | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHINSENSITIVE
|
SEARCH | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHINSENSITIVE
|
||||||
SEARCHB | 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
|
SEC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SEC
|
||||||
SECH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SECH
|
SECH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SECH
|
||||||
SECOND | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::SECOND
|
SECOND | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::SECOND
|
||||||
|
SEQUENCE | CATEGORY_MATH_AND_TRIG | **Not yet Implemented**
|
||||||
SERIESSUM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SERIESSUM
|
SERIESSUM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SERIESSUM
|
||||||
SHEET | CATEGORY_INFORMATION | **Not yet Implemented**
|
SHEET | CATEGORY_INFORMATION | **Not yet Implemented**
|
||||||
SHEETS | CATEGORY_INFORMATION | **Not yet Implemented**
|
SHEETS | CATEGORY_INFORMATION | **Not yet Implemented**
|
||||||
|
@ -427,18 +489,21 @@ SIGN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet
|
||||||
SIN | CATEGORY_MATH_AND_TRIG | sin
|
SIN | CATEGORY_MATH_AND_TRIG | sin
|
||||||
SINH | CATEGORY_MATH_AND_TRIG | sinh
|
SINH | CATEGORY_MATH_AND_TRIG | sinh
|
||||||
SKEW | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SKEW
|
SKEW | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SKEW
|
||||||
|
SKEW.P | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
SLN | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::SLN
|
SLN | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::SLN
|
||||||
SLOPE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SLOPE
|
SLOPE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SLOPE
|
||||||
SMALL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SMALL
|
SMALL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SMALL
|
||||||
|
SORT | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
|
SORTBY | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
SQRT | CATEGORY_MATH_AND_TRIG | sqrt
|
SQRT | CATEGORY_MATH_AND_TRIG | sqrt
|
||||||
SQRTPI | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SQRTPI
|
SQRTPI | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SQRTPI
|
||||||
STANDARDIZE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STANDARDIZE
|
STANDARDIZE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STANDARDIZE
|
||||||
STDEV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV
|
STDEV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV
|
||||||
STDEV.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP
|
|
||||||
STDEV.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV
|
|
||||||
STDEVA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVA
|
STDEVA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVA
|
||||||
STDEVP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP
|
STDEVP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP
|
||||||
|
STDEV.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP
|
||||||
STDEVPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVPA
|
STDEVPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVPA
|
||||||
|
STDEV.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV
|
||||||
STEYX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STEYX
|
STEYX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STEYX
|
||||||
SUBSTITUTE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SUBSTITUTE
|
SUBSTITUTE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SUBSTITUTE
|
||||||
SUBTOTAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUBTOTAL
|
SUBTOTAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUBTOTAL
|
||||||
|
@ -456,7 +521,7 @@ SYD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
## T
|
## T
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
T | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RETURNSTRING
|
T | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RETURNSTRING
|
||||||
TAN | CATEGORY_MATH_AND_TRIG | tan
|
TAN | CATEGORY_MATH_AND_TRIG | tan
|
||||||
TANH | CATEGORY_MATH_AND_TRIG | tanh
|
TANH | CATEGORY_MATH_AND_TRIG | tanh
|
||||||
|
@ -464,11 +529,16 @@ TBILLEQ | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
TBILLPRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLPRICE
|
TBILLPRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLPRICE
|
||||||
TBILLYIELD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLYIELD
|
TBILLYIELD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLYIELD
|
||||||
TDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TDIST
|
TDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TDIST
|
||||||
|
T.DIST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
T.DIST.2T | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
T.DIST.RT | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
TEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTFORMAT
|
TEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTFORMAT
|
||||||
TEXTJOIN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTJOIN
|
TEXTJOIN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTJOIN
|
||||||
TIME | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIME
|
TIME | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIME
|
||||||
TIMEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIMEVALUE
|
TIMEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIMEVALUE
|
||||||
TINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV
|
TINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV
|
||||||
|
T.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV
|
||||||
|
T.INV.2T | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
TODAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATENOW
|
TODAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATENOW
|
||||||
TRANSPOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::TRANSPOSE
|
TRANSPOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::TRANSPOSE
|
||||||
TREND | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TREND
|
TREND | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TREND
|
||||||
|
@ -477,53 +547,59 @@ TRIMMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet
|
||||||
TRUE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::TRUE
|
TRUE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::TRUE
|
||||||
TRUNC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::TRUNC
|
TRUNC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::TRUNC
|
||||||
TTEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
TTEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
|
T.TEST | CATEGORY_STATISTICAL | **Not yet Implemented**
|
||||||
TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::TYPE
|
TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::TYPE
|
||||||
|
|
||||||
## U
|
## U
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
UNICHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER
|
UNICHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER
|
||||||
UNICODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE
|
UNICODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE
|
||||||
|
UNIQUE | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
UPPER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::UPPERCASE
|
UPPER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::UPPERCASE
|
||||||
USDOLLAR | CATEGORY_FINANCIAL | **Not yet Implemented**
|
USDOLLAR | CATEGORY_FINANCIAL | **Not yet Implemented**
|
||||||
|
|
||||||
## V
|
## V
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
VALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::VALUE
|
VALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::VALUE
|
||||||
VAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc
|
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
|
VARA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARA
|
||||||
VARP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
VARP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
||||||
|
VAR.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP
|
||||||
VARPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARPA
|
VARPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARPA
|
||||||
|
VAR.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc
|
||||||
VDB | CATEGORY_FINANCIAL | **Not yet Implemented**
|
VDB | CATEGORY_FINANCIAL | **Not yet Implemented**
|
||||||
VLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::VLOOKUP
|
VLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::VLOOKUP
|
||||||
|
|
||||||
## W
|
## W
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
|
WEBSERVICE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\Web::WEBSERVICE
|
||||||
WEEKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKDAY
|
WEEKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKDAY
|
||||||
WEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKNUM
|
WEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKNUM
|
||||||
WEIBULL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL
|
WEIBULL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL
|
||||||
|
WEIBULL.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL
|
||||||
WORKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WORKDAY
|
WORKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WORKDAY
|
||||||
WORKDAY.INTL | CATEGORY_DATE_AND_TIME | **Not yet Implemented**
|
WORKDAY.INTL | CATEGORY_DATE_AND_TIME | **Not yet Implemented**
|
||||||
|
|
||||||
## X
|
## X
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
XIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XIRR
|
XIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XIRR
|
||||||
|
XLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
|
XMATCH | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
|
||||||
XNPV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XNPV
|
XNPV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XNPV
|
||||||
XOR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalXor
|
XOR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalXor
|
||||||
|
|
||||||
## Y
|
## Y
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
YEAR | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEAR
|
YEAR | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEAR
|
||||||
YEARFRAC | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEARFRAC
|
YEARFRAC | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEARFRAC
|
||||||
YIELD | CATEGORY_FINANCIAL | **Not yet Implemented**
|
YIELD | CATEGORY_FINANCIAL | **Not yet Implemented**
|
||||||
|
@ -533,5 +609,6 @@ YIELDMAT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet
|
||||||
## Z
|
## Z
|
||||||
|
|
||||||
Excel Function | Category | PhpSpreadsheet Function
|
Excel Function | Category | PhpSpreadsheet Function
|
||||||
--------------------|--------------------------------|-------------------------------------------
|
-------------------------|-------------------------------|-------------------------
|
||||||
ZTEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST
|
ZTEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST
|
||||||
|
Z.TEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST
|
||||||
|
|
|
@ -8,7 +8,7 @@ topic lists some of the options to access a cell.
|
||||||
Setting a cell value by coordinate can be done using the worksheet's
|
Setting a cell value by coordinate can be done using the worksheet's
|
||||||
`setCellValue()` method.
|
`setCellValue()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Set cell A1 with a string value
|
// Set cell A1 with a string value
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('A1', 'PhpSpreadsheet');
|
$spreadsheet->getActiveSheet()->setCellValue('A1', 'PhpSpreadsheet');
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ $spreadsheet->getActiveSheet()->setCellValue(
|
||||||
Alternatively, you can retrieve the cell object, and then call the
|
Alternatively, you can retrieve the cell object, and then call the
|
||||||
cell’s `setValue()` method:
|
cell’s `setValue()` method:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->getCell('B8')
|
->getCell('B8')
|
||||||
->setValue('Some value');
|
->setValue('Some value');
|
||||||
|
@ -56,7 +56,7 @@ the cell object will still retain its data values.
|
||||||
|
|
||||||
What does this mean? Consider the following code:
|
What does this mean? Consider the following code:
|
||||||
|
|
||||||
```
|
```php
|
||||||
$spreadSheet = new Spreadsheet();
|
$spreadSheet = new Spreadsheet();
|
||||||
$workSheet = $spreadSheet->getActiveSheet();
|
$workSheet = $spreadSheet->getActiveSheet();
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ was a formula.
|
||||||
|
|
||||||
To do this, you need to "escape" the value by setting it as "quoted text".
|
To do this, you need to "escape" the value by setting it as "quoted text".
|
||||||
|
|
||||||
```
|
```php
|
||||||
// Set cell A4 with a formula
|
// Set cell A4 with a formula
|
||||||
$spreadsheet->getActiveSheet()->setCellValue(
|
$spreadsheet->getActiveSheet()->setCellValue(
|
||||||
'A4',
|
'A4',
|
||||||
|
@ -175,7 +175,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
|
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.
|
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
|
// Get the current date/time and convert to an Excel date/time
|
||||||
$dateTimeNow = time();
|
$dateTimeNow = time();
|
||||||
$excelDateValue = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel( $dateTimeNow );
|
$excelDateValue = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel( $dateTimeNow );
|
||||||
|
@ -210,7 +210,7 @@ behaviour.
|
||||||
Firstly, you can set the datatype explicitly as a string so that it is
|
Firstly, you can set the datatype explicitly as a string so that it is
|
||||||
not converted to a number.
|
not converted to a number.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Set cell A8 with a numeric value, but tell PhpSpreadsheet it should be treated as a string
|
// Set cell A8 with a numeric value, but tell PhpSpreadsheet it should be treated as a string
|
||||||
$spreadsheet->getActiveSheet()->setCellValueExplicit(
|
$spreadsheet->getActiveSheet()->setCellValueExplicit(
|
||||||
'A8',
|
'A8',
|
||||||
|
@ -222,7 +222,7 @@ $spreadsheet->getActiveSheet()->setCellValueExplicit(
|
||||||
Alternatively, you can use a number format mask to display the value
|
Alternatively, you can use a number format mask to display the value
|
||||||
with leading zeroes.
|
with leading zeroes.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Set cell A9 with a numeric value
|
// Set cell A9 with a numeric value
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('A9', 1513789642);
|
$spreadsheet->getActiveSheet()->setCellValue('A9', 1513789642);
|
||||||
// Set a number format mask to display the value as 11 digits with leading zeroes
|
// Set a number format mask to display the value as 11 digits with leading zeroes
|
||||||
|
@ -236,7 +236,7 @@ $spreadsheet->getActiveSheet()->getStyle('A9')
|
||||||
With number format masking, you can even break up the digits into groups
|
With number format masking, you can even break up the digits into groups
|
||||||
to make the value more easily readable.
|
to make the value more easily readable.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Set cell A10 with a numeric value
|
// Set cell A10 with a numeric value
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('A10', 1513789642);
|
$spreadsheet->getActiveSheet()->setCellValue('A10', 1513789642);
|
||||||
// Set a number format mask to display the value as 11 digits with leading zeroes
|
// Set a number format mask to display the value as 11 digits with leading zeroes
|
||||||
|
@ -259,7 +259,7 @@ writers (Xlsx and Xls).
|
||||||
It is also possible to set a range of cell values in a single call by
|
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.
|
passing an array of values to the `fromArray()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$arrayData = [
|
$arrayData = [
|
||||||
[NULL, 2010, 2011, 2012],
|
[NULL, 2010, 2011, 2012],
|
||||||
['Q1', 12, 15, 21],
|
['Q1', 12, 15, 21],
|
||||||
|
@ -282,7 +282,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
|
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.
|
particularly useful if you're fetching an array of data from a database.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$rowArray = ['Value1', 'Value2', 'Value3', 'Value4'];
|
$rowArray = ['Value1', 'Value2', 'Value3', 'Value4'];
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->fromArray(
|
->fromArray(
|
||||||
|
@ -299,7 +299,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
|
the following will convert it into an appropriately structured 2-d array
|
||||||
that can be fed to the `fromArray()` method:
|
that can be fed to the `fromArray()` method:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$rowArray = ['Value1', 'Value2', 'Value3', 'Value4'];
|
$rowArray = ['Value1', 'Value2', 'Value3', 'Value4'];
|
||||||
$columnArray = array_chunk($rowArray, 1);
|
$columnArray = array_chunk($rowArray, 1);
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
|
@ -319,7 +319,7 @@ 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
|
the worksheet using the `getCell()` method. A cell's value can be read
|
||||||
using the `getValue()` method.
|
using the `getValue()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Get the value from cell A1
|
// Get the value from cell A1
|
||||||
$cellValue = $spreadsheet->getActiveSheet()->getCell('A1')->getValue();
|
$cellValue = $spreadsheet->getActiveSheet()->getCell('A1')->getValue();
|
||||||
```
|
```
|
||||||
|
@ -331,7 +331,7 @@ value rather than the formula itself, then use the cell's
|
||||||
`getCalculatedValue()` method. This is further explained in
|
`getCalculatedValue()` method. This is further explained in
|
||||||
[the calculation engine](./calculation-engine.md).
|
[the calculation engine](./calculation-engine.md).
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Get the value from cell A4
|
// Get the value from cell A4
|
||||||
$cellValue = $spreadsheet->getActiveSheet()->getCell('A4')->getCalculatedValue();
|
$cellValue = $spreadsheet->getActiveSheet()->getCell('A4')->getCalculatedValue();
|
||||||
```
|
```
|
||||||
|
@ -340,7 +340,7 @@ 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
|
applied (e.g. for a human-readable date or time value), then you can use
|
||||||
the cell's `getFormattedValue()` method.
|
the cell's `getFormattedValue()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Get the value from cell A6
|
// Get the value from cell A6
|
||||||
$cellValue = $spreadsheet->getActiveSheet()->getCell('A6')->getFormattedValue();
|
$cellValue = $spreadsheet->getActiveSheet()->getCell('A6')->getFormattedValue();
|
||||||
```
|
```
|
||||||
|
@ -350,7 +350,7 @@ $cellValue = $spreadsheet->getActiveSheet()->getCell('A6')->getFormattedValue();
|
||||||
Setting a cell value by coordinate can be done using the worksheet's
|
Setting a cell value by coordinate can be done using the worksheet's
|
||||||
`setCellValueByColumnAndRow()` method.
|
`setCellValueByColumnAndRow()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Set cell A5 with a string value
|
// Set cell A5 with a string value
|
||||||
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow(1, 5, 'PhpSpreadsheet');
|
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow(1, 5, 'PhpSpreadsheet');
|
||||||
```
|
```
|
||||||
|
@ -363,7 +363,7 @@ 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
|
the worksheet using the `getCellByColumnAndRow()` method. A cell’s value can
|
||||||
be read again using the following line of code:
|
be read again using the following line of code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Get the value from cell B5
|
// Get the value from cell B5
|
||||||
$cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(2, 5)->getValue();
|
$cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(2, 5)->getValue();
|
||||||
```
|
```
|
||||||
|
@ -371,7 +371,7 @@ $cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(2, 5)->getVal
|
||||||
If you need the calculated value of a cell, use the following code. This
|
If you need the calculated value of a cell, use the following code. This
|
||||||
is further explained in [the calculation engine](./calculation-engine.md).
|
is further explained in [the calculation engine](./calculation-engine.md).
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Get the value from cell A4
|
// Get the value from cell A4
|
||||||
$cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(1, 4)->getCalculatedValue();
|
$cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(1, 4)->getCalculatedValue();
|
||||||
```
|
```
|
||||||
|
@ -382,7 +382,7 @@ It is also possible to retrieve a range of cell values to an array in a
|
||||||
single call using the `toArray()`, `rangeToArray()` or
|
single call using the `toArray()`, `rangeToArray()` or
|
||||||
`namedRangeToArray()` methods.
|
`namedRangeToArray()` methods.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$dataArray = $spreadsheet->getActiveSheet()
|
$dataArray = $spreadsheet->getActiveSheet()
|
||||||
->rangeToArray(
|
->rangeToArray(
|
||||||
'C3:E5', // The worksheet range that we want to retrieve
|
'C3:E5', // The worksheet range that we want to retrieve
|
||||||
|
@ -409,7 +409,7 @@ cells within a row.
|
||||||
Below is an example where we read all the values in a worksheet and
|
Below is an example where we read all the values in a worksheet and
|
||||||
display them in a table.
|
display them in a table.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
||||||
$reader->setReadDataOnly(TRUE);
|
$reader->setReadDataOnly(TRUE);
|
||||||
$spreadsheet = $reader->load("test.xlsx");
|
$spreadsheet = $reader->load("test.xlsx");
|
||||||
|
@ -456,7 +456,7 @@ loops.
|
||||||
Below is an example where we read all the values in a worksheet and
|
Below is an example where we read all the values in a worksheet and
|
||||||
display them in a table.
|
display them in a table.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
||||||
$reader->setReadDataOnly(TRUE);
|
$reader->setReadDataOnly(TRUE);
|
||||||
$spreadsheet = $reader->load("test.xlsx");
|
$spreadsheet = $reader->load("test.xlsx");
|
||||||
|
@ -482,7 +482,7 @@ echo '</table>' . PHP_EOL;
|
||||||
Alternatively, you can take advantage of PHP's "Perl-style" character
|
Alternatively, you can take advantage of PHP's "Perl-style" character
|
||||||
incrementors to loop through the cells by coordinate:
|
incrementors to loop through the cells by coordinate:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
||||||
$reader->setReadDataOnly(TRUE);
|
$reader->setReadDataOnly(TRUE);
|
||||||
$spreadsheet = $reader->load("test.xlsx");
|
$spreadsheet = $reader->load("test.xlsx");
|
||||||
|
@ -528,7 +528,7 @@ dates entered as strings to the correct format, also setting the cell's
|
||||||
style information. The following example demonstrates how to set the
|
style information. The following example demonstrates how to set the
|
||||||
value binder in PhpSpreadsheet:
|
value binder in PhpSpreadsheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
/** PhpSpreadsheet */
|
/** PhpSpreadsheet */
|
||||||
require_once 'src/Boostrap.php';
|
require_once 'src/Boostrap.php';
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ PhpSpreadsheet supports fluent interfaces in most locations. This means
|
||||||
that you can easily "chain" calls to specific methods without requiring
|
that you can easily "chain" calls to specific methods without requiring
|
||||||
a new PHP statement. For example, take the following code:
|
a new PHP statement. For example, take the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getProperties()->setCreator("Maarten Balliauw");
|
$spreadsheet->getProperties()->setCreator("Maarten Balliauw");
|
||||||
$spreadsheet->getProperties()->setLastModifiedBy("Maarten Balliauw");
|
$spreadsheet->getProperties()->setLastModifiedBy("Maarten Balliauw");
|
||||||
$spreadsheet->getProperties()->setTitle("Office 2007 XLSX Test Document");
|
$spreadsheet->getProperties()->setTitle("Office 2007 XLSX Test Document");
|
||||||
|
@ -55,7 +55,7 @@ $spreadsheet->getProperties()->setCategory("Test result file");
|
||||||
|
|
||||||
This can be rewritten as:
|
This can be rewritten as:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getProperties()
|
$spreadsheet->getProperties()
|
||||||
->setCreator("Maarten Balliauw")
|
->setCreator("Maarten Balliauw")
|
||||||
->setLastModifiedBy("Maarten Balliauw")
|
->setLastModifiedBy("Maarten Balliauw")
|
||||||
|
|
|
@ -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.
|
To set an autoFilter on a range of cells.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setAutoFilter('A1:E20');
|
$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
|
If you want to set the whole worksheet as an autofilter region
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setAutoFilter(
|
$spreadsheet->getActiveSheet()->setAutoFilter(
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->calculateWorksheetDimension()
|
->calculateWorksheetDimension()
|
||||||
|
@ -74,7 +74,7 @@ will extend this to other formats.
|
||||||
To apply a filter expression to an autoFilter range, you first need to
|
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.
|
identify which column you're going to be applying this filter to.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||||
$columnFilter = $autoFilter->getColumn('C');
|
$columnFilter = $autoFilter->getColumn('C');
|
||||||
```
|
```
|
||||||
|
@ -114,7 +114,7 @@ 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
|
filter type. In this case, we're just going to specify that this filter
|
||||||
is a standard filter.
|
is a standard filter.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->setFilterType(
|
$columnFilter->setFilterType(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER
|
||||||
);
|
);
|
||||||
|
@ -127,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
|
specify the values for "checked" columns: you do this by creating a
|
||||||
filter rule for each value.
|
filter rule for each value.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||||
|
@ -152,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:
|
If you want to create a filter to select blank cells, you would use:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||||
|
@ -170,7 +170,7 @@ within a year, or individual days within each month.
|
||||||
|
|
||||||
DateGroup filters are still applied as a Standard Filter type.
|
DateGroup filters are still applied as a Standard Filter type.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->setFilterType(
|
$columnFilter->setFilterType(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER
|
||||||
);
|
);
|
||||||
|
@ -181,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
|
minute and second. To select a year and month, you need to create a
|
||||||
DateGroup rule identifying the selected year and month:
|
DateGroup rule identifying the selected year and month:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||||
|
@ -229,7 +229,7 @@ either an AND or an OR.
|
||||||
|
|
||||||
We start by specifying a Filter type, this time a CUSTOMFILTER.
|
We start by specifying a Filter type, this time a CUSTOMFILTER.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->setFilterType(
|
$columnFilter->setFilterType(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER
|
||||||
);
|
);
|
||||||
|
@ -240,7 +240,7 @@ And then define our rules.
|
||||||
The following shows a simple wildcard filter to show all column entries
|
The following shows a simple wildcard filter to show all column entries
|
||||||
beginning with the letter `U`.
|
beginning with the letter `U`.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||||
|
@ -264,7 +264,7 @@ is the \~ itself.
|
||||||
|
|
||||||
To create a "between" condition, we need to define two rules:
|
To create a "between" condition, we need to define two rules:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL,
|
||||||
|
@ -289,7 +289,7 @@ This defined two rules, filtering numbers that are `>= -20` OR `<=
|
||||||
20`, so we also need to modify the join condition to reflect AND rather
|
20`, so we also need to modify the join condition to reflect AND rather
|
||||||
than OR.
|
than OR.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->setAndOr(
|
$columnFilter->setAndOr(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_ANDOR_AND
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_ANDOR_AND
|
||||||
);
|
);
|
||||||
|
@ -320,7 +320,7 @@ column at a time.
|
||||||
|
|
||||||
Again, we start by specifying a Filter type, this time a DYNAMICFILTER.
|
Again, we start by specifying a Filter type, this time a DYNAMICFILTER.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->setFilterType(
|
$columnFilter->setFilterType(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER
|
||||||
);
|
);
|
||||||
|
@ -330,7 +330,7 @@ When defining the rule for a dynamic filter, we don't define a value (we
|
||||||
can simply set that to NULL) but we do specify the dynamic filter
|
can simply set that to NULL) but we do specify the dynamic filter
|
||||||
category.
|
category.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||||
|
@ -420,7 +420,7 @@ column at a time.
|
||||||
|
|
||||||
We start by specifying a Filter type, this time a DYNAMICFILTER.
|
We start by specifying a Filter type, this time a DYNAMICFILTER.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->setFilterType(
|
$columnFilter->setFilterType(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER
|
||||||
);
|
);
|
||||||
|
@ -428,7 +428,7 @@ $columnFilter->setFilterType(
|
||||||
|
|
||||||
Then we create the rule:
|
Then we create the rule:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT,
|
||||||
|
@ -444,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:
|
To specify the lowest (bottom 2 values), we would specify a rule of:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$columnFilter->createRule()
|
$columnFilter->createRule()
|
||||||
->setRule(
|
->setRule(
|
||||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE,
|
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE,
|
||||||
|
@ -490,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()`
|
this manually. You can do this using the autofilters `showHideRows()`
|
||||||
method.
|
method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||||
$autoFilter->showHideRows();
|
$autoFilter->showHideRows();
|
||||||
```
|
```
|
||||||
|
@ -505,7 +505,7 @@ 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
|
access only the filtered rows, you need to test each row’s visibility
|
||||||
settings.
|
settings.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
foreach ($spreadsheet->getActiveSheet()->getRowIterator() as $row) {
|
foreach ($spreadsheet->getActiveSheet()->getRowIterator() as $row) {
|
||||||
if ($spreadsheet->getActiveSheet()
|
if ($spreadsheet->getActiveSheet()
|
||||||
->getRowDimension($row->getRowIndex())->getVisible()) {
|
->getRowDimension($row->getRowIndex())->getVisible()) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ evaluates to the sum of values in A1, A2, ..., A10.
|
||||||
To calculate a formula, you can call the cell containing the formula’s
|
To calculate a formula, you can call the cell containing the formula’s
|
||||||
method `getCalculatedValue()`, for example:
|
method `getCalculatedValue()`, for example:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getCell('E11')->getCalculatedValue();
|
$spreadsheet->getActiveSheet()->getCell('E11')->getCalculatedValue();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -32,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
|
when I write the following line of code, two new product lines are
|
||||||
added:
|
added:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2);
|
$spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ 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
|
the underlying data and need to re-evaluate the same formula with that new
|
||||||
data.
|
data.
|
||||||
|
|
||||||
```
|
```php
|
||||||
Calculation::getInstance($spreadsheet)->disableCalculationCache();
|
Calculation::getInstance($spreadsheet)->disableCalculationCache();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ Will disable calculation caching, and flush the current calculation cache.
|
||||||
|
|
||||||
If you want only to flush the cache, then you can call
|
If you want only to flush the cache, then you can call
|
||||||
|
|
||||||
```
|
```php
|
||||||
Calculation::getInstance($spreadsheet)->clearCalculationCache();
|
Calculation::getInstance($spreadsheet)->clearCalculationCache();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ date values by calling the
|
||||||
`\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType()`
|
`\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType()`
|
||||||
method:
|
method:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType($returnDateType);
|
\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType($returnDateType);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ if an invalid value is passed in for the return date type).
|
||||||
The `\PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType()`
|
The `\PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType()`
|
||||||
method can be used to determine the current value of this setting:
|
method can be used to determine the current value of this setting:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$returnDateType = \PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType();
|
$returnDateType = \PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ It is possible for scripts to change the calendar used for calculating
|
||||||
Excel date values by calling the
|
Excel date values by calling the
|
||||||
`\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar()` method:
|
`\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar()` method:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar($baseDate);
|
\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar($baseDate);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ if an invalid value is passed in).
|
||||||
The `\PhpOffice\PhpSpreadsheet\Shared\Date::getExcelCalendar()` method can
|
The `\PhpOffice\PhpSpreadsheet\Shared\Date::getExcelCalendar()` method can
|
||||||
be used to determine the current value of this setting:
|
be used to determine the current value of this setting:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$baseDate = \PhpOffice\PhpSpreadsheet\Shared\Date::getExcelCalendar();
|
$baseDate = \PhpOffice\PhpSpreadsheet\Shared\Date::getExcelCalendar();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ This is the statistical mean.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -421,7 +421,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -456,7 +456,7 @@ has not yet been implemented in PhpSpreadsheet.
|
||||||
|
|
||||||
#### DCOUNTA
|
#### DCOUNTA
|
||||||
|
|
||||||
The DCOUNT function returns the count of cells that aren’t blank in a
|
The DCOUNTA 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.
|
column of a list or database and that match conditions that you specify.
|
||||||
|
|
||||||
##### Syntax
|
##### Syntax
|
||||||
|
@ -492,7 +492,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -563,7 +563,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -631,7 +631,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -699,7 +699,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -767,7 +767,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -836,7 +836,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -905,7 +905,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -973,7 +973,7 @@ in which you specify a condition for the column.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$database = [
|
$database = [
|
||||||
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
[ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ],
|
||||||
[ 'Apple', 18, 20, 14, 105.00 ],
|
[ 'Apple', 18, 20, 14, 105.00 ],
|
||||||
|
@ -1074,7 +1074,7 @@ or an Excel timestamp value (real), depending on the value of
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Year')
|
$worksheet->setCellValue('A1', 'Year')
|
||||||
->setCellValue('A2', 'Month')
|
->setCellValue('A2', 'Month')
|
||||||
->setCellValue('A3', 'Day');
|
->setCellValue('A3', 'Day');
|
||||||
|
@ -1089,7 +1089,7 @@ $retVal = $worksheet->getCell('D1')->getCalculatedValue();
|
||||||
// $retVal = 1230681600
|
// $retVal = 1230681600
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// We're going to be calling the same cell calculation multiple times,
|
// We're going to be calling the same cell calculation multiple times,
|
||||||
// and expecting different return values, so disable calculation cacheing
|
// and expecting different return values, so disable calculation cacheing
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->setCalculationCacheEnabled(FALSE);
|
\PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->setCalculationCacheEnabled(FALSE);
|
||||||
|
@ -1170,7 +1170,7 @@ the third parameter.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Year')
|
$worksheet->setCellValue('A1', 'Year')
|
||||||
->setCellValue('A2', 'Month')
|
->setCellValue('A2', 'Month')
|
||||||
->setCellValue('A3', 'Day');
|
->setCellValue('A3', 'Day');
|
||||||
|
@ -1208,7 +1208,7 @@ $retVal = $worksheet->getCell('D6')->getCalculatedValue();
|
||||||
// $retVal = 30
|
// $retVal = 30
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$date1 = 1193317015; // PHP timestamp for 25-Oct-2007
|
$date1 = 1193317015; // PHP timestamp for 25-Oct-2007
|
||||||
$date2 = 1449579415; // PHP timestamp for 8-Dec-2015
|
$date2 = 1449579415; // PHP timestamp for 8-Dec-2015
|
||||||
|
|
||||||
|
@ -1279,7 +1279,7 @@ or an Excel timestamp value (real), depending on the value of
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String');
|
$worksheet->setCellValue('A1', 'Date String');
|
||||||
->setCellValue('A2', '31-Dec-2008')
|
->setCellValue('A2', '31-Dec-2008')
|
||||||
->setCellValue('A3', '31/12/2008')
|
->setCellValue('A3', '31/12/2008')
|
||||||
|
@ -1301,7 +1301,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue();
|
||||||
// $retVal = 39813.0 for all cases
|
// $retVal = 39813.0 for all cases
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// We're going to be calling the same cell calculation multiple times,
|
// We're going to be calling the same cell calculation multiple times,
|
||||||
// and expecting different return values, so disable calculation cacheing
|
// and expecting different return values, so disable calculation cacheing
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->setCalculationCacheEnabled(FALSE);
|
\PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->setCalculationCacheEnabled(FALSE);
|
||||||
|
@ -1371,7 +1371,7 @@ This is an integer ranging from 1 to 31.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String')
|
$worksheet->setCellValue('A1', 'Date String')
|
||||||
->setCellValue('A2', '31-Dec-2008')
|
->setCellValue('A2', '31-Dec-2008')
|
||||||
->setCellValue('A3', '14-Feb-2008');
|
->setCellValue('A3', '14-Feb-2008');
|
||||||
|
@ -1386,7 +1386,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue();
|
||||||
// $retVal = 14
|
// $retVal = 14
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'DAYOFMONTH'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'DAYOFMONTH'],
|
||||||
['25-Dec-2008']
|
['25-Dec-2008']
|
||||||
|
@ -1444,7 +1444,7 @@ day year.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('B1', 'Start Date')
|
$worksheet->setCellValue('B1', 'Start Date')
|
||||||
->setCellValue('C1', 'End Date')
|
->setCellValue('C1', 'End Date')
|
||||||
->setCellValue('A2', 'Year')
|
->setCellValue('A2', 'Year')
|
||||||
|
@ -1469,7 +1469,7 @@ $retVal = $worksheet->getCell('E4')->getCalculatedValue();
|
||||||
// $retVal = 1557
|
// $retVal = 1557
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$date1 = 37655.0; // Excel timestamp for 25-Oct-2007
|
$date1 = 37655.0; // Excel timestamp for 25-Oct-2007
|
||||||
$date2 = 39233.0; // Excel timestamp for 8-Dec-2015
|
$date2 = 39233.0; // Excel timestamp for 8-Dec-2015
|
||||||
|
|
||||||
|
@ -1529,7 +1529,7 @@ or an Excel timestamp value (real), depending on the value of
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String')
|
$worksheet->setCellValue('A1', 'Date String')
|
||||||
->setCellValue('A2', '1-Jan-2008')
|
->setCellValue('A2', '1-Jan-2008')
|
||||||
->setCellValue('A3', '29-Feb-2008');
|
->setCellValue('A3', '29-Feb-2008');
|
||||||
|
@ -1548,7 +1548,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue();
|
||||||
// $retVal = 39141.0 (28-Feb-2007)
|
// $retVal = 39141.0 (28-Feb-2007)
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType(
|
\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType(
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL
|
\PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL
|
||||||
);
|
);
|
||||||
|
@ -1602,7 +1602,7 @@ or an Excel timestamp value (real), depending on the value of
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String')
|
$worksheet->setCellValue('A1', 'Date String')
|
||||||
->setCellValue('A2', '1-Jan-2000')
|
->setCellValue('A2', '1-Jan-2000')
|
||||||
->setCellValue('A3', '14-Feb-2009');
|
->setCellValue('A3', '14-Feb-2009');
|
||||||
|
@ -1619,7 +1619,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue();
|
||||||
// $retVal = 39507.0 (29-Feb-2008)
|
// $retVal = 39507.0 (29-Feb-2008)
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType(
|
\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType(
|
||||||
\PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL
|
\PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL
|
||||||
);
|
);
|
||||||
|
@ -1661,7 +1661,7 @@ This is an integer ranging from 0 to 23.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Time String')
|
$worksheet->setCellValue('A1', 'Time String')
|
||||||
->setCellValue('A2', '31-Dec-2008 17:30')
|
->setCellValue('A2', '31-Dec-2008 17:30')
|
||||||
->setCellValue('A3', '14-Feb-2008 4:20 AM')
|
->setCellValue('A3', '14-Feb-2008 4:20 AM')
|
||||||
|
@ -1681,7 +1681,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue();
|
||||||
// $retVal = 16
|
// $retVal = 16
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'HOUROFDAY'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'HOUROFDAY'],
|
||||||
['09:30']
|
['09:30']
|
||||||
|
@ -1719,7 +1719,7 @@ This is an integer ranging from 0 to 59.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Time String')
|
$worksheet->setCellValue('A1', 'Time String')
|
||||||
->setCellValue('A2', '31-Dec-2008 17:30')
|
->setCellValue('A2', '31-Dec-2008 17:30')
|
||||||
->setCellValue('A3', '14-Feb-2008 4:20 AM')
|
->setCellValue('A3', '14-Feb-2008 4:20 AM')
|
||||||
|
@ -1739,7 +1739,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue();
|
||||||
// $retVal = 45
|
// $retVal = 45
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'MINUTE'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'MINUTE'],
|
||||||
['09:30']
|
['09:30']
|
||||||
|
@ -1777,7 +1777,7 @@ This is an integer ranging from 1 to 12.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String');
|
$worksheet->setCellValue('A1', 'Date String');
|
||||||
$worksheet->setCellValue('A2', '31-Dec-2008');
|
$worksheet->setCellValue('A2', '31-Dec-2008');
|
||||||
$worksheet->setCellValue('A3', '14-Feb-2008');
|
$worksheet->setCellValue('A3', '14-Feb-2008');
|
||||||
|
@ -1792,7 +1792,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue();
|
||||||
// $retVal = 2
|
// $retVal = 2
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'MONTHOFYEAR'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'MONTHOFYEAR'],
|
||||||
['14-July-2008']
|
['14-July-2008']
|
||||||
|
@ -1847,10 +1847,10 @@ The number of working days between startDate and endDate.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Notes
|
##### Notes
|
||||||
|
@ -1880,10 +1880,10 @@ or an Excel timestamp value (real), depending on the value of
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Notes
|
##### Notes
|
||||||
|
@ -1917,7 +1917,7 @@ This is an integer ranging from 0 to 59.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Time String')
|
$worksheet->setCellValue('A1', 'Time String')
|
||||||
->setCellValue('A2', '31-Dec-2008 17:30:20')
|
->setCellValue('A2', '31-Dec-2008 17:30:20')
|
||||||
->setCellValue('A3', '14-Feb-2008 4:20 AM')
|
->setCellValue('A3', '14-Feb-2008 4:20 AM')
|
||||||
|
@ -1937,7 +1937,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue();
|
||||||
// $retVal = 59
|
// $retVal = 59
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'SECOND'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'SECOND'],
|
||||||
['09:30:17']
|
['09:30:17']
|
||||||
|
@ -2002,7 +2002,7 @@ value of method.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String')
|
$worksheet->setCellValue('A1', 'Date String')
|
||||||
->setCellValue('A2', '31-Dec-2008')
|
->setCellValue('A2', '31-Dec-2008')
|
||||||
->setCellValue('A3', '14-Feb-2008');
|
->setCellValue('A3', '14-Feb-2008');
|
||||||
|
@ -2021,7 +2021,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue();
|
||||||
// $retVal = 2
|
// $retVal = 2
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'WEEKDAY'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'WEEKDAY'],
|
||||||
['14-July-2008']
|
['14-July-2008']
|
||||||
|
@ -2066,7 +2066,7 @@ This is an integer year value.
|
||||||
|
|
||||||
##### Examples
|
##### Examples
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->setCellValue('A1', 'Date String')
|
$worksheet->setCellValue('A1', 'Date String')
|
||||||
->setCellValue('A2', '17-Jul-1982')
|
->setCellValue('A2', '17-Jul-1982')
|
||||||
->setCellValue('A3', '16-Apr-2009');
|
->setCellValue('A3', '16-Apr-2009');
|
||||||
|
@ -2081,7 +2081,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue();
|
||||||
// $retVal = 2009
|
// $retVal = 2009
|
||||||
```
|
```
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$retVal = call_user_func_array(
|
$retVal = call_user_func_array(
|
||||||
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'YEAR'],
|
['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'YEAR'],
|
||||||
['14-July-2001']
|
['14-July-2001']
|
||||||
|
|
|
@ -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
|
available to read them into a Spreadsheet object are described fully in
|
||||||
the [Reading Files](./reading-files.md) document.
|
the [Reading Files](./reading-files.md) document.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
|
|
||||||
/** Load $inputFileName to a Spreadsheet object **/
|
/** 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,
|
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.
|
then you simply need to instantiate it as a new Spreadsheet object.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
/** Create a new Spreadsheet Object **/
|
/** Create a new Spreadsheet Object **/
|
||||||
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
$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
|
PhpSpreadsheet provides the `disconnectWorksheets()` method for this
|
||||||
purpose.
|
purpose.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->disconnectWorksheets();
|
$spreadsheet->disconnectWorksheets();
|
||||||
unset($spreadsheet);
|
unset($spreadsheet);
|
||||||
```
|
```
|
||||||
|
|
|
@ -0,0 +1,593 @@
|
||||||
|
# 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 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`.
|
|
@ -16,7 +16,7 @@ cache usages.
|
||||||
|
|
||||||
To enable cell caching, you must provide your own implementation of cache like so:
|
To enable cell caching, you must provide your own implementation of cache like so:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$cache = new MyCustomPsr16Implementation();
|
$cache = new MyCustomPsr16Implementation();
|
||||||
|
|
||||||
\PhpOffice\PhpSpreadsheet\Settings::setCache($cache);
|
\PhpOffice\PhpSpreadsheet\Settings::setCache($cache);
|
||||||
|
|
|
@ -12,7 +12,7 @@ need to be done.
|
||||||
automatically your codebase. Assuming your files to be migrated lives
|
automatically your codebase. Assuming your files to be migrated lives
|
||||||
in `src/`, you can run the migration like so:
|
in `src/`, you can run the migration like so:
|
||||||
|
|
||||||
``` sh
|
```sh
|
||||||
composer require rector/rector --dev
|
composer require rector/rector --dev
|
||||||
vendor/bin/rector process src --set phpexcel-to-phpspreadsheet
|
vendor/bin/rector process src --set phpexcel-to-phpspreadsheet
|
||||||
composer remove rector/rector
|
composer remove rector/rector
|
||||||
|
|
|
@ -33,7 +33,7 @@ You can create a `\PhpOffice\PhpSpreadsheet\Reader\IReader` instance using
|
||||||
`\PhpOffice\PhpSpreadsheet\IOFactory` in automatic file type resolving
|
`\PhpOffice\PhpSpreadsheet\IOFactory` in automatic file type resolving
|
||||||
mode using the following code sample:
|
mode using the following code sample:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load("05featuredemo.xlsx");
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load("05featuredemo.xlsx");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -45,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
|
data, see more about this later), then you may instead want to use this
|
||||||
variant:
|
variant:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("05featuredemo.xlsx");
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("05featuredemo.xlsx");
|
||||||
$reader->setReadDataOnly(true);
|
$reader->setReadDataOnly(true);
|
||||||
$reader->load("05featuredemo.xlsx");
|
$reader->load("05featuredemo.xlsx");
|
||||||
|
@ -55,7 +55,7 @@ You can create a `\PhpOffice\PhpSpreadsheet\Reader\IReader` instance using
|
||||||
`\PhpOffice\PhpSpreadsheet\IOFactory` in explicit mode using the following
|
`\PhpOffice\PhpSpreadsheet\IOFactory` in explicit mode using the following
|
||||||
code sample:
|
code sample:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx");
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx");
|
||||||
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
||||||
```
|
```
|
||||||
|
@ -68,7 +68,7 @@ mode.
|
||||||
You can create a `\PhpOffice\PhpSpreadsheet\Writer\IWriter` instance using
|
You can create a `\PhpOffice\PhpSpreadsheet\Writer\IWriter` instance using
|
||||||
`\PhpOffice\PhpSpreadsheet\IOFactory`:
|
`\PhpOffice\PhpSpreadsheet\IOFactory`:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
|
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
|
||||||
$writer->save("05featuredemo.xlsx");
|
$writer->save("05featuredemo.xlsx");
|
||||||
```
|
```
|
||||||
|
@ -84,7 +84,7 @@ outputting the in-memory spreadsheet to a .xlsx file.
|
||||||
|
|
||||||
You can read an .xlsx file using the following code:
|
You can read an .xlsx file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||||
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
||||||
```
|
```
|
||||||
|
@ -94,7 +94,7 @@ $spreadsheet = $reader->load("05featuredemo.xlsx");
|
||||||
You can set the option setReadDataOnly on the reader, to instruct the
|
You can set the option setReadDataOnly on the reader, to instruct the
|
||||||
reader to ignore styling, data validation, … and just read cell data:
|
reader to ignore styling, data validation, … and just read cell data:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||||
$reader->setReadDataOnly(true);
|
$reader->setReadDataOnly(true);
|
||||||
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
||||||
|
@ -105,7 +105,7 @@ $spreadsheet = $reader->load("05featuredemo.xlsx");
|
||||||
You can set the option setLoadSheetsOnly on the reader, to instruct the
|
You can set the option setLoadSheetsOnly on the reader, to instruct the
|
||||||
reader to only load the sheets with a given name:
|
reader to only load the sheets with a given name:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||||
$reader->setLoadSheetsOnly(["Sheet 1", "My special sheet"]);
|
$reader->setLoadSheetsOnly(["Sheet 1", "My special sheet"]);
|
||||||
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
$spreadsheet = $reader->load("05featuredemo.xlsx");
|
||||||
|
@ -122,7 +122,7 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`.
|
||||||
The following code will only read row 1 and rows 20 – 30 of any sheet in
|
The following code will only read row 1 and rows 20 – 30 of any sheet in
|
||||||
the Excel file:
|
the Excel file:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
||||||
|
|
||||||
public function readCell($column, $row, $worksheetName = '') {
|
public function readCell($column, $row, $worksheetName = '') {
|
||||||
|
@ -145,7 +145,7 @@ $spreadsheet = $reader->load("06largescale.xlsx");
|
||||||
|
|
||||||
You can write an .xlsx file using the following code:
|
You can write an .xlsx file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
||||||
$writer->save("05featuredemo.xlsx");
|
$writer->save("05featuredemo.xlsx");
|
||||||
```
|
```
|
||||||
|
@ -156,7 +156,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
|
This can be slow on large spreadsheets, and maybe even unwanted. You can
|
||||||
however disable formula pre-calculation:
|
however disable formula pre-calculation:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
||||||
$writer->setPreCalculateFormulas(false);
|
$writer->setPreCalculateFormulas(false);
|
||||||
$writer->save("05featuredemo.xlsx");
|
$writer->save("05featuredemo.xlsx");
|
||||||
|
@ -201,7 +201,7 @@ PHP.
|
||||||
|
|
||||||
You can read an .xls file using the following code:
|
You can read an .xls file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
||||||
$spreadsheet = $reader->load("05featuredemo.xls");
|
$spreadsheet = $reader->load("05featuredemo.xls");
|
||||||
```
|
```
|
||||||
|
@ -211,7 +211,7 @@ $spreadsheet = $reader->load("05featuredemo.xls");
|
||||||
You can set the option setReadDataOnly on the reader, to instruct the
|
You can set the option setReadDataOnly on the reader, to instruct the
|
||||||
reader to ignore styling, data validation, … and just read cell data:
|
reader to ignore styling, data validation, … and just read cell data:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
||||||
$reader->setReadDataOnly(true);
|
$reader->setReadDataOnly(true);
|
||||||
$spreadsheet = $reader->load("05featuredemo.xls");
|
$spreadsheet = $reader->load("05featuredemo.xls");
|
||||||
|
@ -222,7 +222,7 @@ $spreadsheet = $reader->load("05featuredemo.xls");
|
||||||
You can set the option setLoadSheetsOnly on the reader, to instruct the
|
You can set the option setLoadSheetsOnly on the reader, to instruct the
|
||||||
reader to only load the sheets with a given name:
|
reader to only load the sheets with a given name:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
||||||
$reader->setLoadSheetsOnly(["Sheet 1", "My special sheet"]);
|
$reader->setLoadSheetsOnly(["Sheet 1", "My special sheet"]);
|
||||||
$spreadsheet = $reader->load("05featuredemo.xls");
|
$spreadsheet = $reader->load("05featuredemo.xls");
|
||||||
|
@ -239,7 +239,7 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`.
|
||||||
The following code will only read row 1 and rows 20 to 30 of any sheet
|
The following code will only read row 1 and rows 20 to 30 of any sheet
|
||||||
in the Excel file:
|
in the Excel file:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
||||||
|
|
||||||
public function readCell($column, $row, $worksheetName = '') {
|
public function readCell($column, $row, $worksheetName = '') {
|
||||||
|
@ -262,7 +262,7 @@ $spreadsheet = $reader->load("06largescale.xls");
|
||||||
|
|
||||||
You can write an .xls file using the following code:
|
You can write an .xls file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet);
|
||||||
$writer->save("05featuredemo.xls");
|
$writer->save("05featuredemo.xls");
|
||||||
```
|
```
|
||||||
|
@ -282,7 +282,7 @@ spreadsheets via PHP.
|
||||||
|
|
||||||
You can read an Excel 2003 .xml file using the following code:
|
You can read an Excel 2003 .xml file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xml();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xml();
|
||||||
$spreadsheet = $reader->load("05featuredemo.xml");
|
$spreadsheet = $reader->load("05featuredemo.xml");
|
||||||
```
|
```
|
||||||
|
@ -298,7 +298,7 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`.
|
||||||
The following code will only read row 1 and rows 20 to 30 of any sheet
|
The following code will only read row 1 and rows 20 to 30 of any sheet
|
||||||
in the Excel file:
|
in the Excel file:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
||||||
|
|
||||||
public function readCell($column, $row, $worksheetName = '') {
|
public function readCell($column, $row, $worksheetName = '') {
|
||||||
|
@ -333,7 +333,7 @@ regarding to styling cells and handling large spreadsheets via PHP.
|
||||||
|
|
||||||
You can read an .slk file using the following code:
|
You can read an .slk file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Slk();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Slk();
|
||||||
$spreadsheet = $reader->load("05featuredemo.slk");
|
$spreadsheet = $reader->load("05featuredemo.slk");
|
||||||
```
|
```
|
||||||
|
@ -349,7 +349,7 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`.
|
||||||
The following code will only read row 1 and rows 20 to 30 of any sheet
|
The following code will only read row 1 and rows 20 to 30 of any sheet
|
||||||
in the SYLK file:
|
in the SYLK file:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
||||||
|
|
||||||
public function readCell($column, $row, $worksheetName = '') {
|
public function readCell($column, $row, $worksheetName = '') {
|
||||||
|
@ -378,7 +378,7 @@ Open Office or Libre Office Calc files.
|
||||||
|
|
||||||
You can read an .ods file using the following code:
|
You can read an .ods file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
|
||||||
$spreadsheet = $reader->load("05featuredemo.ods");
|
$spreadsheet = $reader->load("05featuredemo.ods");
|
||||||
```
|
```
|
||||||
|
@ -394,7 +394,7 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`.
|
||||||
The following code will only read row 1 and rows 20 to 30 of any sheet
|
The following code will only read row 1 and rows 20 to 30 of any sheet
|
||||||
in the Calc file:
|
in the Calc file:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
|
||||||
|
|
||||||
public function readCell($column, $row, $worksheetName = '') {
|
public function readCell($column, $row, $worksheetName = '') {
|
||||||
|
@ -427,7 +427,7 @@ regarding to styling cells, number formatting, ...
|
||||||
|
|
||||||
You can read a .csv file using the following code:
|
You can read a .csv file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
|
||||||
$spreadsheet = $reader->load("sample.csv");
|
$spreadsheet = $reader->load("sample.csv");
|
||||||
```
|
```
|
||||||
|
@ -449,7 +449,7 @@ were created in Microsoft Office Excel the correct input encoding may
|
||||||
rather be Windows-1252 (CP1252). Always make sure that the input
|
rather be Windows-1252 (CP1252). Always make sure that the input
|
||||||
encoding is set appropriately.
|
encoding is set appropriately.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
|
||||||
$reader->setInputEncoding('CP1252');
|
$reader->setInputEncoding('CP1252');
|
||||||
$reader->setDelimiter(';');
|
$reader->setDelimiter(';');
|
||||||
|
@ -464,7 +464,7 @@ $spreadsheet = $reader->load("sample.csv");
|
||||||
CSV files can only contain one worksheet. Therefore, you can specify
|
CSV files can only contain one worksheet. Therefore, you can specify
|
||||||
which sheet to read from CSV:
|
which sheet to read from CSV:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader->setSheetIndex(0);
|
$reader->setSheetIndex(0);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -475,10 +475,10 @@ data into an existing `Spreadsheet` object. The following code loads a
|
||||||
CSV file into an existing `$spreadsheet` containing some sheets, and
|
CSV file into an existing `$spreadsheet` containing some sheets, and
|
||||||
imports onto the 6th sheet:
|
imports onto the 6th sheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
|
||||||
$reader->setDelimiter(';');
|
$reader->setDelimiter(';');
|
||||||
$reader->setEnclosure('');
|
$reader->setEnclosure('"');
|
||||||
$reader->setSheetIndex(5);
|
$reader->setSheetIndex(5);
|
||||||
|
|
||||||
$reader->loadIntoExisting("05featuredemo.csv", $spreadsheet);
|
$reader->loadIntoExisting("05featuredemo.csv", $spreadsheet);
|
||||||
|
@ -490,7 +490,7 @@ $reader->loadIntoExisting("05featuredemo.csv", $spreadsheet);
|
||||||
|
|
||||||
You can write a .csv file using the following code:
|
You can write a .csv file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
||||||
$writer->save("05featuredemo.csv");
|
$writer->save("05featuredemo.csv");
|
||||||
```
|
```
|
||||||
|
@ -502,22 +502,35 @@ as a separator. You can instruct
|
||||||
`\PhpOffice\PhpSpreadsheet\Writer\Csv` some options before writing a CSV
|
`\PhpOffice\PhpSpreadsheet\Writer\Csv` some options before writing a CSV
|
||||||
file:
|
file:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
||||||
$writer->setDelimiter(';');
|
$writer->setDelimiter(';');
|
||||||
$writer->setEnclosure('');
|
$writer->setEnclosure('"');
|
||||||
$writer->setLineEnding("\r\n");
|
$writer->setLineEnding("\r\n");
|
||||||
$writer->setSheetIndex(0);
|
$writer->setSheetIndex(0);
|
||||||
|
|
||||||
$writer->save("05featuredemo.csv");
|
$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
|
#### Write a specific worksheet
|
||||||
|
|
||||||
CSV files can only contain one worksheet. Therefore, you can specify
|
CSV files can only contain one worksheet. Therefore, you can specify
|
||||||
which sheet to write to CSV:
|
which sheet to write to CSV:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer->setSheetIndex(0);
|
$writer->setSheetIndex(0);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -527,7 +540,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
|
This can be slow on large spreadsheets, and maybe even unwanted. You can
|
||||||
however disable formula pre-calculation:
|
however disable formula pre-calculation:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
||||||
$writer->setPreCalculateFormulas(false);
|
$writer->setPreCalculateFormulas(false);
|
||||||
$writer->save("05featuredemo.csv");
|
$writer->save("05featuredemo.csv");
|
||||||
|
@ -538,11 +551,12 @@ $writer->save("05featuredemo.csv");
|
||||||
CSV files are written in UTF-8. If they do not contain characters
|
CSV files are written in UTF-8. If they do not contain characters
|
||||||
outside the ASCII range, nothing else need be done.
|
outside the ASCII range, nothing else need be done.
|
||||||
However, if such characters are in the file,
|
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;
|
it should explicitly include a BOM file header;
|
||||||
if it doesn't, Excel will not interpret those characters correctly.
|
if it doesn't, Excel will not interpret those characters correctly.
|
||||||
This can be enabled by using the following code:
|
This can be enabled by using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
|
||||||
$writer->setUseBOM(true);
|
$writer->setUseBOM(true);
|
||||||
$writer->save("05featuredemo.csv");
|
$writer->save("05featuredemo.csv");
|
||||||
|
@ -560,14 +574,14 @@ to set the characters explicitly as shown below.
|
||||||
|
|
||||||
English users will want to use this before doing the export:
|
English users will want to use this before doing the export:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setDecimalSeparator('.');
|
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setDecimalSeparator('.');
|
||||||
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setThousandsSeparator(',');
|
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setThousandsSeparator(',');
|
||||||
```
|
```
|
||||||
|
|
||||||
German users will want to use the opposite values.
|
German users will want to use the opposite values.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setDecimalSeparator(',');
|
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setDecimalSeparator(',');
|
||||||
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setThousandsSeparator('.');
|
\PhpOffice\PhpSpreadsheet\Shared\StringHelper::setThousandsSeparator('.');
|
||||||
```
|
```
|
||||||
|
@ -592,7 +606,7 @@ regarding to styling cells, number formatting, ...
|
||||||
|
|
||||||
You can read an .html or .htm file using the following code:
|
You can read an .html or .htm file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Html();
|
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Html();
|
||||||
|
|
||||||
$spreadsheet = $reader->load("05featuredemo.html");
|
$spreadsheet = $reader->load("05featuredemo.html");
|
||||||
|
@ -610,7 +624,7 @@ first worksheet by default.
|
||||||
|
|
||||||
You can write a .htm file using the following code:
|
You can write a .htm file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
||||||
|
|
||||||
$writer->save("05featuredemo.htm");
|
$writer->save("05featuredemo.htm");
|
||||||
|
@ -621,7 +635,7 @@ $writer->save("05featuredemo.htm");
|
||||||
HTML files can contain one or more worksheets. If you want to write all
|
HTML files can contain one or more worksheets. If you want to write all
|
||||||
sheets into a single HTML file, use the following code:
|
sheets into a single HTML file, use the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer->writeAllSheets();
|
$writer->writeAllSheets();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -630,7 +644,7 @@ $writer->writeAllSheets();
|
||||||
HTML files can contain one or more worksheets. Therefore, you can
|
HTML files can contain one or more worksheets. Therefore, you can
|
||||||
specify which sheet to write to HTML:
|
specify which sheet to write to HTML:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer->setSheetIndex(0);
|
$writer->setSheetIndex(0);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -639,19 +653,19 @@ $writer->setSheetIndex(0);
|
||||||
There might be situations where you want to explicitly set the included
|
There might be situations where you want to explicitly set the included
|
||||||
images root. For example, instead of:
|
images root. For example, instead of:
|
||||||
|
|
||||||
``` html
|
```html
|
||||||
<img src="./images/logo.jpg">
|
<img src="./images/logo.jpg">
|
||||||
```
|
```
|
||||||
|
|
||||||
You might want to see:
|
You might want to see:
|
||||||
|
|
||||||
``` html
|
```html
|
||||||
<img src="http://www.domain.com/images/logo.jpg">
|
<img src="http://www.domain.com/images/logo.jpg">
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use the following code to achieve this result:
|
You can use the following code to achieve this result:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer->setImagesRoot('http://www.example.com');
|
$writer->setImagesRoot('http://www.example.com');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -661,7 +675,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
|
This can be slow on large spreadsheets, and maybe even unwanted. You can
|
||||||
however disable formula pre-calculation:
|
however disable formula pre-calculation:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
||||||
$writer->setPreCalculateFormulas(false);
|
$writer->setPreCalculateFormulas(false);
|
||||||
|
|
||||||
|
@ -686,14 +700,14 @@ Supported methods:
|
||||||
Here's an example which retrieves all parts independently and merges
|
Here's an example which retrieves all parts independently and merges
|
||||||
them into a resulting HTML page:
|
them into a resulting HTML page:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
||||||
$hdr = $writer->generateHTMLHeader();
|
$hdr = $writer->generateHTMLHeader();
|
||||||
$sty = $writer->generateStyles(false); // do not write <style> and </style>
|
$sty = $writer->generateStyles(false); // do not write <style> and </style>
|
||||||
$newstyle = <<<EOF
|
$newstyle = <<<EOF
|
||||||
<style type='text/css'>
|
<style type='text/css'>
|
||||||
$sty
|
$sty
|
||||||
html {
|
body {
|
||||||
background-color: yellow;
|
background-color: yellow;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -703,16 +717,22 @@ echo $writer->generateSheetData();
|
||||||
echo $writer->generateHTMLFooter();
|
echo $writer->generateHTMLFooter();
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Writing UTF-8 HTML files
|
#### Editing HTML during save via a callback
|
||||||
|
|
||||||
A HTML file can be marked as UTF-8 by writing a BOM file header. This
|
You can also add a callback function to edit the generated html
|
||||||
can be enabled by using the following code:
|
before saving. For example, you could change the gridlines
|
||||||
|
from a thin solid black line:
|
||||||
|
|
||||||
``` php
|
``` 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 = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
|
||||||
$writer->setUseBOM(true);
|
$writer->setEditHtmlCallback('changeGridlines');
|
||||||
|
$writer->save($filename);
|
||||||
$writer->save("05featuredemo.htm");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Decimal and thousands separators
|
#### Decimal and thousands separators
|
||||||
|
@ -751,7 +771,7 @@ own circumstances.
|
||||||
|
|
||||||
You can instantiate a writer with its specific name, like so:
|
You can instantiate a writer with its specific name, like so:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Mpdf');
|
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Mpdf');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -759,7 +779,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
|
so you don't need to remember which library you chose, only that you want
|
||||||
to write PDF files:
|
to write PDF files:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$class = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class;
|
$class = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class;
|
||||||
\PhpOffice\PhpSpreadsheet\IOFactory::registerWriter('Pdf', $class);
|
\PhpOffice\PhpSpreadsheet\IOFactory::registerWriter('Pdf', $class);
|
||||||
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf');
|
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf');
|
||||||
|
@ -767,7 +787,7 @@ $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf')
|
||||||
|
|
||||||
Or you can instantiate directly the writer of your choice like so:
|
Or you can instantiate directly the writer of your choice like so:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
$writer = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -776,7 +796,7 @@ $writer = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
||||||
If you need a custom implementation, or custom configuration, of a supported
|
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:
|
PDF library. You can extends the PDF library, and the PDF writer like so:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
class My_Custom_TCPDF extends TCPDF
|
class My_Custom_TCPDF extends TCPDF
|
||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
|
@ -802,7 +822,7 @@ class My_Custom_TCPDF_Writer extends \PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf
|
||||||
Once you have identified the Renderer that you wish to use for PDF
|
Once you have identified the Renderer that you wish to use for PDF
|
||||||
generation, you can write a .pdf file using the following code:
|
generation, you can write a .pdf file using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
||||||
$writer->save("05featuredemo.pdf");
|
$writer->save("05featuredemo.pdf");
|
||||||
```
|
```
|
||||||
|
@ -815,7 +835,7 @@ first worksheet by default.
|
||||||
PDF files can contain one or more worksheets. If you want to write all
|
PDF files can contain one or more worksheets. If you want to write all
|
||||||
sheets into a single PDF file, use the following code:
|
sheets into a single PDF file, use the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer->writeAllSheets();
|
$writer->writeAllSheets();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -824,7 +844,7 @@ $writer->writeAllSheets();
|
||||||
PDF files can contain one or more worksheets. Therefore, you can specify
|
PDF files can contain one or more worksheets. Therefore, you can specify
|
||||||
which sheet to write to PDF:
|
which sheet to write to PDF:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer->setSheetIndex(0);
|
$writer->setSheetIndex(0);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -834,13 +854,19 @@ By default, this writer pre-calculates all formulas in the spreadsheet.
|
||||||
This can be slow on large spreadsheets, and maybe even unwanted. You can
|
This can be slow on large spreadsheets, and maybe even unwanted. You can
|
||||||
however disable formula pre-calculation:
|
however disable formula pre-calculation:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
|
||||||
$writer->setPreCalculateFormulas(false);
|
$writer->setPreCalculateFormulas(false);
|
||||||
|
|
||||||
$writer->save("05featuredemo.pdf");
|
$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
|
#### Decimal and thousands separators
|
||||||
|
|
||||||
See section `\PhpOffice\PhpSpreadsheet\Writer\Csv` how to control the
|
See section `\PhpOffice\PhpSpreadsheet\Writer\Csv` how to control the
|
||||||
|
@ -856,7 +882,7 @@ page setup properties, headers etc.
|
||||||
Here is an example how to open a template file, fill in a couple of
|
Here is an example how to open a template file, fill in a couple of
|
||||||
fields and save it again:
|
fields and save it again:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('template.xlsx');
|
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('template.xlsx');
|
||||||
|
|
||||||
$worksheet = $spreadsheet->getActiveSheet();
|
$worksheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
|
@ -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()`
|
Factory identify the file type and load it, calling the static `load()`
|
||||||
method of the `\PhpOffice\PhpSpreadsheet\IOFactory` class.
|
method of the `\PhpOffice\PhpSpreadsheet\IOFactory` class.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
|
|
||||||
/** Load $inputFileName to a Spreadsheet Object **/
|
/** Load $inputFileName to a Spreadsheet Object **/
|
||||||
|
@ -59,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
|
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.
|
of .xls), although this type of exception should normally be trapped.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
|
|
||||||
/** Create a new Xls Reader **/
|
/** Create a new Xls Reader **/
|
||||||
|
@ -81,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
|
instantiate the reader object for you, simply telling it the file type
|
||||||
of the reader that you want instantiating.
|
of the reader that you want instantiating.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
// $inputFileType = 'Xlsx';
|
// $inputFileType = 'Xlsx';
|
||||||
// $inputFileType = 'Xml';
|
// $inputFileType = 'Xml';
|
||||||
|
@ -104,7 +104,7 @@ If you're uncertain of the filetype, you can use the `IOFactory::identify()`
|
||||||
method to identify the reader that you need, before using the
|
method to identify the reader that you need, before using the
|
||||||
`createReader()` method to instantiate the reader object.
|
`createReader()` method to instantiate the reader object.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
|
|
||||||
/** Identify the type of $inputFileName **/
|
/** Identify the type of $inputFileName **/
|
||||||
|
@ -131,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
|
to read only the data values and any formulae from each cell using the
|
||||||
`setReadDataOnly()` method.
|
`setReadDataOnly()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ in reading.
|
||||||
To read a single sheet, you can pass that sheet name as a parameter to
|
To read a single sheet, you can pass that sheet name as a parameter to
|
||||||
the `setLoadSheetsOnly()` method.
|
the `setLoadSheetsOnly()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
$sheetname = 'Data Sheet #2';
|
$sheetname = 'Data Sheet #2';
|
||||||
|
@ -195,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
|
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.
|
of sheet names as an array parameter to the `setLoadSheetsOnly()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
$sheetnames = ['Data Sheet #1','Data Sheet #3'];
|
$sheetnames = ['Data Sheet #1','Data Sheet #3'];
|
||||||
|
@ -214,7 +214,7 @@ for a working example of this code.
|
||||||
To reset this option to the default, you can call the `setLoadAllSheets()`
|
To reset this option to the default, you can call the `setLoadAllSheets()`
|
||||||
method.
|
method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
|
|
||||||
|
@ -248,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
|
whether a workbook cell identified by those arguments should be read or
|
||||||
not.
|
not.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
$inputFileName = './sampleData/example1.xls';
|
$inputFileName = './sampleData/example1.xls';
|
||||||
$sheetname = 'Data Sheet #3';
|
$sheetname = 'Data Sheet #3';
|
||||||
|
@ -286,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
|
A1:E7 from your worksheet. A generic Read Filter would probably be more
|
||||||
useful:
|
useful:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
/** Define a Read Filter class implementing \PhpOffice\PhpSpreadsheet\Reader\IReadFilter */
|
/** Define a Read Filter class implementing \PhpOffice\PhpSpreadsheet\Reader\IReadFilter */
|
||||||
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter
|
class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter
|
||||||
{
|
{
|
||||||
|
@ -324,7 +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
|
usage might be when transferring data from an Excel worksheet to a
|
||||||
database.
|
database.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Xls';
|
$inputFileType = 'Xls';
|
||||||
$inputFileName = './sampleData/example2.xls';
|
$inputFileName = './sampleData/example2.xls';
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ the `setSheetIndex()` method of the `$reader`, then use the
|
||||||
`loadIntoExisting()` method rather than the `load()` method to actually read
|
`loadIntoExisting()` method rather than the `load()` method to actually read
|
||||||
the file into that worksheet.
|
the file into that worksheet.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Csv';
|
$inputFileType = 'Csv';
|
||||||
$inputFileNames = [
|
$inputFileNames = [
|
||||||
'./sampleData/example1.csv',
|
'./sampleData/example1.csv',
|
||||||
|
@ -452,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
|
and the `setSheetIndex()` method of the `$reader`, we can split the CSV
|
||||||
file across several individual worksheets.
|
file across several individual worksheets.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Csv';
|
$inputFileType = 'Csv';
|
||||||
$inputFileName = './sampleData/example2.csv';
|
$inputFileName = './sampleData/example2.csv';
|
||||||
|
|
||||||
|
@ -523,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()`
|
use-case, you can manually specify a separator by using the `setDelimiter()`
|
||||||
method.
|
method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileType = 'Csv';
|
$inputFileType = 'Csv';
|
||||||
$inputFileName = './sampleData/example1.tsv';
|
$inputFileName = './sampleData/example1.tsv';
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ it encountered a hyperlink, or HTML markup within a CSV file.
|
||||||
So using a Value Binder allows a great deal more flexibility in the
|
So using a Value Binder allows a great deal more flexibility in the
|
||||||
loader logic when reading unformatted text files.
|
loader logic when reading unformatted text files.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
/** Tell PhpSpreadsheet that we want to use the Advanced Value Binder **/
|
/** Tell PhpSpreadsheet that we want to use the Advanced Value Binder **/
|
||||||
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
|
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
|
||||||
|
|
||||||
|
@ -619,7 +619,7 @@ manner.
|
||||||
The PhpSpreadsheet Readers throw a
|
The PhpSpreadsheet Readers throw a
|
||||||
`\PhpOffice\PhpSpreadsheet\Reader\Exception`.
|
`\PhpOffice\PhpSpreadsheet\Reader\Exception`.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$inputFileName = './sampleData/example-1.xls';
|
$inputFileName = './sampleData/example-1.xls';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -646,7 +646,7 @@ whole file.
|
||||||
The `listWorksheetNames()` method returns a simple array listing each
|
The `listWorksheetNames()` method returns a simple array listing each
|
||||||
worksheet name within the workbook:
|
worksheet name within the workbook:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
|
||||||
|
|
||||||
$worksheetNames = $reader->listWorksheetNames($inputFileName);
|
$worksheetNames = $reader->listWorksheetNames($inputFileName);
|
||||||
|
@ -667,7 +667,7 @@ for a working example of this code.
|
||||||
The `listWorksheetInfo()` method returns a nested array, with each entry
|
The `listWorksheetInfo()` method returns a nested array, with each entry
|
||||||
listing the name and dimensions for a worksheet:
|
listing the name and dimensions for a worksheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
|
||||||
|
|
||||||
$worksheetData = $reader->listWorksheetInfo($inputFileName);
|
$worksheetData = $reader->listWorksheetInfo($inputFileName);
|
||||||
|
|
|
@ -20,7 +20,7 @@ metadata to search for a specific document in its document lists.
|
||||||
|
|
||||||
Setting spreadsheet metadata is done as follows:
|
Setting spreadsheet metadata is done as follows:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getProperties()
|
$spreadsheet->getProperties()
|
||||||
->setCreator("Maarten Balliauw")
|
->setCreator("Maarten Balliauw")
|
||||||
->setLastModifiedBy("Maarten Balliauw")
|
->setLastModifiedBy("Maarten Balliauw")
|
||||||
|
@ -38,13 +38,13 @@ $spreadsheet->getProperties()
|
||||||
The following line of code sets the active sheet index to the first
|
The following line of code sets the active sheet index to the first
|
||||||
sheet:
|
sheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->setActiveSheetIndex(0);
|
$spreadsheet->setActiveSheetIndex(0);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also set the active sheet by its name/title
|
You can also set the active sheet by its name/title
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->setActiveSheetIndexByName('DataSheet')
|
$spreadsheet->setActiveSheetIndexByName('DataSheet')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ UST.
|
||||||
Writing a date value in a cell consists of 2 lines of code. Select the
|
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:
|
method that suits you the best. Here are some examples:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
|
|
||||||
// MySQL-like timestamp '2008-12-31' or date string
|
// MySQL-like timestamp '2008-12-31' or date string
|
||||||
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
|
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
|
||||||
|
@ -136,14 +136,14 @@ The following line of code writes the formula
|
||||||
formula must start with `=` to make PhpSpreadsheet recognise this as a
|
formula must start with `=` to make PhpSpreadsheet recognise this as a
|
||||||
formula.
|
formula.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('B8','=IF(C4>500,"profit","loss")');
|
$spreadsheet->getActiveSheet()->setCellValue('B8','=IF(C4>500,"profit","loss")');
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to write a string beginning with an `=` character to a
|
If you want to write a string beginning with an `=` character to a
|
||||||
cell, then you should use the `setCellValueExplicit()` method.
|
cell, then you should use the `setCellValueExplicit()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->setCellValueExplicit(
|
->setCellValueExplicit(
|
||||||
'B8',
|
'B8',
|
||||||
|
@ -154,14 +154,14 @@ $spreadsheet->getActiveSheet()
|
||||||
|
|
||||||
A cell's formula can be read again using the following line of code:
|
A cell's formula can be read again using the following line of code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$formula = $spreadsheet->getActiveSheet()->getCell('B8')->getValue();
|
$formula = $spreadsheet->getActiveSheet()->getCell('B8')->getValue();
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need the calculated value of a cell, use the following code. This
|
If you need the calculated value of a cell, use the following code. This
|
||||||
is further explained in [the calculation engine](./calculation-engine.md).
|
is further explained in [the calculation engine](./calculation-engine.md).
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$value = $spreadsheet->getActiveSheet()->getCell('B8')->getCalculatedValue();
|
$value = $spreadsheet->getActiveSheet()->getCell('B8')->getCalculatedValue();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ Some localisation elements have been included in PhpSpreadsheet. You can
|
||||||
set a locale by changing the settings. To set the locale to Russian you
|
set a locale by changing the settings. To set the locale to Russian you
|
||||||
would use:
|
would use:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$locale = 'ru';
|
$locale = 'ru';
|
||||||
$validLocale = \PhpOffice\PhpSpreadsheet\Settings::setLocale($locale);
|
$validLocale = \PhpOffice\PhpSpreadsheet\Settings::setLocale($locale);
|
||||||
if (!$validLocale) {
|
if (!$validLocale) {
|
||||||
|
@ -185,7 +185,7 @@ will return an error, and English settings will be used throughout.
|
||||||
Once you have set a locale, you can translate a formula from its
|
Once you have set a locale, you can translate a formula from its
|
||||||
internal English coding.
|
internal English coding.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$formula = $spreadsheet->getActiveSheet()->getCell('B8')->getValue();
|
$formula = $spreadsheet->getActiveSheet()->getCell('B8')->getValue();
|
||||||
$translatedFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->_translateFormulaToLocale($formula);
|
$translatedFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->_translateFormulaToLocale($formula);
|
||||||
```
|
```
|
||||||
|
@ -194,7 +194,7 @@ You can also create a formula using the function names and argument
|
||||||
separators appropriate to the defined locale; then translate it to
|
separators appropriate to the defined locale; then translate it to
|
||||||
English before setting the cell value:
|
English before setting the cell value:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$formula = '=ДНЕЙ360(ДАТА(2010;2;5);ДАТА(2010;12;31);ИСТИНА)';
|
$formula = '=ДНЕЙ360(ДАТА(2010;2;5);ДАТА(2010;12;31);ИСТИНА)';
|
||||||
$internalFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->translateFormulaToEnglish($formula);
|
$internalFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->translateFormulaToEnglish($formula);
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('B8',$internalFormula);
|
$spreadsheet->getActiveSheet()->setCellValue('B8',$internalFormula);
|
||||||
|
@ -232,7 +232,7 @@ the cell.
|
||||||
|
|
||||||
Here is how to achieve this in PhpSpreadsheet:
|
Here is how to achieve this in PhpSpreadsheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld");
|
$spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld");
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1')->getAlignment()->setWrapText(true);
|
$spreadsheet->getActiveSheet()->getStyle('A1')->getAlignment()->setWrapText(true);
|
||||||
```
|
```
|
||||||
|
@ -247,7 +247,7 @@ 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
|
when it sees a newline character in a string that you are inserting in a
|
||||||
cell. Just like Microsoft Office Excel. Try this:
|
cell. Just like Microsoft Office Excel. Try this:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
|
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
|
||||||
|
|
||||||
$spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld");
|
$spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld");
|
||||||
|
@ -261,7 +261,7 @@ You can set a cell's datatype explicitly by using the cell's
|
||||||
setValueExplicit method, or the setCellValueExplicit method of a
|
setValueExplicit method, or the setCellValueExplicit method of a
|
||||||
worksheet. Here's an example:
|
worksheet. Here's an example:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getCell('A1')
|
$spreadsheet->getActiveSheet()->getCell('A1')
|
||||||
->setValueExplicit(
|
->setValueExplicit(
|
||||||
'25',
|
'25',
|
||||||
|
@ -273,7 +273,7 @@ $spreadsheet->getActiveSheet()->getCell('A1')
|
||||||
|
|
||||||
You can make a cell a clickable URL by setting its hyperlink property:
|
You can make a cell a clickable URL by setting its hyperlink property:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.phpexcel.net');
|
$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.phpexcel.net');
|
||||||
$spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl('https://www.example.com');
|
$spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl('https://www.example.com');
|
||||||
```
|
```
|
||||||
|
@ -281,7 +281,7 @@ $spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl('https://
|
||||||
If you want to make a hyperlink to another worksheet/cell, use the
|
If you want to make a hyperlink to another worksheet/cell, use the
|
||||||
following code:
|
following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.phpexcel.net');
|
$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.phpexcel.net');
|
||||||
$spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl("sheet://'Sheetname'!A1");
|
$spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl("sheet://'Sheetname'!A1");
|
||||||
```
|
```
|
||||||
|
@ -293,7 +293,7 @@ $spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl("sheet://
|
||||||
Setting a worksheet's page orientation and size can be done using the
|
Setting a worksheet's page orientation and size can be done using the
|
||||||
following lines of code:
|
following lines of code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()
|
$spreadsheet->getActiveSheet()->getPageSetup()
|
||||||
->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
|
->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()
|
$spreadsheet->getActiveSheet()->getPageSetup()
|
||||||
|
@ -324,7 +324,7 @@ setFitToHeight(...) | 1 | setFitToPage(TRUE) | value 0 mean
|
||||||
|
|
||||||
Here is how to fit to 1 page wide by infinite pages tall:
|
Here is how to fit to 1 page wide by infinite pages tall:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setFitToWidth(1);
|
$spreadsheet->getActiveSheet()->getPageSetup()->setFitToWidth(1);
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setFitToHeight(0);
|
$spreadsheet->getActiveSheet()->getPageSetup()->setFitToHeight(0);
|
||||||
```
|
```
|
||||||
|
@ -340,7 +340,7 @@ the initial values.
|
||||||
|
|
||||||
To set page margins for a worksheet, use this code:
|
To set page margins for a worksheet, use this code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageMargins()->setTop(1);
|
$spreadsheet->getActiveSheet()->getPageMargins()->setTop(1);
|
||||||
$spreadsheet->getActiveSheet()->getPageMargins()->setRight(0.75);
|
$spreadsheet->getActiveSheet()->getPageMargins()->setRight(0.75);
|
||||||
$spreadsheet->getActiveSheet()->getPageMargins()->setLeft(0.75);
|
$spreadsheet->getActiveSheet()->getPageMargins()->setLeft(0.75);
|
||||||
|
@ -356,7 +356,7 @@ Note that the margin values are specified in inches.
|
||||||
To center a page horizontally/vertically, you can use the following
|
To center a page horizontally/vertically, you can use the following
|
||||||
code:
|
code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setHorizontalCentered(true);
|
$spreadsheet->getActiveSheet()->getPageSetup()->setHorizontalCentered(true);
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setVerticalCentered(false);
|
$spreadsheet->getActiveSheet()->getPageSetup()->setVerticalCentered(false);
|
||||||
```
|
```
|
||||||
|
@ -366,7 +366,7 @@ $spreadsheet->getActiveSheet()->getPageSetup()->setVerticalCentered(false);
|
||||||
Setting a worksheet's print header and footer can be done using the
|
Setting a worksheet's print header and footer can be done using the
|
||||||
following lines of code:
|
following lines of code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getHeaderFooter()
|
$spreadsheet->getActiveSheet()->getHeaderFooter()
|
||||||
->setOddHeader('&C&HPlease treat this document as confidential!');
|
->setOddHeader('&C&HPlease treat this document as confidential!');
|
||||||
$spreadsheet->getActiveSheet()->getHeaderFooter()
|
$spreadsheet->getActiveSheet()->getHeaderFooter()
|
||||||
|
@ -460,13 +460,13 @@ $spreadsheet->getActiveSheet()->getHeaderFooter()->addImage($drawing, \PhpOffice
|
||||||
To set a print break, use the following code, which sets a row break on
|
To set a print break, use the following code, which sets a row break on
|
||||||
row 10.
|
row 10.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setBreak('A10', \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_ROW);
|
$spreadsheet->getActiveSheet()->setBreak('A10', \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_ROW);
|
||||||
```
|
```
|
||||||
|
|
||||||
The following line of code sets a print break on column D:
|
The following line of code sets a print break on column D:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setBreak('D10', \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_COLUMN);
|
$spreadsheet->getActiveSheet()->setBreak('D10', \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_COLUMN);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -484,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
|
following code is an example of how to repeat row 1 to 5 on each printed
|
||||||
page of a specific worksheet:
|
page of a specific worksheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEnd(1, 5);
|
$spreadsheet->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEnd(1, 5);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -492,13 +492,13 @@ $spreadsheet->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEn
|
||||||
|
|
||||||
To specify a worksheet's printing area, use the following code:
|
To specify a worksheet's printing area, use the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setPrintArea('A1:E5');
|
$spreadsheet->getActiveSheet()->getPageSetup()->setPrintArea('A1:E5');
|
||||||
```
|
```
|
||||||
|
|
||||||
There can also be multiple printing areas in a single worksheet:
|
There can also be multiple printing areas in a single worksheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getPageSetup()->setPrintArea('A1:E5,G4:M20');
|
$spreadsheet->getActiveSheet()->getPageSetup()->setPrintArea('A1:E5,G4:M20');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -511,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
|
to the right, and the border to black and thick border style. Let's do
|
||||||
that on cell B2:
|
that on cell B2:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('B2')
|
$spreadsheet->getActiveSheet()->getStyle('B2')
|
||||||
->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
|
->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
|
||||||
$spreadsheet->getActiveSheet()->getStyle('B2')
|
$spreadsheet->getActiveSheet()->getStyle('B2')
|
||||||
|
@ -533,7 +533,7 @@ $spreadsheet->getActiveSheet()->getStyle('B2')
|
||||||
`getStyle()` also accepts a cell range as a parameter. For example, you
|
`getStyle()` also accepts a cell range as a parameter. For example, you
|
||||||
can set a red background color on a range of cells:
|
can set a red background color on a range of cells:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('B3:B7')->getFill()
|
$spreadsheet->getActiveSheet()->getStyle('B3:B7')->getFill()
|
||||||
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
||||||
->getStartColor()->setARGB('FFFF0000');
|
->getStartColor()->setARGB('FFFF0000');
|
||||||
|
@ -548,7 +548,7 @@ 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
|
sets a cell's style to font bold, alignment right, top border thin and a
|
||||||
gradient fill:
|
gradient fill:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$styleArray = [
|
$styleArray = [
|
||||||
'font' => [
|
'font' => [
|
||||||
'bold' => true,
|
'bold' => true,
|
||||||
|
@ -578,7 +578,7 @@ $spreadsheet->getActiveSheet()->getStyle('A3')->applyFromArray($styleArray);
|
||||||
|
|
||||||
Or with a range of cells:
|
Or with a range of cells:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('B3:B7')->applyFromArray($styleArray);
|
$spreadsheet->getActiveSheet()->getStyle('B3:B7')->applyFromArray($styleArray);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -587,6 +587,13 @@ execution whenever you are setting more than one style property. But the
|
||||||
difference may barely be measurable unless you have many different
|
difference may barely be measurable unless you have many different
|
||||||
styles in your workbook.
|
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
|
### Number formats
|
||||||
|
|
||||||
You often want to format numbers in Excel. For example you may want a
|
You often want to format numbers in Excel. For example you may want a
|
||||||
|
@ -602,7 +609,7 @@ number format code unless you need a custom number format.
|
||||||
In PhpSpreadsheet, you can also apply various predefined number formats.
|
In PhpSpreadsheet, you can also apply various predefined number formats.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
||||||
->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1);
|
->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1);
|
||||||
```
|
```
|
||||||
|
@ -614,7 +621,7 @@ up as 1.587,20)
|
||||||
|
|
||||||
You can achieve exactly the same as the above by using this:
|
You can achieve exactly the same as the above by using this:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
||||||
->setFormatCode('#,##0.00');
|
->setFormatCode('#,##0.00');
|
||||||
```
|
```
|
||||||
|
@ -623,7 +630,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
|
to interact with raw number format codes whenever you need some special
|
||||||
custom number format. Example:
|
custom number format. Example:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
||||||
->setFormatCode('[Blue][>=3000]$#,##0;[Red][<0]$#,##0;$#,##0');
|
->setFormatCode('[Blue][>=3000]$#,##0;[Red][<0]$#,##0;$#,##0');
|
||||||
```
|
```
|
||||||
|
@ -631,7 +638,7 @@ $spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
||||||
Another example is when you want numbers zero-padded with leading zeros
|
Another example is when you want numbers zero-padded with leading zeros
|
||||||
to a fixed length:
|
to a fixed length:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getCell('A1')->setValue(19);
|
$spreadsheet->getActiveSheet()->getCell('A1')->setValue(19);
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
$spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()
|
||||||
->setFormatCode('0000'); // will show as 0019 in Excel
|
->setFormatCode('0000'); // will show as 0019 in Excel
|
||||||
|
@ -646,7 +653,7 @@ The readers shipped with PhpSpreadsheet come to the rescue. Load your
|
||||||
template workbook using e.g. Xlsx reader to reveal the number format
|
template workbook using e.g. Xlsx reader to reveal the number format
|
||||||
code. Example how read a number format code for cell A1:
|
code. Example how read a number format code for cell A1:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
||||||
$spreadsheet = $reader->load('template.xlsx');
|
$spreadsheet = $reader->load('template.xlsx');
|
||||||
var_dump($spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()->getFormatCode());
|
var_dump($spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()->getFormatCode());
|
||||||
|
@ -661,14 +668,14 @@ code in *xl/styles.xml*.
|
||||||
|
|
||||||
Let's set vertical alignment to the top for cells A1:D4
|
Let's set vertical alignment to the top for cells A1:D4
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1:D4')
|
$spreadsheet->getActiveSheet()->getStyle('A1:D4')
|
||||||
->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP);
|
->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP);
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is how to achieve wrap text:
|
Here is how to achieve wrap text:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('A1:D4')
|
$spreadsheet->getActiveSheet()->getStyle('A1:D4')
|
||||||
->getAlignment()->setWrapText(true);
|
->getAlignment()->setWrapText(true);
|
||||||
```
|
```
|
||||||
|
@ -678,7 +685,7 @@ $spreadsheet->getActiveSheet()->getStyle('A1:D4')
|
||||||
It is possible to set the default style of a workbook. Let's set the
|
It is possible to set the default style of a workbook. Let's set the
|
||||||
default font to Arial size 8:
|
default font to Arial size 8:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getDefaultStyle()->getFont()->setName('Arial');
|
$spreadsheet->getDefaultStyle()->getFont()->setName('Arial');
|
||||||
$spreadsheet->getDefaultStyle()->getFont()->setSize(8);
|
$spreadsheet->getDefaultStyle()->getFont()->setSize(8);
|
||||||
```
|
```
|
||||||
|
@ -689,7 +696,7 @@ 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
|
selection. Here is how to apply a thick red border outline around cells
|
||||||
B2:G8.
|
B2:G8.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$styleArray = [
|
$styleArray = [
|
||||||
'borders' => [
|
'borders' => [
|
||||||
'outline' => [
|
'outline' => [
|
||||||
|
@ -753,69 +760,74 @@ another style array.
|
||||||
|
|
||||||
Array key | Maps to property
|
Array key | Maps to property
|
||||||
-------------|-------------------
|
-------------|-------------------
|
||||||
fill | getFill()
|
alignment | setAlignment()
|
||||||
font | getFont()
|
borders | setBorders()
|
||||||
borders | getBorders()
|
fill | setFill()
|
||||||
alignment | getAlignment()
|
font | setFont()
|
||||||
numberFormat | getNumberFormat()
|
numberFormat | setNumberFormat()
|
||||||
protection | getProtection()
|
protection | setProtection()
|
||||||
|
quotePrefix | setQuotePrefix()
|
||||||
**\PhpOffice\PhpSpreadsheet\Style\Fill**
|
|
||||||
|
|
||||||
Array key | Maps to property
|
|
||||||
-----------|-------------------
|
|
||||||
fillType | setFillType()
|
|
||||||
rotation | setRotation()
|
|
||||||
startColor | getStartColor()
|
|
||||||
endColor | getEndColor()
|
|
||||||
color | getStartColor()
|
|
||||||
|
|
||||||
**\PhpOffice\PhpSpreadsheet\Style\Font**
|
|
||||||
|
|
||||||
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()
|
|
||||||
left | getLeft()
|
|
||||||
right | getRight()
|
|
||||||
top | getTop()
|
|
||||||
bottom | getBottom()
|
|
||||||
diagonal | getDiagonal()
|
|
||||||
vertical | getVertical()
|
|
||||||
horizontal | getHorizontal()
|
|
||||||
diagonalDirection | setDiagonalDirection()
|
|
||||||
outline | setOutline()
|
|
||||||
|
|
||||||
**\PhpOffice\PhpSpreadsheet\Style\Border**
|
|
||||||
|
|
||||||
Array key | Maps to property
|
|
||||||
------------|-------------------
|
|
||||||
borderStyle | setBorderStyle()
|
|
||||||
color | getColor()
|
|
||||||
|
|
||||||
**\PhpOffice\PhpSpreadsheet\Style\Alignment**
|
**\PhpOffice\PhpSpreadsheet\Style\Alignment**
|
||||||
|
|
||||||
Array key | Maps to property
|
Array key | Maps to property
|
||||||
------------|-------------------
|
------------|-------------------
|
||||||
horizontal | setHorizontal()
|
horizontal | setHorizontal()
|
||||||
vertical | setVertical()
|
|
||||||
textRotation| setTextRotation()
|
|
||||||
wrapText | setWrapText()
|
|
||||||
shrinkToFit | setShrinkToFit()
|
|
||||||
indent | setIndent()
|
indent | setIndent()
|
||||||
|
readOrder | setReadOrder()
|
||||||
|
shrinkToFit | setShrinkToFit()
|
||||||
|
textRotation| setTextRotation()
|
||||||
|
vertical | setVertical()
|
||||||
|
wrapText | setWrapText()
|
||||||
|
|
||||||
|
**\PhpOffice\PhpSpreadsheet\Style\Border**
|
||||||
|
|
||||||
|
Array key | Maps to property
|
||||||
|
------------|-------------------
|
||||||
|
borderStyle | setBorderStyle()
|
||||||
|
color | setColor()
|
||||||
|
|
||||||
|
**\PhpOffice\PhpSpreadsheet\Style\Borders**
|
||||||
|
|
||||||
|
Array key | Maps to property
|
||||||
|
------------------|-------------------
|
||||||
|
allBorders | setLeft(); setRight(); setTop(); setBottom()
|
||||||
|
bottom | setBottom()
|
||||||
|
diagonal | setDiagonal()
|
||||||
|
diagonalDirection | setDiagonalDirection()
|
||||||
|
left | setLeft()
|
||||||
|
right | setRight()
|
||||||
|
top | setTop()
|
||||||
|
|
||||||
|
**\PhpOffice\PhpSpreadsheet\Style\Color**
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
**\PhpOffice\PhpSpreadsheet\Style\Font**
|
||||||
|
|
||||||
|
Array key | Maps to property
|
||||||
|
------------|-------------------
|
||||||
|
bold | setBold()
|
||||||
|
color | getColor()
|
||||||
|
italic | setItalic()
|
||||||
|
name | setName()
|
||||||
|
size | setSize()
|
||||||
|
strikethrough | setStrikethrough()
|
||||||
|
subscript | setSubscript()
|
||||||
|
superscript | setSuperscript()
|
||||||
|
underline | setUnderline()
|
||||||
|
|
||||||
**\PhpOffice\PhpSpreadsheet\Style\NumberFormat**
|
**\PhpOffice\PhpSpreadsheet\Style\NumberFormat**
|
||||||
|
|
||||||
|
@ -839,7 +851,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
|
One can set a conditional style ruleset to a cell using the following
|
||||||
code:
|
code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$conditional1 = new \PhpOffice\PhpSpreadsheet\Style\Conditional();
|
$conditional1 = new \PhpOffice\PhpSpreadsheet\Style\Conditional();
|
||||||
$conditional1->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS);
|
$conditional1->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS);
|
||||||
$conditional1->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN);
|
$conditional1->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN);
|
||||||
|
@ -864,7 +876,7 @@ $spreadsheet->getActiveSheet()->getStyle('B2')->setConditionalStyles($conditiona
|
||||||
If you want to copy the ruleset to other cells, you can duplicate the
|
If you want to copy the ruleset to other cells, you can duplicate the
|
||||||
style object:
|
style object:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->duplicateStyle(
|
->duplicateStyle(
|
||||||
$spreadsheet->getActiveSheet()->getStyle('B2'),
|
$spreadsheet->getActiveSheet()->getStyle('B2'),
|
||||||
|
@ -877,7 +889,7 @@ $spreadsheet->getActiveSheet()
|
||||||
To add a comment to a cell, use the following code. The example below
|
To add a comment to a cell, use the following code. The example below
|
||||||
adds a comment to cell E11:
|
adds a comment to cell E11:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->getComment('E11')
|
->getComment('E11')
|
||||||
->setAuthor('Mark Baker');
|
->setAuthor('Mark Baker');
|
||||||
|
@ -899,7 +911,7 @@ $spreadsheet->getActiveSheet()
|
||||||
|
|
||||||
To apply an autofilter to a range of cells, use the following code:
|
To apply an autofilter to a range of cells, use the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setAutoFilter('A1:C9');
|
$spreadsheet->getActiveSheet()->setAutoFilter('A1:C9');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -919,45 +931,85 @@ disallow inserting rows on a specific sheet, disallow sorting, ...
|
||||||
- Cell: offers the option to lock/unlock a cell as well as show/hide
|
- Cell: offers the option to lock/unlock a cell as well as show/hide
|
||||||
the internal formula.
|
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);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Document
|
||||||
|
|
||||||
An example on setting document security:
|
An example on setting document security:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getSecurity()->setLockWindows(true);
|
$security = $spreadsheet->getSecurity();
|
||||||
$spreadsheet->getSecurity()->setLockStructure(true);
|
$security->setLockWindows(true);
|
||||||
$spreadsheet->getSecurity()->setWorkbookPassword("PhpSpreadsheet");
|
$security->setLockStructure(true);
|
||||||
|
$security->setWorkbookPassword("PhpSpreadsheet");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Worksheet
|
||||||
|
|
||||||
An example on setting worksheet security:
|
An example on setting worksheet security:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()
|
$protection = $spreadsheet->getActiveSheet()->getProtection();
|
||||||
->getProtection()->setPassword('PhpSpreadsheet');
|
$protection->setPassword('PhpSpreadsheet');
|
||||||
$spreadsheet->getActiveSheet()
|
$protection->setSheet(true);
|
||||||
->getProtection()->setSheet(true);
|
$protection->setSort(true);
|
||||||
$spreadsheet->getActiveSheet()
|
$protection->setInsertRows(true);
|
||||||
->getProtection()->setSort(true);
|
$protection->setFormatCells(true);
|
||||||
$spreadsheet->getActiveSheet()
|
|
||||||
->getProtection()->setInsertRows(true);
|
|
||||||
$spreadsheet->getActiveSheet()
|
|
||||||
->getProtection()->setFormatCells(true);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If writing Xlsx files you can specify the algorithm used to hash the password
|
||||||
|
before calling `setPassword()` like so:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$protection = $spreadsheet->getActiveSheet()->getProtection();
|
||||||
|
$protection->setAlgorithm(Protection::ALGORITHM_SHA_512);
|
||||||
|
$protection->setSpinCount(20000);
|
||||||
|
$protection->setPassword('PhpSpreadsheet');
|
||||||
|
```
|
||||||
|
|
||||||
|
The salt should **not** be set manually and will be automatically generated
|
||||||
|
when setting a new password.
|
||||||
|
|
||||||
|
### Cell
|
||||||
|
|
||||||
An example on setting cell security:
|
An example on setting cell security:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getStyle('B1')
|
$spreadsheet->getActiveSheet()->getStyle('B1')
|
||||||
->getProtection()
|
->getProtection()
|
||||||
->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
|
->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Make sure you enable worksheet protection if you need any of the
|
## Reading protected spreadsheet
|
||||||
worksheet protection features!** This can be done using the following
|
|
||||||
code:
|
|
||||||
|
|
||||||
``` php
|
Spreadsheets that are protected as described above can always be read by
|
||||||
$spreadsheet->getActiveSheet()->getProtection()->setSheet(true);
|
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');
|
||||||
|
|
||||||
|
if ($allowed) {
|
||||||
|
doSomething();
|
||||||
|
} else {
|
||||||
|
throw new Exception('Incorrect password');
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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
|
## Setting data validation on a cell
|
||||||
|
|
||||||
Data validation is a powerful feature of Xlsx. It allows to specify an
|
Data validation is a powerful feature of Xlsx. It allows to specify an
|
||||||
|
@ -968,7 +1020,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
|
The following piece of code only allows numbers between 10 and 20 to be
|
||||||
entered in cell B3:
|
entered in cell B3:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$validation = $spreadsheet->getActiveSheet()->getCell('B3')
|
$validation = $spreadsheet->getActiveSheet()->getCell('B3')
|
||||||
->getDataValidation();
|
->getDataValidation();
|
||||||
$validation->setType( \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_WHOLE );
|
$validation->setType( \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_WHOLE );
|
||||||
|
@ -987,7 +1039,7 @@ $validation->setFormula2(20);
|
||||||
The following piece of code only allows an item picked from a list of
|
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 B5:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$validation = $spreadsheet->getActiveSheet()->getCell('B5')
|
$validation = $spreadsheet->getActiveSheet()->getCell('B5')
|
||||||
->getDataValidation();
|
->getDataValidation();
|
||||||
$validation->setType( \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST );
|
$validation->setType( \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST );
|
||||||
|
@ -1017,7 +1069,7 @@ the item values themselves can contain the comma `,` character itself.
|
||||||
If you need data validation on multiple cells, one can clone the
|
If you need data validation on multiple cells, one can clone the
|
||||||
ruleset:
|
ruleset:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getCell('B8')->setDataValidation(clone $validation);
|
$spreadsheet->getActiveSheet()->getCell('B8')->setDataValidation(clone $validation);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1025,7 +1077,7 @@ $spreadsheet->getActiveSheet()->getCell('B8')->setDataValidation(clone $validati
|
||||||
|
|
||||||
A column's width can be set using the following code:
|
A column's width can be set using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(12);
|
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(12);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1033,7 +1085,7 @@ If you want PhpSpreadsheet to perform an automatic width calculation,
|
||||||
use the following code. PhpSpreadsheet will approximate the column with
|
use the following code. PhpSpreadsheet will approximate the column with
|
||||||
to the width of the widest column value.
|
to the width of the widest column value.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('B')->setAutoSize(true);
|
$spreadsheet->getActiveSheet()->getColumnDimension('B')->setAutoSize(true);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1070,7 +1122,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
|
The first line explicitly shows the column C, the second line hides
|
||||||
column D.
|
column D.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('C')->setVisible(true);
|
$spreadsheet->getActiveSheet()->getColumnDimension('C')->setVisible(true);
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setVisible(false);
|
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setVisible(false);
|
||||||
```
|
```
|
||||||
|
@ -1079,7 +1131,7 @@ $spreadsheet->getActiveSheet()->getColumnDimension('D')->setVisible(false);
|
||||||
|
|
||||||
To group/outline a column, you can use the following code:
|
To group/outline a column, you can use the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('E')->setOutlineLevel(1);
|
$spreadsheet->getActiveSheet()->getColumnDimension('E')->setOutlineLevel(1);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1087,7 +1139,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
|
column invisible, otherwise the collapse will not be visible in Excel
|
||||||
2007.
|
2007.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('E')->setCollapsed(true);
|
$spreadsheet->getActiveSheet()->getColumnDimension('E')->setCollapsed(true);
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension('E')->setVisible(false);
|
$spreadsheet->getActiveSheet()->getColumnDimension('E')->setVisible(false);
|
||||||
```
|
```
|
||||||
|
@ -1098,7 +1150,7 @@ on collapsing.
|
||||||
You can instruct PhpSpreadsheet to add a summary to the right (default),
|
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:
|
or to the left. The following code adds the summary to the left:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setShowSummaryRight(false);
|
$spreadsheet->getActiveSheet()->setShowSummaryRight(false);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1106,7 +1158,7 @@ $spreadsheet->getActiveSheet()->setShowSummaryRight(false);
|
||||||
|
|
||||||
A row's height can be set using the following code:
|
A row's height can be set using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getRowDimension('10')->setRowHeight(100);
|
$spreadsheet->getActiveSheet()->getRowDimension('10')->setRowHeight(100);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1119,7 +1171,7 @@ of values is between 0 and 409 pts, where 0 pts is a hidden row.
|
||||||
To set a worksheet''s row visibility, you can use the following code.
|
To set a worksheet''s row visibility, you can use the following code.
|
||||||
The following example hides row number 10.
|
The following example hides row number 10.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getRowDimension('10')->setVisible(false);
|
$spreadsheet->getActiveSheet()->getRowDimension('10')->setVisible(false);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1131,21 +1183,21 @@ AutoFilter range if you save the file.
|
||||||
|
|
||||||
To group/outline a row, you can use the following code:
|
To group/outline a row, you can use the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getRowDimension('5')->setOutlineLevel(1);
|
$spreadsheet->getActiveSheet()->getRowDimension('5')->setOutlineLevel(1);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also collapse the row. Note that you should also set the row
|
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.
|
invisible, otherwise the collapse will not be visible in Excel 2007.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getRowDimension('5')->setCollapsed(true);
|
$spreadsheet->getActiveSheet()->getRowDimension('5')->setCollapsed(true);
|
||||||
$spreadsheet->getActiveSheet()->getRowDimension('5')->setVisible(false);
|
$spreadsheet->getActiveSheet()->getRowDimension('5')->setVisible(false);
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's an example which collapses rows 50 to 80:
|
Here's an example which collapses rows 50 to 80:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
for ($i = 51; $i <= 80; $i++) {
|
for ($i = 51; $i <= 80; $i++) {
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('A' . $i, "FName $i");
|
$spreadsheet->getActiveSheet()->setCellValue('A' . $i, "FName $i");
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('B' . $i, "LName $i");
|
$spreadsheet->getActiveSheet()->setCellValue('B' . $i, "LName $i");
|
||||||
|
@ -1162,7 +1214,7 @@ $spreadsheet->getActiveSheet()->getRowDimension(81)->setCollapsed(true);
|
||||||
You can instruct PhpSpreadsheet to add a summary below the collapsible
|
You can instruct PhpSpreadsheet to add a summary below the collapsible
|
||||||
rows (default), or above. The following code adds the summary above:
|
rows (default), or above. The following code adds the summary above:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->setShowSummaryBelow(false);
|
$spreadsheet->getActiveSheet()->setShowSummaryBelow(false);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1172,13 +1224,13 @@ 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
|
can merge two or more cells together, to become one cell. This can be
|
||||||
done using the following code:
|
done using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->mergeCells('A18:E22');
|
$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');
|
$spreadsheet->getActiveSheet()->unmergeCells('A18:E22');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1187,7 +1239,7 @@ $spreadsheet->getActiveSheet()->unmergeCells('A18:E22');
|
||||||
You can insert/remove rows/columns at a specific position. The following
|
You can insert/remove rows/columns at a specific position. The following
|
||||||
code inserts 2 new rows, right before row 7:
|
code inserts 2 new rows, right before row 7:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2);
|
$spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1198,7 +1250,7 @@ to a worksheet. Therefore, you must first instantiate a new
|
||||||
`\PhpOffice\PhpSpreadsheet\Worksheet\Drawing`, and assign its properties a
|
`\PhpOffice\PhpSpreadsheet\Worksheet\Drawing`, and assign its properties a
|
||||||
meaningful value:
|
meaningful value:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
|
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
|
||||||
$drawing->setName('Logo');
|
$drawing->setName('Logo');
|
||||||
$drawing->setDescription('Logo');
|
$drawing->setDescription('Logo');
|
||||||
|
@ -1210,13 +1262,13 @@ To add the above drawing to the worksheet, use the following snippet of
|
||||||
code. PhpSpreadsheet creates the link between the drawing and the
|
code. PhpSpreadsheet creates the link between the drawing and the
|
||||||
worksheet:
|
worksheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$drawing->setWorksheet($spreadsheet->getActiveSheet());
|
$drawing->setWorksheet($spreadsheet->getActiveSheet());
|
||||||
```
|
```
|
||||||
|
|
||||||
You can set numerous properties on a drawing, here are some examples:
|
You can set numerous properties on a drawing, here are some examples:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$drawing->setName('Paid');
|
$drawing->setName('Paid');
|
||||||
$drawing->setDescription('Paid');
|
$drawing->setDescription('Paid');
|
||||||
$drawing->setPath('./images/paid.png');
|
$drawing->setPath('./images/paid.png');
|
||||||
|
@ -1230,7 +1282,7 @@ $drawing->getShadow()->setDirection(45);
|
||||||
You can also add images created using GD functions without needing to
|
You can also add images created using GD functions without needing to
|
||||||
save them to disk first as In-Memory drawings.
|
save them to disk first as In-Memory drawings.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Use GD to create an in-memory image
|
// Use GD to create an in-memory image
|
||||||
$gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream');
|
$gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream');
|
||||||
$textColor = imagecolorallocate($gdImage, 255, 255, 255);
|
$textColor = imagecolorallocate($gdImage, 255, 255, 255);
|
||||||
|
@ -1258,7 +1310,7 @@ that has been loaded, and save them as individual image files to disk.
|
||||||
The following code extracts images from the current active worksheet,
|
The following code extracts images from the current active worksheet,
|
||||||
and writes each as a separate file.
|
and writes each as a separate file.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$i = 0;
|
$i = 0;
|
||||||
foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $drawing) {
|
foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $drawing) {
|
||||||
if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
|
if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
|
||||||
|
@ -1303,7 +1355,7 @@ creates the following rich text string:
|
||||||
> This invoice is ***payable within thirty days after the end of the
|
> This invoice is ***payable within thirty days after the end of the
|
||||||
> month*** unless specified otherwise on the invoice.
|
> month*** unless specified otherwise on the invoice.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$richText = new \PhpOffice\PhpSpreadsheet\RichText\RichText();
|
$richText = new \PhpOffice\PhpSpreadsheet\RichText\RichText();
|
||||||
$richText->createText('This invoice is ');
|
$richText->createText('This invoice is ');
|
||||||
$payable = $richText->createTextRun('payable within thirty days after the end of the month');
|
$payable = $richText->createTextRun('payable within thirty days after the end of the month');
|
||||||
|
@ -1319,7 +1371,7 @@ $spreadsheet->getActiveSheet()->getCell('A18')->setValue($richText);
|
||||||
PhpSpreadsheet supports the definition of named ranges. These can be
|
PhpSpreadsheet supports the definition of named ranges. These can be
|
||||||
defined using the following code:
|
defined using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Add some data
|
// Add some data
|
||||||
$spreadsheet->setActiveSheetIndex(0);
|
$spreadsheet->setActiveSheetIndex(0);
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('A1', 'Firstname:');
|
$spreadsheet->getActiveSheet()->setCellValue('A1', 'Firstname:');
|
||||||
|
@ -1328,14 +1380,73 @@ $spreadsheet->getActiveSheet()->setCellValue('B1', 'Maarten');
|
||||||
$spreadsheet->getActiveSheet()->setCellValue('B2', 'Balliauw');
|
$spreadsheet->getActiveSheet()->setCellValue('B2', 'Balliauw');
|
||||||
|
|
||||||
// Define named ranges
|
// Define named ranges
|
||||||
$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonFN', $spreadsheet->getActiveSheet(), 'B1') );
|
$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonFN', $spreadsheet->getActiveSheet(), '$B$1'));
|
||||||
$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonLN', $spreadsheet->getActiveSheet(), 'B2') );
|
$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonLN', $spreadsheet->getActiveSheet(), '$B$2'));
|
||||||
```
|
```
|
||||||
|
|
||||||
Optionally, a fourth parameter can be passed defining the named range
|
Optionally, a fourth parameter can be passed defining the named range
|
||||||
local (i.e. only usable on the current worksheet). Named ranges are
|
local (i.e. only usable on the current worksheet). Named ranges are
|
||||||
global by default.
|
global by default.
|
||||||
|
|
||||||
|
## Define a named formula
|
||||||
|
|
||||||
|
In addition to named ranges, PhpSpreadsheet also supports the definition of named formulae. 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 formulae are
|
||||||
|
global by default.
|
||||||
|
|
||||||
## Redirect output to a client's web browser
|
## Redirect output to a client's web browser
|
||||||
|
|
||||||
Sometimes, one really wants to output a file to a client''s browser,
|
Sometimes, one really wants to output a file to a client''s browser,
|
||||||
|
@ -1362,7 +1473,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
|
Example of a script redirecting an Excel 2007 file to the client's
|
||||||
browser:
|
browser:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
/* Here there will be some code where you create $spreadsheet */
|
/* Here there will be some code where you create $spreadsheet */
|
||||||
|
|
||||||
// redirect output to client browser
|
// redirect output to client browser
|
||||||
|
@ -1376,7 +1487,7 @@ $writer->save('php://output');
|
||||||
|
|
||||||
Example of a script redirecting an Xls file to the client's browser:
|
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 */
|
/* Here there will be some code where you create $spreadsheet */
|
||||||
|
|
||||||
// redirect output to client browser
|
// redirect output to client browser
|
||||||
|
@ -1404,7 +1515,7 @@ at the client browser, and/or that headers cannot be set by PHP
|
||||||
|
|
||||||
Default column width can be set using the following code:
|
Default column width can be set using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(12);
|
$spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(12);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1412,7 +1523,7 @@ $spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(12);
|
||||||
|
|
||||||
Default row height can be set using the following code:
|
Default row height can be set using the following code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getDefaultRowDimension()->setRowHeight(15);
|
$spreadsheet->getActiveSheet()->getDefaultRowDimension()->setRowHeight(15);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1425,7 +1536,7 @@ file to a temporary location.
|
||||||
Here''s an example which generates an image in memory and adds it to the
|
Here''s an example which generates an image in memory and adds it to the
|
||||||
active worksheet:
|
active worksheet:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Generate an image
|
// Generate an image
|
||||||
$gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream');
|
$gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream');
|
||||||
$textColor = imagecolorallocate($gdImage, 255, 255, 255);
|
$textColor = imagecolorallocate($gdImage, 255, 255, 255);
|
||||||
|
@ -1446,7 +1557,7 @@ $drawing->setWorksheet($spreadsheet->getActiveSheet());
|
||||||
|
|
||||||
To set a worksheet's zoom level, the following code can be used:
|
To set a worksheet's zoom level, the following code can be used:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->getSheetView()->setZoomScale(75);
|
$spreadsheet->getActiveSheet()->getSheetView()->setZoomScale(75);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1457,7 +1568,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
|
Sometimes you want to set a color for sheet tab. For example you can
|
||||||
have a red sheet tab:
|
have a red sheet tab:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet->getTabColor()->setRGB('FF0000');
|
$worksheet->getTabColor()->setRGB('FF0000');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1465,7 +1576,7 @@ $worksheet->getTabColor()->setRGB('FF0000');
|
||||||
|
|
||||||
If you need to create more worksheets in the workbook, here is how:
|
If you need to create more worksheets in the workbook, here is how:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$worksheet1 = $spreadsheet->createSheet();
|
$worksheet1 = $spreadsheet->createSheet();
|
||||||
$worksheet1->setTitle('Another sheet');
|
$worksheet1->setTitle('Another sheet');
|
||||||
```
|
```
|
||||||
|
@ -1478,7 +1589,7 @@ worksheets in the workbook.
|
||||||
|
|
||||||
Set a worksheet to be **hidden** using this code:
|
Set a worksheet to be **hidden** using this code:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->setSheetState(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::SHEETSTATE_HIDDEN);
|
->setSheetState(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::SHEETSTATE_HIDDEN);
|
||||||
```
|
```
|
||||||
|
@ -1500,7 +1611,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
|
left or right side. Default is left. Here is how to set columns from
|
||||||
right-to-left.
|
right-to-left.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// right-to-left worksheet
|
// right-to-left worksheet
|
||||||
$spreadsheet->getActiveSheet()->setRightToLeft(true);
|
$spreadsheet->getActiveSheet()->setRightToLeft(true);
|
||||||
```
|
```
|
||||||
|
|
|
@ -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:
|
To enable cell caching, you must provide your own implementation of cache like so:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$cache = new MyCustomPsr16Implementation();
|
$cache = new MyCustomPsr16Implementation();
|
||||||
|
|
||||||
\PhpOffice\PhpSpreadsheet\Settings::setCache($cache);
|
\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
|
set a locale by changing the settings. To set the locale to Brazilian
|
||||||
Portuguese you would use:
|
Portuguese you would use:
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$locale = 'pt_br';
|
$locale = 'pt_br';
|
||||||
$validLocale = \PhpOffice\PhpSpreadsheet\Settings::setLocale($locale);
|
$validLocale = \PhpOffice\PhpSpreadsheet\Settings::setLocale($locale);
|
||||||
if (!$validLocale) {
|
if (!$validLocale) {
|
||||||
|
@ -43,3 +43,20 @@ More details of the features available once a locale has been set,
|
||||||
including a list of the languages and locales currently supported, can
|
including a list of the languages and locales currently supported, can
|
||||||
be found in [Locale Settings for
|
be found in [Locale Settings for
|
||||||
Formulae](./recipes.md#locale-settings-for-formulae).
|
Formulae](./recipes.md#locale-settings-for-formulae).
|
||||||
|
|
||||||
|
## 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);
|
||||||
|
```
|
||||||
|
|
|
@ -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
|
(or other appropriate Spreadsheet program). To access a sheet by its
|
||||||
index, use the `getSheet()` method.
|
index, use the `getSheet()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Get the second sheet in the workbook
|
// Get the second sheet in the workbook
|
||||||
// Note that sheets are indexed from 0
|
// Note that sheets are indexed from 0
|
||||||
$spreadsheet->getSheet(1);
|
$spreadsheet->getSheet(1);
|
||||||
|
@ -38,7 +38,7 @@ workbook.
|
||||||
To access a sheet by name, use the `getSheetByName()` method, specifying
|
To access a sheet by name, use the `getSheetByName()` method, specifying
|
||||||
the name of the worksheet that you want to access.
|
the name of the worksheet that you want to access.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Retrieve the worksheet called 'Worksheet 1'
|
// Retrieve the worksheet called 'Worksheet 1'
|
||||||
$spreadsheet->getSheetByName('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
|
one that will be active when the workbook is opened in MS Excel (or
|
||||||
other appropriate Spreadsheet program).
|
other appropriate Spreadsheet program).
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Retrieve the current active worksheet
|
// Retrieve the current active worksheet
|
||||||
$spreadsheet->getActiveSheet();
|
$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
|
argument, and the worksheet will be inserted at that position, shuffling
|
||||||
all subsequent worksheets in the collection down a place.
|
all subsequent worksheets in the collection down a place.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$spreadsheet->createSheet();
|
$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
|
whatever you choose) and then insert it into your workbook using the
|
||||||
`addSheet()` method.
|
`addSheet()` method.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
// Create a new worksheet called "My Data"
|
// Create a new worksheet called "My Data"
|
||||||
$myWorkSheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'My Data');
|
$myWorkSheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'My Data');
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ 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
|
worksheet you wish to copy, and then using the `addSheet()` method to
|
||||||
insert the clone into the workbook.
|
insert the clone into the workbook.
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$clonedWorksheet = clone $spreadsheet->getSheetByName('Worksheet 1');
|
$clonedWorksheet = clone $spreadsheet->getSheetByName('Worksheet 1');
|
||||||
$clonedWorksheet->setTitle('Copy of Worksheet 1');
|
$clonedWorksheet->setTitle('Copy of Worksheet 1');
|
||||||
$spreadsheet->addSheet($clonedWorksheet);
|
$spreadsheet->addSheet($clonedWorksheet);
|
||||||
|
@ -117,7 +117,7 @@ duplicate name.
|
||||||
You can delete a worksheet from a workbook, identified by its index
|
You can delete a worksheet from a workbook, identified by its index
|
||||||
position, using the `removeSheetByIndex()` method
|
position, using the `removeSheetByIndex()` method
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$sheetIndex = $spreadsheet->getIndex(
|
$sheetIndex = $spreadsheet->getIndex(
|
||||||
$spreadsheet->getSheetByName('Worksheet 1')
|
$spreadsheet->getSheetByName('Worksheet 1')
|
||||||
);
|
);
|
||||||
|
|
|
@ -157,8 +157,10 @@ $spreadsheet->getActiveSheet()->setCellValue('E23', 'Mode of both ranges:')
|
||||||
$helper->log('Calculated data');
|
$helper->log('Calculated data');
|
||||||
for ($col = 'B'; $col != 'G'; ++$col) {
|
for ($col = 'B'; $col != 'G'; ++$col) {
|
||||||
for ($row = 14; $row <= 41; ++$row) {
|
for ($row = 14; $row <= 41; ++$row) {
|
||||||
if ((($formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue()) !== null) &&
|
if (
|
||||||
($formula[0] == '=')) {
|
(($formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue()) !== null) &&
|
||||||
|
($formula[0] == '=')
|
||||||
|
) {
|
||||||
$helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValue());
|
$helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,10 @@ Calculation::getInstance($spreadsheet)->cyclicFormulaCount = 15;
|
||||||
$helper->log('Calculated data');
|
$helper->log('Calculated data');
|
||||||
for ($row = 1; $row <= 2; ++$row) {
|
for ($row = 1; $row <= 2; ++$row) {
|
||||||
for ($col = 'A'; $col != 'C'; ++$col) {
|
for ($col = 'A'; $col != 'C'; ++$col) {
|
||||||
if ((($formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue()) !== null) &&
|
if (
|
||||||
($formula[0] == '=')) {
|
(($formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue()) !== null) &&
|
||||||
|
($formula[0] == '=')
|
||||||
|
) {
|
||||||
$helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValue());
|
$helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Html;
|
||||||
|
|
||||||
|
require __DIR__ . '/../Header.php';
|
||||||
|
$spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
||||||
|
|
||||||
|
$filename = $helper->getFilename(__FILE__, 'html');
|
||||||
|
$writer = new Html($spreadsheet);
|
||||||
|
|
||||||
|
function changeGridlines(string $html): string
|
||||||
|
{
|
||||||
|
return str_replace('{border: 1px solid black;}', '{border: 2px dashed red;}', $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
$callStartTime = microtime(true);
|
||||||
|
$writer->setEmbedImages(true);
|
||||||
|
$writer->setEditHtmlCallback('changeGridlines');
|
||||||
|
$writer->save($filename);
|
||||||
|
$helper->logWrite($writer, $filename, $callStartTime);
|
|
@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
|
||||||
require __DIR__ . '/../Header.php';
|
require __DIR__ . '/../Header.php';
|
||||||
|
|
||||||
$filename = __DIR__ . '/../templates/Excel2003XMLTest.xml';
|
$filename = __DIR__ . '/../templates/excel2003.xml';
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$spreadsheet = IOFactory::load($filename);
|
$spreadsheet = IOFactory::load($filename);
|
||||||
$helper->logRead('Xml', $filename, $callStartTime);
|
$helper->logRead('Xml', $filename, $callStartTime);
|
||||||
|
|
|
@ -12,10 +12,12 @@ $spreadsheet = $reader->load(__DIR__ . '/../templates/26template.xlsx');
|
||||||
// at this point, we could do some manipulations with the template, but we skip this step
|
// at this point, we could do some manipulations with the template, but we skip this step
|
||||||
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']);
|
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']);
|
||||||
|
|
||||||
// Export to PDF (.pdf)
|
if (\PHP_VERSION_ID < 80000) {
|
||||||
$helper->log('Write to PDF format');
|
// Export to PDF (.pdf)
|
||||||
IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class);
|
$helper->log('Write to PDF format');
|
||||||
$helper->write($spreadsheet, __FILE__, ['Pdf']);
|
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
|
// Remove first two rows with field headers before exporting to CSV
|
||||||
$helper->log('Removing first two heading rows for CSV export');
|
$helper->log('Removing first two heading rows for CSV export');
|
||||||
|
|
|
@ -30,7 +30,7 @@ $html1 = '<font color="#0000ff">
|
||||||
while this block uses an <u>underline</u>.
|
while this block uses an <u>underline</u>.
|
||||||
</font>
|
</font>
|
||||||
</p>
|
</p>
|
||||||
<p align="right"><font size="9" color="red">
|
<p align="right"><font size="9" color="red" face="Times New Roman, serif">
|
||||||
I want to eat <ins><del>healthy food</del> <strong>pizza</strong></ins>.
|
I want to eat <ins><del>healthy food</del> <strong>pizza</strong></ins>.
|
||||||
</font>
|
</font>
|
||||||
';
|
';
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
|
|
||||||
require __DIR__ . '/../Header.php';
|
require __DIR__ . '/../Header.php';
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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})");
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'AbsoluteNamedRange.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedFormula;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
|
||||||
|
$data2019 = [
|
||||||
|
[151600, 21600],
|
||||||
|
[160320, 30320],
|
||||||
|
[243500, 73500],
|
||||||
|
[113450, 13450],
|
||||||
|
[143200, 23200],
|
||||||
|
[134000, 14000],
|
||||||
|
[89400, -10600],
|
||||||
|
[184500, 24500],
|
||||||
|
[100800, 800],
|
||||||
|
[241850, 5150],
|
||||||
|
[142425, 12425],
|
||||||
|
[243400, 43400],
|
||||||
|
];
|
||||||
|
|
||||||
|
$data2020 = [
|
||||||
|
[183250, 33250],
|
||||||
|
[210350, 40350],
|
||||||
|
[298650, 48650],
|
||||||
|
[140550, 20550],
|
||||||
|
[183145, 33145],
|
||||||
|
[172355, 22355],
|
||||||
|
];
|
||||||
|
|
||||||
|
$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): 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();
|
||||||
|
|
||||||
|
echo "Growth for {$month} is {$growth}, with a Profit Growth of {$profitGrowth}", PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$outputFileName = 'CrossWorksheetNamedFormula.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedFormula;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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');
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'NamedFormulaeAndRanges.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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})");
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'RelativeNamedRange.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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)');
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'RelativeNamedRange2.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedFormula;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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)');
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'RelativeNamedRangeAsFunction.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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)');
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'ScopedNamedRange.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
$worksheet = $spreadsheet->setActiveSheetIndex(0);
|
||||||
|
|
||||||
|
$outputFileName = 'ScopedNamedRange2.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedFormula;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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');
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'SimpleNamedFormula.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
|
||||||
|
require_once __DIR__ . '/../Bootstrap.php';
|
||||||
|
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$worksheet = $spreadsheet->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)');
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
$outputFileName = 'SimpleNamedRange.xlsx';
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($outputFileName);
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
|
||||||
|
|
||||||
|
require __DIR__ . '/../Header.php';
|
||||||
|
$spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
||||||
|
|
||||||
|
$helper->log('Hide grid lines');
|
||||||
|
$spreadsheet->getActiveSheet()->setShowGridLines(false);
|
||||||
|
|
||||||
|
$helper->log('Set orientation to landscape');
|
||||||
|
$spreadsheet->getActiveSheet()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
|
||||||
|
$spreadsheet->setActiveSheetIndex(0)->setPrintGridlines(true);
|
||||||
|
|
||||||
|
function changeGridlines(string $html): string
|
||||||
|
{
|
||||||
|
return str_replace('{border: 1px solid black;}', '{border: 2px dashed red;}', $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
$helper->log('Write to Mpdf');
|
||||||
|
$writer = new Mpdf($spreadsheet);
|
||||||
|
$filename = $helper->getFileName('21a_Pdf_mpdf.xlsx', 'pdf');
|
||||||
|
$writer->setEditHtmlCallback('changeGridlines');
|
||||||
|
$writer->save($filename);
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf;
|
||||||
|
|
||||||
|
function replaceBody(string $html): string
|
||||||
|
{
|
||||||
|
$lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
|
||||||
|
$bodystring = '~<body>.*</body>~ms';
|
||||||
|
$bodyrepl = <<<EOF
|
||||||
|
<body>
|
||||||
|
<h1>Serif</h1>
|
||||||
|
<p style='font-family: serif; font-size: 12pt;'>$lorem</p>
|
||||||
|
<h1>Sans-Serif</h1>
|
||||||
|
<p style='font-family: sans-serif; font-size: 12pt;'>$lorem</p>
|
||||||
|
<h1>Monospace</h1>
|
||||||
|
<p style='font-family: monospace; font-size: 12pt;'>$lorem</p>
|
||||||
|
</body>
|
||||||
|
EOF;
|
||||||
|
|
||||||
|
return preg_replace($bodystring, $bodyrepl, $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/../Header.php';
|
||||||
|
$spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
||||||
|
|
||||||
|
$helper->log('Hide grid lines');
|
||||||
|
$spreadsheet->getActiveSheet()->setShowGridLines(false);
|
||||||
|
|
||||||
|
$helper->log('Set orientation to landscape');
|
||||||
|
$spreadsheet->getActiveSheet()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
|
||||||
|
|
||||||
|
if (\PHP_VERSION_ID < 80000) {
|
||||||
|
$helper->log('Write to Dompdf');
|
||||||
|
$writer = new Dompdf($spreadsheet);
|
||||||
|
$filename = $helper->getFileName('21b_Pdf_dompdf.xlsx', 'pdf');
|
||||||
|
$writer->setEditHtmlCallback('replaceBody');
|
||||||
|
$writer->save($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$helper->log('Write to Mpdf');
|
||||||
|
$writer = new Mpdf($spreadsheet);
|
||||||
|
$filename = $helper->getFileName('21b_Pdf_mpdf.xlsx', 'pdf');
|
||||||
|
$writer->setEditHtmlCallback('replaceBody');
|
||||||
|
$writer->save($filename);
|
||||||
|
|
||||||
|
if (\PHP_VERSION_ID < 80000) {
|
||||||
|
$helper->log('Write to Tcpdf');
|
||||||
|
$writer = new Tcpdf($spreadsheet);
|
||||||
|
$filename = $helper->getFileName('21b_Pdf_tcpdf.xlsx', 'pdf');
|
||||||
|
$writer->setEditHtmlCallback('replaceBody');
|
||||||
|
$writer->save($filename);
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
@ -52,7 +52,7 @@ P;EArial;M200
|
||||||
P;EArial;M200;SI
|
P;EArial;M200;SI
|
||||||
P;EArial;M200;SBI
|
P;EArial;M200;SBI
|
||||||
P;EArial;M200;SBU
|
P;EArial;M200;SBU
|
||||||
P;EArial;M200;SBIU
|
P;EArial;M220;SBIU
|
||||||
P;EArial;M200
|
P;EArial;M200
|
||||||
P;EArial;M200;SI
|
P;EArial;M200;SI
|
||||||
F;P0;DG0G8;M255
|
F;P0;DG0G8;M255
|
||||||
|
@ -115,6 +115,7 @@ F;P19;FG0G;X4
|
||||||
C;Y7;X2;K2.34
|
C;Y7;X2;K2.34
|
||||||
C;X3;KFALSE
|
C;X3;KFALSE
|
||||||
C;Y8;X2;K3.45
|
C;Y8;X2;K3.45
|
||||||
|
C;Y9;X2;K2.34;EMEDIAN(R[-3]C:R[-1]C)
|
||||||
F;Y9;X1
|
F;Y9;X1
|
||||||
F;X2
|
F;X2
|
||||||
F;X3
|
F;X3
|
||||||
|
|
|
@ -20,6 +20,19 @@
|
||||||
<ProtectStructure>False</ProtectStructure>
|
<ProtectStructure>False</ProtectStructure>
|
||||||
<ProtectWindows>False</ProtectWindows>
|
<ProtectWindows>False</ProtectWindows>
|
||||||
</ExcelWorkbook>
|
</ExcelWorkbook>
|
||||||
|
<Styles>
|
||||||
|
<Style ss:ID="ce9">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:Rotate="0"/>
|
||||||
|
<Borders/>
|
||||||
|
<Font ss:Color="#000000" ss:FontName="Arial1" ss:Size="11"/>
|
||||||
|
<NumberFormat ss:Format="Short Date"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="ce32">
|
||||||
|
<Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1" ss:Rotate="0"/>
|
||||||
|
<Borders/>
|
||||||
|
<Font ss:Color="#000000" ss:FontName="Calibri" ss:Size="11"/>
|
||||||
|
</Style>
|
||||||
|
</Styles>
|
||||||
<ss:Worksheet ss:Name="Sample Data">
|
<ss:Worksheet ss:Name="Sample Data">
|
||||||
<Table>
|
<Table>
|
||||||
<Column ss:Width="96.4913"/>
|
<Column ss:Width="96.4913"/>
|
||||||
|
@ -28,7 +41,7 @@
|
||||||
<Column ss:Span="6" ss:Width="48.3874"/>
|
<Column ss:Span="6" ss:Width="48.3874"/>
|
||||||
<Column ss:Index="12" ss:Width="50.2583"/>
|
<Column ss:Index="12" ss:Width="50.2583"/>
|
||||||
<Column ss:Span="1011" ss:Width="48.3874"/>
|
<Column ss:Span="1011" ss:Width="48.3874"/>
|
||||||
<Row ss:AutoFitHeight="0" ss:Height="14.9953">
|
<Row ss:Index="8" ss:AutoFitHeight="0" ss:Height="14.9953">
|
||||||
<Cell>
|
<Cell>
|
||||||
<ss:Data xmlns="http://www.w3.org/TR/REC-html40" ss:Type="String">Test String 1</ss:Data>
|
<ss:Data xmlns="http://www.w3.org/TR/REC-html40" ss:Type="String">Test String 1</ss:Data>
|
||||||
<Comment>
|
<Comment>
|
||||||
|
@ -38,7 +51,16 @@
|
||||||
</Comment>
|
</Comment>
|
||||||
</Cell>
|
</Cell>
|
||||||
<Cell>
|
<Cell>
|
||||||
<Data ss:Type="Number">1</Data>
|
<Data ss:StyleID="ce32" ss:Type="Number">1</Data>
|
||||||
|
</Cell>
|
||||||
|
<Cell ss:Formula="of:=12/1">
|
||||||
|
<Data ss:Type="Number">12</Data>
|
||||||
|
</Cell>
|
||||||
|
<Cell ss:Formula="of:=[.C8]-[.B8]">
|
||||||
|
<Data ss:Type="Number">11</Data>
|
||||||
|
</Cell>
|
||||||
|
<Cell ss:StyleID="ce9">
|
||||||
|
<Data ss:Type="DateTime">1960-12-19T00:00:00.000</Data>
|
||||||
</Cell>
|
</Cell>
|
||||||
</Row>
|
</Row>
|
||||||
</Table>
|
</Table>
|
|
@ -0,0 +1,944 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?mso-application progid="Excel.Sheet"?>
|
||||||
|
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
|
||||||
|
xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||||
|
xmlns:x="urn:schemas-microsoft-com:office:excel"
|
||||||
|
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
|
||||||
|
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
|
||||||
|
xmlns:html="http://www.w3.org/TR/REC-html40">
|
||||||
|
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
|
||||||
|
<Title>Xml2003 Workbook</Title>
|
||||||
|
<Subject>Test Gnumeric Workbook Subject</Subject>
|
||||||
|
<Author>Mark Baker</Author>
|
||||||
|
<Keywords>PHPExcel Xml Reader Test Keywords</Keywords>
|
||||||
|
<Description>Some comments about the PHPExcel Gnumeric Reader</Description>
|
||||||
|
<LastAuthor>Owen Leibman</LastAuthor>
|
||||||
|
<Created>2010-09-02T20:48:39Z</Created>
|
||||||
|
<LastSaved>2010-09-02T20:48:39Z</LastSaved>
|
||||||
|
<Category>PHPExcel Xml Reader Test Category</Category>
|
||||||
|
<Manager>Maarten Balliauw</Manager>
|
||||||
|
<Company>PHPExcel</Company>
|
||||||
|
<HyperlinkBase>https://github.com/PHPOffice/PhpSpreadsheet</HyperlinkBase>
|
||||||
|
<Version>16.00</Version>
|
||||||
|
</DocumentProperties>
|
||||||
|
<CustomDocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
|
||||||
|
<my_API_Token dt:dt="string">AbCd1234</my_API_Token>
|
||||||
|
<my_API_Token_Expiry dt:dt="dateTime.tz">2019-01-31T07:00:00Z</my_API_Token_Expiry>
|
||||||
|
<my_API_Boolean dt:dt="boolean">1</my_API_Boolean>
|
||||||
|
<my_API_Int dt:dt="string">3</my_API_Int>
|
||||||
|
<myאInt dt:dt="string">2</myאInt>
|
||||||
|
<my_API_Float dt:dt="float">3.14159</my_API_Float>
|
||||||
|
</CustomDocumentProperties>
|
||||||
|
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
|
||||||
|
<AllowPNG/>
|
||||||
|
</OfficeDocumentSettings>
|
||||||
|
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
|
||||||
|
<WindowHeight>8964</WindowHeight>
|
||||||
|
<WindowWidth>23040</WindowWidth>
|
||||||
|
<WindowTopX>32767</WindowTopX>
|
||||||
|
<WindowTopY>32767</WindowTopY>
|
||||||
|
<ProtectStructure>False</ProtectStructure>
|
||||||
|
<ProtectWindows>False</ProtectWindows>
|
||||||
|
</ExcelWorkbook>
|
||||||
|
<Styles>
|
||||||
|
<Style ss:ID="Default" ss:Name="Normal">
|
||||||
|
<Alignment ss:Vertical="Bottom"/>
|
||||||
|
<Borders/>
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
<Interior/>
|
||||||
|
<NumberFormat/>
|
||||||
|
<Protection/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s62" ss:Name="Hyperlink">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#0066CC"
|
||||||
|
ss:Underline="Single"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="m1867777004784">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="3"
|
||||||
|
ss:Color="#00B050"/>
|
||||||
|
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="3"
|
||||||
|
ss:Color="#0070C0"/>
|
||||||
|
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="3"
|
||||||
|
ss:Color="#FFFF00"/>
|
||||||
|
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="3"
|
||||||
|
ss:Color="#FF0000"/>
|
||||||
|
</Borders>
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s63">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#FF0000" ss:Bold="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s64">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s65">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000" ss:Bold="1"
|
||||||
|
ss:Italic="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s66">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000" ss:Bold="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s68">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000" ss:Underline="Single"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s69">
|
||||||
|
<Interior ss:Color="#FF0000" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s70">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#FF0000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s72">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000" ss:Italic="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s73">
|
||||||
|
<Interior ss:Color="#FF9900" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s74">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#FF6600"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s75">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="DashDotDot" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s76">
|
||||||
|
<Interior ss:Color="#FFFF00" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s77">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#FFFF00"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s78">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="DashDot" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s79">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#000000"
|
||||||
|
ss:Underline="Single"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s80">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
<NumberFormat ss:Format="dd/mm/yyyy"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s81">
|
||||||
|
<Interior ss:Color="#008000" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s82">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#008000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s83">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s84">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#000000"
|
||||||
|
ss:Underline="Double"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s85">
|
||||||
|
<Interior ss:Color="#0000FF" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s86">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#0000FF"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s87">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="DashDotDot" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s88">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#000000" ss:StrikeThrough="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s89">
|
||||||
|
<Interior ss:Color="#993366" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s90">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#800080"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s91">
|
||||||
|
<Interior ss:Color="#FF99CC" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s92">
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#FF00FF"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s93">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="DashDot" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s94">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s95">
|
||||||
|
<Interior ss:Color="#DDBC7D" ss:Pattern="Solid"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s96">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Dash" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s97">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
<NumberFormat ss:Format="#\ ?0/??0"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s98">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s99">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s100">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="3"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s101">
|
||||||
|
<NumberFormat ss:Format="hh":"mm":"ss"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s102">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Double" ss:Weight="3"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s103">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s104">
|
||||||
|
<NumberFormat ss:Format="d/m/yy\ hh":"mm"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s105">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="2"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s113">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="DiagonalLeft" ss:LineStyle="Double" ss:Weight="3"
|
||||||
|
ss:Color="#FF0000"/>
|
||||||
|
<Border ss:Position="DiagonalRight" ss:LineStyle="Double" ss:Weight="3"
|
||||||
|
ss:Color="#FF0000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s114">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s115">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="DiagonalLeft" ss:LineStyle="Continuous" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s116">
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="DiagonalRight" ss:LineStyle="Continuous" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s118">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
|
||||||
|
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#CCFFCC"/>
|
||||||
|
<Interior ss:Color="#FF0000" ss:Pattern="Gray0625" ss:PatternColor="#FFFF00"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s121">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s123">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:Rotate="90"/>
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s125">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:Rotate="45"/>
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s127">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:Rotate="-90"/>
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s129">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:Rotate="-45"/>
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s130">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000" ss:Underline="Single"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s131">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000" ss:VerticalAlign="Subscript"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s132">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000" ss:Underline="Double"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s133">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000" ss:VerticalAlign="Superscript"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s134">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000" ss:Underline="SingleAccounting"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s135">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000" ss:Underline="DoubleAccounting"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s136">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s139">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#0000FF" ss:Underline="Single"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s140">
|
||||||
|
<Font ss:FontName="Sans" ss:Color="#000000"/>
|
||||||
|
<NumberFormat ss:Format="0"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s141">
|
||||||
|
<Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="12" ss:Color="#000000" ss:Bold="1"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s142">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
<NumberFormat ss:Format="0.00;[Red]0.00"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s143">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
<NumberFormat ss:Format="dd\-mmm\-yyyy"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s144">
|
||||||
|
<Font ss:FontName="Arial1" ss:Size="11" ss:Color="#000000"/>
|
||||||
|
<NumberFormat ss:Format="hh":"mm\ AM/PM"/>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s145">
|
||||||
|
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Dot" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s146">
|
||||||
|
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom"/>
|
||||||
|
<Borders>
|
||||||
|
<Border ss:Position="Bottom" ss:LineStyle="Dash" ss:Weight="1"
|
||||||
|
ss:Color="#000000"/>
|
||||||
|
</Borders>
|
||||||
|
</Style>
|
||||||
|
<Style ss:ID="s147">
|
||||||
|
<Alignment ss:Vertical="Top"/>
|
||||||
|
<Interior ss:Color="#00CCFF" ss:Pattern="HorzStripe" ss:PatternColor="#0000FF"/>
|
||||||
|
</Style>
|
||||||
|
</Styles>
|
||||||
|
<Names>
|
||||||
|
<NamedRange ss:Name="goodname" ss:RefersTo="='Sample Data'!R30C1"/>
|
||||||
|
<NamedRange ss:Name="MarksRange" ss:RefersTo="='Sample Data'!R1C2:R4C3"/>
|
||||||
|
</Names>
|
||||||
|
<Worksheet ss:Name="Sample Data">
|
||||||
|
<Table ss:ExpandedColumnCount="14" ss:ExpandedRowCount="32" x:FullColumns="1"
|
||||||
|
x:FullRows="1" ss:DefaultRowHeight="14.55">
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="96.6"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="48.6" ss:Span="1"/>
|
||||||
|
<Column ss:Index="4" ss:AutoFitWidth="0" ss:Width="36"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="48.6" ss:Span="6"/>
|
||||||
|
<Column ss:Index="12" ss:AutoFitWidth="0" ss:Width="50.4"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="48.6" ss:Span="1"/>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s63"><Data ss:Type="String">Test String 1</Data><Comment
|
||||||
|
ss:Author="Mark"><ss:Data xmlns="http://www.w3.org/TR/REC-html40"><Font
|
||||||
|
html:Face="Tahoma" html:Size="9" html:Color="#000000">Test for a simple colour-formatted string</Font></ss:Data></Comment></Cell>
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="Number">1</Data><NamedCell
|
||||||
|
ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="Number">5</Data><NamedCell
|
||||||
|
ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:Index="5" ss:StyleID="s65"><Data ss:Type="String">A</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s66"><Data ss:Type="String">E</Data></Cell>
|
||||||
|
<Cell ss:Index="8" ss:Formula="=RC[-6]+RC[-5]"><Data ss:Type="Number">6</Data></Cell>
|
||||||
|
<Cell ss:Index="10" ss:Formula="=RC[-5]&RC[-4]"><Data ss:Type="String">AE</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s65"><Data ss:Type="String">Test - String 2</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">2</Data><NamedCell ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="Number">6</Data><NamedCell
|
||||||
|
ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:Index="5"><Data ss:Type="String">B</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="String">F</Data></Cell>
|
||||||
|
<Cell ss:Index="8" ss:Formula="=RC[-6]+RC[-5]"><Data ss:Type="Number">8</Data></Cell>
|
||||||
|
<Cell ss:Index="10" ss:Formula="=RC[-5]&RC[-4]"><Data ss:Type="String">BF</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s145"><Data ss:Type="String">Dot</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s68"><Data ss:Type="String">Test #3</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="Number">3</Data><NamedCell
|
||||||
|
ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="Number">7</Data><NamedCell
|
||||||
|
ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:Index="5" ss:StyleID="s66"><Data ss:Type="String">C</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s65"><Data ss:Type="String">G</Data></Cell>
|
||||||
|
<Cell ss:Index="8" ss:Formula="=RC[-6]+RC[-5]"><Data ss:Type="Number">10</Data></Cell>
|
||||||
|
<Cell ss:Index="10" ss:Formula="=RC[-5]&RC[-4]"><Data ss:Type="String">CG</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s69"><Data ss:Type="String">Red</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s70"><Data ss:Type="String">Red</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s146"><Data ss:Type="String">Dash</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="String">Test with (") in string</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">4</Data><NamedCell ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:StyleID="s64"><Data ss:Type="Number">8</Data><NamedCell
|
||||||
|
ss:Name="MarksRange"/></Cell>
|
||||||
|
<Cell ss:Index="5" ss:StyleID="s72"><Data ss:Type="String">D</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="String">H</Data></Cell>
|
||||||
|
<Cell ss:Index="8" ss:Formula="=RC[-6]+RC[-5]"><Data ss:Type="Number">12</Data></Cell>
|
||||||
|
<Cell ss:Index="10" ss:Formula="=RC[-5]&RC[-4]"><Data ss:Type="String">DH</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s73"><Data ss:Type="String">Orange</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s74"><Data ss:Type="String">Orange</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s75"><Data ss:Type="String">Dash/Dot/Dot</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:Index="8" ss:Formula="=SUM(R[-4]C[-6]:R[-1]C[-6])"><Data
|
||||||
|
ss:Type="Number">10</Data></Cell>
|
||||||
|
<Cell ss:Formula="=SUM(R[-4]C[-6]:R[-1]C[-6])"><Data ss:Type="Number">26</Data></Cell>
|
||||||
|
<Cell ss:Formula="=SUM(R[-4]C[-8]:R[-1]C[-7])"><Data ss:Type="Number">36</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s76"><Data ss:Type="String">Yellow</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s77"><Data ss:Type="String">Yellow</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s78"><Data ss:Type="String">Dash/Dot</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s79"><Data ss:Type="String">Test #3</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">1.23</Data></Cell>
|
||||||
|
<Cell ss:Formula="=TRUE()"><Data ss:Type="Boolean">1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s80"><Data ss:Type="Boolean">1</Data></Cell>
|
||||||
|
<Cell ss:Index="8" ss:Formula="=SUM(R[-1]C+R[-2]C)"><Data ss:Type="Number">22</Data></Cell>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s81"><Data ss:Type="String">Green</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s82"><Data ss:Type="String">Green</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s83"><Data ss:Type="String">Thin Line</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s84"><Data ss:Type="String">Test #3</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">2.34</Data></Cell>
|
||||||
|
<Cell ss:Formula="=FALSE()"><Data ss:Type="Boolean">0</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Boolean">0</Data></Cell>
|
||||||
|
<Cell ss:Index="8" ss:Formula="=SUM(MarksRange)"><Data ss:Type="Number">36</Data></Cell>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s85"><Data ss:Type="String">Blue</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s86"><Data ss:Type="String">Blue</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s87"><Data ss:Type="String">Thick Dash/Dot/Dot</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s88"><Data ss:Type="String">Test #3</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">3.45</Data></Cell>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s89"><Data ss:Type="String">Purple</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s90"><Data ss:Type="String">Purple</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s87"><Data ss:Type="String">Variant Thick Dash/Dot/Dot</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="13.5">
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s91"><Data ss:Type="String">Pink</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s92"><Data ss:Type="String">Pink</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s93"><Data ss:Type="String">Thick Dash/Dot</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s80"><Data ss:Type="DateTime">1960-12-19T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="3" ss:StyleID="s94"><Data ss:Type="String">TOP</Data></Cell>
|
||||||
|
<Cell ss:Index="7"><Data ss:Type="Number">0</Data></Cell>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s95"><Data ss:Type="String">Brown</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s74"><Data ss:Type="String">Brown</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s96"><Data ss:Type="String">Thick Dash</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s97"><Data ss:Type="Number">1.5</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:Formula="=12/0"><Data ss:Type="Error">#DIV/0!</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s98"><Data ss:Type="String">Thick Line</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="13.5">
|
||||||
|
<Cell ss:Index="3" ss:StyleID="s99"><Data ss:Type="String">BOTTOM</Data></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s100"><Data ss:Type="String">Extra Thick Line</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s101"><Data ss:Type="DateTime">1899-12-31T02:30:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="6"><Data ss:Type="String">Мойва сушеная</Data><Comment
|
||||||
|
ss:Author="Mark"><ss:Data xmlns="http://www.w3.org/TR/REC-html40"><Font
|
||||||
|
html:Face="Tahoma" html:Size="9" html:Color="#000000">Tests for UTF-8 content</Font></ss:Data></Comment></Cell>
|
||||||
|
<Cell ss:Index="14" ss:StyleID="s102"><Data ss:Type="String">Double Line</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:Index="3" ss:StyleID="s103"><Data ss:Type="String">LEFT</Data></Cell>
|
||||||
|
<Cell ss:Index="6"><Data ss:Type="String">Ärendetext</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s104"><Data ss:Type="DateTime">1960-12-19T01:30:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="6"><Data ss:Type="String">Højde</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:Index="3" ss:StyleID="s105"><Data ss:Type="String">RIGHT</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="13.5"/>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="27.75">
|
||||||
|
<Cell ss:Index="2" ss:MergeAcross="1" ss:MergeDown="1"
|
||||||
|
ss:StyleID="m1867777004784"><Data ss:Type="String">BOX</Data></Cell>
|
||||||
|
<Cell ss:Index="5" ss:StyleID="s113"/>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s114"><Data ss:Type="String">Test Column 1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s114"/>
|
||||||
|
<Cell ss:StyleID="s115"/>
|
||||||
|
<Cell ss:StyleID="s116"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="27.75">
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s114"/>
|
||||||
|
<Cell ss:StyleID="s114"><Data ss:Type="String">Test Column 2</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s114"/>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s147"><Data ss:Type="String">Patterned</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s118"><Data ss:Type="String">Patterned 2</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="27.75">
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s114"/>
|
||||||
|
<Cell ss:StyleID="s114"/>
|
||||||
|
<Cell ss:StyleID="s114"><Data ss:Type="String">Test Column 3</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s62" ss:HRef="https://github.com/PHPOffice/PhpSpreadsheet"><Data
|
||||||
|
ss:Type="String">PhpSpreadsheet</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s121"><Data ss:Type="String">Underline None</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:MergeAcross="1" ss:MergeDown="4" ss:StyleID="s123"><Data
|
||||||
|
ss:Type="String">Rotate 90</Data></Cell>
|
||||||
|
<Cell ss:MergeAcross="1" ss:MergeDown="4" ss:StyleID="s125"><Data
|
||||||
|
ss:Type="String">Rotate 45</Data></Cell>
|
||||||
|
<Cell ss:MergeAcross="1" ss:MergeDown="4" ss:StyleID="s127"><Data
|
||||||
|
ss:Type="String">Rotate -90</Data></Cell>
|
||||||
|
<Cell ss:MergeAcross="1" ss:MergeDown="4" ss:StyleID="s129"><Data
|
||||||
|
ss:Type="String">Rotate -45</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s130"><Data ss:Type="String">Underline 1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s131"><Data ss:Type="String">Subscript</Data></Cell>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s132"><Data ss:Type="String">Underline 2</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s133"><Data ss:Type="String">Superscript</Data></Cell>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s134"><Data ss:Type="String">Underline 3</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s135"><Data ss:Type="String">Underline 4</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:Index="11" ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:MergeAcross="2" ss:StyleID="s136"><Data ss:Type="String">I don't know if Gnumeric supports Rich Text in the same way as Excel, And this row should be autofit height with text wrap</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
<Cell ss:StyleID="s136"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell ss:MergeAcross="2" ss:StyleID="s139"><Data ss:Type="String">Blue with underline</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15" ss:Hidden="1">
|
||||||
|
<Cell ss:StyleID="s140"><Data ss:Type="Number">5</Data><NamedCell
|
||||||
|
ss:Name="goodname"/></Cell>
|
||||||
|
<Cell ss:StyleID="s121" ss:Formula="=goodname"><Data ss:Type="Number">5</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121" ss:Formula="=@badname"><Data ss:Type="Error">#NAME?</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0">
|
||||||
|
<Cell ss:StyleID="s121"><Data ss:Type="String">Hidden row above</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0">
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
</Table>
|
||||||
|
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
|
||||||
|
<PageSetup>
|
||||||
|
<Header x:Margin="0.72"/>
|
||||||
|
<Footer x:Margin="0.72"/>
|
||||||
|
<PageMargins x:Bottom="1.2" x:Left="0.72" x:Right="0.72" x:Top="1.2"/>
|
||||||
|
</PageSetup>
|
||||||
|
<Unsynced/>
|
||||||
|
<Print>
|
||||||
|
<ValidPrinterInfo/>
|
||||||
|
<HorizontalResolution>600</HorizontalResolution>
|
||||||
|
<VerticalResolution>600</VerticalResolution>
|
||||||
|
</Print>
|
||||||
|
<Selected/>
|
||||||
|
<TopRowVisible>3</TopRowVisible>
|
||||||
|
<Panes>
|
||||||
|
<Pane>
|
||||||
|
<Number>3</Number>
|
||||||
|
<ActiveRow>18</ActiveRow>
|
||||||
|
<ActiveCol>10</ActiveCol>
|
||||||
|
</Pane>
|
||||||
|
</Panes>
|
||||||
|
<ProtectObjects>False</ProtectObjects>
|
||||||
|
<ProtectScenarios>False</ProtectScenarios>
|
||||||
|
<AllowFormatCells/>
|
||||||
|
<AllowSizeCols/>
|
||||||
|
<AllowSizeRows/>
|
||||||
|
<AllowInsertCols/>
|
||||||
|
<AllowInsertRows/>
|
||||||
|
<AllowInsertHyperlinks/>
|
||||||
|
<AllowDeleteCols/>
|
||||||
|
<AllowDeleteRows/>
|
||||||
|
<AllowSort/>
|
||||||
|
<AllowFilter/>
|
||||||
|
<AllowUsePivotTables/>
|
||||||
|
</WorksheetOptions>
|
||||||
|
</Worksheet>
|
||||||
|
<Worksheet ss:Name="Report Data">
|
||||||
|
<Table ss:ExpandedColumnCount="11" ss:ExpandedRowCount="16" x:FullColumns="1"
|
||||||
|
x:FullRows="1" ss:DefaultRowHeight="14.55">
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="56.4" ss:Span="2"/>
|
||||||
|
<Column ss:Index="4" ss:AutoFitWidth="0" ss:Width="78.599999999999994"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="58.2"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="27.6"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="78.599999999999994"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="68.399999999999991"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="48.6"/>
|
||||||
|
<Column ss:Hidden="1" ss:AutoFitWidth="0" ss:Width="48.6"/>
|
||||||
|
<Column ss:AutoFitWidth="0" ss:Width="48.6"/>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="31.5">
|
||||||
|
<Cell ss:StyleID="s141"/>
|
||||||
|
<Cell ss:StyleID="s141"/>
|
||||||
|
<Cell ss:StyleID="s141"/>
|
||||||
|
<Cell ss:StyleID="s141"/>
|
||||||
|
<Cell ss:StyleID="s141"/>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s141"/>
|
||||||
|
<Cell ss:StyleID="s141"/>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="31.5">
|
||||||
|
<Cell ss:StyleID="s141"><Data ss:Type="String">Heading 1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s141"><Data ss:Type="String">Heading 2</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s141"><Data ss:Type="String">Third Heading</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s141"><Data ss:Type="String">Date Heading</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s141"><Data ss:Type="String">Time Heading</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s141"><Data ss:Type="String">Adjusted Date</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s141"><Data ss:Type="String">Adjusted Number</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">ABC</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">1.1100000000000001</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2001-01-01T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T01:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2000-12-31T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">1.1100000000000001</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">A</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">1A</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">BCD</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">2</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">2.2200000000000002</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2002-02-02T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T02:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2002-01-31T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">4.4400000000000004</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">B</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">2B</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">CDE</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">3</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">3.33</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2003-03-03T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T03:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2003-02-28T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">9.99</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">C</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">3C</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">DEF</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">4</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">4.4400000000000004</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2004-04-03T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T04:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2004-03-30T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">17.760000000000002</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">D</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">4D</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">EFG</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">5</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">5.55</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2005-05-04T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T05:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2005-04-29T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">27.75</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">E</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">5E</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">FGH</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">6</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">6.66</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2006-06-05T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T06:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2006-05-30T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">39.96</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">F</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">6F</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">GHI</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">7</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">7.77</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2007-07-06T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T07:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2007-06-29T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">54.39</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">G</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">7G</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">HIJ</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">8</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">8.8800000000000008</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2008-08-07T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T08:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2008-07-30T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">71.040000000000006</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">H</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">8H</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">IJK</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">9</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">9.99</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2009-09-08T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T09:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2009-08-30T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">89.91</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">I</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">9I</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">JKL</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">10</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">11.1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2010-10-09T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T10:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2010-09-29T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">111</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">J</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">10J</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">KLM</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">11</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">12.21</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2011-11-11T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T11:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2011-10-31T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">134.31</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">K</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">11K</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">LMN</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">12</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">13.32</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">2012-12-12T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1900-01-12T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">2012-11-30T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">159.84</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">L</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">12L</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0" ss:Height="15">
|
||||||
|
<Cell><Data ss:Type="String">ZYX</Data></Cell>
|
||||||
|
<Cell><Data ss:Type="Number">-1</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142"><Data ss:Type="Number">-1.1100000000000001</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s143"><Data ss:Type="DateTime">1999-12-01T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s144"><Data ss:Type="DateTime">1899-12-31T23:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:Index="7" ss:StyleID="s143" ss:Formula="=RC[-3]-RC[-5]"><Data
|
||||||
|
ss:Type="DateTime">1999-12-02T00:00:00.000</Data></Cell>
|
||||||
|
<Cell ss:StyleID="s142" ss:Formula="=RC[-6]*RC[-5]"><Data ss:Type="Number">1.1100000000000001</Data></Cell>
|
||||||
|
<Cell ss:Index="10"><Data ss:Type="String">M</Data></Cell>
|
||||||
|
<Cell ss:Formula="=RC[-9]&RC[-1]"><Data ss:Type="String">-1M</Data></Cell>
|
||||||
|
</Row>
|
||||||
|
<Row ss:AutoFitHeight="0">
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
<Cell ss:StyleID="s121"/>
|
||||||
|
</Row>
|
||||||
|
</Table>
|
||||||
|
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
|
||||||
|
<PageSetup>
|
||||||
|
<Header x:Margin="0.72"/>
|
||||||
|
<Footer x:Margin="0.72"/>
|
||||||
|
<PageMargins x:Bottom="1.2" x:Left="0.72" x:Right="0.72" x:Top="1.2"/>
|
||||||
|
</PageSetup>
|
||||||
|
<Unsynced/>
|
||||||
|
<Print>
|
||||||
|
<ValidPrinterInfo/>
|
||||||
|
<NoOrientation/>
|
||||||
|
<HorizontalResolution>600</HorizontalResolution>
|
||||||
|
<VerticalResolution>600</VerticalResolution>
|
||||||
|
</Print>
|
||||||
|
<Panes>
|
||||||
|
<Pane>
|
||||||
|
<Number>3</Number>
|
||||||
|
<ActiveCol>8</ActiveCol>
|
||||||
|
<RangeSelection>R1C9:R15C11</RangeSelection>
|
||||||
|
</Pane>
|
||||||
|
</Panes>
|
||||||
|
<ProtectObjects>False</ProtectObjects>
|
||||||
|
<ProtectScenarios>False</ProtectScenarios>
|
||||||
|
<AllowFormatCells/>
|
||||||
|
<AllowSizeCols/>
|
||||||
|
<AllowSizeRows/>
|
||||||
|
<AllowInsertCols/>
|
||||||
|
<AllowInsertRows/>
|
||||||
|
<AllowInsertHyperlinks/>
|
||||||
|
<AllowDeleteCols/>
|
||||||
|
<AllowDeleteRows/>
|
||||||
|
<AllowSort/>
|
||||||
|
<AllowFilter/>
|
||||||
|
<AllowUsePivotTables/>
|
||||||
|
</WorksheetOptions>
|
||||||
|
</Worksheet>
|
||||||
|
</Workbook>
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -16,4 +16,5 @@ abstract class Category
|
||||||
const CATEGORY_MATH_AND_TRIG = 'Math and Trig';
|
const CATEGORY_MATH_AND_TRIG = 'Math and Trig';
|
||||||
const CATEGORY_STATISTICAL = 'Statistical';
|
const CATEGORY_STATISTICAL = 'Statistical';
|
||||||
const CATEGORY_TEXT_AND_DATA = 'Text and Data';
|
const CATEGORY_TEXT_AND_DATA = 'Text and Data';
|
||||||
|
const CATEGORY_WEB = 'Web';
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,7 +552,7 @@ class Database
|
||||||
* the column label in which you specify a condition for the
|
* the column label in which you specify a condition for the
|
||||||
* column.
|
* column.
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function DVAR($database, $field, $criteria)
|
public static function DVAR($database, $field, $criteria)
|
||||||
{
|
{
|
||||||
|
@ -591,7 +591,7 @@ class Database
|
||||||
* the column label in which you specify a condition for the
|
* the column label in which you specify a condition for the
|
||||||
* column.
|
* column.
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function DVARP($database, $field, $criteria)
|
public static function DVARP($database, $field, $criteria)
|
||||||
{
|
{
|
||||||
|
|
|
@ -274,9 +274,11 @@ class DateTime
|
||||||
$year = ($year !== null) ? StringHelper::testStringAsNumeric($year) : 0;
|
$year = ($year !== null) ? StringHelper::testStringAsNumeric($year) : 0;
|
||||||
$month = ($month !== null) ? StringHelper::testStringAsNumeric($month) : 0;
|
$month = ($month !== null) ? StringHelper::testStringAsNumeric($month) : 0;
|
||||||
$day = ($day !== null) ? StringHelper::testStringAsNumeric($day) : 0;
|
$day = ($day !== null) ? StringHelper::testStringAsNumeric($day) : 0;
|
||||||
if ((!is_numeric($year)) ||
|
if (
|
||||||
|
(!is_numeric($year)) ||
|
||||||
(!is_numeric($month)) ||
|
(!is_numeric($month)) ||
|
||||||
(!is_numeric($day))) {
|
(!is_numeric($day))
|
||||||
|
) {
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
$year = (int) $year;
|
$year = (int) $year;
|
||||||
|
@ -487,7 +489,7 @@ class DateTime
|
||||||
if ($yearFound) {
|
if ($yearFound) {
|
||||||
array_unshift($t1, 1);
|
array_unshift($t1, 1);
|
||||||
} else {
|
} else {
|
||||||
if ($t1[1] > 29) {
|
if (is_numeric($t1[1]) && $t1[1] > 29) {
|
||||||
$t1[1] += 1900;
|
$t1[1] += 1900;
|
||||||
array_unshift($t1, 1);
|
array_unshift($t1, 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -668,30 +670,19 @@ class DateTime
|
||||||
$endMonths = $PHPEndDateObject->format('n');
|
$endMonths = $PHPEndDateObject->format('n');
|
||||||
$endYears = $PHPEndDateObject->format('Y');
|
$endYears = $PHPEndDateObject->format('Y');
|
||||||
|
|
||||||
|
$PHPDiffDateObject = $PHPEndDateObject->diff($PHPStartDateObject);
|
||||||
|
|
||||||
switch ($unit) {
|
switch ($unit) {
|
||||||
case 'D':
|
case 'D':
|
||||||
$retVal = (int) $difference;
|
$retVal = (int) $difference;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
$retVal = (int) ($endMonths - $startMonths) + ((int) ($endYears - $startYears) * 12);
|
$retVal = (int) 12 * $PHPDiffDateObject->format('%y') + $PHPDiffDateObject->format('%m');
|
||||||
// We're only interested in full months
|
|
||||||
if ($endDays < $startDays) {
|
|
||||||
--$retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Y':
|
case 'Y':
|
||||||
$retVal = (int) ($endYears - $startYears);
|
$retVal = (int) $PHPDiffDateObject->format('%y');
|
||||||
// We're only interested in full months
|
|
||||||
if ($endMonths < $startMonths) {
|
|
||||||
--$retVal;
|
|
||||||
} elseif (($endMonths == $startMonths) && ($endDays < $startDays)) {
|
|
||||||
// Remove start month
|
|
||||||
--$retVal;
|
|
||||||
// Remove end month
|
|
||||||
--$retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'MD':
|
case 'MD':
|
||||||
|
@ -701,19 +692,12 @@ class DateTime
|
||||||
$adjustDays = $PHPEndDateObject->format('j');
|
$adjustDays = $PHPEndDateObject->format('j');
|
||||||
$retVal += ($adjustDays - $startDays);
|
$retVal += ($adjustDays - $startDays);
|
||||||
} else {
|
} else {
|
||||||
$retVal = $endDays - $startDays;
|
$retVal = (int) $PHPDiffDateObject->format('%d');
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'YM':
|
case 'YM':
|
||||||
$retVal = (int) ($endMonths - $startMonths);
|
$retVal = (int) $PHPDiffDateObject->format('%m');
|
||||||
if ($retVal < 0) {
|
|
||||||
$retVal += 12;
|
|
||||||
}
|
|
||||||
// We're only interested in full months
|
|
||||||
if ($endDays < $startDays) {
|
|
||||||
--$retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'YD':
|
case 'YD':
|
||||||
|
|
|
@ -106,6 +106,20 @@ class Logger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a series of entries to the calculation engine debug log.
|
||||||
|
*
|
||||||
|
* @param string[] $args
|
||||||
|
*/
|
||||||
|
public function mergeDebugLog(array $args): void
|
||||||
|
{
|
||||||
|
if ($this->writeDebugLog) {
|
||||||
|
foreach ($args as $entry) {
|
||||||
|
$this->writeDebugLog($entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the calculation engine debug log.
|
* Clear the calculation engine debug log.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1674,7 +1674,8 @@ class Engineering
|
||||||
$imaginary = ($imaginary === null) ? 0.0 : Functions::flattenSingleValue($imaginary);
|
$imaginary = ($imaginary === null) ? 0.0 : Functions::flattenSingleValue($imaginary);
|
||||||
$suffix = ($suffix === null) ? 'i' : Functions::flattenSingleValue($suffix);
|
$suffix = ($suffix === null) ? 'i' : Functions::flattenSingleValue($suffix);
|
||||||
|
|
||||||
if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
|
if (
|
||||||
|
((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
|
||||||
(($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
|
(($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
|
||||||
) {
|
) {
|
||||||
$complex = new Complex($realNumber, $imaginary, $suffix);
|
$complex = new Complex($realNumber, $imaginary, $suffix);
|
||||||
|
@ -2729,11 +2730,13 @@ class Engineering
|
||||||
}
|
}
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
} elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
|
} elseif (
|
||||||
|
(($fromUOM == 'K') || ($fromUOM == 'kel')) &&
|
||||||
(($toUOM == 'K') || ($toUOM == 'kel'))
|
(($toUOM == 'K') || ($toUOM == 'kel'))
|
||||||
) {
|
) {
|
||||||
return $value;
|
return $value;
|
||||||
} elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
|
} elseif (
|
||||||
|
(($fromUOM == 'C') || ($fromUOM == 'cel')) &&
|
||||||
(($toUOM == 'C') || ($toUOM == 'cel'))
|
(($toUOM == 'C') || ($toUOM == 'cel'))
|
||||||
) {
|
) {
|
||||||
return $value;
|
return $value;
|
||||||
|
|
|
@ -395,9 +395,11 @@ class Financial
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($settlement >= $maturity) ||
|
if (
|
||||||
|
($settlement >= $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,9 +454,11 @@ class Financial
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($settlement >= $maturity) ||
|
if (
|
||||||
|
($settlement >= $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,9 +524,11 @@ class Financial
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($settlement >= $maturity) ||
|
if (
|
||||||
|
($settlement >= $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,9 +580,11 @@ class Financial
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($settlement >= $maturity) ||
|
if (
|
||||||
|
($settlement >= $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,9 +633,11 @@ class Financial
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($settlement >= $maturity) ||
|
if (
|
||||||
|
($settlement >= $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,9 +688,11 @@ class Financial
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($settlement >= $maturity) ||
|
if (
|
||||||
|
($settlement >= $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,9 +1631,11 @@ class Financial
|
||||||
$frequency = (int) $frequency;
|
$frequency = (int) $frequency;
|
||||||
$basis = (int) $basis;
|
$basis = (int) $basis;
|
||||||
|
|
||||||
if (($settlement > $maturity) ||
|
if (
|
||||||
|
($settlement > $maturity) ||
|
||||||
(!self::isValidFrequency($frequency)) ||
|
(!self::isValidFrequency($frequency)) ||
|
||||||
(($basis < 0) || ($basis > 4))) {
|
(($basis < 0) || ($basis > 4))
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -490,11 +490,13 @@ class FormulaParser
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(
|
if (
|
||||||
|
!(
|
||||||
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)
|
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
)) {
|
)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,11 +504,13 @@ class FormulaParser
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(
|
if (
|
||||||
|
!(
|
||||||
(($nextToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_START)) ||
|
(($nextToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_START)) ||
|
||||||
(($nextToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_START)) ||
|
(($nextToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_START)) ||
|
||||||
($nextToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)
|
($nextToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
)) {
|
)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,12 +542,14 @@ class FormulaParser
|
||||||
if ($token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == '-') {
|
if ($token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == '-') {
|
||||||
if ($i == 0) {
|
if ($i == 0) {
|
||||||
$token->setTokenType(FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
|
$token->setTokenType(FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
|
||||||
} elseif ((($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) &&
|
} elseif (
|
||||||
|
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) &&
|
||||||
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) &&
|
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) &&
|
||||||
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
|
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
|
||||||
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)) {
|
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
|
) {
|
||||||
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_MATH);
|
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_MATH);
|
||||||
} else {
|
} else {
|
||||||
$token->setTokenType(FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
|
$token->setTokenType(FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
|
||||||
|
@ -557,12 +563,14 @@ class FormulaParser
|
||||||
if ($token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == '+') {
|
if ($token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == '+') {
|
||||||
if ($i == 0) {
|
if ($i == 0) {
|
||||||
continue;
|
continue;
|
||||||
} elseif ((($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) &&
|
} elseif (
|
||||||
|
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_FUNCTION) &&
|
||||||
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) &&
|
(($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_SUBEXPRESSION) &&
|
||||||
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
($previousToken->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
|
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
|
||||||
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)) {
|
($previousToken->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
|
) {
|
||||||
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_MATH);
|
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_MATH);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -573,8 +581,10 @@ class FormulaParser
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORINFIX &&
|
if (
|
||||||
$token->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_NOTHING) {
|
$token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERATORINFIX &&
|
||||||
|
$token->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_NOTHING
|
||||||
|
) {
|
||||||
if (strpos('<>=', substr($token->getValue(), 0, 1)) !== false) {
|
if (strpos('<>=', substr($token->getValue(), 0, 1)) !== false) {
|
||||||
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
||||||
} elseif ($token->getValue() == '&') {
|
} elseif ($token->getValue() == '&') {
|
||||||
|
@ -588,8 +598,10 @@ class FormulaParser
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND &&
|
if (
|
||||||
$token->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_NOTHING) {
|
$token->getTokenType() == FormulaToken::TOKEN_TYPE_OPERAND &&
|
||||||
|
$token->getTokenSubType() == FormulaToken::TOKEN_SUBTYPE_NOTHING
|
||||||
|
) {
|
||||||
if (!is_numeric($token->getValue())) {
|
if (!is_numeric($token->getValue())) {
|
||||||
if (strtoupper($token->getValue()) == 'TRUE' || strtoupper($token->getValue()) == 'FALSE') {
|
if (strtoupper($token->getValue()) == 'TRUE' || strtoupper($token->getValue()) == 'FALSE') {
|
||||||
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
$token->setTokenSubType(FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
||||||
|
|
|
@ -67,7 +67,8 @@ class Functions
|
||||||
*/
|
*/
|
||||||
public static function setCompatibilityMode($compatibilityMode)
|
public static function setCompatibilityMode($compatibilityMode)
|
||||||
{
|
{
|
||||||
if (($compatibilityMode == self::COMPATIBILITY_EXCEL) ||
|
if (
|
||||||
|
($compatibilityMode == self::COMPATIBILITY_EXCEL) ||
|
||||||
($compatibilityMode == self::COMPATIBILITY_GNUMERIC) ||
|
($compatibilityMode == self::COMPATIBILITY_GNUMERIC) ||
|
||||||
($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)
|
($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)
|
||||||
) {
|
) {
|
||||||
|
@ -106,7 +107,8 @@ class Functions
|
||||||
*/
|
*/
|
||||||
public static function setReturnDateType($returnDateType)
|
public static function setReturnDateType($returnDateType)
|
||||||
{
|
{
|
||||||
if (($returnDateType == self::RETURNDATE_UNIX_TIMESTAMP) ||
|
if (
|
||||||
|
($returnDateType == self::RETURNDATE_UNIX_TIMESTAMP) ||
|
||||||
($returnDateType == self::RETURNDATE_PHP_DATETIME_OBJECT) ||
|
($returnDateType == self::RETURNDATE_PHP_DATETIME_OBJECT) ||
|
||||||
($returnDateType == self::RETURNDATE_EXCEL)
|
($returnDateType == self::RETURNDATE_EXCEL)
|
||||||
) {
|
) {
|
||||||
|
@ -645,7 +647,7 @@ class Functions
|
||||||
preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellReference, $matches);
|
preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellReference, $matches);
|
||||||
|
|
||||||
$cellReference = $matches[6] . $matches[7];
|
$cellReference = $matches[6] . $matches[7];
|
||||||
$worksheetName = trim($matches[3], "'");
|
$worksheetName = str_replace("''", "'", trim($matches[2], "'"));
|
||||||
|
|
||||||
$worksheet = (!empty($worksheetName))
|
$worksheet = (!empty($worksheetName))
|
||||||
? $pCell->getWorksheet()->getParent()->getSheetByName($worksheetName)
|
? $pCell->getWorksheet()->getParent()->getSheetByName($worksheetName)
|
||||||
|
|
|
@ -352,4 +352,39 @@ class Logical
|
||||||
|
|
||||||
return self::statementIf(Functions::isNa($testValue), $napart, $testValue);
|
return self::statementIf(Functions::isNa($testValue), $napart, $testValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IFS.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* =IFS(testValue1;returnIfTrue1;testValue2;returnIfTrue2;...;testValue_n;returnIfTrue_n)
|
||||||
|
*
|
||||||
|
* testValue1 ... testValue_n
|
||||||
|
* Conditions to Evaluate
|
||||||
|
* returnIfTrue1 ... returnIfTrue_n
|
||||||
|
* Value returned if corresponding testValue (nth) was true
|
||||||
|
*
|
||||||
|
* @param mixed ...$arguments Statement arguments
|
||||||
|
*
|
||||||
|
* @return mixed|string The value of returnIfTrue_n, if testValue_n was true. #N/A if none of testValues was true
|
||||||
|
*/
|
||||||
|
public static function IFS(...$arguments)
|
||||||
|
{
|
||||||
|
if (count($arguments) % 2 != 0) {
|
||||||
|
return Functions::NA();
|
||||||
|
}
|
||||||
|
// We use instance of Exception as a falseValue in order to prevent string collision with value in cell
|
||||||
|
$falseValueException = new Exception();
|
||||||
|
for ($i = 0; $i < count($arguments); $i += 2) {
|
||||||
|
$testValue = ($arguments[$i] === null) ? '' : Functions::flattenSingleValue($arguments[$i]);
|
||||||
|
$returnIfTrue = ($arguments[$i + 1] === null) ? '' : Functions::flattenSingleValue($arguments[$i + 1]);
|
||||||
|
$result = self::statementIf($testValue, $returnIfTrue, $falseValueException);
|
||||||
|
|
||||||
|
if ($result !== $falseValueException) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::NA();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ class LookupRef
|
||||||
*
|
*
|
||||||
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns
|
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns
|
||||||
*
|
*
|
||||||
* @return int The number of columns in cellAddress
|
* @return int|string The number of columns in cellAddress, or a string if arguments are invalid
|
||||||
*/
|
*/
|
||||||
public static function COLUMNS($cellAddress = null)
|
public static function COLUMNS($cellAddress = null)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ class LookupRef
|
||||||
*
|
*
|
||||||
* @param null|array|string $cellAddress A reference to a range of cells for which you want the row numbers
|
* @param null|array|string $cellAddress A reference to a range of cells for which you want the row numbers
|
||||||
*
|
*
|
||||||
* @return int or array of integer
|
* @return int|mixed[]|string
|
||||||
*/
|
*/
|
||||||
public static function ROW($cellAddress = null)
|
public static function ROW($cellAddress = null)
|
||||||
{
|
{
|
||||||
|
@ -203,7 +203,7 @@ class LookupRef
|
||||||
*
|
*
|
||||||
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows
|
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows
|
||||||
*
|
*
|
||||||
* @return int The number of rows in cellAddress
|
* @return int|string The number of rows in cellAddress, or a string if arguments are invalid
|
||||||
*/
|
*/
|
||||||
public static function ROWS($cellAddress = null)
|
public static function ROWS($cellAddress = null)
|
||||||
{
|
{
|
||||||
|
@ -286,9 +286,11 @@ class LookupRef
|
||||||
[$cellAddress1, $cellAddress2] = explode(':', $cellAddress);
|
[$cellAddress1, $cellAddress2] = explode(':', $cellAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress1, $matches)) ||
|
if (
|
||||||
(($cellAddress2 !== null) && (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress2, $matches)))) {
|
(!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress1, $matches)) ||
|
||||||
if (!preg_match('/^' . Calculation::CALCULATION_REGEXP_NAMEDRANGE . '$/i', $cellAddress1, $matches)) {
|
(($cellAddress2 !== null) && (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress2, $matches)))
|
||||||
|
) {
|
||||||
|
if (!preg_match('/^' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '$/i', $cellAddress1, $matches)) {
|
||||||
return Functions::REF();
|
return Functions::REF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,10 +487,18 @@ class LookupRef
|
||||||
return Functions::NA();
|
return Functions::NA();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($matchType == 1) {
|
||||||
|
// If match_type is 1 the list has to be processed from last to first
|
||||||
|
|
||||||
|
$lookupArray = array_reverse($lookupArray);
|
||||||
|
$keySet = array_reverse(array_keys($lookupArray));
|
||||||
|
}
|
||||||
|
|
||||||
// Lookup_array should contain only number, text, or logical values, or empty (null) cells
|
// Lookup_array should contain only number, text, or logical values, or empty (null) cells
|
||||||
foreach ($lookupArray as $i => $lookupArrayValue) {
|
foreach ($lookupArray as $i => $lookupArrayValue) {
|
||||||
// check the type of the value
|
// check the type of the value
|
||||||
if ((!is_numeric($lookupArrayValue)) && (!is_string($lookupArrayValue)) &&
|
if (
|
||||||
|
(!is_numeric($lookupArrayValue)) && (!is_string($lookupArrayValue)) &&
|
||||||
(!is_bool($lookupArrayValue)) && ($lookupArrayValue !== null)
|
(!is_bool($lookupArrayValue)) && ($lookupArrayValue !== null)
|
||||||
) {
|
) {
|
||||||
return Functions::NA();
|
return Functions::NA();
|
||||||
|
@ -498,24 +508,17 @@ class LookupRef
|
||||||
$lookupArray[$i] = StringHelper::strToLower($lookupArrayValue);
|
$lookupArray[$i] = StringHelper::strToLower($lookupArrayValue);
|
||||||
}
|
}
|
||||||
if (($lookupArrayValue === null) && (($matchType == 1) || ($matchType == -1))) {
|
if (($lookupArrayValue === null) && (($matchType == 1) || ($matchType == -1))) {
|
||||||
$lookupArray = array_slice($lookupArray, 0, $i - 1);
|
unset($lookupArray[$i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($matchType == 1) {
|
|
||||||
// If match_type is 1 the list has to be processed from last to first
|
|
||||||
|
|
||||||
$lookupArray = array_reverse($lookupArray);
|
|
||||||
$keySet = array_reverse(array_keys($lookupArray));
|
|
||||||
}
|
|
||||||
|
|
||||||
// **
|
// **
|
||||||
// find the match
|
// find the match
|
||||||
// **
|
// **
|
||||||
|
|
||||||
if ($matchType === 0 || $matchType === 1) {
|
if ($matchType === 0 || $matchType === 1) {
|
||||||
foreach ($lookupArray as $i => $lookupArrayValue) {
|
foreach ($lookupArray as $i => $lookupArrayValue) {
|
||||||
$typeMatch = gettype($lookupValue) === gettype($lookupArrayValue);
|
$typeMatch = ((gettype($lookupValue) === gettype($lookupArrayValue)) || (is_numeric($lookupValue) && is_numeric($lookupArrayValue)));
|
||||||
$exactTypeMatch = $typeMatch && $lookupArrayValue === $lookupValue;
|
$exactTypeMatch = $typeMatch && $lookupArrayValue === $lookupValue;
|
||||||
$nonOnlyNumericExactMatch = !$typeMatch && $lookupArrayValue === $lookupValue;
|
$nonOnlyNumericExactMatch = !$typeMatch && $lookupArrayValue === $lookupValue;
|
||||||
$exactMatch = $exactTypeMatch || $nonOnlyNumericExactMatch;
|
$exactMatch = $exactTypeMatch || $nonOnlyNumericExactMatch;
|
||||||
|
@ -750,18 +753,23 @@ class LookupRef
|
||||||
$firstLower = StringHelper::strToLower($rowData[$firstColumn]);
|
$firstLower = StringHelper::strToLower($rowData[$firstColumn]);
|
||||||
|
|
||||||
// break if we have passed possible keys
|
// break if we have passed possible keys
|
||||||
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) ||
|
if (
|
||||||
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && ($firstLower > $lookupLower))) {
|
(is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) ||
|
||||||
|
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && ($firstLower > $lookupLower))
|
||||||
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// remember the last key, but only if datatypes match
|
// remember the last key, but only if datatypes match
|
||||||
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn])) ||
|
if (
|
||||||
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]))) {
|
(is_numeric($lookup_value) && is_numeric($rowData[$firstColumn])) ||
|
||||||
|
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]))
|
||||||
|
) {
|
||||||
if ($not_exact_match) {
|
if ($not_exact_match) {
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} elseif (($firstLower == $lookupLower)
|
} elseif (
|
||||||
|
($firstLower == $lookupLower)
|
||||||
// Spreadsheets software returns first exact match,
|
// Spreadsheets software returns first exact match,
|
||||||
// we have sorted and we might have broken key orders
|
// we have sorted and we might have broken key orders
|
||||||
// we want the first one (by its initial index)
|
// we want the first one (by its initial index)
|
||||||
|
@ -807,7 +815,7 @@ class LookupRef
|
||||||
return Functions::REF();
|
return Functions::REF();
|
||||||
}
|
}
|
||||||
$f = array_keys($lookup_array);
|
$f = array_keys($lookup_array);
|
||||||
$firstRow = array_pop($f);
|
$firstRow = reset($f);
|
||||||
if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array))) {
|
if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array))) {
|
||||||
return Functions::REF();
|
return Functions::REF();
|
||||||
}
|
}
|
||||||
|
@ -823,10 +831,12 @@ class LookupRef
|
||||||
$lookupLower = StringHelper::strToLower($lookup_value);
|
$lookupLower = StringHelper::strToLower($lookup_value);
|
||||||
$rowDataLower = StringHelper::strToLower($rowData);
|
$rowDataLower = StringHelper::strToLower($rowData);
|
||||||
|
|
||||||
if ($not_exact_match && (
|
if (
|
||||||
|
$not_exact_match && (
|
||||||
($bothNumeric && $rowData > $lookup_value) ||
|
($bothNumeric && $rowData > $lookup_value) ||
|
||||||
($bothNotNumeric && $rowDataLower > $lookupLower)
|
($bothNotNumeric && $rowDataLower > $lookupLower)
|
||||||
)) {
|
)
|
||||||
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,7 +846,8 @@ class LookupRef
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} elseif ($rowDataLower === $lookupLower
|
} elseif (
|
||||||
|
$rowDataLower === $lookupLower
|
||||||
&& ($rowNumber === null || $rowKey < $rowNumber)
|
&& ($rowNumber === null || $rowKey < $rowNumber)
|
||||||
) {
|
) {
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
|
|
|
@ -147,8 +147,10 @@ class MathTrig
|
||||||
$xCoordinate = ($xCoordinate !== null) ? $xCoordinate : 0.0;
|
$xCoordinate = ($xCoordinate !== null) ? $xCoordinate : 0.0;
|
||||||
$yCoordinate = ($yCoordinate !== null) ? $yCoordinate : 0.0;
|
$yCoordinate = ($yCoordinate !== null) ? $yCoordinate : 0.0;
|
||||||
|
|
||||||
if (((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) &&
|
if (
|
||||||
((is_numeric($yCoordinate))) || (is_bool($yCoordinate))) {
|
((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) &&
|
||||||
|
((is_numeric($yCoordinate))) || (is_bool($yCoordinate))
|
||||||
|
) {
|
||||||
$xCoordinate = (float) $xCoordinate;
|
$xCoordinate = (float) $xCoordinate;
|
||||||
$yCoordinate = (float) $yCoordinate;
|
$yCoordinate = (float) $yCoordinate;
|
||||||
|
|
||||||
|
@ -224,8 +226,10 @@ class MathTrig
|
||||||
$number = Functions::flattenSingleValue($number);
|
$number = Functions::flattenSingleValue($number);
|
||||||
$significance = Functions::flattenSingleValue($significance);
|
$significance = Functions::flattenSingleValue($significance);
|
||||||
|
|
||||||
if (($significance === null) &&
|
if (
|
||||||
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) {
|
($significance === null) &&
|
||||||
|
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)
|
||||||
|
) {
|
||||||
$significance = $number / abs($number);
|
$significance = $number / abs($number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,8 +335,10 @@ class MathTrig
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
$factLoop = floor($factVal);
|
$factLoop = floor($factVal);
|
||||||
if ((Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) &&
|
if (
|
||||||
($factVal > $factLoop)) {
|
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) &&
|
||||||
|
($factVal > $factLoop)
|
||||||
|
) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,8 +404,10 @@ class MathTrig
|
||||||
$number = Functions::flattenSingleValue($number);
|
$number = Functions::flattenSingleValue($number);
|
||||||
$significance = Functions::flattenSingleValue($significance);
|
$significance = Functions::flattenSingleValue($significance);
|
||||||
|
|
||||||
if (($significance === null) &&
|
if (
|
||||||
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) {
|
($significance === null) &&
|
||||||
|
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)
|
||||||
|
) {
|
||||||
$significance = $number / abs($number);
|
$significance = $number / abs($number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,7 +871,7 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the ratio of the factorial of a sum of values to the product of factorials.
|
* Returns the ratio of the factorial of a sum of values to the product of factorials.
|
||||||
*
|
*
|
||||||
* @param array of mixed Data Series
|
* @param mixed[] $args An array of mixed values for the Data Series
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
|
@ -1141,7 +1149,7 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the sum of a power series
|
* Returns the sum of a power series
|
||||||
*
|
*
|
||||||
* @param array of mixed Data Series
|
* @param mixed[] $args An array of mixed values for the Data Series
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
|
@ -1265,21 +1273,22 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns a subtotal in a list or database.
|
* Returns a subtotal in a list or database.
|
||||||
*
|
*
|
||||||
* @param int the number 1 to 11 that specifies which function to
|
* @param int $functionType
|
||||||
|
* A number 1 to 11 that specifies which function to
|
||||||
* use in calculating subtotals within a range
|
* use in calculating subtotals within a range
|
||||||
* list
|
* list
|
||||||
* Numbers 101 to 111 shadow the functions of 1 to 11
|
* Numbers 101 to 111 shadow the functions of 1 to 11
|
||||||
* but ignore any values in the range that are
|
* but ignore any values in the range that are
|
||||||
* in hidden rows or columns
|
* in hidden rows or columns
|
||||||
* @param array of mixed Data Series
|
* @param mixed[] $args A mixed data series of values
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function SUBTOTAL(...$args)
|
public static function SUBTOTAL($functionType, ...$args)
|
||||||
{
|
{
|
||||||
$cellReference = array_pop($args);
|
$cellReference = array_pop($args);
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
$subtotal = array_shift($aArgs);
|
$subtotal = Functions::flattenSingleValue($functionType);
|
||||||
|
|
||||||
// Calculate
|
// Calculate
|
||||||
if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
|
if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
|
||||||
|
@ -1381,8 +1390,10 @@ class MathTrig
|
||||||
$testCondition = '=' . $arg . $condition;
|
$testCondition = '=' . $arg . $condition;
|
||||||
$sumValue = array_key_exists($key, $sumArgs) ? $sumArgs[$key] : 0;
|
$sumValue = array_key_exists($key, $sumArgs) ? $sumArgs[$key] : 0;
|
||||||
|
|
||||||
if (is_numeric($sumValue) &&
|
if (
|
||||||
Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
|
is_numeric($sumValue) &&
|
||||||
|
Calculation::getInstance()->_calculateFormulaValue($testCondition)
|
||||||
|
) {
|
||||||
// Is it a value within our criteria and only numeric can be added to the result
|
// Is it a value within our criteria and only numeric can be added to the result
|
||||||
$returnValue += $sumValue;
|
$returnValue += $sumValue;
|
||||||
}
|
}
|
||||||
|
@ -1532,8 +1543,10 @@ class MathTrig
|
||||||
|
|
||||||
$result = 0;
|
$result = 0;
|
||||||
for ($i = 0; $i < $count; ++$i) {
|
for ($i = 0; $i < $count; ++$i) {
|
||||||
if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
|
if (
|
||||||
((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
|
((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
|
||||||
|
((is_numeric($array2[$i])) && (!is_string($array2[$i])))
|
||||||
|
) {
|
||||||
$result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]);
|
$result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1557,8 +1570,10 @@ class MathTrig
|
||||||
|
|
||||||
$result = 0;
|
$result = 0;
|
||||||
for ($i = 0; $i < $count; ++$i) {
|
for ($i = 0; $i < $count; ++$i) {
|
||||||
if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
|
if (
|
||||||
((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
|
((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
|
||||||
|
((is_numeric($array2[$i])) && (!is_string($array2[$i])))
|
||||||
|
) {
|
||||||
$result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]);
|
$result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1582,8 +1597,10 @@ class MathTrig
|
||||||
|
|
||||||
$result = 0;
|
$result = 0;
|
||||||
for ($i = 0; $i < $count; ++$i) {
|
for ($i = 0; $i < $count; ++$i) {
|
||||||
if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
|
if (
|
||||||
((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
|
((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
|
||||||
|
((is_numeric($array2[$i])) && (!is_string($array2[$i])))
|
||||||
|
) {
|
||||||
$result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]);
|
$result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -530,9 +530,11 @@ class Statistical
|
||||||
*/
|
*/
|
||||||
private static function testAcceptedBoolean($arg, $k)
|
private static function testAcceptedBoolean($arg, $k)
|
||||||
{
|
{
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
|
(is_bool($arg)) &&
|
||||||
((!Functions::isCellValue($k) && (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_EXCEL)) ||
|
((!Functions::isCellValue($k) && (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_EXCEL)) ||
|
||||||
(Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE))) {
|
(Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE))
|
||||||
|
) {
|
||||||
$arg = (int) $arg;
|
$arg = (int) $arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,9 +549,11 @@ class Statistical
|
||||||
*/
|
*/
|
||||||
private static function isAcceptedCountable($arg, $k)
|
private static function isAcceptedCountable($arg, $k)
|
||||||
{
|
{
|
||||||
if (((is_numeric($arg)) && (!is_string($arg))) ||
|
if (
|
||||||
|
((is_numeric($arg)) && (!is_string($arg))) ||
|
||||||
((is_numeric($arg)) && (!Functions::isCellValue($k)) &&
|
((is_numeric($arg)) && (!Functions::isCellValue($k)) &&
|
||||||
(Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_GNUMERIC))) {
|
(Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_GNUMERIC))
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,8 +668,10 @@ class Statistical
|
||||||
$aCount = 0;
|
$aCount = 0;
|
||||||
// Loop through arguments
|
// Loop through arguments
|
||||||
foreach (Functions::flattenArrayIndexed($args) as $k => $arg) {
|
foreach (Functions::flattenArrayIndexed($args) as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_bool($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
|
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
|
||||||
if (is_bool($arg)) {
|
if (is_bool($arg)) {
|
||||||
|
@ -779,7 +785,7 @@ class Statistical
|
||||||
/**
|
/**
|
||||||
* BETAINV.
|
* BETAINV.
|
||||||
*
|
*
|
||||||
* Returns the inverse of the beta distribution.
|
* Returns the inverse of the Beta distribution.
|
||||||
*
|
*
|
||||||
* @param float $probability Probability at which you want to evaluate the distribution
|
* @param float $probability Probability at which you want to evaluate the distribution
|
||||||
* @param float $alpha Parameter to the distribution
|
* @param float $alpha Parameter to the distribution
|
||||||
|
@ -1414,9 +1420,11 @@ class Statistical
|
||||||
$aCount = -1;
|
$aCount = -1;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
|
(is_bool($arg)) &&
|
||||||
((!Functions::isCellValue($k)) ||
|
((!Functions::isCellValue($k)) ||
|
||||||
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
|
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))
|
||||||
|
) {
|
||||||
$arg = (int) $arg;
|
$arg = (int) $arg;
|
||||||
}
|
}
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
@ -1437,7 +1445,7 @@ class Statistical
|
||||||
return $returnValue;
|
return $returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::NA();
|
return Functions::NA();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1475,6 +1483,62 @@ class Statistical
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function betaFunction($a, $b)
|
||||||
|
{
|
||||||
|
return (self::gamma($a) * self::gamma($b)) / self::gamma($a + $b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function regularizedIncompleteBeta($value, $a, $b)
|
||||||
|
{
|
||||||
|
return self::incompleteBeta($value, $a, $b) / self::betaFunction($a, $b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.DIST.
|
||||||
|
*
|
||||||
|
* Returns the F probability distribution.
|
||||||
|
* You can use this function to determine whether two data sets have different degrees of diversity.
|
||||||
|
* For example, you can examine the test scores of men and women entering high school, and determine
|
||||||
|
* if the variability in the females is different from that found in the males.
|
||||||
|
*
|
||||||
|
* @param float $value Value of the function
|
||||||
|
* @param int $u The numerator degrees of freedom
|
||||||
|
* @param int $v The denominator degrees of freedom
|
||||||
|
* @param bool $cumulative If cumulative is TRUE, F.DIST returns the cumulative distribution function;
|
||||||
|
* if FALSE, it returns the probability density function.
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function FDIST2($value, $u, $v, $cumulative)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
$u = Functions::flattenSingleValue($u);
|
||||||
|
$v = Functions::flattenSingleValue($v);
|
||||||
|
$cumulative = Functions::flattenSingleValue($cumulative);
|
||||||
|
|
||||||
|
if (is_numeric($value) && is_numeric($u) && is_numeric($v)) {
|
||||||
|
if ($value < 0 || $u < 1 || $v < 1) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
$cumulative = (bool) $cumulative;
|
||||||
|
$u = (int) $u;
|
||||||
|
$v = (int) $v;
|
||||||
|
|
||||||
|
if ($cumulative) {
|
||||||
|
$adjustedValue = ($u * $value) / ($u * $value + $v);
|
||||||
|
|
||||||
|
return self::incompleteBeta($adjustedValue, $u / 2, $v / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (self::gamma(($v + $u) / 2) / (self::gamma($u / 2) * self::gamma($v / 2))) *
|
||||||
|
(($u / $v) ** ($u / 2)) *
|
||||||
|
(($value ** (($u - 2) / 2)) / ((1 + ($u / $v) * $value) ** (($u + $v) / 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FISHER.
|
* FISHER.
|
||||||
*
|
*
|
||||||
|
@ -1556,6 +1620,27 @@ class Statistical
|
||||||
return $bestFitLinear->getValueOfYForX($xValue);
|
return $bestFitLinear->getValueOfYForX($xValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GAMMA.
|
||||||
|
*
|
||||||
|
* Return the gamma function value.
|
||||||
|
*
|
||||||
|
* @param float $value
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function GAMMAFunction($value)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
if (!is_numeric($value)) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
} elseif ((((int) $value) == ((float) $value)) && $value <= 0.0) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::gamma($value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GAMMADIST.
|
* GAMMADIST.
|
||||||
*
|
*
|
||||||
|
@ -1593,7 +1678,7 @@ class Statistical
|
||||||
/**
|
/**
|
||||||
* GAMMAINV.
|
* GAMMAINV.
|
||||||
*
|
*
|
||||||
* Returns the inverse of the beta distribution.
|
* Returns the inverse of the Gamma distribution.
|
||||||
*
|
*
|
||||||
* @param float $probability Probability at which you want to evaluate the distribution
|
* @param float $probability Probability at which you want to evaluate the distribution
|
||||||
* @param float $alpha Parameter to the distribution
|
* @param float $alpha Parameter to the distribution
|
||||||
|
@ -1616,7 +1701,6 @@ class Statistical
|
||||||
$xHi = $alpha * $beta * 5;
|
$xHi = $alpha * $beta * 5;
|
||||||
|
|
||||||
$x = $xNew = 1;
|
$x = $xNew = 1;
|
||||||
$error = $pdf = 0;
|
|
||||||
$dx = 1024;
|
$dx = 1024;
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
|
||||||
|
@ -1677,6 +1761,26 @@ class Statistical
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GAUSS.
|
||||||
|
*
|
||||||
|
* Calculates the probability that a member of a standard normal population will fall between
|
||||||
|
* the mean and z standard deviations from the mean.
|
||||||
|
*
|
||||||
|
* @param float $value
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function GAUSS($value)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
if (!is_numeric($value)) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::NORMDIST($value, 0, 1, true) - 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GEOMEAN.
|
* GEOMEAN.
|
||||||
*
|
*
|
||||||
|
@ -1796,12 +1900,17 @@ class Statistical
|
||||||
*/
|
*/
|
||||||
public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
|
public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
|
||||||
{
|
{
|
||||||
$sampleSuccesses = floor(Functions::flattenSingleValue($sampleSuccesses));
|
$sampleSuccesses = Functions::flattenSingleValue($sampleSuccesses);
|
||||||
$sampleNumber = floor(Functions::flattenSingleValue($sampleNumber));
|
$sampleNumber = Functions::flattenSingleValue($sampleNumber);
|
||||||
$populationSuccesses = floor(Functions::flattenSingleValue($populationSuccesses));
|
$populationSuccesses = Functions::flattenSingleValue($populationSuccesses);
|
||||||
$populationNumber = floor(Functions::flattenSingleValue($populationNumber));
|
$populationNumber = Functions::flattenSingleValue($populationNumber);
|
||||||
|
|
||||||
if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
|
if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
|
||||||
|
$sampleSuccesses = floor($sampleSuccesses);
|
||||||
|
$sampleNumber = floor($sampleNumber);
|
||||||
|
$populationSuccesses = floor($populationSuccesses);
|
||||||
|
$populationNumber = floor($populationNumber);
|
||||||
|
|
||||||
if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
|
if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
@ -1871,8 +1980,10 @@ class Statistical
|
||||||
$count = $summer = 0;
|
$count = $summer = 0;
|
||||||
// Loop through arguments
|
// Loop through arguments
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_bool($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
@ -1907,11 +2018,12 @@ class Statistical
|
||||||
public static function LARGE(...$args)
|
public static function LARGE(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArray($args);
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
$entry = array_pop($aArgs);
|
||||||
// Calculate
|
|
||||||
$entry = floor(array_pop($aArgs));
|
|
||||||
|
|
||||||
if ((is_numeric($entry)) && (!is_string($entry))) {
|
if ((is_numeric($entry)) && (!is_string($entry))) {
|
||||||
|
$entry = (int) floor($entry);
|
||||||
|
|
||||||
|
// Calculate
|
||||||
$mArgs = [];
|
$mArgs = [];
|
||||||
foreach ($aArgs as $arg) {
|
foreach ($aArgs as $arg) {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
|
@ -1920,7 +2032,7 @@ class Statistical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$count = self::COUNT($mArgs);
|
$count = self::COUNT($mArgs);
|
||||||
$entry = floor(--$entry);
|
--$entry;
|
||||||
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
@ -2117,6 +2229,42 @@ class Statistical
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LOGNORM.DIST.
|
||||||
|
*
|
||||||
|
* Returns the lognormal distribution of x, where ln(x) is normally distributed
|
||||||
|
* with parameters mean and standard_dev.
|
||||||
|
*
|
||||||
|
* @param float $value
|
||||||
|
* @param float $mean
|
||||||
|
* @param float $stdDev
|
||||||
|
* @param bool $cumulative
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function LOGNORMDIST2($value, $mean, $stdDev, $cumulative = false)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
$mean = Functions::flattenSingleValue($mean);
|
||||||
|
$stdDev = Functions::flattenSingleValue($stdDev);
|
||||||
|
$cumulative = (bool) Functions::flattenSingleValue($cumulative);
|
||||||
|
|
||||||
|
if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
|
||||||
|
if (($value <= 0) || ($stdDev <= 0)) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cumulative === true) {
|
||||||
|
return self::NORMSDIST2((log($value) - $mean) / $stdDev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1 / (sqrt(2 * M_PI) * $stdDev * $value)) *
|
||||||
|
exp(0 - ((log($value) - $mean) ** 2 / (2 * $stdDev ** 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MAX.
|
* MAX.
|
||||||
*
|
*
|
||||||
|
@ -2623,10 +2771,36 @@ class Statistical
|
||||||
public static function NORMSDIST($value)
|
public static function NORMSDIST($value)
|
||||||
{
|
{
|
||||||
$value = Functions::flattenSingleValue($value);
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
if (!is_numeric($value)) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
return self::NORMDIST($value, 0, 1, true);
|
return self::NORMDIST($value, 0, 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NORM.S.DIST.
|
||||||
|
*
|
||||||
|
* Returns the standard normal cumulative distribution function. The distribution has
|
||||||
|
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
|
||||||
|
* table of standard normal curve areas.
|
||||||
|
*
|
||||||
|
* @param float $value
|
||||||
|
* @param bool $cumulative
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function NORMSDIST2($value, $cumulative)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
if (!is_numeric($value)) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
$cumulative = (bool) Functions::flattenSingleValue($cumulative);
|
||||||
|
|
||||||
|
return self::NORMDIST($value, 0, 1, $cumulative);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NORMSINV.
|
* NORMSINV.
|
||||||
*
|
*
|
||||||
|
@ -2699,7 +2873,7 @@ class Statistical
|
||||||
* @param int $value the number whose rank you want to find
|
* @param int $value the number whose rank you want to find
|
||||||
* @param int $significance the number of significant digits for the returned percentage value
|
* @param int $significance the number of significant digits for the returned percentage value
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function PERCENTRANK($valueSet, $value, $significance = 3)
|
public static function PERCENTRANK($valueSet, $value, $significance = 3)
|
||||||
{
|
{
|
||||||
|
@ -2925,8 +3099,10 @@ class Statistical
|
||||||
$count = $summer = 0;
|
$count = $summer = 0;
|
||||||
// Loop through arguments
|
// Loop through arguments
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_bool($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
@ -2993,6 +3169,8 @@ class Statistical
|
||||||
$entry = array_pop($aArgs);
|
$entry = array_pop($aArgs);
|
||||||
|
|
||||||
if ((is_numeric($entry)) && (!is_string($entry))) {
|
if ((is_numeric($entry)) && (!is_string($entry))) {
|
||||||
|
$entry = (int) floor($entry);
|
||||||
|
|
||||||
$mArgs = [];
|
$mArgs = [];
|
||||||
foreach ($aArgs as $arg) {
|
foreach ($aArgs as $arg) {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
|
@ -3001,7 +3179,7 @@ class Statistical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$count = self::COUNT($mArgs);
|
$count = self::COUNT($mArgs);
|
||||||
$entry = floor(--$entry);
|
--$entry;
|
||||||
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
@ -3065,8 +3243,10 @@ class Statistical
|
||||||
if ($aMean !== null) {
|
if ($aMean !== null) {
|
||||||
$aCount = -1;
|
$aCount = -1;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
|
(is_bool($arg)) &&
|
||||||
|
((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))
|
||||||
|
) {
|
||||||
$arg = (int) $arg;
|
$arg = (int) $arg;
|
||||||
}
|
}
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
|
@ -3111,8 +3291,10 @@ class Statistical
|
||||||
if ($aMean !== null) {
|
if ($aMean !== null) {
|
||||||
$aCount = -1;
|
$aCount = -1;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_bool($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
||||||
|
@ -3161,8 +3343,10 @@ class Statistical
|
||||||
if ($aMean !== null) {
|
if ($aMean !== null) {
|
||||||
$aCount = 0;
|
$aCount = 0;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
|
(is_bool($arg)) &&
|
||||||
|
((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))
|
||||||
|
) {
|
||||||
$arg = (int) $arg;
|
$arg = (int) $arg;
|
||||||
}
|
}
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
|
@ -3206,8 +3390,10 @@ class Statistical
|
||||||
if ($aMean !== null) {
|
if ($aMean !== null) {
|
||||||
$aCount = 0;
|
$aCount = 0;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_bool($arg)) &&
|
if (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_bool($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
||||||
|
@ -3297,7 +3483,6 @@ class Statistical
|
||||||
$ttheta = atan2($value, sqrt($tterm));
|
$ttheta = atan2($value, sqrt($tterm));
|
||||||
$tc = cos($ttheta);
|
$tc = cos($ttheta);
|
||||||
$ts = sin($ttheta);
|
$ts = sin($ttheta);
|
||||||
$tsum = 0;
|
|
||||||
|
|
||||||
if (($degrees % 2) == 1) {
|
if (($degrees % 2) == 1) {
|
||||||
$ti = 3;
|
$ti = 3;
|
||||||
|
@ -3473,7 +3658,7 @@ class Statistical
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function VARFunc(...$args)
|
public static function VARFunc(...$args)
|
||||||
{
|
{
|
||||||
|
@ -3515,7 +3700,7 @@ class Statistical
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function VARA(...$args)
|
public static function VARA(...$args)
|
||||||
{
|
{
|
||||||
|
@ -3527,11 +3712,15 @@ class Statistical
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
$aCount = 0;
|
$aCount = 0;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_string($arg)) &&
|
if (
|
||||||
(Functions::isValue($k))) {
|
(is_string($arg)) &&
|
||||||
|
(Functions::isValue($k))
|
||||||
|
) {
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
} elseif ((is_string($arg)) &&
|
} elseif (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_string($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
||||||
|
@ -3566,7 +3755,7 @@ class Statistical
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function VARP(...$args)
|
public static function VARP(...$args)
|
||||||
{
|
{
|
||||||
|
@ -3609,7 +3798,7 @@ class Statistical
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function VARPA(...$args)
|
public static function VARPA(...$args)
|
||||||
{
|
{
|
||||||
|
@ -3621,11 +3810,15 @@ class Statistical
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
$aCount = 0;
|
$aCount = 0;
|
||||||
foreach ($aArgs as $k => $arg) {
|
foreach ($aArgs as $k => $arg) {
|
||||||
if ((is_string($arg)) &&
|
if (
|
||||||
(Functions::isValue($k))) {
|
(is_string($arg)) &&
|
||||||
|
(Functions::isValue($k))
|
||||||
|
) {
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
} elseif ((is_string($arg)) &&
|
} elseif (
|
||||||
(!Functions::isMatrixValue($k))) {
|
(is_string($arg)) &&
|
||||||
|
(!Functions::isMatrixValue($k))
|
||||||
|
) {
|
||||||
} else {
|
} else {
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
|
||||||
|
@ -3661,7 +3854,7 @@ class Statistical
|
||||||
* @param float $beta Beta Parameter
|
* @param float $beta Beta Parameter
|
||||||
* @param bool $cumulative
|
* @param bool $cumulative
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function WEIBULL($value, $alpha, $beta, $cumulative)
|
public static function WEIBULL($value, $alpha, $beta, $cumulative)
|
||||||
{
|
{
|
||||||
|
@ -3695,7 +3888,7 @@ class Statistical
|
||||||
* @param float $m0 Alpha Parameter
|
* @param float $m0 Alpha Parameter
|
||||||
* @param float $sigma Beta Parameter
|
* @param float $sigma Beta Parameter
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string (string if result is an error)
|
||||||
*/
|
*/
|
||||||
public static function ZTEST($dataSet, $m0, $sigma = null)
|
public static function ZTEST($dataSet, $m0, $sigma = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
|
@ -98,7 +99,7 @@ class TextData
|
||||||
*
|
*
|
||||||
* @param string $characters Value
|
* @param string $characters Value
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int|string A string if arguments are invalid
|
||||||
*/
|
*/
|
||||||
public static function ASCIICODE($characters)
|
public static function ASCIICODE($characters)
|
||||||
{
|
{
|
||||||
|
@ -543,7 +544,7 @@ class TextData
|
||||||
*
|
*
|
||||||
* @param mixed $value Value to check
|
* @param mixed $value Value to check
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return DateTimeInterface|float|int|string A string if arguments are invalid
|
||||||
*/
|
*/
|
||||||
public static function VALUE($value = '')
|
public static function VALUE($value = '')
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
|
use Psr\Http\Client\ClientExceptionInterface;
|
||||||
|
|
||||||
|
class Web
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* WEBSERVICE.
|
||||||
|
*
|
||||||
|
* Returns data from a web service on the Internet or Intranet.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* Webservice(url)
|
||||||
|
*
|
||||||
|
* @return string the output resulting from a call to the webservice
|
||||||
|
*/
|
||||||
|
public static function WEBSERVICE(string $url)
|
||||||
|
{
|
||||||
|
$url = trim($url);
|
||||||
|
if (strlen($url) > 2048) {
|
||||||
|
return Functions::VALUE(); // Invalid URL length
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/^http[s]?:\/\//', $url)) {
|
||||||
|
return Functions::VALUE(); // Invalid protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get results from the the webservice
|
||||||
|
$client = Settings::getHttpClient();
|
||||||
|
$requestFactory = Settings::getRequestFactory();
|
||||||
|
$request = $requestFactory->createRequest('GET', $url);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $client->sendRequest($request);
|
||||||
|
} catch (ClientExceptionInterface $e) {
|
||||||
|
return Functions::VALUE(); // cURL error
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() != 200) {
|
||||||
|
return Functions::VALUE(); // cURL error
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = $response->getBody()->getContents();
|
||||||
|
if (strlen($output) > 32767) {
|
||||||
|
return Functions::VALUE(); // Output not a string or too long
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
|
@ -163,6 +163,7 @@ HYPERLINK
|
||||||
HYPGEOMDIST
|
HYPGEOMDIST
|
||||||
IF
|
IF
|
||||||
IFERROR
|
IFERROR
|
||||||
|
IFS
|
||||||
IMABS
|
IMABS
|
||||||
IMAGINARY
|
IMAGINARY
|
||||||
IMARGUMENT
|
IMARGUMENT
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Cell;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Exception;
|
||||||
|
|
||||||
|
class AddressHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Converts an R1C1 format cell address to an A1 format cell address.
|
||||||
|
*/
|
||||||
|
public static function convertToA1(
|
||||||
|
string $address,
|
||||||
|
int $currentRowNumber = 1,
|
||||||
|
int $currentColumnNumber = 1
|
||||||
|
): string {
|
||||||
|
$validityCheck = preg_match('/^(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))$/i', $address, $cellReference);
|
||||||
|
|
||||||
|
if ($validityCheck === 0) {
|
||||||
|
throw new Exception('Invalid R1C1-format Cell Reference');
|
||||||
|
}
|
||||||
|
|
||||||
|
$rowReference = $cellReference[2];
|
||||||
|
// Empty R reference is the current row
|
||||||
|
if ($rowReference === '') {
|
||||||
|
$rowReference = (string) $currentRowNumber;
|
||||||
|
}
|
||||||
|
// Bracketed R references are relative to the current row
|
||||||
|
if ($rowReference[0] === '[') {
|
||||||
|
$rowReference = $currentRowNumber + trim($rowReference, '[]');
|
||||||
|
}
|
||||||
|
$columnReference = $cellReference[4];
|
||||||
|
// Empty C reference is the current column
|
||||||
|
if ($columnReference === '') {
|
||||||
|
$columnReference = (string) $currentColumnNumber;
|
||||||
|
}
|
||||||
|
// Bracketed C references are relative to the current column
|
||||||
|
if (is_string($columnReference) && $columnReference[0] === '[') {
|
||||||
|
$columnReference = $currentColumnNumber + trim($columnReference, '[]');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($columnReference <= 0 || $rowReference <= 0) {
|
||||||
|
throw new Exception('Invalid R1C1-format Cell Reference, Value out of range');
|
||||||
|
}
|
||||||
|
$A1CellReference = Coordinate::stringFromColumnIndex($columnReference) . $rowReference;
|
||||||
|
|
||||||
|
return $A1CellReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a formula that uses R1C1 format cell address to an A1 format cell address.
|
||||||
|
*/
|
||||||
|
public static function convertFormulaToA1(
|
||||||
|
string $formula,
|
||||||
|
int $currentRowNumber = 1,
|
||||||
|
int $currentColumnNumber = 1
|
||||||
|
): string {
|
||||||
|
if (substr($formula, 0, 3) == 'of:') {
|
||||||
|
$formula = substr($formula, 3);
|
||||||
|
$temp = explode('"', $formula);
|
||||||
|
$key = false;
|
||||||
|
foreach ($temp as &$value) {
|
||||||
|
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
||||||
|
if ($key = !$key) {
|
||||||
|
$value = str_replace(['[.', '.', ']'], '', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Convert R1C1 style references to A1 style references (but only when not quoted)
|
||||||
|
$temp = explode('"', $formula);
|
||||||
|
$key = false;
|
||||||
|
foreach ($temp as &$value) {
|
||||||
|
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
||||||
|
if ($key = !$key) {
|
||||||
|
preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/', $value, $cellReferences, PREG_SET_ORDER + PREG_OFFSET_CAPTURE);
|
||||||
|
// Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way
|
||||||
|
// through the formula from left to right. Reversing means that we work right to left.through
|
||||||
|
// the formula
|
||||||
|
$cellReferences = array_reverse($cellReferences);
|
||||||
|
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
|
||||||
|
// then modify the formula to use that new reference
|
||||||
|
foreach ($cellReferences as $cellReference) {
|
||||||
|
$A1CellReference = self::convertToA1($cellReference[0][0], $currentRowNumber, $currentColumnNumber);
|
||||||
|
$value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($value);
|
||||||
|
// Then rebuild the formula string
|
||||||
|
$formula = implode('"', $temp);
|
||||||
|
|
||||||
|
return $formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an A1 format cell address to an R1C1 format cell address.
|
||||||
|
* If $currentRowNumber or $currentColumnNumber are provided, then the R1C1 address will be formatted as a relative address.
|
||||||
|
*/
|
||||||
|
public static function convertToR1C1(
|
||||||
|
string $address,
|
||||||
|
?int $currentRowNumber = null,
|
||||||
|
?int $currentColumnNumber = null
|
||||||
|
): string {
|
||||||
|
$validityCheck = preg_match('/^\$?([A-Z]{1,3})\$?(\d{1,7})$/i', $address, $cellReference);
|
||||||
|
|
||||||
|
if ($validityCheck === 0) {
|
||||||
|
throw new Exception('Invalid A1-format Cell Reference');
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnId = Coordinate::columnIndexFromString($cellReference[1]);
|
||||||
|
$rowId = (int) $cellReference[2];
|
||||||
|
|
||||||
|
if ($currentRowNumber !== null) {
|
||||||
|
if ($rowId === $currentRowNumber) {
|
||||||
|
$rowId = '';
|
||||||
|
} else {
|
||||||
|
$rowId = '[' . ($rowId - $currentRowNumber) . ']';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($currentColumnNumber !== null) {
|
||||||
|
if ($columnId === $currentColumnNumber) {
|
||||||
|
$columnId = '';
|
||||||
|
} else {
|
||||||
|
$columnId = '[' . ($columnId - $currentColumnNumber) . ']';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$R1C1Address = "R{$rowId}C{$columnId}";
|
||||||
|
|
||||||
|
return $R1C1Address;
|
||||||
|
}
|
||||||
|
}
|
|
@ -251,9 +251,11 @@ class Cell
|
||||||
{
|
{
|
||||||
if ($this->dataType == DataType::TYPE_FORMULA) {
|
if ($this->dataType == DataType::TYPE_FORMULA) {
|
||||||
try {
|
try {
|
||||||
|
$index = $this->getWorksheet()->getParent()->getActiveSheetIndex();
|
||||||
$result = Calculation::getInstance(
|
$result = Calculation::getInstance(
|
||||||
$this->getWorksheet()->getParent()
|
$this->getWorksheet()->getParent()
|
||||||
)->calculateCellValue($this, $resetLog);
|
)->calculateCellValue($this, $resetLog);
|
||||||
|
$this->getWorksheet()->getParent()->setActiveSheetIndex($index);
|
||||||
// We don't yet handle array returns
|
// We don't yet handle array returns
|
||||||
if (is_array($result)) {
|
if (is_array($result)) {
|
||||||
while (is_array($result)) {
|
while (is_array($result)) {
|
||||||
|
@ -263,6 +265,8 @@ class Cell
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->calculatedValue !== null)) {
|
if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->calculatedValue !== null)) {
|
||||||
return $this->calculatedValue; // Fallback for calculations referencing external files.
|
return $this->calculatedValue; // Fallback for calculations referencing external files.
|
||||||
|
} elseif (strpos($ex->getMessage(), 'undefined name') !== false) {
|
||||||
|
return \PhpOffice\PhpSpreadsheet\Calculation\Functions::NAME();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \PhpOffice\PhpSpreadsheet\Calculation\Exception(
|
throw new \PhpOffice\PhpSpreadsheet\Calculation\Exception(
|
||||||
|
|
|
@ -312,32 +312,59 @@ abstract class Coordinate
|
||||||
/**
|
/**
|
||||||
* Extract all cell references in range, which may be comprised of multiple cell ranges.
|
* Extract all cell references in range, which may be comprised of multiple cell ranges.
|
||||||
*
|
*
|
||||||
* @param string $pRange Range (e.g. A1 or A1:C10 or A1:E10 A20:E25)
|
* @param string $cellRange Range: e.g. 'A1' or 'A1:C10' or 'A1:E10,A20:E25' or 'A1:E5 C3:G7' or 'A1:C1,A3:C3 B1:C3'
|
||||||
*
|
*
|
||||||
* @return array Array containing single cell references
|
* @return array Array containing single cell references
|
||||||
*/
|
*/
|
||||||
public static function extractAllCellReferencesInRange($pRange)
|
public static function extractAllCellReferencesInRange($cellRange): array
|
||||||
{
|
{
|
||||||
$returnValue = [];
|
[$ranges, $operators] = self::getCellBlocksFromRangeString($cellRange);
|
||||||
|
|
||||||
// Explode spaces
|
$cells = [];
|
||||||
$cellBlocks = self::getCellBlocksFromRangeString($pRange);
|
foreach ($ranges as $range) {
|
||||||
foreach ($cellBlocks as $cellBlock) {
|
$cells[] = self::getReferencesForCellBlock($range);
|
||||||
$returnValue = array_merge($returnValue, self::getReferencesForCellBlock($cellBlock));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$cells = self::processRangeSetOperators($operators, $cells);
|
||||||
|
|
||||||
|
if (empty($cells)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$cellList = array_merge(...$cells);
|
||||||
|
$cellList = self::sortCellReferenceArray($cellList);
|
||||||
|
|
||||||
|
return $cellList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function processRangeSetOperators(array $operators, array $cells): array
|
||||||
|
{
|
||||||
|
for ($offset = 0; $offset < count($operators); ++$offset) {
|
||||||
|
$operator = $operators[$offset];
|
||||||
|
if ($operator !== ' ') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cells[$offset] = array_intersect($cells[$offset], $cells[$offset + 1]);
|
||||||
|
unset($operators[$offset], $cells[$offset + 1]);
|
||||||
|
$operators = array_values($operators);
|
||||||
|
$cells = array_values($cells);
|
||||||
|
--$offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function sortCellReferenceArray(array $cellList): array
|
||||||
|
{
|
||||||
// Sort the result by column and row
|
// Sort the result by column and row
|
||||||
$sortKeys = [];
|
$sortKeys = [];
|
||||||
foreach (array_unique($returnValue) as $coord) {
|
foreach ($cellList as $coord) {
|
||||||
$column = '';
|
[$column, $row] = sscanf($coord, '%[A-Z]%d');
|
||||||
$row = 0;
|
|
||||||
|
|
||||||
sscanf($coord, '%[A-Z]%d', $column, $row);
|
|
||||||
$sortKeys[sprintf('%3s%09d', $column, $row)] = $coord;
|
$sortKeys[sprintf('%3s%09d', $column, $row)] = $coord;
|
||||||
}
|
}
|
||||||
ksort($sortKeys);
|
ksort($sortKeys);
|
||||||
|
|
||||||
// Return value
|
|
||||||
return array_values($sortKeys);
|
return array_values($sortKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,15 +509,25 @@ abstract class Coordinate
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the individual cell blocks from a range string, splitting by space and removing any $ characters.
|
* Get the individual cell blocks from a range string, removing any $ characters.
|
||||||
|
* then splitting by operators and returning an array with ranges and operators.
|
||||||
*
|
*
|
||||||
* @param string $pRange
|
* @param string $rangeString
|
||||||
*
|
*
|
||||||
* @return string[]
|
* @return array[]
|
||||||
*/
|
*/
|
||||||
private static function getCellBlocksFromRangeString($pRange)
|
private static function getCellBlocksFromRangeString($rangeString)
|
||||||
{
|
{
|
||||||
return explode(' ', str_replace('$', '', strtoupper($pRange)));
|
$rangeString = str_replace('$', '', strtoupper($rangeString));
|
||||||
|
|
||||||
|
// split range sets on intersection (space) or union (,) operators
|
||||||
|
$tokens = preg_split('/([ ,])/', $rangeString, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
// separate the range sets and the operators into arrays
|
||||||
|
$split = array_chunk($tokens, 2);
|
||||||
|
$ranges = array_column($split, 0);
|
||||||
|
$operators = array_column($split, 1);
|
||||||
|
|
||||||
|
return [$ranges, $operators];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,8 +21,6 @@ use ScatterPlot;
|
||||||
use Spline;
|
use Spline;
|
||||||
use StockPlot;
|
use StockPlot;
|
||||||
|
|
||||||
require_once __DIR__ . '/Polyfill.php';
|
|
||||||
|
|
||||||
class JpGraph implements IRenderer
|
class JpGraph implements IRenderer
|
||||||
{
|
{
|
||||||
private static $width = 640;
|
private static $width = 640;
|
||||||
|
@ -219,9 +217,11 @@ class JpGraph implements IRenderer
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
$this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); // top
|
$this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); // top
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
$this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); // bottom
|
$this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); // bottom
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); // top-right
|
$this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); // top-right
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
// This is a dirty workaround to output JpGraph charts even when antialiasing is not available
|
|
||||||
if (!function_exists('imageantialias')) {
|
|
||||||
function imageantialias(...$args): void
|
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
abstract class DefinedName
|
||||||
|
{
|
||||||
|
protected const REGEXP_IDENTIFY_FORMULA = '[^_\p{N}\p{L}:, \$\'!]';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Worksheet on which the defined name can be resolved.
|
||||||
|
*
|
||||||
|
* @var Worksheet
|
||||||
|
*/
|
||||||
|
protected $worksheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of the named object.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the defined named local? (i.e. can only be used on $this->worksheet).
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $localOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope.
|
||||||
|
*
|
||||||
|
* @var Worksheet
|
||||||
|
*/
|
||||||
|
protected $scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this is a named range or a named formula.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $isFormula;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Defined Name.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $name,
|
||||||
|
?Worksheet $worksheet = null,
|
||||||
|
?string $value = null,
|
||||||
|
bool $localOnly = false,
|
||||||
|
?Worksheet $scope = null
|
||||||
|
) {
|
||||||
|
if ($worksheet === null) {
|
||||||
|
$worksheet = $scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set local members
|
||||||
|
$this->name = $name;
|
||||||
|
$this->worksheet = $worksheet;
|
||||||
|
$this->value = (string) $value;
|
||||||
|
$this->localOnly = $localOnly;
|
||||||
|
// If local only, then the scope will be set to worksheet unless a scope is explicitly set
|
||||||
|
$this->scope = ($localOnly === true) ? (($scope === null) ? $worksheet : $scope) : null;
|
||||||
|
// If the range string contains characters that aren't associated with the range definition (A-Z,1-9
|
||||||
|
// for cell references, and $, or the range operators (colon comma or space), quotes and ! for
|
||||||
|
// worksheet names
|
||||||
|
// then this is treated as a named formula, and not a named range
|
||||||
|
$this->isFormula = self::testIfFormula($this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new defined name, either a range or a formula.
|
||||||
|
*/
|
||||||
|
public static function createInstance(
|
||||||
|
string $name,
|
||||||
|
?Worksheet $worksheet = null,
|
||||||
|
?string $value = null,
|
||||||
|
bool $localOnly = false,
|
||||||
|
?Worksheet $scope = null
|
||||||
|
): self {
|
||||||
|
$value = (string) $value;
|
||||||
|
$isFormula = self::testIfFormula($value);
|
||||||
|
if ($isFormula) {
|
||||||
|
return new NamedFormula($name, $worksheet, $value, $localOnly, $scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NamedRange($name, $worksheet, $value, $localOnly, $scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function testIfFormula(string $value): bool
|
||||||
|
{
|
||||||
|
if (substr($value, 0, 1) === '=') {
|
||||||
|
$value = substr($value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_numeric($value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$segMatcher = false;
|
||||||
|
foreach (explode("'", $value) as $subVal) {
|
||||||
|
// Only test in alternate array entries (the non-quoted blocks)
|
||||||
|
if (
|
||||||
|
($segMatcher = !$segMatcher) &&
|
||||||
|
(preg_match('/' . self::REGEXP_IDENTIFY_FORMULA . '/miu', $subVal))
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get name.
|
||||||
|
*/
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set name.
|
||||||
|
*/
|
||||||
|
public function setName(string $name): self
|
||||||
|
{
|
||||||
|
if (!empty($name)) {
|
||||||
|
// Old title
|
||||||
|
$oldTitle = $this->name;
|
||||||
|
|
||||||
|
// Re-attach
|
||||||
|
if ($this->worksheet !== null) {
|
||||||
|
$this->worksheet->getParent()->removeNamedRange($this->name, $this->worksheet);
|
||||||
|
}
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
if ($this->worksheet !== null) {
|
||||||
|
$this->worksheet->getParent()->addNamedRange($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New title
|
||||||
|
$newTitle = $this->name;
|
||||||
|
ReferenceHelper::getInstance()->updateNamedFormulas($this->worksheet->getParent(), $oldTitle, $newTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get worksheet.
|
||||||
|
*/
|
||||||
|
public function getWorksheet(): ?Worksheet
|
||||||
|
{
|
||||||
|
return $this->worksheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set worksheet.
|
||||||
|
*/
|
||||||
|
public function setWorksheet(?Worksheet $value): self
|
||||||
|
{
|
||||||
|
$this->worksheet = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get range or formula value.
|
||||||
|
*/
|
||||||
|
public function getValue(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set range or formula value.
|
||||||
|
*/
|
||||||
|
public function setValue(string $value): self
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get localOnly.
|
||||||
|
*/
|
||||||
|
public function getLocalOnly(): bool
|
||||||
|
{
|
||||||
|
return $this->localOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set localOnly.
|
||||||
|
*/
|
||||||
|
public function setLocalOnly(bool $value): self
|
||||||
|
{
|
||||||
|
$this->localOnly = $value;
|
||||||
|
$this->scope = $value ? $this->worksheet : null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get scope.
|
||||||
|
*/
|
||||||
|
public function getScope(): ?Worksheet
|
||||||
|
{
|
||||||
|
return $this->scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set scope.
|
||||||
|
*/
|
||||||
|
public function setScope(?Worksheet $value): self
|
||||||
|
{
|
||||||
|
$this->scope = $value;
|
||||||
|
$this->localOnly = $value !== null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify whether this is a named range or a named formula.
|
||||||
|
*/
|
||||||
|
public function isFormula(): bool
|
||||||
|
{
|
||||||
|
return $this->isFormula;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a named range to a regular cell range or formula.
|
||||||
|
*/
|
||||||
|
public static function resolveName(string $pDefinedName, Worksheet $pSheet): ?self
|
||||||
|
{
|
||||||
|
return $pSheet->getParent()->getDefinedName($pDefinedName, $pSheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||||
|
*/
|
||||||
|
public function __clone()
|
||||||
|
{
|
||||||
|
$vars = get_object_vars($this);
|
||||||
|
foreach ($vars as $key => $value) {
|
||||||
|
if (is_object($value)) {
|
||||||
|
$this->$key = clone $value;
|
||||||
|
} else {
|
||||||
|
$this->$key = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -457,11 +457,14 @@ class Properties
|
||||||
*/
|
*/
|
||||||
public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null)
|
public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null)
|
||||||
{
|
{
|
||||||
if (($propertyType === null) || (!in_array($propertyType, [self::PROPERTY_TYPE_INTEGER,
|
if (
|
||||||
|
($propertyType === null) || (!in_array($propertyType, [self::PROPERTY_TYPE_INTEGER,
|
||||||
self::PROPERTY_TYPE_FLOAT,
|
self::PROPERTY_TYPE_FLOAT,
|
||||||
self::PROPERTY_TYPE_STRING,
|
self::PROPERTY_TYPE_STRING,
|
||||||
self::PROPERTY_TYPE_DATE,
|
self::PROPERTY_TYPE_DATE,
|
||||||
self::PROPERTY_TYPE_BOOLEAN, ]))) {
|
self::PROPERTY_TYPE_BOOLEAN,
|
||||||
|
]))
|
||||||
|
) {
|
||||||
if ($propertyValue === null) {
|
if ($propertyValue === null) {
|
||||||
$propertyType = self::PROPERTY_TYPE_STRING;
|
$propertyType = self::PROPERTY_TYPE_STRING;
|
||||||
} elseif (is_float($propertyValue)) {
|
} elseif (is_float($propertyValue)) {
|
||||||
|
|
|
@ -694,9 +694,9 @@ class Html
|
||||||
return implode('', $values[0]);
|
return implode('', $values[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function colourNameLookup($rgb)
|
public static function colourNameLookup(string $rgb): string
|
||||||
{
|
{
|
||||||
return self::$colourMap[$rgb];
|
return self::$colourMap[$rgb] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function startFontTag($tag): void
|
protected function startFontTag($tag): void
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class NamedFormula extends DefinedName
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new Named Formula.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $name,
|
||||||
|
?Worksheet $worksheet = null,
|
||||||
|
?string $formula = null,
|
||||||
|
bool $localOnly = false,
|
||||||
|
?Worksheet $scope = null
|
||||||
|
) {
|
||||||
|
// Validate data
|
||||||
|
if (empty($formula)) {
|
||||||
|
throw new Exception('Tou must specify a Formula value for a Named Formula');
|
||||||
|
}
|
||||||
|
parent::__construct($name, $worksheet, $formula, $localOnly, $scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the formula value.
|
||||||
|
*/
|
||||||
|
public function getFormula(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the formula value.
|
||||||
|
*/
|
||||||
|
public function setFormula(string $formula): self
|
||||||
|
{
|
||||||
|
if (!empty($formula)) {
|
||||||
|
$this->value = $formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,234 +2,54 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet;
|
namespace PhpOffice\PhpSpreadsheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
class NamedRange
|
class NamedRange extends DefinedName
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Range name.
|
* Create a new Named Range.
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private $name;
|
public function __construct(
|
||||||
|
string $name,
|
||||||
|
?Worksheet $worksheet = null,
|
||||||
|
string $range = 'A1',
|
||||||
|
bool $localOnly = false,
|
||||||
|
?Worksheet $scope = null
|
||||||
|
) {
|
||||||
|
if ($worksheet === null && $scope === null) {
|
||||||
|
throw new Exception('You must specify a worksheet or a scope for a Named Range');
|
||||||
|
}
|
||||||
|
parent::__construct($name, $worksheet, $range, $localOnly, $scope);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worksheet on which the named range can be resolved.
|
* Get the range value.
|
||||||
*
|
|
||||||
* @var Worksheet
|
|
||||||
*/
|
*/
|
||||||
private $worksheet;
|
public function getRange(): string
|
||||||
|
|
||||||
/**
|
|
||||||
* Range of the referenced cells.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $range;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the named range local? (i.e. can only be used on $this->worksheet).
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $localOnly;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scope.
|
|
||||||
*
|
|
||||||
* @var Worksheet
|
|
||||||
*/
|
|
||||||
private $scope;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new NamedRange.
|
|
||||||
*
|
|
||||||
* @param string $pName
|
|
||||||
* @param string $pRange
|
|
||||||
* @param bool $pLocalOnly
|
|
||||||
* @param null|Worksheet $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope.
|
|
||||||
*/
|
|
||||||
public function __construct($pName, Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null)
|
|
||||||
{
|
{
|
||||||
// Validate data
|
return $this->value;
|
||||||
if (($pName === null) || ($pWorksheet === null) || ($pRange === null)) {
|
|
||||||
throw new Exception('Parameters can not be null.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set local members
|
|
||||||
$this->name = $pName;
|
|
||||||
$this->worksheet = $pWorksheet;
|
|
||||||
$this->range = $pRange;
|
|
||||||
$this->localOnly = $pLocalOnly;
|
|
||||||
$this->scope = ($pLocalOnly == true) ? (($pScope == null) ? $pWorksheet : $pScope) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get name.
|
* Set the range value.
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function getName()
|
public function setRange(string $range): self
|
||||||
{
|
{
|
||||||
return $this->name;
|
if (!empty($range)) {
|
||||||
}
|
$this->value = $range;
|
||||||
|
|
||||||
/**
|
|
||||||
* Set name.
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setName($value)
|
|
||||||
{
|
|
||||||
if ($value !== null) {
|
|
||||||
// Old title
|
|
||||||
$oldTitle = $this->name;
|
|
||||||
|
|
||||||
// Re-attach
|
|
||||||
if ($this->worksheet !== null) {
|
|
||||||
$this->worksheet->getParent()->removeNamedRange($this->name, $this->worksheet);
|
|
||||||
}
|
|
||||||
$this->name = $value;
|
|
||||||
|
|
||||||
if ($this->worksheet !== null) {
|
|
||||||
$this->worksheet->getParent()->addNamedRange($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// New title
|
|
||||||
$newTitle = $this->name;
|
|
||||||
ReferenceHelper::getInstance()->updateNamedFormulas($this->worksheet->getParent(), $oldTitle, $newTitle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getCellsInRange(): array
|
||||||
* Get worksheet.
|
|
||||||
*
|
|
||||||
* @return Worksheet
|
|
||||||
*/
|
|
||||||
public function getWorksheet()
|
|
||||||
{
|
{
|
||||||
return $this->worksheet;
|
$range = $this->value;
|
||||||
|
if (substr($range, 0, 1) === '=') {
|
||||||
|
$range = substr($range, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return Coordinate::extractAllCellReferencesInRange($range);
|
||||||
* Set worksheet.
|
|
||||||
*
|
|
||||||
* @param Worksheet $value
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setWorksheet(?Worksheet $value = null)
|
|
||||||
{
|
|
||||||
if ($value !== null) {
|
|
||||||
$this->worksheet = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get range.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getRange()
|
|
||||||
{
|
|
||||||
return $this->range;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set range.
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setRange($value)
|
|
||||||
{
|
|
||||||
if ($value !== null) {
|
|
||||||
$this->range = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get localOnly.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getLocalOnly()
|
|
||||||
{
|
|
||||||
return $this->localOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set localOnly.
|
|
||||||
*
|
|
||||||
* @param bool $value
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setLocalOnly($value)
|
|
||||||
{
|
|
||||||
$this->localOnly = $value;
|
|
||||||
$this->scope = $value ? $this->worksheet : null;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get scope.
|
|
||||||
*
|
|
||||||
* @return null|Worksheet
|
|
||||||
*/
|
|
||||||
public function getScope()
|
|
||||||
{
|
|
||||||
return $this->scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set scope.
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setScope(?Worksheet $value = null)
|
|
||||||
{
|
|
||||||
$this->scope = $value;
|
|
||||||
$this->localOnly = $value != null;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve a named range to a regular cell range.
|
|
||||||
*
|
|
||||||
* @param string $pNamedRange Named range
|
|
||||||
* @param null|Worksheet $pSheet Scope. Use null for global scope
|
|
||||||
*
|
|
||||||
* @return NamedRange
|
|
||||||
*/
|
|
||||||
public static function resolveRange($pNamedRange, Worksheet $pSheet)
|
|
||||||
{
|
|
||||||
return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
|
||||||
*/
|
|
||||||
public function __clone()
|
|
||||||
{
|
|
||||||
$vars = get_object_vars($this);
|
|
||||||
foreach ($vars as $key => $value) {
|
|
||||||
if (is_object($value)) {
|
|
||||||
$this->$key = clone $value;
|
|
||||||
} else {
|
|
||||||
$this->$key = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Reader;
|
namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||||
|
|
||||||
|
@ -133,13 +134,9 @@ abstract class BaseReader implements IReader
|
||||||
|
|
||||||
public function getSecurityScanner()
|
public function getSecurityScanner()
|
||||||
{
|
{
|
||||||
if (property_exists($this, 'securityScanner')) {
|
|
||||||
return $this->securityScanner;
|
return $this->securityScanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open file for reading.
|
* Open file for reading.
|
||||||
*
|
*
|
||||||
|
@ -147,12 +144,18 @@ abstract class BaseReader implements IReader
|
||||||
*/
|
*/
|
||||||
protected function openFile($pFilename): void
|
protected function openFile($pFilename): void
|
||||||
{
|
{
|
||||||
|
if ($pFilename) {
|
||||||
File::assertFile($pFilename);
|
File::assertFile($pFilename);
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
$this->fileHandle = fopen($pFilename, 'rb');
|
$fileHandle = fopen($pFilename, 'rb');
|
||||||
if ($this->fileHandle === false) {
|
} else {
|
||||||
throw new Exception('Could not open file ' . $pFilename . ' for reading.');
|
$fileHandle = false;
|
||||||
|
}
|
||||||
|
if ($fileHandle !== false) {
|
||||||
|
$this->fileHandle = $fileHandle;
|
||||||
|
} else {
|
||||||
|
throw new ReaderException('Could not open file ' . $pFilename . ' for reading.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,6 +523,7 @@ class Csv extends BaseReader
|
||||||
// Attempt to guess mimetype
|
// Attempt to guess mimetype
|
||||||
$type = mime_content_type($pFilename);
|
$type = mime_content_type($pFilename);
|
||||||
$supportedTypes = [
|
$supportedTypes = [
|
||||||
|
'application/csv',
|
||||||
'text/csv',
|
'text/csv',
|
||||||
'text/plain',
|
'text/plain',
|
||||||
'inode/x-empty',
|
'inode/x-empty',
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,143 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageMargins;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup as WorksheetPageSetup;
|
||||||
|
use SimpleXMLElement;
|
||||||
|
|
||||||
|
class PageSetup
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Spreadsheet
|
||||||
|
*/
|
||||||
|
private $spreadsheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $gnm;
|
||||||
|
|
||||||
|
public function __construct(Spreadsheet $spreadsheet, string $gnm)
|
||||||
|
{
|
||||||
|
$this->spreadsheet = $spreadsheet;
|
||||||
|
$this->gnm = $gnm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function printInformation(SimpleXMLElement $sheet): self
|
||||||
|
{
|
||||||
|
if (isset($sheet->PrintInformation)) {
|
||||||
|
$printInformation = $sheet->PrintInformation[0];
|
||||||
|
$scale = (string) $printInformation->Scale->attributes()['percentage'];
|
||||||
|
$pageOrder = (string) $printInformation->order;
|
||||||
|
$orientation = (string) $printInformation->orientation;
|
||||||
|
$horizontalCentered = (string) $printInformation->hcenter->attributes()['value'];
|
||||||
|
$verticalCentered = (string) $printInformation->vcenter->attributes()['value'];
|
||||||
|
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageSetup()
|
||||||
|
->setPageOrder($pageOrder === 'r_then_d' ? WorksheetPageSetup::PAGEORDER_OVER_THEN_DOWN : WorksheetPageSetup::PAGEORDER_DOWN_THEN_OVER)
|
||||||
|
->setScale((int) $scale)
|
||||||
|
->setOrientation($orientation ?? WorksheetPageSetup::ORIENTATION_DEFAULT)
|
||||||
|
->setHorizontalCentered((bool) $horizontalCentered)
|
||||||
|
->setVerticalCentered((bool) $verticalCentered);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sheetMargins(SimpleXMLElement $sheet): self
|
||||||
|
{
|
||||||
|
if (isset($sheet->PrintInformation, $sheet->PrintInformation->Margins)) {
|
||||||
|
$marginSet = [
|
||||||
|
// Default Settings
|
||||||
|
'top' => 0.75,
|
||||||
|
'header' => 0.3,
|
||||||
|
'left' => 0.7,
|
||||||
|
'right' => 0.7,
|
||||||
|
'bottom' => 0.75,
|
||||||
|
'footer' => 0.3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$marginSet = $this->buildMarginSet($sheet, $marginSet);
|
||||||
|
$this->adjustMargins($marginSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildMarginSet(SimpleXMLElement $sheet, array $marginSet): array
|
||||||
|
{
|
||||||
|
foreach ($sheet->PrintInformation->Margins->children($this->gnm, true) as $key => $margin) {
|
||||||
|
$marginAttributes = $margin->attributes();
|
||||||
|
$marginSize = ($marginAttributes['Points']) ?? 72; // Default is 72pt
|
||||||
|
// Convert value in points to inches
|
||||||
|
$marginSize = PageMargins::fromPoints((float) $marginSize);
|
||||||
|
$marginSet[$key] = $marginSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $marginSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function adjustMargins(array $marginSet): void
|
||||||
|
{
|
||||||
|
foreach ($marginSet as $key => $marginSize) {
|
||||||
|
// Gnumeric is quirky in the way it displays the header/footer values:
|
||||||
|
// header is actually the sum of top and header; footer is actually the sum of bottom and footer
|
||||||
|
// then top is actually the header value, and bottom is actually the footer value
|
||||||
|
switch ($key) {
|
||||||
|
case 'left':
|
||||||
|
case 'right':
|
||||||
|
$this->sheetMargin($key, $marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'top':
|
||||||
|
$this->sheetMargin($key, $marginSet['header'] ?? 0);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
$this->sheetMargin($key, $marginSet['footer'] ?? 0);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'header':
|
||||||
|
$this->sheetMargin($key, ($marginSet['top'] ?? 0) - $marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'footer':
|
||||||
|
$this->sheetMargin($key, ($marginSet['bottom'] ?? 0) - $marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sheetMargin(string $key, float $marginSize): void
|
||||||
|
{
|
||||||
|
switch ($key) {
|
||||||
|
case 'top':
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageMargins()->setTop($marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageMargins()->setBottom($marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'left':
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageMargins()->setLeft($marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageMargins()->setRight($marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'header':
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageMargins()->setHeader($marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'footer':
|
||||||
|
$this->spreadsheet->getActiveSheet()->getPageMargins()->setFooter($marginSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
/** PhpSpreadsheet root directory */
|
/** PhpSpreadsheet root directory */
|
||||||
class Html extends BaseReader
|
class Html extends BaseReader
|
||||||
|
@ -219,9 +220,13 @@ class Html extends BaseReader
|
||||||
/**
|
/**
|
||||||
* Set input encoding.
|
* Set input encoding.
|
||||||
*
|
*
|
||||||
|
* @deprecated no use is made of this property
|
||||||
|
*
|
||||||
* @param string $pValue Input encoding, eg: 'ANSI'
|
* @param string $pValue Input encoding, eg: 'ANSI'
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function setInputEncoding($pValue)
|
public function setInputEncoding($pValue)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +238,11 @@ class Html extends BaseReader
|
||||||
/**
|
/**
|
||||||
* Get input encoding.
|
* Get input encoding.
|
||||||
*
|
*
|
||||||
|
* @deprecated no use is made of this property
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function getInputEncoding()
|
public function getInputEncoding()
|
||||||
{
|
{
|
||||||
|
@ -289,86 +298,72 @@ class Html extends BaseReader
|
||||||
$cellContent = (string) '';
|
$cellContent = (string) '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function processDomElementBody(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child): void
|
||||||
* @param int $row
|
|
||||||
* @param string $column
|
|
||||||
* @param string $cellContent
|
|
||||||
*/
|
|
||||||
protected function processDomElement(DOMNode $element, Worksheet $sheet, &$row, &$column, &$cellContent): void
|
|
||||||
{
|
{
|
||||||
foreach ($element->childNodes as $child) {
|
|
||||||
if ($child instanceof DOMText) {
|
|
||||||
$domText = preg_replace('/\s+/u', ' ', trim($child->nodeValue));
|
|
||||||
if (is_string($cellContent)) {
|
|
||||||
// simply append the text if the cell content is a plain text string
|
|
||||||
$cellContent .= $domText;
|
|
||||||
}
|
|
||||||
// but if we have a rich text run instead, we need to append it correctly
|
|
||||||
// TODO
|
|
||||||
} elseif ($child instanceof DOMElement) {
|
|
||||||
$attributeArray = [];
|
$attributeArray = [];
|
||||||
foreach ($child->attributes as $attribute) {
|
foreach ($child->attributes as $attribute) {
|
||||||
$attributeArray[$attribute->name] = $attribute->value;
|
$attributeArray[$attribute->name] = $attribute->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($child->nodeName) {
|
if ($child->nodeName === 'body') {
|
||||||
case 'meta':
|
$row = 1;
|
||||||
foreach ($attributeArray as $attributeName => $attributeValue) {
|
$column = 'A';
|
||||||
// Extract character set, so we can convert to UTF-8 if required
|
$cellContent = '';
|
||||||
if ($attributeName === 'charset') {
|
$this->tableLevel = 0;
|
||||||
$this->setInputEncoding($attributeValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
|
} else {
|
||||||
|
$this->processDomElementTitle($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementTitle(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'title':
|
{
|
||||||
|
if ($child->nodeName === 'title') {
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
$sheet->setTitle($cellContent, true, false);
|
$sheet->setTitle($cellContent, true, false);
|
||||||
$cellContent = '';
|
$cellContent = '';
|
||||||
|
} else {
|
||||||
|
$this->processDomElementSpanEtc($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private static $spanEtc = ['span', 'div', 'font', 'i', 'em', 'strong', 'b'];
|
||||||
case 'span':
|
|
||||||
case 'div':
|
private function processDomElementSpanEtc(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'font':
|
{
|
||||||
case 'i':
|
if (in_array($child->nodeName, self::$spanEtc)) {
|
||||||
case 'em':
|
|
||||||
case 'strong':
|
|
||||||
case 'b':
|
|
||||||
if (isset($attributeArray['class']) && $attributeArray['class'] === 'comment') {
|
if (isset($attributeArray['class']) && $attributeArray['class'] === 'comment') {
|
||||||
$sheet->getComment($column . $row)
|
$sheet->getComment($column . $row)
|
||||||
->getText()
|
->getText()
|
||||||
->createTextRun($child->textContent);
|
->createTextRun($child->textContent);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cellContent > '') {
|
|
||||||
$cellContent .= ' ';
|
|
||||||
}
|
}
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
if ($cellContent > '') {
|
|
||||||
$cellContent .= ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->formats[$child->nodeName])) {
|
if (isset($this->formats[$child->nodeName])) {
|
||||||
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
|
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
case 'hr':
|
|
||||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
|
||||||
++$row;
|
|
||||||
if (isset($this->formats[$child->nodeName])) {
|
|
||||||
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
|
|
||||||
} else {
|
} else {
|
||||||
$cellContent = '----------';
|
$this->processDomElementHr($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementHr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
|
{
|
||||||
|
if ($child->nodeName === 'hr') {
|
||||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||||
|
++$row;
|
||||||
|
if (isset($this->formats[$child->nodeName])) {
|
||||||
|
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
|
||||||
}
|
}
|
||||||
++$row;
|
++$row;
|
||||||
// Add a break after a horizontal rule, simply by allowing the code to dropthru
|
}
|
||||||
// no break
|
// fall through to br
|
||||||
case 'br':
|
$this->processDomElementBr($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementBr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
|
{
|
||||||
|
if ($child->nodeName === 'br' || $child->nodeName === 'hr') {
|
||||||
if ($this->tableLevel > 0) {
|
if ($this->tableLevel > 0) {
|
||||||
// If we're inside a table, replace with a \n and set the cell to wrap
|
// If we're inside a table, replace with a \n and set the cell to wrap
|
||||||
$cellContent .= "\n";
|
$cellContent .= "\n";
|
||||||
|
@ -378,9 +373,14 @@ class Html extends BaseReader
|
||||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||||
++$row;
|
++$row;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->processDomElementA($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementA(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'a':
|
{
|
||||||
|
if ($child->nodeName === 'a') {
|
||||||
foreach ($attributeArray as $attributeName => $attributeValue) {
|
foreach ($attributeArray as $attributeName => $attributeValue) {
|
||||||
switch ($attributeName) {
|
switch ($attributeName) {
|
||||||
case 'href':
|
case 'href':
|
||||||
|
@ -396,22 +396,23 @@ class Html extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cellContent .= ' ';
|
// no idea why this should be needed
|
||||||
|
//$cellContent .= ' ';
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
|
} else {
|
||||||
|
$this->processDomElementH1Etc($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private static $h1Etc = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'p'];
|
||||||
case 'h1':
|
|
||||||
case 'h2':
|
private function processDomElementH1Etc(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'h3':
|
{
|
||||||
case 'h4':
|
if (in_array($child->nodeName, self::$h1Etc)) {
|
||||||
case 'h5':
|
|
||||||
case 'h6':
|
|
||||||
case 'ol':
|
|
||||||
case 'ul':
|
|
||||||
case 'p':
|
|
||||||
if ($this->tableLevel > 0) {
|
if ($this->tableLevel > 0) {
|
||||||
// If we're inside a table, replace with a \n
|
// If we're inside a table, replace with a \n
|
||||||
$cellContent .= "\n";
|
$cellContent .= $cellContent ? "\n" : '';
|
||||||
|
$sheet->getStyle($column . $row)->getAlignment()->setWrapText(true);
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
} else {
|
} else {
|
||||||
if ($cellContent > '') {
|
if ($cellContent > '') {
|
||||||
|
@ -428,12 +429,17 @@ class Html extends BaseReader
|
||||||
++$row;
|
++$row;
|
||||||
$column = 'A';
|
$column = 'A';
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->processDomElementLi($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementLi(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'li':
|
{
|
||||||
|
if ($child->nodeName === 'li') {
|
||||||
if ($this->tableLevel > 0) {
|
if ($this->tableLevel > 0) {
|
||||||
// If we're inside a table, replace with a \n
|
// If we're inside a table, replace with a \n
|
||||||
$cellContent .= "\n";
|
$cellContent .= $cellContent ? "\n" : '';
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
} else {
|
} else {
|
||||||
if ($cellContent > '') {
|
if ($cellContent > '') {
|
||||||
|
@ -444,13 +450,23 @@ class Html extends BaseReader
|
||||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||||
$column = 'A';
|
$column = 'A';
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->processDomElementImg($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementImg(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'img':
|
{
|
||||||
|
if ($child->nodeName === 'img') {
|
||||||
$this->insertImage($sheet, $column, $row, $attributeArray);
|
$this->insertImage($sheet, $column, $row, $attributeArray);
|
||||||
|
} else {
|
||||||
|
$this->processDomElementTable($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementTable(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'table':
|
{
|
||||||
|
if ($child->nodeName === 'table') {
|
||||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||||
$column = $this->setTableStartColumn($column);
|
$column = $this->setTableStartColumn($column);
|
||||||
if ($this->tableLevel > 1) {
|
if ($this->tableLevel > 1) {
|
||||||
|
@ -463,14 +479,14 @@ class Html extends BaseReader
|
||||||
} else {
|
} else {
|
||||||
++$row;
|
++$row;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->processDomElementTr($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementTr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'thead':
|
{
|
||||||
case 'tbody':
|
if ($child->nodeName === 'tr') {
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'tr':
|
|
||||||
$column = $this->getTableStartColumn();
|
$column = $this->getTableStartColumn();
|
||||||
$cellContent = '';
|
$cellContent = '';
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
|
@ -480,21 +496,88 @@ class Html extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
++$row;
|
++$row;
|
||||||
|
} else {
|
||||||
|
$this->processDomElementThTdOther($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
private function processDomElementThTdOther(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
case 'th':
|
{
|
||||||
case 'td':
|
if ($child->nodeName !== 'td' && $child->nodeName !== 'th') {
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
|
} else {
|
||||||
|
$this->processDomElementThTd($sheet, $row, $column, $cellContent, $child, $attributeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementBgcolor(Worksheet $sheet, int $row, string $column, array $attributeArray): void
|
||||||
|
{
|
||||||
|
if (isset($attributeArray['bgcolor'])) {
|
||||||
|
$sheet->getStyle("$column$row")->applyFromArray(
|
||||||
|
[
|
||||||
|
'fill' => [
|
||||||
|
'fillType' => Fill::FILL_SOLID,
|
||||||
|
'color' => ['rgb' => $this->getStyleColor($attributeArray['bgcolor'])],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementWidth(Worksheet $sheet, string $column, array $attributeArray): void
|
||||||
|
{
|
||||||
|
if (isset($attributeArray['width'])) {
|
||||||
|
$sheet->getColumnDimension($column)->setWidth($attributeArray['width']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementHeight(Worksheet $sheet, int $row, array $attributeArray): void
|
||||||
|
{
|
||||||
|
if (isset($attributeArray['height'])) {
|
||||||
|
$sheet->getRowDimension($row)->setRowHeight($attributeArray['height']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementAlign(Worksheet $sheet, int $row, string $column, array $attributeArray): void
|
||||||
|
{
|
||||||
|
if (isset($attributeArray['align'])) {
|
||||||
|
$sheet->getStyle($column . $row)->getAlignment()->setHorizontal($attributeArray['align']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementVAlign(Worksheet $sheet, int $row, string $column, array $attributeArray): void
|
||||||
|
{
|
||||||
|
if (isset($attributeArray['valign'])) {
|
||||||
|
$sheet->getStyle($column . $row)->getAlignment()->setVertical($attributeArray['valign']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementDataFormat(Worksheet $sheet, int $row, string $column, array $attributeArray): void
|
||||||
|
{
|
||||||
|
if (isset($attributeArray['data-format'])) {
|
||||||
|
$sheet->getStyle($column . $row)->getNumberFormat()->setFormatCode($attributeArray['data-format']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDomElementThTd(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||||
|
{
|
||||||
while (isset($this->rowspan[$column . $row])) {
|
while (isset($this->rowspan[$column . $row])) {
|
||||||
++$column;
|
++$column;
|
||||||
}
|
}
|
||||||
|
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||||
|
|
||||||
// apply inline style
|
// apply inline style
|
||||||
$this->applyInlineStyle($sheet, $row, $column, $attributeArray);
|
$this->applyInlineStyle($sheet, $row, $column, $attributeArray);
|
||||||
|
|
||||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||||
|
|
||||||
|
$this->processDomElementBgcolor($sheet, $row, $column, $attributeArray);
|
||||||
|
$this->processDomElementWidth($sheet, $column, $attributeArray);
|
||||||
|
$this->processDomElementHeight($sheet, $row, $attributeArray);
|
||||||
|
$this->processDomElementAlign($sheet, $row, $column, $attributeArray);
|
||||||
|
$this->processDomElementVAlign($sheet, $row, $column, $attributeArray);
|
||||||
|
$this->processDomElementDataFormat($sheet, $row, $column, $attributeArray);
|
||||||
|
|
||||||
if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) {
|
if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) {
|
||||||
//create merging rowspan and colspan
|
//create merging rowspan and colspan
|
||||||
$columnTo = $column;
|
$columnTo = $column;
|
||||||
|
@ -522,51 +605,24 @@ class Html extends BaseReader
|
||||||
}
|
}
|
||||||
$sheet->mergeCells($column . $row . ':' . $columnTo . $row);
|
$sheet->mergeCells($column . $row . ':' . $columnTo . $row);
|
||||||
$column = $columnTo;
|
$column = $columnTo;
|
||||||
} elseif (isset($attributeArray['bgcolor'])) {
|
|
||||||
$sheet->getStyle($column . $row)->applyFromArray(
|
|
||||||
[
|
|
||||||
'fill' => [
|
|
||||||
'fillType' => Fill::FILL_SOLID,
|
|
||||||
'color' => ['rgb' => $attributeArray['bgcolor']],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($attributeArray['width'])) {
|
|
||||||
$sheet->getColumnDimension($column)->setWidth($attributeArray['width']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($attributeArray['height'])) {
|
|
||||||
$sheet->getRowDimension($row)->setRowHeight($attributeArray['height']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($attributeArray['align'])) {
|
|
||||||
$sheet->getStyle($column . $row)->getAlignment()->setHorizontal($attributeArray['align']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($attributeArray['valign'])) {
|
|
||||||
$sheet->getStyle($column . $row)->getAlignment()->setVertical($attributeArray['valign']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($attributeArray['data-format'])) {
|
|
||||||
$sheet->getStyle($column . $row)->getNumberFormat()->setFormatCode($attributeArray['data-format']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++$column;
|
++$column;
|
||||||
|
|
||||||
break;
|
|
||||||
case 'body':
|
|
||||||
$row = 1;
|
|
||||||
$column = 'A';
|
|
||||||
$cellContent = '';
|
|
||||||
$this->tableLevel = 0;
|
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function processDomElement(DOMNode $element, Worksheet $sheet, int &$row, string &$column, string &$cellContent): void
|
||||||
|
{
|
||||||
|
foreach ($element->childNodes as $child) {
|
||||||
|
if ($child instanceof DOMText) {
|
||||||
|
$domText = preg_replace('/\s+/u', ' ', trim($child->nodeValue));
|
||||||
|
if (is_string($cellContent)) {
|
||||||
|
// simply append the text if the cell content is a plain text string
|
||||||
|
$cellContent .= $domText;
|
||||||
|
}
|
||||||
|
// but if we have a rich text run instead, we need to append it correctly
|
||||||
|
// TODO
|
||||||
|
} elseif ($child instanceof DOMElement) {
|
||||||
|
$this->processDomElementBody($sheet, $row, $column, $cellContent, $child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,7 +644,11 @@ class Html extends BaseReader
|
||||||
// Create a new DOM object
|
// Create a new DOM object
|
||||||
$dom = new DOMDocument();
|
$dom = new DOMDocument();
|
||||||
// Reload the HTML file into the DOM object
|
// Reload the HTML file into the DOM object
|
||||||
|
try {
|
||||||
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scanFile($pFilename), 'HTML-ENTITIES', 'UTF-8'));
|
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scanFile($pFilename), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$loaded = false;
|
||||||
|
}
|
||||||
if ($loaded === false) {
|
if ($loaded === false) {
|
||||||
throw new Exception('Failed to load ' . $pFilename . ' as a DOM Document');
|
throw new Exception('Failed to load ' . $pFilename . ' as a DOM Document');
|
||||||
}
|
}
|
||||||
|
@ -606,7 +666,11 @@ class Html extends BaseReader
|
||||||
// Create a new DOM object
|
// Create a new DOM object
|
||||||
$dom = new DOMDocument();
|
$dom = new DOMDocument();
|
||||||
// Reload the HTML file into the DOM object
|
// Reload the HTML file into the DOM object
|
||||||
|
try {
|
||||||
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scan($content), 'HTML-ENTITIES', 'UTF-8'));
|
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scan($content), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$loaded = false;
|
||||||
|
}
|
||||||
if ($loaded === false) {
|
if ($loaded === false) {
|
||||||
throw new Exception('Failed to load content as a DOM Document');
|
throw new Exception('Failed to load content as a DOM Document');
|
||||||
}
|
}
|
||||||
|
@ -682,7 +746,26 @@ class Html extends BaseReader
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) {
|
||||||
|
$columnTo = $column;
|
||||||
|
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
|
||||||
|
++$columnTo;
|
||||||
|
}
|
||||||
|
$range = $column . $row . ':' . $columnTo . ($row + (int) $attributeArray['rowspan'] - 1);
|
||||||
|
$cellStyle = $sheet->getStyle($range);
|
||||||
|
} elseif (isset($attributeArray['rowspan'])) {
|
||||||
|
$range = $column . $row . ':' . $column . ($row + (int) $attributeArray['rowspan'] - 1);
|
||||||
|
$cellStyle = $sheet->getStyle($range);
|
||||||
|
} elseif (isset($attributeArray['colspan'])) {
|
||||||
|
$columnTo = $column;
|
||||||
|
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
|
||||||
|
++$columnTo;
|
||||||
|
}
|
||||||
|
$range = $column . $row . ':' . $columnTo . $row;
|
||||||
|
$cellStyle = $sheet->getStyle($range);
|
||||||
|
} else {
|
||||||
$cellStyle = $sheet->getStyle($column . $row);
|
$cellStyle = $sheet->getStyle($column . $row);
|
||||||
|
}
|
||||||
|
|
||||||
// add color styles (background & text) from dom element,currently support : td & th, using ONLY inline css style with RGB color
|
// add color styles (background & text) from dom element,currently support : td & th, using ONLY inline css style with RGB color
|
||||||
$styles = explode(';', $attributeArray['style']);
|
$styles = explode(';', $attributeArray['style']);
|
||||||
|
@ -837,7 +920,7 @@ class Html extends BaseReader
|
||||||
return substr($value, 1);
|
return substr($value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return \PhpOffice\PhpSpreadsheet\Helper\Html::colourNameLookup((string) $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -853,7 +936,7 @@ class Html extends BaseReader
|
||||||
$src = urldecode($attributes['src']);
|
$src = urldecode($attributes['src']);
|
||||||
$width = isset($attributes['width']) ? (float) $attributes['width'] : null;
|
$width = isset($attributes['width']) ? (float) $attributes['width'] : null;
|
||||||
$height = isset($attributes['height']) ? (float) $attributes['height'] : null;
|
$height = isset($attributes['height']) ? (float) $attributes['height'] : null;
|
||||||
$name = isset($attributes['alt']) ? (float) $attributes['alt'] : null;
|
$name = $attributes['alt'] ?? null;
|
||||||
|
|
||||||
$drawing = new Drawing();
|
$drawing = new Drawing();
|
||||||
$drawing->setPath($src);
|
$drawing->setPath($src);
|
||||||
|
@ -884,6 +967,28 @@ class Html extends BaseReader
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static $borderMappings = [
|
||||||
|
'dash-dot' => Border::BORDER_DASHDOT,
|
||||||
|
'dash-dot-dot' => Border::BORDER_DASHDOTDOT,
|
||||||
|
'dashed' => Border::BORDER_DASHED,
|
||||||
|
'dotted' => Border::BORDER_DOTTED,
|
||||||
|
'double' => Border::BORDER_DOUBLE,
|
||||||
|
'hair' => Border::BORDER_HAIR,
|
||||||
|
'medium' => Border::BORDER_MEDIUM,
|
||||||
|
'medium-dashed' => Border::BORDER_MEDIUMDASHED,
|
||||||
|
'medium-dash-dot' => Border::BORDER_MEDIUMDASHDOT,
|
||||||
|
'medium-dash-dot-dot' => Border::BORDER_MEDIUMDASHDOTDOT,
|
||||||
|
'none' => Border::BORDER_NONE,
|
||||||
|
'slant-dash-dot' => Border::BORDER_SLANTDASHDOT,
|
||||||
|
'solid' => Border::BORDER_THIN,
|
||||||
|
'thick' => Border::BORDER_THICK,
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function getBorderMappings(): array
|
||||||
|
{
|
||||||
|
return self::$borderMappings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map html border style to PhpSpreadsheet border style.
|
* Map html border style to PhpSpreadsheet border style.
|
||||||
*
|
*
|
||||||
|
@ -893,38 +998,7 @@ class Html extends BaseReader
|
||||||
*/
|
*/
|
||||||
public function getBorderStyle($style)
|
public function getBorderStyle($style)
|
||||||
{
|
{
|
||||||
switch ($style) {
|
return (array_key_exists($style, self::$borderMappings)) ? self::$borderMappings[$style] : null;
|
||||||
case 'solid':
|
|
||||||
return Border::BORDER_THIN;
|
|
||||||
case 'dashed':
|
|
||||||
return Border::BORDER_DASHED;
|
|
||||||
case 'dotted':
|
|
||||||
return Border::BORDER_DOTTED;
|
|
||||||
case 'medium':
|
|
||||||
return Border::BORDER_MEDIUM;
|
|
||||||
case 'thick':
|
|
||||||
return Border::BORDER_THICK;
|
|
||||||
case 'none':
|
|
||||||
return Border::BORDER_NONE;
|
|
||||||
case 'dash-dot':
|
|
||||||
return Border::BORDER_DASHDOT;
|
|
||||||
case 'dash-dot-dot':
|
|
||||||
return Border::BORDER_DASHDOTDOT;
|
|
||||||
case 'double':
|
|
||||||
return Border::BORDER_DOUBLE;
|
|
||||||
case 'hair':
|
|
||||||
return Border::BORDER_HAIR;
|
|
||||||
case 'medium-dash-dot':
|
|
||||||
return Border::BORDER_MEDIUMDASHDOT;
|
|
||||||
case 'medium-dash-dot-dot':
|
|
||||||
return Border::BORDER_MEDIUMDASHDOTDOT;
|
|
||||||
case 'medium-dashed':
|
|
||||||
return Border::BORDER_MEDIUMDASHED;
|
|
||||||
case 'slant-dash-dot':
|
|
||||||
return Border::BORDER_SLANTDASHDOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,9 @@ use DOMNode;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\DefinedName;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Ods\PageSettings;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Ods\Properties as DocumentProperties;
|
use PhpOffice\PhpSpreadsheet\Reader\Ods\Properties as DocumentProperties;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
|
@ -19,6 +22,7 @@ use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
use XMLReader;
|
use XMLReader;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
|
|
||||||
|
@ -75,11 +79,9 @@ class Ods extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
$zip->close();
|
$zip->close();
|
||||||
|
|
||||||
return $mimeType === 'application/vnd.oasis.opendocument.spreadsheet';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return $mimeType === 'application/vnd.oasis.opendocument.spreadsheet';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,8 +96,8 @@ class Ods extends BaseReader
|
||||||
File::assertFile($pFilename);
|
File::assertFile($pFilename);
|
||||||
|
|
||||||
$zip = new ZipArchive();
|
$zip = new ZipArchive();
|
||||||
if (!$zip->open($pFilename)) {
|
if ($zip->open($pFilename) !== true) {
|
||||||
throw new Exception('Could not open ' . $pFilename . ' for reading! Error opening file.');
|
throw new ReaderException('Could not open ' . $pFilename . ' for reading! Error opening file.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$worksheetNames = [];
|
$worksheetNames = [];
|
||||||
|
@ -148,8 +150,8 @@ class Ods extends BaseReader
|
||||||
$worksheetInfo = [];
|
$worksheetInfo = [];
|
||||||
|
|
||||||
$zip = new ZipArchive();
|
$zip = new ZipArchive();
|
||||||
if (!$zip->open($pFilename)) {
|
if ($zip->open($pFilename) !== true) {
|
||||||
throw new Exception('Could not open ' . $pFilename . ' for reading! Error opening file.');
|
throw new ReaderException('Could not open ' . $pFilename . ' for reading! Error opening file.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$xml = new XMLReader();
|
$xml = new XMLReader();
|
||||||
|
@ -197,18 +199,18 @@ class Ods extends BaseReader
|
||||||
// Step into the row
|
// Step into the row
|
||||||
$xml->read();
|
$xml->read();
|
||||||
do {
|
do {
|
||||||
|
$doread = true;
|
||||||
if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
|
if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
|
||||||
if (!$xml->isEmptyElement) {
|
if (!$xml->isEmptyElement) {
|
||||||
++$currCells;
|
++$currCells;
|
||||||
$xml->next();
|
$xml->next();
|
||||||
} else {
|
$doread = false;
|
||||||
$xml->read();
|
|
||||||
}
|
}
|
||||||
} elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
|
} elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
|
||||||
$mergeSize = $xml->getAttribute('table:number-columns-repeated');
|
$mergeSize = $xml->getAttribute('table:number-columns-repeated');
|
||||||
$currCells += (int) $mergeSize;
|
$currCells += (int) $mergeSize;
|
||||||
$xml->read();
|
}
|
||||||
} else {
|
if ($doread) {
|
||||||
$xml->read();
|
$xml->read();
|
||||||
}
|
}
|
||||||
} while ($xml->name != 'table:table-row');
|
} while ($xml->name != 'table:table-row');
|
||||||
|
@ -257,13 +259,13 @@ class Ods extends BaseReader
|
||||||
$GMT = new DateTimeZone('UTC');
|
$GMT = new DateTimeZone('UTC');
|
||||||
|
|
||||||
$zip = new ZipArchive();
|
$zip = new ZipArchive();
|
||||||
if (!$zip->open($pFilename)) {
|
if ($zip->open($pFilename) !== true) {
|
||||||
throw new Exception("Could not open {$pFilename} for reading! Error opening file.");
|
throw new Exception("Could not open {$pFilename} for reading! Error opening file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Meta
|
// Meta
|
||||||
|
|
||||||
$xml = simplexml_load_string(
|
$xml = @simplexml_load_string(
|
||||||
$this->securityScanner->scan($zip->getFromName('meta.xml')),
|
$this->securityScanner->scan($zip->getFromName('meta.xml')),
|
||||||
'SimpleXMLElement',
|
'SimpleXMLElement',
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
|
@ -276,7 +278,17 @@ class Ods extends BaseReader
|
||||||
|
|
||||||
(new DocumentProperties($spreadsheet))->load($xml, $namespacesMeta);
|
(new DocumentProperties($spreadsheet))->load($xml, $namespacesMeta);
|
||||||
|
|
||||||
// Content
|
// Styles
|
||||||
|
|
||||||
|
$dom = new DOMDocument('1.01', 'UTF-8');
|
||||||
|
$dom->loadXML(
|
||||||
|
$this->securityScanner->scan($zip->getFromName('styles.xml')),
|
||||||
|
Settings::getLibXmlLoaderOptions()
|
||||||
|
);
|
||||||
|
|
||||||
|
$pageSettings = new PageSettings($dom);
|
||||||
|
|
||||||
|
// Main Content
|
||||||
|
|
||||||
$dom = new DOMDocument('1.01', 'UTF-8');
|
$dom = new DOMDocument('1.01', 'UTF-8');
|
||||||
$dom->loadXML(
|
$dom->loadXML(
|
||||||
|
@ -289,6 +301,10 @@ class Ods extends BaseReader
|
||||||
$textNs = $dom->lookupNamespaceUri('text');
|
$textNs = $dom->lookupNamespaceUri('text');
|
||||||
$xlinkNs = $dom->lookupNamespaceUri('xlink');
|
$xlinkNs = $dom->lookupNamespaceUri('xlink');
|
||||||
|
|
||||||
|
$pageSettings->readStyleCrossReferences($dom);
|
||||||
|
|
||||||
|
// Content
|
||||||
|
|
||||||
$spreadsheets = $dom->getElementsByTagNameNS($officeNs, 'body')
|
$spreadsheets = $dom->getElementsByTagNameNS($officeNs, 'body')
|
||||||
->item(0)
|
->item(0)
|
||||||
->getElementsByTagNameNS($officeNs, 'spreadsheet');
|
->getElementsByTagNameNS($officeNs, 'spreadsheet');
|
||||||
|
@ -303,12 +319,16 @@ class Ods extends BaseReader
|
||||||
$worksheetName = $worksheetDataSet->getAttributeNS($tableNs, 'name');
|
$worksheetName = $worksheetDataSet->getAttributeNS($tableNs, 'name');
|
||||||
|
|
||||||
// Check loadSheetsOnly
|
// Check loadSheetsOnly
|
||||||
if (isset($this->loadSheetsOnly)
|
if (
|
||||||
|
isset($this->loadSheetsOnly)
|
||||||
&& $worksheetName
|
&& $worksheetName
|
||||||
&& !in_array($worksheetName, $this->loadSheetsOnly)) {
|
&& !in_array($worksheetName, $this->loadSheetsOnly)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$worksheetStyleName = $worksheetDataSet->getAttributeNS($tableNs, 'style-name');
|
||||||
|
|
||||||
// Create sheet
|
// Create sheet
|
||||||
if ($worksheetID > 0) {
|
if ($worksheetID > 0) {
|
||||||
$spreadsheet->createSheet(); // First sheet is added by default
|
$spreadsheet->createSheet(); // First sheet is added by default
|
||||||
|
@ -319,7 +339,7 @@ class Ods extends BaseReader
|
||||||
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
|
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
|
||||||
// formula cells... during the load, all formulae should be correct, and we're simply
|
// formula cells... during the load, all formulae should be correct, and we're simply
|
||||||
// bringing the worksheet name in line with the formula, not the reverse
|
// bringing the worksheet name in line with the formula, not the reverse
|
||||||
$spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false);
|
$spreadsheet->getActiveSheet()->setTitle((string) $worksheetName, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through every child of table element
|
// Go through every child of table element
|
||||||
|
@ -448,9 +468,10 @@ class Ods extends BaseReader
|
||||||
$type = DataType::TYPE_NUMERIC;
|
$type = DataType::TYPE_NUMERIC;
|
||||||
$dataValue = (float) $cellData->getAttributeNS($officeNs, 'value');
|
$dataValue = (float) $cellData->getAttributeNS($officeNs, 'value');
|
||||||
|
|
||||||
if (floor($dataValue) == $dataValue) {
|
// percentage should always be float
|
||||||
$dataValue = (int) $dataValue;
|
//if (floor($dataValue) == $dataValue) {
|
||||||
}
|
// $dataValue = (int) $dataValue;
|
||||||
|
//}
|
||||||
$formatting = NumberFormat::FORMAT_PERCENTAGE_00;
|
$formatting = NumberFormat::FORMAT_PERCENTAGE_00;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -471,8 +492,6 @@ class Ods extends BaseReader
|
||||||
if (floor($dataValue) == $dataValue) {
|
if (floor($dataValue) == $dataValue) {
|
||||||
if ($dataValue == (int) $dataValue) {
|
if ($dataValue == (int) $dataValue) {
|
||||||
$dataValue = (int) $dataValue;
|
$dataValue = (int) $dataValue;
|
||||||
} else {
|
|
||||||
$dataValue = (float) $dataValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,30 +549,7 @@ class Ods extends BaseReader
|
||||||
if ($hasCalculatedValue) {
|
if ($hasCalculatedValue) {
|
||||||
$type = DataType::TYPE_FORMULA;
|
$type = DataType::TYPE_FORMULA;
|
||||||
$cellDataFormula = substr($cellDataFormula, strpos($cellDataFormula, ':=') + 1);
|
$cellDataFormula = substr($cellDataFormula, strpos($cellDataFormula, ':=') + 1);
|
||||||
$temp = explode('"', $cellDataFormula);
|
$cellDataFormula = $this->convertToExcelFormulaValue($cellDataFormula);
|
||||||
$tKey = false;
|
|
||||||
foreach ($temp as &$value) {
|
|
||||||
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
|
||||||
if ($tKey = !$tKey) {
|
|
||||||
// Cell range reference in another sheet
|
|
||||||
$value = preg_replace('/\[([^\.]+)\.([^\.]+):\.([^\.]+)\]/U', '$1!$2:$3', $value);
|
|
||||||
|
|
||||||
// Cell reference in another sheet
|
|
||||||
$value = preg_replace('/\[([^\.]+)\.([^\.]+)\]/U', '$1!$2', $value);
|
|
||||||
|
|
||||||
// Cell range reference
|
|
||||||
$value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/U', '$1:$2', $value);
|
|
||||||
|
|
||||||
// Simple cell reference
|
|
||||||
$value = preg_replace('/\[\.([^\.]+)\]/U', '$1', $value);
|
|
||||||
|
|
||||||
$value = Calculation::translateSeparator(';', ',', $value, $inBraces);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($value);
|
|
||||||
|
|
||||||
// Then rebuild the formula string
|
|
||||||
$cellDataFormula = implode('"', $temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cellData->hasAttributeNS($tableNs, 'number-columns-repeated')) {
|
if ($cellData->hasAttributeNS($tableNs, 'number-columns-repeated')) {
|
||||||
|
@ -609,7 +605,8 @@ class Ods extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merged cells
|
// Merged cells
|
||||||
if ($cellData->hasAttributeNS($tableNs, 'number-columns-spanned')
|
if (
|
||||||
|
$cellData->hasAttributeNS($tableNs, 'number-columns-spanned')
|
||||||
|| $cellData->hasAttributeNS($tableNs, 'number-rows-spanned')
|
|| $cellData->hasAttributeNS($tableNs, 'number-rows-spanned')
|
||||||
) {
|
) {
|
||||||
if (($type !== DataType::TYPE_NULL) || (!$this->readDataOnly)) {
|
if (($type !== DataType::TYPE_NULL) || (!$this->readDataOnly)) {
|
||||||
|
@ -641,10 +638,14 @@ class Ods extends BaseReader
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$pageSettings->setPrintSettingsForWorksheet($spreadsheet->getActiveSheet(), $worksheetStyleName);
|
||||||
++$worksheetID;
|
++$worksheetID;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
$this->readDefinedRanges($spreadsheet, $workbookData, $tableNs);
|
||||||
|
$this->readDefinedExpressions($spreadsheet, $workbookData, $tableNs);
|
||||||
|
}
|
||||||
|
$spreadsheet->setActiveSheetIndex(0);
|
||||||
// Return
|
// Return
|
||||||
return $spreadsheet;
|
return $spreadsheet;
|
||||||
}
|
}
|
||||||
|
@ -696,4 +697,99 @@ class Ods extends BaseReader
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function convertToExcelAddressValue(string $openOfficeAddress): string
|
||||||
|
{
|
||||||
|
$excelAddress = $openOfficeAddress;
|
||||||
|
|
||||||
|
// Cell range 3-d reference
|
||||||
|
// As we don't support 3-d ranges, we're just going to take a quick and dirty approach
|
||||||
|
// and assume that the second worksheet reference is the same as the first
|
||||||
|
$excelAddress = preg_replace('/\$?([^\.]+)\.([^\.]+):\$?([^\.]+)\.([^\.]+)/miu', '$1!$2:$4', $excelAddress);
|
||||||
|
// Cell range reference in another sheet
|
||||||
|
$excelAddress = preg_replace('/\$?([^\.]+)\.([^\.]+):\.([^\.]+)/miu', '$1!$2:$3', $excelAddress);
|
||||||
|
// Cell reference in another sheet
|
||||||
|
$excelAddress = preg_replace('/\$?([^\.]+)\.([^\.]+)/miu', '$1!$2', $excelAddress);
|
||||||
|
// Cell range reference
|
||||||
|
$excelAddress = preg_replace('/\.([^\.]+):\.([^\.]+)/miu', '$1:$2', $excelAddress);
|
||||||
|
// Simple cell reference
|
||||||
|
$excelAddress = preg_replace('/\.([^\.]+)/miu', '$1', $excelAddress);
|
||||||
|
|
||||||
|
return $excelAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function convertToExcelFormulaValue(string $openOfficeFormula): string
|
||||||
|
{
|
||||||
|
$temp = explode('"', $openOfficeFormula);
|
||||||
|
$tKey = false;
|
||||||
|
foreach ($temp as &$value) {
|
||||||
|
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
||||||
|
if ($tKey = !$tKey) {
|
||||||
|
// Cell range reference in another sheet
|
||||||
|
$value = preg_replace('/\[\$?([^\.]+)\.([^\.]+):\.([^\.]+)\]/miu', '$1!$2:$3', $value);
|
||||||
|
// Cell reference in another sheet
|
||||||
|
$value = preg_replace('/\[\$?([^\.]+)\.([^\.]+)\]/miu', '$1!$2', $value);
|
||||||
|
// Cell range reference
|
||||||
|
$value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/miu', '$1:$2', $value);
|
||||||
|
// Simple cell reference
|
||||||
|
$value = preg_replace('/\[\.([^\.]+)\]/miu', '$1', $value);
|
||||||
|
|
||||||
|
$value = Calculation::translateSeparator(';', ',', $value, $inBraces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then rebuild the formula string
|
||||||
|
$excelFormula = implode('"', $temp);
|
||||||
|
|
||||||
|
return $excelFormula;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read any Named Ranges that are defined in this spreadsheet.
|
||||||
|
*/
|
||||||
|
private function readDefinedRanges(Spreadsheet $spreadsheet, DOMElement $workbookData, string $tableNs): void
|
||||||
|
{
|
||||||
|
$namedRanges = $workbookData->getElementsByTagNameNS($tableNs, 'named-range');
|
||||||
|
foreach ($namedRanges as $definedNameElement) {
|
||||||
|
$definedName = $definedNameElement->getAttributeNS($tableNs, 'name');
|
||||||
|
$baseAddress = $definedNameElement->getAttributeNS($tableNs, 'base-cell-address');
|
||||||
|
$range = $definedNameElement->getAttributeNS($tableNs, 'cell-range-address');
|
||||||
|
|
||||||
|
$baseAddress = $this->convertToExcelAddressValue($baseAddress);
|
||||||
|
$range = $this->convertToExcelAddressValue($range);
|
||||||
|
|
||||||
|
$this->addDefinedName($spreadsheet, $baseAddress, $definedName, $range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read any Named Formulae that are defined in this spreadsheet.
|
||||||
|
*/
|
||||||
|
private function readDefinedExpressions(Spreadsheet $spreadsheet, DOMElement $workbookData, string $tableNs): void
|
||||||
|
{
|
||||||
|
$namedExpressions = $workbookData->getElementsByTagNameNS($tableNs, 'named-expression');
|
||||||
|
foreach ($namedExpressions as $definedNameElement) {
|
||||||
|
$definedName = $definedNameElement->getAttributeNS($tableNs, 'name');
|
||||||
|
$baseAddress = $definedNameElement->getAttributeNS($tableNs, 'base-cell-address');
|
||||||
|
$expression = $definedNameElement->getAttributeNS($tableNs, 'expression');
|
||||||
|
|
||||||
|
$baseAddress = $this->convertToExcelAddressValue($baseAddress);
|
||||||
|
$expression = $this->convertToExcelFormulaValue($expression);
|
||||||
|
|
||||||
|
$this->addDefinedName($spreadsheet, $baseAddress, $definedName, $expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assess scope and store the Defined Name.
|
||||||
|
*/
|
||||||
|
private function addDefinedName(Spreadsheet $spreadsheet, string $baseAddress, string $definedName, string $value): void
|
||||||
|
{
|
||||||
|
[$sheetReference] = Worksheet::extractSheetTitle($baseAddress, true);
|
||||||
|
$worksheet = $spreadsheet->getSheetByName($sheetReference);
|
||||||
|
// Worksheet might still be null if we're only loading selected sheets rather than the full spreadsheet
|
||||||
|
if ($worksheet !== null) {
|
||||||
|
$spreadsheet->addDefinedName(DefinedName::createInstance((string) $definedName, $worksheet, $value));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Reader\Ods;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class PageSettings
|
||||||
|
{
|
||||||
|
private $officeNs;
|
||||||
|
|
||||||
|
private $stylesNs;
|
||||||
|
|
||||||
|
private $stylesFo;
|
||||||
|
|
||||||
|
private $pageLayoutStyles = [];
|
||||||
|
|
||||||
|
private $masterStylesCrossReference = [];
|
||||||
|
|
||||||
|
private $masterPrintStylesCrossReference = [];
|
||||||
|
|
||||||
|
public function __construct(DOMDocument $styleDom)
|
||||||
|
{
|
||||||
|
$this->setDomNameSpaces($styleDom);
|
||||||
|
$this->readPageSettingStyles($styleDom);
|
||||||
|
$this->readStyleMasterLookup($styleDom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setDomNameSpaces(DOMDocument $styleDom): void
|
||||||
|
{
|
||||||
|
$this->officeNs = $styleDom->lookupNamespaceUri('office');
|
||||||
|
$this->stylesNs = $styleDom->lookupNamespaceUri('style');
|
||||||
|
$this->stylesFo = $styleDom->lookupNamespaceUri('fo');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readPageSettingStyles(DOMDocument $styleDom): void
|
||||||
|
{
|
||||||
|
$styles = $styleDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')
|
||||||
|
->item(0)
|
||||||
|
->getElementsByTagNameNS($this->stylesNs, 'page-layout');
|
||||||
|
|
||||||
|
foreach ($styles as $styleSet) {
|
||||||
|
$styleName = $styleSet->getAttributeNS($this->stylesNs, 'name');
|
||||||
|
$pageLayoutProperties = $styleSet->getElementsByTagNameNS($this->stylesNs, 'page-layout-properties')[0];
|
||||||
|
$styleOrientation = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-orientation');
|
||||||
|
$styleScale = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'scale-to');
|
||||||
|
$stylePrintOrder = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-page-order');
|
||||||
|
$centered = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'table-centering');
|
||||||
|
|
||||||
|
$marginLeft = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-left');
|
||||||
|
$marginRight = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-right');
|
||||||
|
$marginTop = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-top');
|
||||||
|
$marginBottom = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-bottom');
|
||||||
|
$header = $styleSet->getElementsByTagNameNS($this->stylesNs, 'header-style')[0];
|
||||||
|
$headerProperties = $header->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0];
|
||||||
|
$marginHeader = $headerProperties->getAttributeNS($this->stylesFo, 'min-height');
|
||||||
|
$footer = $styleSet->getElementsByTagNameNS($this->stylesNs, 'footer-style')[0];
|
||||||
|
$footerProperties = $footer->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0];
|
||||||
|
$marginFooter = $footerProperties->getAttributeNS($this->stylesFo, 'min-height');
|
||||||
|
|
||||||
|
$this->pageLayoutStyles[$styleName] = (object) [
|
||||||
|
'orientation' => $styleOrientation ?: PageSetup::ORIENTATION_DEFAULT,
|
||||||
|
'scale' => $styleScale ?: 100,
|
||||||
|
'printOrder' => $stylePrintOrder,
|
||||||
|
'horizontalCentered' => $centered === 'horizontal' || $centered === 'both',
|
||||||
|
'verticalCentered' => $centered === 'vertical' || $centered === 'both',
|
||||||
|
// margin size is already stored in inches, so no UOM conversion is required
|
||||||
|
'marginLeft' => (float) $marginLeft ?? 0.7,
|
||||||
|
'marginRight' => (float) $marginRight ?? 0.7,
|
||||||
|
'marginTop' => (float) $marginTop ?? 0.3,
|
||||||
|
'marginBottom' => (float) $marginBottom ?? 0.3,
|
||||||
|
'marginHeader' => (float) $marginHeader ?? 0.45,
|
||||||
|
'marginFooter' => (float) $marginFooter ?? 0.45,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readStyleMasterLookup(DOMDocument $styleDom): void
|
||||||
|
{
|
||||||
|
$styleMasterLookup = $styleDom->getElementsByTagNameNS($this->officeNs, 'master-styles')
|
||||||
|
->item(0)
|
||||||
|
->getElementsByTagNameNS($this->stylesNs, 'master-page');
|
||||||
|
|
||||||
|
foreach ($styleMasterLookup as $styleMasterSet) {
|
||||||
|
$styleMasterName = $styleMasterSet->getAttributeNS($this->stylesNs, 'name');
|
||||||
|
$pageLayoutName = $styleMasterSet->getAttributeNS($this->stylesNs, 'page-layout-name');
|
||||||
|
$this->masterPrintStylesCrossReference[$styleMasterName] = $pageLayoutName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStyleCrossReferences(DOMDocument $contentDom): void
|
||||||
|
{
|
||||||
|
$styleXReferences = $contentDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')
|
||||||
|
->item(0)
|
||||||
|
->getElementsByTagNameNS($this->stylesNs, 'style');
|
||||||
|
|
||||||
|
foreach ($styleXReferences as $styleXreferenceSet) {
|
||||||
|
$styleXRefName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'name');
|
||||||
|
$stylePageLayoutName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'master-page-name');
|
||||||
|
if (!empty($stylePageLayoutName)) {
|
||||||
|
$this->masterStylesCrossReference[$styleXRefName] = $stylePageLayoutName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrintSettingsForWorksheet(Worksheet $worksheet, string $styleName): void
|
||||||
|
{
|
||||||
|
if (!array_key_exists($styleName, $this->masterStylesCrossReference)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$masterStyleName = $this->masterStylesCrossReference[$styleName];
|
||||||
|
|
||||||
|
if (!array_key_exists($masterStyleName, $this->masterPrintStylesCrossReference)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$printSettingsIndex = $this->masterPrintStylesCrossReference[$masterStyleName];
|
||||||
|
|
||||||
|
if (!array_key_exists($printSettingsIndex, $this->pageLayoutStyles)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$printSettings = $this->pageLayoutStyles[$printSettingsIndex];
|
||||||
|
|
||||||
|
$worksheet->getPageSetup()
|
||||||
|
->setOrientation($printSettings->orientation ?? PageSetup::ORIENTATION_DEFAULT)
|
||||||
|
->setPageOrder($printSettings->printOrder === 'ltr' ? PageSetup::PAGEORDER_OVER_THEN_DOWN : PageSetup::PAGEORDER_DOWN_THEN_OVER)
|
||||||
|
->setScale((int) trim($printSettings->scale, '%'))
|
||||||
|
->setHorizontalCentered($printSettings->horizontalCentered)
|
||||||
|
->setVerticalCentered($printSettings->verticalCentered);
|
||||||
|
|
||||||
|
$worksheet->getPageMargins()
|
||||||
|
->setLeft($printSettings->marginLeft)
|
||||||
|
->setRight($printSettings->marginRight)
|
||||||
|
->setTop($printSettings->marginTop)
|
||||||
|
->setBottom($printSettings->marginBottom)
|
||||||
|
->setHeader($printSettings->marginHeader)
|
||||||
|
->setFooter($printSettings->marginFooter);
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,15 +54,11 @@ class Properties
|
||||||
$docProps->setLastModifiedBy($propertyValue);
|
$docProps->setLastModifiedBy($propertyValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'creation-date':
|
case 'date':
|
||||||
$creationDate = strtotime($propertyValue);
|
$creationDate = strtotime($propertyValue);
|
||||||
$docProps->setCreated($creationDate);
|
$docProps->setCreated($creationDate);
|
||||||
$docProps->setModified($creationDate);
|
$docProps->setModified($creationDate);
|
||||||
|
|
||||||
break;
|
|
||||||
case 'keyword':
|
|
||||||
$docProps->setKeywords($propertyValue);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'description':
|
case 'description':
|
||||||
$docProps->setDescription($propertyValue);
|
$docProps->setDescription($propertyValue);
|
||||||
|
|
|
@ -63,7 +63,7 @@ class XmlScanner
|
||||||
|
|
||||||
private function disableEntityLoaderCheck(): void
|
private function disableEntityLoaderCheck(): void
|
||||||
{
|
{
|
||||||
if (Settings::getLibXmlDisableEntityLoader()) {
|
if (Settings::getLibXmlDisableEntityLoader() && \PHP_VERSION_ID < 80000) {
|
||||||
$libxmlDisableEntityLoaderValue = libxml_disable_entity_loader(true);
|
$libxmlDisableEntityLoaderValue = libxml_disable_entity_loader(true);
|
||||||
|
|
||||||
if (self::$libxmlDisableEntityLoaderValue === null) {
|
if (self::$libxmlDisableEntityLoaderValue === null) {
|
||||||
|
@ -74,7 +74,7 @@ class XmlScanner
|
||||||
|
|
||||||
public static function shutdown(): void
|
public static function shutdown(): void
|
||||||
{
|
{
|
||||||
if (self::$libxmlDisableEntityLoaderValue !== null) {
|
if (self::$libxmlDisableEntityLoaderValue !== null && \PHP_VERSION_ID < 80000) {
|
||||||
libxml_disable_entity_loader(self::$libxmlDisableEntityLoaderValue);
|
libxml_disable_entity_loader(self::$libxmlDisableEntityLoaderValue);
|
||||||
self::$libxmlDisableEntityLoaderValue = null;
|
self::$libxmlDisableEntityLoaderValue = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Reader;
|
namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
|
@ -38,6 +40,20 @@ class Slk extends BaseReader
|
||||||
*/
|
*/
|
||||||
private $format = 0;
|
private $format = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonts.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $fonts = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Font Count.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $fontcount = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new SYLK Reader instance.
|
* Create a new SYLK Reader instance.
|
||||||
*/
|
*/
|
||||||
|
@ -55,10 +71,9 @@ class Slk extends BaseReader
|
||||||
*/
|
*/
|
||||||
public function canRead($pFilename)
|
public function canRead($pFilename)
|
||||||
{
|
{
|
||||||
// Check if file exists
|
|
||||||
try {
|
try {
|
||||||
$this->openFile($pFilename);
|
$this->openFile($pFilename);
|
||||||
} catch (Exception $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +93,24 @@ class Slk extends BaseReader
|
||||||
return $hasDelimiter && $hasId;
|
return $hasDelimiter && $hasId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function canReadOrBust(string $pFilename): void
|
||||||
|
{
|
||||||
|
if (!$this->canRead($pFilename)) {
|
||||||
|
throw new ReaderException($pFilename . ' is an Invalid SYLK file.');
|
||||||
|
}
|
||||||
|
$this->openFile($pFilename);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set input encoding.
|
* Set input encoding.
|
||||||
*
|
*
|
||||||
|
* @deprecated no use is made of this property
|
||||||
|
*
|
||||||
* @param string $pValue Input encoding, eg: 'ANSI'
|
* @param string $pValue Input encoding, eg: 'ANSI'
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function setInputEncoding($pValue)
|
public function setInputEncoding($pValue)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +122,11 @@ class Slk extends BaseReader
|
||||||
/**
|
/**
|
||||||
* Get input encoding.
|
* Get input encoding.
|
||||||
*
|
*
|
||||||
|
* @deprecated no use is made of this property
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function getInputEncoding()
|
public function getInputEncoding()
|
||||||
{
|
{
|
||||||
|
@ -112,22 +143,16 @@ class Slk extends BaseReader
|
||||||
public function listWorksheetInfo($pFilename)
|
public function listWorksheetInfo($pFilename)
|
||||||
{
|
{
|
||||||
// Open file
|
// Open file
|
||||||
if (!$this->canRead($pFilename)) {
|
$this->canReadOrBust($pFilename);
|
||||||
throw new Exception($pFilename . ' is an Invalid Spreadsheet file.');
|
|
||||||
}
|
|
||||||
$this->openFile($pFilename);
|
|
||||||
$fileHandle = $this->fileHandle;
|
$fileHandle = $this->fileHandle;
|
||||||
rewind($fileHandle);
|
rewind($fileHandle);
|
||||||
|
|
||||||
$worksheetInfo = [];
|
$worksheetInfo = [];
|
||||||
$worksheetInfo[0]['worksheetName'] = 'Worksheet';
|
$worksheetInfo[0]['worksheetName'] = basename($pFilename, '.slk');
|
||||||
$worksheetInfo[0]['lastColumnLetter'] = 'A';
|
|
||||||
$worksheetInfo[0]['lastColumnIndex'] = 0;
|
|
||||||
$worksheetInfo[0]['totalRows'] = 0;
|
|
||||||
$worksheetInfo[0]['totalColumns'] = 0;
|
|
||||||
|
|
||||||
// loop through one row (line) at a time in the file
|
// loop through one row (line) at a time in the file
|
||||||
$rowIndex = 0;
|
$rowIndex = 0;
|
||||||
|
$columnIndex = 0;
|
||||||
while (($rowData = fgets($fileHandle)) !== false) {
|
while (($rowData = fgets($fileHandle)) !== false) {
|
||||||
$columnIndex = 0;
|
$columnIndex = 0;
|
||||||
|
|
||||||
|
@ -139,28 +164,26 @@ class Slk extends BaseReader
|
||||||
$rowData = explode("\t", str_replace('¤', ';', str_replace(';', "\t", str_replace(';;', '¤', rtrim($rowData)))));
|
$rowData = explode("\t", str_replace('¤', ';', str_replace(';', "\t", str_replace(';;', '¤', rtrim($rowData)))));
|
||||||
|
|
||||||
$dataType = array_shift($rowData);
|
$dataType = array_shift($rowData);
|
||||||
if ($dataType == 'C') {
|
if ($dataType == 'B') {
|
||||||
// Read cell value data
|
|
||||||
foreach ($rowData as $rowDatum) {
|
foreach ($rowData as $rowDatum) {
|
||||||
switch ($rowDatum[0]) {
|
switch ($rowDatum[0]) {
|
||||||
case 'C':
|
|
||||||
case 'X':
|
case 'X':
|
||||||
$columnIndex = substr($rowDatum, 1) - 1;
|
$columnIndex = substr($rowDatum, 1) - 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'R':
|
|
||||||
case 'Y':
|
case 'Y':
|
||||||
$rowIndex = substr($rowDatum, 1);
|
$rowIndex = substr($rowDatum, 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$worksheetInfo[0]['totalRows'] = max($worksheetInfo[0]['totalRows'], $rowIndex);
|
|
||||||
$worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], $columnIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$worksheetInfo[0]['lastColumnIndex'] = $columnIndex;
|
||||||
|
$worksheetInfo[0]['totalRows'] = $rowIndex;
|
||||||
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
|
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
|
||||||
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
|
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
|
||||||
|
|
||||||
|
@ -186,120 +209,25 @@ class Slk extends BaseReader
|
||||||
return $this->loadIntoExisting($pFilename, $spreadsheet);
|
return $this->loadIntoExisting($pFilename, $spreadsheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private $colorArray = [
|
||||||
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
|
'FF00FFFF', // 0 - cyan
|
||||||
*
|
'FF000000', // 1 - black
|
||||||
* @param string $pFilename
|
'FFFFFFFF', // 2 - white
|
||||||
*
|
'FFFF0000', // 3 - red
|
||||||
* @return Spreadsheet
|
'FF00FF00', // 4 - green
|
||||||
*/
|
'FF0000FF', // 5 - blue
|
||||||
public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet)
|
'FFFFFF00', // 6 - yellow
|
||||||
|
'FFFF00FF', // 7 - magenta
|
||||||
|
];
|
||||||
|
|
||||||
|
private $fontStyleMappings = [
|
||||||
|
'B' => 'bold',
|
||||||
|
'I' => 'italic',
|
||||||
|
'U' => 'underline',
|
||||||
|
];
|
||||||
|
|
||||||
|
private function processFormula(string $rowDatum, bool &$hasCalculatedValue, string &$cellDataFormula, string $row, string $column): void
|
||||||
{
|
{
|
||||||
// Open file
|
|
||||||
if (!$this->canRead($pFilename)) {
|
|
||||||
throw new Exception($pFilename . ' is an Invalid Spreadsheet file.');
|
|
||||||
}
|
|
||||||
$this->openFile($pFilename);
|
|
||||||
$fileHandle = $this->fileHandle;
|
|
||||||
rewind($fileHandle);
|
|
||||||
|
|
||||||
// Create new Worksheets
|
|
||||||
while ($spreadsheet->getSheetCount() <= $this->sheetIndex) {
|
|
||||||
$spreadsheet->createSheet();
|
|
||||||
}
|
|
||||||
$spreadsheet->setActiveSheetIndex($this->sheetIndex);
|
|
||||||
|
|
||||||
$fromFormats = ['\-', '\ '];
|
|
||||||
$toFormats = ['-', ' '];
|
|
||||||
|
|
||||||
// Loop through file
|
|
||||||
$column = $row = '';
|
|
||||||
|
|
||||||
// loop through one row (line) at a time in the file
|
|
||||||
while (($rowData = fgets($fileHandle)) !== false) {
|
|
||||||
// convert SYLK encoded $rowData to UTF-8
|
|
||||||
$rowData = StringHelper::SYLKtoUTF8($rowData);
|
|
||||||
|
|
||||||
// explode each row at semicolons while taking into account that literal semicolon (;)
|
|
||||||
// is escaped like this (;;)
|
|
||||||
$rowData = explode("\t", str_replace('¤', ';', str_replace(';', "\t", str_replace(';;', '¤', rtrim($rowData)))));
|
|
||||||
|
|
||||||
$dataType = array_shift($rowData);
|
|
||||||
// Read shared styles
|
|
||||||
if ($dataType == 'P') {
|
|
||||||
$formatArray = [];
|
|
||||||
foreach ($rowData as $rowDatum) {
|
|
||||||
switch ($rowDatum[0]) {
|
|
||||||
case 'P':
|
|
||||||
$formatArray['numberFormat']['formatCode'] = str_replace($fromFormats, $toFormats, substr($rowDatum, 1));
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
case 'F':
|
|
||||||
$formatArray['font']['name'] = substr($rowDatum, 1);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
$formatArray['font']['size'] = substr($rowDatum, 1);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
$styleSettings = substr($rowDatum, 1);
|
|
||||||
$iMax = strlen($styleSettings);
|
|
||||||
for ($i = 0; $i < $iMax; ++$i) {
|
|
||||||
switch ($styleSettings[$i]) {
|
|
||||||
case 'I':
|
|
||||||
$formatArray['font']['italic'] = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
$formatArray['font']['bold'] = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
$formatArray['borders']['top']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
$formatArray['borders']['bottom']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
$formatArray['borders']['left']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
$formatArray['borders']['right']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->formats['P' . $this->format++] = $formatArray;
|
|
||||||
// Read cell value data
|
|
||||||
} elseif ($dataType == 'C') {
|
|
||||||
$hasCalculatedValue = false;
|
|
||||||
$cellData = $cellDataFormula = '';
|
|
||||||
foreach ($rowData as $rowDatum) {
|
|
||||||
switch ($rowDatum[0]) {
|
|
||||||
case 'C':
|
|
||||||
case 'X':
|
|
||||||
$column = substr($rowDatum, 1);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
case 'Y':
|
|
||||||
$row = substr($rowDatum, 1);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'K':
|
|
||||||
$cellData = substr($rowDatum, 1);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
$cellDataFormula = '=' . substr($rowDatum, 1);
|
$cellDataFormula = '=' . substr($rowDatum, 1);
|
||||||
// Convert R1C1 style references to A1 style references (but only when not quoted)
|
// Convert R1C1 style references to A1 style references (but only when not quoted)
|
||||||
$temp = explode('"', $cellDataFormula);
|
$temp = explode('"', $cellDataFormula);
|
||||||
|
@ -343,22 +271,58 @@ class Slk extends BaseReader
|
||||||
// Then rebuild the formula string
|
// Then rebuild the formula string
|
||||||
$cellDataFormula = implode('"', $temp);
|
$cellDataFormula = implode('"', $temp);
|
||||||
$hasCalculatedValue = true;
|
$hasCalculatedValue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processCRecord(array $rowData, Spreadsheet &$spreadsheet, string &$row, string &$column): void
|
||||||
|
{
|
||||||
|
// Read cell value data
|
||||||
|
$hasCalculatedValue = false;
|
||||||
|
$cellDataFormula = $cellData = '';
|
||||||
|
foreach ($rowData as $rowDatum) {
|
||||||
|
switch ($rowDatum[0]) {
|
||||||
|
case 'C':
|
||||||
|
case 'X':
|
||||||
|
$column = substr($rowDatum, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
case 'Y':
|
||||||
|
$row = substr($rowDatum, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
$cellData = substr($rowDatum, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
$this->processFormula($rowDatum, $hasCalculatedValue, $cellDataFormula, $row, $column);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$columnLetter = Coordinate::stringFromColumnIndex($column);
|
$columnLetter = Coordinate::stringFromColumnIndex((int) $column);
|
||||||
$cellData = Calculation::unwrapResult($cellData);
|
$cellData = Calculation::unwrapResult($cellData);
|
||||||
|
|
||||||
// Set cell value
|
// Set cell value
|
||||||
$spreadsheet->getActiveSheet()->getCell($columnLetter . $row)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData);
|
$this->processCFinal($spreadsheet, $hasCalculatedValue, $cellDataFormula, $cellData, "$columnLetter$row");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processCFinal(Spreadsheet &$spreadsheet, bool $hasCalculatedValue, string $cellDataFormula, string $cellData, string $coordinate): void
|
||||||
|
{
|
||||||
|
// Set cell value
|
||||||
|
$spreadsheet->getActiveSheet()->getCell($coordinate)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData);
|
||||||
if ($hasCalculatedValue) {
|
if ($hasCalculatedValue) {
|
||||||
$cellData = Calculation::unwrapResult($cellData);
|
$cellData = Calculation::unwrapResult($cellData);
|
||||||
$spreadsheet->getActiveSheet()->getCell($columnLetter . $row)->setCalculatedValue($cellData);
|
$spreadsheet->getActiveSheet()->getCell($coordinate)->setCalculatedValue($cellData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processFRecord(array $rowData, Spreadsheet &$spreadsheet, string &$row, string &$column): void
|
||||||
|
{
|
||||||
// Read cell formatting
|
// Read cell formatting
|
||||||
} elseif ($dataType == 'F') {
|
$formatStyle = $columnWidth = '';
|
||||||
$formatStyle = $columnWidth = $styleSettings = '';
|
$startCol = $endCol = '';
|
||||||
|
$fontStyle = '';
|
||||||
$styleData = [];
|
$styleData = [];
|
||||||
foreach ($rowData as $rowDatum) {
|
foreach ($rowData as $rowDatum) {
|
||||||
switch ($rowDatum[0]) {
|
switch ($rowDatum[0]) {
|
||||||
|
@ -381,78 +345,203 @@ class Slk extends BaseReader
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
|
$this->styleSettings($rowDatum, $styleData, $fontStyle);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->addFormats($spreadsheet, $formatStyle, $row, $column);
|
||||||
|
$this->addFonts($spreadsheet, $fontStyle, $row, $column);
|
||||||
|
$this->addStyle($spreadsheet, $styleData, $row, $column);
|
||||||
|
$this->addWidth($spreadsheet, $columnWidth, $startCol, $endCol);
|
||||||
|
}
|
||||||
|
|
||||||
|
private $styleSettingsFont = ['D' => 'bold', 'I' => 'italic'];
|
||||||
|
|
||||||
|
private $styleSettingsBorder = [
|
||||||
|
'B' => 'bottom',
|
||||||
|
'L' => 'left',
|
||||||
|
'R' => 'right',
|
||||||
|
'T' => 'top',
|
||||||
|
];
|
||||||
|
|
||||||
|
private function styleSettings(string $rowDatum, array &$styleData, string &$fontStyle): void
|
||||||
|
{
|
||||||
$styleSettings = substr($rowDatum, 1);
|
$styleSettings = substr($rowDatum, 1);
|
||||||
$iMax = strlen($styleSettings);
|
$iMax = strlen($styleSettings);
|
||||||
for ($i = 0; $i < $iMax; ++$i) {
|
for ($i = 0; $i < $iMax; ++$i) {
|
||||||
switch ($styleSettings[$i]) {
|
$char = $styleSettings[$i];
|
||||||
case 'I':
|
if (array_key_exists($char, $this->styleSettingsFont)) {
|
||||||
$styleData['font']['italic'] = true;
|
$styleData['font'][$this->styleSettingsFont[$char]] = true;
|
||||||
|
} elseif (array_key_exists($char, $this->styleSettingsBorder)) {
|
||||||
break;
|
$styleData['borders'][$this->styleSettingsBorder[$char]]['borderStyle'] = Border::BORDER_THIN;
|
||||||
case 'D':
|
} elseif ($char == 'S') {
|
||||||
$styleData['font']['bold'] = true;
|
$styleData['fill']['fillType'] = \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY125;
|
||||||
|
} elseif ($char == 'M') {
|
||||||
break;
|
if (preg_match('/M([1-9]\\d*)/', $styleSettings, $matches)) {
|
||||||
case 'T':
|
$fontStyle = $matches[1];
|
||||||
$styleData['borders']['top']['borderStyle'] = Border::BORDER_THIN;
|
}
|
||||||
|
}
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
$styleData['borders']['bottom']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
$styleData['borders']['left']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
$styleData['borders']['right']['borderStyle'] = Border::BORDER_THIN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
private function addFormats(Spreadsheet &$spreadsheet, string $formatStyle, string $row, string $column): void
|
||||||
}
|
{
|
||||||
}
|
if ($formatStyle && $column > '' && $row > '') {
|
||||||
if (($formatStyle > '') && ($column > '') && ($row > '')) {
|
$columnLetter = Coordinate::stringFromColumnIndex((int) $column);
|
||||||
$columnLetter = Coordinate::stringFromColumnIndex($column);
|
|
||||||
if (isset($this->formats[$formatStyle])) {
|
if (isset($this->formats[$formatStyle])) {
|
||||||
$spreadsheet->getActiveSheet()->getStyle($columnLetter . $row)->applyFromArray($this->formats[$formatStyle]);
|
$spreadsheet->getActiveSheet()->getStyle($columnLetter . $row)->applyFromArray($this->formats[$formatStyle]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((!empty($styleData)) && ($column > '') && ($row > '')) {
|
}
|
||||||
|
|
||||||
|
private function addFonts(Spreadsheet &$spreadsheet, string $fontStyle, string $row, string $column): void
|
||||||
|
{
|
||||||
|
if ($fontStyle && $column > '' && $row > '') {
|
||||||
|
$columnLetter = Coordinate::stringFromColumnIndex((int) $column);
|
||||||
|
if (isset($this->fonts[$fontStyle])) {
|
||||||
|
$spreadsheet->getActiveSheet()->getStyle($columnLetter . $row)->applyFromArray($this->fonts[$fontStyle]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addStyle(Spreadsheet &$spreadsheet, array $styleData, string $row, string $column): void
|
||||||
|
{
|
||||||
|
if ((!empty($styleData)) && $column > '' && $row > '') {
|
||||||
$columnLetter = Coordinate::stringFromColumnIndex($column);
|
$columnLetter = Coordinate::stringFromColumnIndex($column);
|
||||||
$spreadsheet->getActiveSheet()->getStyle($columnLetter . $row)->applyFromArray($styleData);
|
$spreadsheet->getActiveSheet()->getStyle($columnLetter . $row)->applyFromArray($styleData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addWidth(Spreadsheet $spreadsheet, string $columnWidth, string $startCol, string $endCol): void
|
||||||
|
{
|
||||||
if ($columnWidth > '') {
|
if ($columnWidth > '') {
|
||||||
if ($startCol == $endCol) {
|
if ($startCol == $endCol) {
|
||||||
$startCol = Coordinate::stringFromColumnIndex($startCol);
|
$startCol = Coordinate::stringFromColumnIndex((int) $startCol);
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
|
$spreadsheet->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
|
||||||
} else {
|
} else {
|
||||||
$startCol = Coordinate::stringFromColumnIndex($startCol);
|
$startCol = Coordinate::stringFromColumnIndex($startCol);
|
||||||
$endCol = Coordinate::stringFromColumnIndex($endCol);
|
$endCol = Coordinate::stringFromColumnIndex($endCol);
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
|
$spreadsheet->getActiveSheet()->getColumnDimension($startCol)->setWidth((float) $columnWidth);
|
||||||
do {
|
do {
|
||||||
$spreadsheet->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth);
|
$spreadsheet->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth);
|
||||||
} while ($startCol != $endCol);
|
} while ($startCol != $endCol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
private function processPRecord(array $rowData, Spreadsheet &$spreadsheet): void
|
||||||
|
{
|
||||||
|
// Read shared styles
|
||||||
|
$formatArray = [];
|
||||||
|
$fromFormats = ['\-', '\ '];
|
||||||
|
$toFormats = ['-', ' '];
|
||||||
foreach ($rowData as $rowDatum) {
|
foreach ($rowData as $rowDatum) {
|
||||||
switch ($rowDatum[0]) {
|
switch ($rowDatum[0]) {
|
||||||
case 'C':
|
case 'P':
|
||||||
case 'X':
|
$formatArray['numberFormat']['formatCode'] = str_replace($fromFormats, $toFormats, substr($rowDatum, 1));
|
||||||
$column = substr($rowDatum, 1);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'E':
|
||||||
case 'Y':
|
case 'F':
|
||||||
$row = substr($rowDatum, 1);
|
$formatArray['font']['name'] = substr($rowDatum, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
$formatArray['font']['size'] = substr($rowDatum, 1) / 20;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
$this->processPColors($rowDatum, $formatArray);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
$this->processPFontStyles($rowDatum, $formatArray);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->processPFinal($spreadsheet, $formatArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processPColors(string $rowDatum, array &$formatArray): void
|
||||||
|
{
|
||||||
|
if (preg_match('/L([1-9]\\d*)/', $rowDatum, $matches)) {
|
||||||
|
$fontColor = $matches[1] % 8;
|
||||||
|
$formatArray['font']['color']['argb'] = $this->colorArray[$fontColor];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processPFontStyles(string $rowDatum, array &$formatArray): void
|
||||||
|
{
|
||||||
|
$styleSettings = substr($rowDatum, 1);
|
||||||
|
$iMax = strlen($styleSettings);
|
||||||
|
for ($i = 0; $i < $iMax; ++$i) {
|
||||||
|
if (array_key_exists($styleSettings[$i], $this->fontStyleMappings)) {
|
||||||
|
$formatArray['font'][$this->fontStyleMappings[$styleSettings[$i]]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processPFinal(Spreadsheet &$spreadsheet, array $formatArray): void
|
||||||
|
{
|
||||||
|
if (array_key_exists('numberFormat', $formatArray)) {
|
||||||
|
$this->formats['P' . $this->format] = $formatArray;
|
||||||
|
++$this->format;
|
||||||
|
} elseif (array_key_exists('font', $formatArray)) {
|
||||||
|
++$this->fontcount;
|
||||||
|
$this->fonts[$this->fontcount] = $formatArray;
|
||||||
|
if ($this->fontcount === 1) {
|
||||||
|
$spreadsheet->getDefaultStyle()->applyFromArray($formatArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
*
|
||||||
|
* @return Spreadsheet
|
||||||
|
*/
|
||||||
|
public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet)
|
||||||
|
{
|
||||||
|
// Open file
|
||||||
|
$this->canReadOrBust($pFilename);
|
||||||
|
$fileHandle = $this->fileHandle;
|
||||||
|
rewind($fileHandle);
|
||||||
|
|
||||||
|
// Create new Worksheets
|
||||||
|
while ($spreadsheet->getSheetCount() <= $this->sheetIndex) {
|
||||||
|
$spreadsheet->createSheet();
|
||||||
|
}
|
||||||
|
$spreadsheet->setActiveSheetIndex($this->sheetIndex);
|
||||||
|
$spreadsheet->getActiveSheet()->setTitle(basename($pFilename, '.slk'));
|
||||||
|
|
||||||
|
// Loop through file
|
||||||
|
$column = $row = '';
|
||||||
|
|
||||||
|
// loop through one row (line) at a time in the file
|
||||||
|
while (($rowDataTxt = fgets($fileHandle)) !== false) {
|
||||||
|
// convert SYLK encoded $rowData to UTF-8
|
||||||
|
$rowDataTxt = StringHelper::SYLKtoUTF8($rowDataTxt);
|
||||||
|
|
||||||
|
// explode each row at semicolons while taking into account that literal semicolon (;)
|
||||||
|
// is escaped like this (;;)
|
||||||
|
$rowData = explode("\t", str_replace('¤', ';', str_replace(';', "\t", str_replace(';;', '¤', rtrim($rowDataTxt)))));
|
||||||
|
|
||||||
|
$dataType = array_shift($rowData);
|
||||||
|
if ($dataType == 'P') {
|
||||||
|
// Read shared styles
|
||||||
|
$this->processPRecord($rowData, $spreadsheet);
|
||||||
|
} elseif ($dataType == 'C') {
|
||||||
|
// Read cell value data
|
||||||
|
$this->processCRecord($rowData, $spreadsheet, $row, $column);
|
||||||
|
} elseif ($dataType == 'F') {
|
||||||
|
// Read cell formatting
|
||||||
|
$this->processFRecord($rowData, $spreadsheet, $row, $column);
|
||||||
|
} else {
|
||||||
|
$this->columnRowFromRowData($rowData, $column, $row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,6 +552,18 @@ class Slk extends BaseReader
|
||||||
return $spreadsheet;
|
return $spreadsheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function columnRowFromRowData(array $rowData, string &$column, string &$row): void
|
||||||
|
{
|
||||||
|
foreach ($rowData as $rowDatum) {
|
||||||
|
$char0 = $rowDatum[0];
|
||||||
|
if ($char0 === 'X' || $char0 == 'C') {
|
||||||
|
$column = substr($rowDatum, 1);
|
||||||
|
} elseif ($char0 === 'Y' || $char0 == 'R') {
|
||||||
|
$row = substr($rowDatum, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get sheet index.
|
* Get sheet index.
|
||||||
*
|
*
|
||||||
|
|
|
@ -439,6 +439,15 @@ class Xls extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCodepage(string $codepage): void
|
||||||
|
{
|
||||||
|
if (!CodePage::validate($codepage)) {
|
||||||
|
throw new PhpSpreadsheetException('Unknown codepage: ' . $codepage);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->codepage = $codepage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads names of the worksheets from a file, without parsing the whole file to a PhpSpreadsheet object.
|
* Reads names of the worksheets from a file, without parsing the whole file to a PhpSpreadsheet object.
|
||||||
*
|
*
|
||||||
|
@ -640,7 +649,7 @@ class Xls extends BaseReader
|
||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
$this->pos = 0;
|
$this->pos = 0;
|
||||||
$this->codepage = 'CP1252';
|
$this->codepage = $this->codepage ?: CodePage::DEFAULT_CODE_PAGE;
|
||||||
$this->formats = [];
|
$this->formats = [];
|
||||||
$this->objFonts = [];
|
$this->objFonts = [];
|
||||||
$this->palette = [];
|
$this->palette = [];
|
||||||
|
@ -1266,8 +1275,10 @@ class Xls extends BaseReader
|
||||||
// Extract range
|
// Extract range
|
||||||
if (strpos($definedName['formula'], '!') !== false) {
|
if (strpos($definedName['formula'], '!') !== false) {
|
||||||
$explodes = Worksheet::extractSheetTitle($definedName['formula'], true);
|
$explodes = Worksheet::extractSheetTitle($definedName['formula'], true);
|
||||||
if (($docSheet = $this->spreadsheet->getSheetByName($explodes[0])) ||
|
if (
|
||||||
($docSheet = $this->spreadsheet->getSheetByName(trim($explodes[0], "'")))) {
|
($docSheet = $this->spreadsheet->getSheetByName($explodes[0])) ||
|
||||||
|
($docSheet = $this->spreadsheet->getSheetByName(trim($explodes[0], "'")))
|
||||||
|
) {
|
||||||
$extractedRange = $explodes[1];
|
$extractedRange = $explodes[1];
|
||||||
$extractedRange = str_replace('$', '', $extractedRange);
|
$extractedRange = str_replace('$', '', $extractedRange);
|
||||||
|
|
||||||
|
@ -3435,6 +3446,9 @@ class Xls extends BaseReader
|
||||||
|
|
||||||
// offset: 10; size: 2; option flags
|
// offset: 10; size: 2; option flags
|
||||||
|
|
||||||
|
// bit: 0; mask: 0x0001; 0=down then over, 1=over then down
|
||||||
|
$isOverThenDown = (0x0001 & self::getUInt2d($recordData, 10));
|
||||||
|
|
||||||
// bit: 1; mask: 0x0002; 0=landscape, 1=portrait
|
// bit: 1; mask: 0x0002; 0=landscape, 1=portrait
|
||||||
$isPortrait = (0x0002 & self::getUInt2d($recordData, 10)) >> 1;
|
$isPortrait = (0x0002 & self::getUInt2d($recordData, 10)) >> 1;
|
||||||
|
|
||||||
|
@ -3444,16 +3458,8 @@ class Xls extends BaseReader
|
||||||
|
|
||||||
if (!$isNotInit) {
|
if (!$isNotInit) {
|
||||||
$this->phpSheet->getPageSetup()->setPaperSize($paperSize);
|
$this->phpSheet->getPageSetup()->setPaperSize($paperSize);
|
||||||
switch ($isPortrait) {
|
$this->phpSheet->getPageSetup()->setPageOrder(((bool) $isOverThenDown) ? PageSetup::PAGEORDER_OVER_THEN_DOWN : PageSetup::PAGEORDER_DOWN_THEN_OVER);
|
||||||
case 0:
|
$this->phpSheet->getPageSetup()->setOrientation(((bool) $isPortrait) ? PageSetup::ORIENTATION_PORTRAIT : PageSetup::ORIENTATION_LANDSCAPE);
|
||||||
$this->phpSheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
$this->phpSheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_PORTRAIT);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->phpSheet->getPageSetup()->setScale($scale, false);
|
$this->phpSheet->getPageSetup()->setScale($scale, false);
|
||||||
$this->phpSheet->getPageSetup()->setFitToPage((bool) $this->isFitToPages);
|
$this->phpSheet->getPageSetup()->setFitToPage((bool) $this->isFitToPages);
|
||||||
|
@ -3622,10 +3628,12 @@ class Xls extends BaseReader
|
||||||
$this->phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden);
|
$this->phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden);
|
||||||
$this->phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level);
|
$this->phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level);
|
||||||
$this->phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed);
|
$this->phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed);
|
||||||
|
if (isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
$this->phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$this->phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ROW.
|
* ROW.
|
||||||
|
@ -3731,7 +3739,7 @@ class Xls extends BaseReader
|
||||||
$numValue = self::getIEEE754($rknum);
|
$numValue = self::getIEEE754($rknum);
|
||||||
|
|
||||||
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
// add style information
|
// add style information
|
||||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
|
@ -3866,7 +3874,7 @@ class Xls extends BaseReader
|
||||||
// offset: var; size: 4; RK value
|
// offset: var; size: 4; RK value
|
||||||
$numValue = self::getIEEE754(self::getInt4d($recordData, $offset + 2));
|
$numValue = self::getIEEE754(self::getInt4d($recordData, $offset + 2));
|
||||||
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
// add style
|
// add style
|
||||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
|
@ -3910,7 +3918,7 @@ class Xls extends BaseReader
|
||||||
$numValue = self::extractNumber(substr($recordData, 6, 8));
|
$numValue = self::extractNumber(substr($recordData, 6, 8));
|
||||||
|
|
||||||
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
// add cell style
|
// add cell style
|
||||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
|
@ -3993,21 +4001,27 @@ class Xls extends BaseReader
|
||||||
|
|
||||||
// read STRING record
|
// read STRING record
|
||||||
$value = $this->readString();
|
$value = $this->readString();
|
||||||
} elseif ((ord($recordData[6]) == 1)
|
} elseif (
|
||||||
|
(ord($recordData[6]) == 1)
|
||||||
&& (ord($recordData[12]) == 255)
|
&& (ord($recordData[12]) == 255)
|
||||||
&& (ord($recordData[13]) == 255)) {
|
&& (ord($recordData[13]) == 255)
|
||||||
|
) {
|
||||||
// Boolean formula. Result is in +2; 0=false, 1=true
|
// Boolean formula. Result is in +2; 0=false, 1=true
|
||||||
$dataType = DataType::TYPE_BOOL;
|
$dataType = DataType::TYPE_BOOL;
|
||||||
$value = (bool) ord($recordData[8]);
|
$value = (bool) ord($recordData[8]);
|
||||||
} elseif ((ord($recordData[6]) == 2)
|
} elseif (
|
||||||
|
(ord($recordData[6]) == 2)
|
||||||
&& (ord($recordData[12]) == 255)
|
&& (ord($recordData[12]) == 255)
|
||||||
&& (ord($recordData[13]) == 255)) {
|
&& (ord($recordData[13]) == 255)
|
||||||
|
) {
|
||||||
// Error formula. Error code is in +2
|
// Error formula. Error code is in +2
|
||||||
$dataType = DataType::TYPE_ERROR;
|
$dataType = DataType::TYPE_ERROR;
|
||||||
$value = Xls\ErrorCode::lookup(ord($recordData[8]));
|
$value = Xls\ErrorCode::lookup(ord($recordData[8]));
|
||||||
} elseif ((ord($recordData[6]) == 3)
|
} elseif (
|
||||||
|
(ord($recordData[6]) == 3)
|
||||||
&& (ord($recordData[12]) == 255)
|
&& (ord($recordData[12]) == 255)
|
||||||
&& (ord($recordData[13]) == 255)) {
|
&& (ord($recordData[13]) == 255)
|
||||||
|
) {
|
||||||
// Formula result is a null string
|
// Formula result is a null string
|
||||||
$dataType = DataType::TYPE_NULL;
|
$dataType = DataType::TYPE_NULL;
|
||||||
$value = '';
|
$value = '';
|
||||||
|
@ -4018,7 +4032,7 @@ class Xls extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
// add cell style
|
// add cell style
|
||||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
|
@ -4156,7 +4170,7 @@ class Xls extends BaseReader
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
// add cell style
|
// add cell style
|
||||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
|
@ -4194,10 +4208,12 @@ class Xls extends BaseReader
|
||||||
// Read cell?
|
// Read cell?
|
||||||
if (($this->getReadFilter() !== null) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->phpSheet->getTitle())) {
|
if (($this->getReadFilter() !== null) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->phpSheet->getTitle())) {
|
||||||
$xfIndex = self::getUInt2d($recordData, 4 + 2 * $i);
|
$xfIndex = self::getUInt2d($recordData, 4 + 2 * $i);
|
||||||
|
if (isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
$this->phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$this->phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// offset: 6; size 2; index to last column (not needed)
|
// offset: 6; size 2; index to last column (not needed)
|
||||||
}
|
}
|
||||||
|
@ -4245,7 +4261,7 @@ class Xls extends BaseReader
|
||||||
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
$cell = $this->phpSheet->getCell($columnString . ($row + 1));
|
||||||
$cell->setValueExplicit($value, DataType::TYPE_STRING);
|
$cell->setValueExplicit($value, DataType::TYPE_STRING);
|
||||||
|
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
// add cell style
|
// add cell style
|
||||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
|
@ -4277,7 +4293,7 @@ class Xls extends BaseReader
|
||||||
$xfIndex = self::getUInt2d($recordData, 4);
|
$xfIndex = self::getUInt2d($recordData, 4);
|
||||||
|
|
||||||
// add style information
|
// add style information
|
||||||
if (!$this->readDataOnly && $this->readEmptyCells) {
|
if (!$this->readDataOnly && $this->readEmptyCells && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||||
$this->phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
$this->phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4361,11 +4377,22 @@ class Xls extends BaseReader
|
||||||
// offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%)
|
// offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%)
|
||||||
// offset: 12; size: 2; cached magnification factor in normal view (in percent); 0 = Default (100%)
|
// offset: 12; size: 2; cached magnification factor in normal view (in percent); 0 = Default (100%)
|
||||||
// offset: 14; size: 4; not used
|
// offset: 14; size: 4; not used
|
||||||
|
if (!isset($recordData[10])) {
|
||||||
|
$zoomscaleInPageBreakPreview = 0;
|
||||||
|
} else {
|
||||||
$zoomscaleInPageBreakPreview = self::getUInt2d($recordData, 10);
|
$zoomscaleInPageBreakPreview = self::getUInt2d($recordData, 10);
|
||||||
|
}
|
||||||
|
|
||||||
if ($zoomscaleInPageBreakPreview === 0) {
|
if ($zoomscaleInPageBreakPreview === 0) {
|
||||||
$zoomscaleInPageBreakPreview = 60;
|
$zoomscaleInPageBreakPreview = 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isset($recordData[12])) {
|
||||||
|
$zoomscaleInNormalView = 0;
|
||||||
|
} else {
|
||||||
$zoomscaleInNormalView = self::getUInt2d($recordData, 12);
|
$zoomscaleInNormalView = self::getUInt2d($recordData, 12);
|
||||||
|
}
|
||||||
|
|
||||||
if ($zoomscaleInNormalView === 0) {
|
if ($zoomscaleInNormalView === 0) {
|
||||||
$zoomscaleInNormalView = 100;
|
$zoomscaleInNormalView = 100;
|
||||||
}
|
}
|
||||||
|
@ -4591,8 +4618,10 @@ class Xls extends BaseReader
|
||||||
if ($this->version == self::XLS_BIFF8 && !$this->readDataOnly) {
|
if ($this->version == self::XLS_BIFF8 && !$this->readDataOnly) {
|
||||||
$cellRangeAddressList = $this->readBIFF8CellRangeAddressList($recordData);
|
$cellRangeAddressList = $this->readBIFF8CellRangeAddressList($recordData);
|
||||||
foreach ($cellRangeAddressList['cellRangeAddresses'] as $cellRangeAddress) {
|
foreach ($cellRangeAddressList['cellRangeAddresses'] as $cellRangeAddress) {
|
||||||
if ((strpos($cellRangeAddress, ':') !== false) &&
|
if (
|
||||||
($this->includeCellRangeFiltered($cellRangeAddress))) {
|
(strpos($cellRangeAddress, ':') !== false) &&
|
||||||
|
($this->includeCellRangeFiltered($cellRangeAddress))
|
||||||
|
) {
|
||||||
$this->phpSheet->mergeCells($cellRangeAddress);
|
$this->phpSheet->mergeCells($cellRangeAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4940,6 +4969,7 @@ class Xls extends BaseReader
|
||||||
// offset: var; size: $sz1; formula data for first condition (without size field)
|
// offset: var; size: $sz1; formula data for first condition (without size field)
|
||||||
$formula1 = substr($recordData, $offset, $sz1);
|
$formula1 = substr($recordData, $offset, $sz1);
|
||||||
$formula1 = pack('v', $sz1) . $formula1; // prepend the length
|
$formula1 = pack('v', $sz1) . $formula1; // prepend the length
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$formula1 = $this->getFormulaFromStructure($formula1);
|
$formula1 = $this->getFormulaFromStructure($formula1);
|
||||||
|
|
||||||
|
@ -4962,6 +4992,7 @@ class Xls extends BaseReader
|
||||||
// offset: var; size: $sz2; formula data for second condition (without size field)
|
// offset: var; size: $sz2; formula data for second condition (without size field)
|
||||||
$formula2 = substr($recordData, $offset, $sz2);
|
$formula2 = substr($recordData, $offset, $sz2);
|
||||||
$formula2 = pack('v', $sz2) . $formula2; // prepend the length
|
$formula2 = pack('v', $sz2) . $formula2; // prepend the length
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$formula2 = $this->getFormulaFromStructure($formula2);
|
$formula2 = $this->getFormulaFromStructure($formula2);
|
||||||
} catch (PhpSpreadsheetException $e) {
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
@ -5759,6 +5790,7 @@ class Xls extends BaseReader
|
||||||
$size = 9;
|
$size = 9;
|
||||||
$data = self::extractNumber(substr($formulaData, 1));
|
$data = self::extractNumber(substr($formulaData, 1));
|
||||||
$data = str_replace(',', '.', (string) $data); // in case non-English locale
|
$data = str_replace(',', '.', (string) $data); // in case non-English locale
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0x20: // array constant
|
case 0x20: // array constant
|
||||||
case 0x40:
|
case 0x40:
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
|
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
|
||||||
use PhpOffice\PhpSpreadsheet\NamedRange;
|
use PhpOffice\PhpSpreadsheet\DefinedName;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\AutoFilter;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\AutoFilter;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart;
|
||||||
|
@ -502,8 +502,10 @@ class Xlsx extends BaseReader
|
||||||
// We shouldn't override any of the built-in MS Excel values (values below id 164)
|
// We shouldn't override any of the built-in MS Excel values (values below id 164)
|
||||||
// But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used
|
// But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used
|
||||||
// So we make allowance for them rather than lose formatting masks
|
// So we make allowance for them rather than lose formatting masks
|
||||||
if ((int) $xf['numFmtId'] < 164 &&
|
if (
|
||||||
NumberFormat::builtInFormatCode((int) $xf['numFmtId']) !== '') {
|
(int) $xf['numFmtId'] < 164 &&
|
||||||
|
NumberFormat::builtInFormatCode((int) $xf['numFmtId']) !== ''
|
||||||
|
) {
|
||||||
$numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']);
|
$numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,6 +661,9 @@ class Xlsx extends BaseReader
|
||||||
$coordinates = Coordinate::coordinateFromString($r);
|
$coordinates = Coordinate::coordinateFromString($r);
|
||||||
|
|
||||||
if (!$this->getReadFilter()->readCell($coordinates[0], (int) $coordinates[1], $docSheet->getTitle())) {
|
if (!$this->getReadFilter()->readCell($coordinates[0], (int) $coordinates[1], $docSheet->getTitle())) {
|
||||||
|
if (isset($c->f)) {
|
||||||
|
$this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
|
||||||
|
}
|
||||||
++$rowIndex;
|
++$rowIndex;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -763,13 +768,8 @@ class Xlsx extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
|
if ($xmlSheet) {
|
||||||
$docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection['password'], true);
|
$this->readSheetProtection($docSheet, $xmlSheet);
|
||||||
if ($xmlSheet->protectedRanges->protectedRange) {
|
|
||||||
foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
|
|
||||||
$docSheet->protectCells((string) $protectedRange['sqref'], (string) $protectedRange['password'], true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
|
if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
|
||||||
|
@ -1348,11 +1348,6 @@ class Xlsx extends BaseReader
|
||||||
foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
|
foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
|
||||||
// Extract range
|
// Extract range
|
||||||
$extractedRange = (string) $definedName;
|
$extractedRange = (string) $definedName;
|
||||||
if (($spos = strpos($extractedRange, '!')) !== false) {
|
|
||||||
$extractedRange = substr($extractedRange, 0, $spos) . str_replace('$', '', substr($extractedRange, $spos));
|
|
||||||
} else {
|
|
||||||
$extractedRange = str_replace('$', '', $extractedRange);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid range?
|
// Valid range?
|
||||||
if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') {
|
if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') {
|
||||||
|
@ -1370,39 +1365,40 @@ class Xlsx extends BaseReader
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ($mapSheetId[(int) $definedName['localSheetId']] !== null) {
|
if ($mapSheetId[(int) $definedName['localSheetId']] !== null) {
|
||||||
if (strpos((string) $definedName, '!') !== false) {
|
|
||||||
$range = Worksheet::extractSheetTitle((string) $definedName, true);
|
$range = Worksheet::extractSheetTitle((string) $definedName, true);
|
||||||
|
$scope = $excel->getSheet($mapSheetId[(int) $definedName['localSheetId']]);
|
||||||
|
if (strpos((string) $definedName, '!') !== false) {
|
||||||
$range[0] = str_replace("''", "'", $range[0]);
|
$range[0] = str_replace("''", "'", $range[0]);
|
||||||
$range[0] = str_replace("'", '', $range[0]);
|
$range[0] = str_replace("'", '', $range[0]);
|
||||||
if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) {
|
if ($worksheet = $excel->getSheetByName($range[0])) {
|
||||||
$extractedRange = str_replace('$', '', $range[1]);
|
$excel->addDefinedName(DefinedName::createInstance((string) $definedName['name'], $worksheet, $extractedRange, true, $scope));
|
||||||
$scope = $docSheet->getParent()->getSheet($mapSheetId[(int) $definedName['localSheetId']]);
|
} else {
|
||||||
$excel->addNamedRange(new NamedRange((string) $definedName['name'], $worksheet, $extractedRange, true, $scope));
|
$excel->addDefinedName(DefinedName::createInstance((string) $definedName['name'], $scope, $extractedRange, true, $scope));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$excel->addDefinedName(DefinedName::createInstance((string) $definedName['name'], $scope, $extractedRange, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} elseif (!isset($definedName['localSheetId'])) {
|
} elseif (!isset($definedName['localSheetId'])) {
|
||||||
|
$definedRange = (string) $definedName;
|
||||||
// "Global" definedNames
|
// "Global" definedNames
|
||||||
$locatedSheet = null;
|
$locatedSheet = null;
|
||||||
$extractedSheetName = '';
|
|
||||||
if (strpos((string) $definedName, '!') !== false) {
|
if (strpos((string) $definedName, '!') !== false) {
|
||||||
|
// Modify range, and extract the first worksheet reference
|
||||||
|
// Need to split on a comma or a space if not in quotes, and extract the first part.
|
||||||
|
$definedNameValueParts = preg_split("/[ ,](?=([^']*'[^']*')*[^']*$)/miuU", $definedRange);
|
||||||
// Extract sheet name
|
// Extract sheet name
|
||||||
$extractedSheetName = Worksheet::extractSheetTitle((string) $definedName, true);
|
[$extractedSheetName] = Worksheet::extractSheetTitle((string) $definedNameValueParts[0], true);
|
||||||
$extractedSheetName = trim($extractedSheetName[0], "'");
|
$extractedSheetName = trim($extractedSheetName, "'");
|
||||||
|
|
||||||
// Locate sheet
|
// Locate sheet
|
||||||
$locatedSheet = $excel->getSheetByName($extractedSheetName);
|
$locatedSheet = $excel->getSheetByName($extractedSheetName);
|
||||||
|
|
||||||
// Modify range
|
|
||||||
[$worksheetName, $extractedRange] = Worksheet::extractSheetTitle($extractedRange, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($locatedSheet !== null) {
|
$excel->addDefinedName(DefinedName::createInstance((string) $definedName['name'], $locatedSheet, $definedRange, false));
|
||||||
$excel->addNamedRange(new NamedRange((string) $definedName['name'], $locatedSheet, $extractedRange, false));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1725,12 +1721,16 @@ class Xlsx extends BaseReader
|
||||||
if (isset($run->rPr->color)) {
|
if (isset($run->rPr->color)) {
|
||||||
$objText->getFont()->setColor(new Color(self::readColor($run->rPr->color)));
|
$objText->getFont()->setColor(new Color(self::readColor($run->rPr->color)));
|
||||||
}
|
}
|
||||||
if ((isset($run->rPr->b['val']) && self::boolean((string) $run->rPr->b['val'])) ||
|
if (
|
||||||
(isset($run->rPr->b) && !isset($run->rPr->b['val']))) {
|
(isset($run->rPr->b['val']) && self::boolean((string) $run->rPr->b['val'])) ||
|
||||||
|
(isset($run->rPr->b) && !isset($run->rPr->b['val']))
|
||||||
|
) {
|
||||||
$objText->getFont()->setBold(true);
|
$objText->getFont()->setBold(true);
|
||||||
}
|
}
|
||||||
if ((isset($run->rPr->i['val']) && self::boolean((string) $run->rPr->i['val'])) ||
|
if (
|
||||||
(isset($run->rPr->i) && !isset($run->rPr->i['val']))) {
|
(isset($run->rPr->i['val']) && self::boolean((string) $run->rPr->i['val'])) ||
|
||||||
|
(isset($run->rPr->i) && !isset($run->rPr->i['val']))
|
||||||
|
) {
|
||||||
$objText->getFont()->setItalic(true);
|
$objText->getFont()->setItalic(true);
|
||||||
}
|
}
|
||||||
if (isset($run->rPr->vertAlign, $run->rPr->vertAlign['val'])) {
|
if (isset($run->rPr->vertAlign, $run->rPr->vertAlign['val'])) {
|
||||||
|
@ -1747,8 +1747,10 @@ class Xlsx extends BaseReader
|
||||||
} elseif (isset($run->rPr->u, $run->rPr->u['val'])) {
|
} elseif (isset($run->rPr->u, $run->rPr->u['val'])) {
|
||||||
$objText->getFont()->setUnderline((string) $run->rPr->u['val']);
|
$objText->getFont()->setUnderline((string) $run->rPr->u['val']);
|
||||||
}
|
}
|
||||||
if ((isset($run->rPr->strike['val']) && self::boolean((string) $run->rPr->strike['val'])) ||
|
if (
|
||||||
(isset($run->rPr->strike) && !isset($run->rPr->strike['val']))) {
|
(isset($run->rPr->strike['val']) && self::boolean((string) $run->rPr->strike['val'])) ||
|
||||||
|
(isset($run->rPr->strike) && !isset($run->rPr->strike['val']))
|
||||||
|
) {
|
||||||
$objText->getFont()->setStrikethrough(true);
|
$objText->getFont()->setStrikethrough(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2031,4 +2033,29 @@ class Xlsx extends BaseReader
|
||||||
|
|
||||||
return $workbookBasename;
|
return $workbookBasename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function readSheetProtection(Worksheet $docSheet, SimpleXMLElement $xmlSheet): void
|
||||||
|
{
|
||||||
|
if ($this->readDataOnly || !$xmlSheet->sheetProtection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$algorithmName = (string) $xmlSheet->sheetProtection['algorithmName'];
|
||||||
|
$protection = $docSheet->getProtection();
|
||||||
|
$protection->setAlgorithm($algorithmName);
|
||||||
|
|
||||||
|
if ($algorithmName) {
|
||||||
|
$protection->setPassword((string) $xmlSheet->sheetProtection['hashValue'], true);
|
||||||
|
$protection->setSalt((string) $xmlSheet->sheetProtection['saltValue']);
|
||||||
|
$protection->setSpinCount((int) $xmlSheet->sheetProtection['spinCount']);
|
||||||
|
} else {
|
||||||
|
$protection->setPassword((string) $xmlSheet->sheetProtection['password'], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($xmlSheet->protectedRanges->protectedRange) {
|
||||||
|
foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
|
||||||
|
$docSheet->protectCells((string) $protectedRange['sqref'], (string) $protectedRange['password'], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,8 +94,10 @@ class ColumnAndRowAttributes extends BaseParserClass
|
||||||
// set columns/rows attributes
|
// set columns/rows attributes
|
||||||
$columnsAttributesAreSet = [];
|
$columnsAttributesAreSet = [];
|
||||||
foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
|
foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
|
||||||
if ($readFilter === null ||
|
if (
|
||||||
!$this->isFilteredColumn($readFilter, $columnCoordinate, $rowsAttributes)) {
|
$readFilter === null ||
|
||||||
|
!$this->isFilteredColumn($readFilter, $columnCoordinate, $rowsAttributes)
|
||||||
|
) {
|
||||||
if (!isset($columnsAttributesAreSet[$columnCoordinate])) {
|
if (!isset($columnsAttributesAreSet[$columnCoordinate])) {
|
||||||
$this->setColumnAttributes($columnCoordinate, $columnAttributes);
|
$this->setColumnAttributes($columnCoordinate, $columnAttributes);
|
||||||
$columnsAttributesAreSet[$columnCoordinate] = true;
|
$columnsAttributesAreSet[$columnCoordinate] = true;
|
||||||
|
@ -105,8 +107,10 @@ class ColumnAndRowAttributes extends BaseParserClass
|
||||||
|
|
||||||
$rowsAttributesAreSet = [];
|
$rowsAttributesAreSet = [];
|
||||||
foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
|
foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
|
||||||
if ($readFilter === null ||
|
if (
|
||||||
!$this->isFilteredRow($readFilter, $rowCoordinate, $columnsAttributes)) {
|
$readFilter === null ||
|
||||||
|
!$this->isFilteredRow($readFilter, $rowCoordinate, $columnsAttributes)
|
||||||
|
) {
|
||||||
if (!isset($rowsAttributesAreSet[$rowCoordinate])) {
|
if (!isset($rowsAttributesAreSet[$rowCoordinate])) {
|
||||||
$this->setRowAttributes($rowCoordinate, $rowAttributes);
|
$this->setRowAttributes($rowCoordinate, $rowAttributes);
|
||||||
$rowsAttributesAreSet[$rowCoordinate] = true;
|
$rowsAttributesAreSet[$rowCoordinate] = true;
|
||||||
|
|
|
@ -34,13 +34,15 @@ class ConditionalStyles
|
||||||
$conditionals = [];
|
$conditionals = [];
|
||||||
foreach ($xmlSheet->conditionalFormatting as $conditional) {
|
foreach ($xmlSheet->conditionalFormatting as $conditional) {
|
||||||
foreach ($conditional->cfRule as $cfRule) {
|
foreach ($conditional->cfRule as $cfRule) {
|
||||||
if (((string) $cfRule['type'] == Conditional::CONDITION_NONE
|
if (
|
||||||
|
((string) $cfRule['type'] == Conditional::CONDITION_NONE
|
||||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CELLIS
|
|| (string) $cfRule['type'] == Conditional::CONDITION_CELLIS
|
||||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT
|
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT
|
||||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS
|
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS
|
||||||
|| (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS
|
|| (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS
|
||||||
|| (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION)
|
|| (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION)
|
||||||
&& isset($this->dxfs[(int) ($cfRule['dxfId'])])) {
|
&& isset($this->dxfs[(int) ($cfRule['dxfId'])])
|
||||||
|
) {
|
||||||
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
|
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,15 @@ class PageSetup extends BaseParserClass
|
||||||
if (isset($xmlSheet->pageSetup['fitToWidth']) && (int) ($xmlSheet->pageSetup['fitToWidth']) >= 0) {
|
if (isset($xmlSheet->pageSetup['fitToWidth']) && (int) ($xmlSheet->pageSetup['fitToWidth']) >= 0) {
|
||||||
$docPageSetup->setFitToWidth((int) ($xmlSheet->pageSetup['fitToWidth']), false);
|
$docPageSetup->setFitToWidth((int) ($xmlSheet->pageSetup['fitToWidth']), false);
|
||||||
}
|
}
|
||||||
if (isset($xmlSheet->pageSetup['firstPageNumber'], $xmlSheet->pageSetup['useFirstPageNumber']) &&
|
if (
|
||||||
self::boolean((string) $xmlSheet->pageSetup['useFirstPageNumber'])) {
|
isset($xmlSheet->pageSetup['firstPageNumber'], $xmlSheet->pageSetup['useFirstPageNumber']) &&
|
||||||
|
self::boolean((string) $xmlSheet->pageSetup['useFirstPageNumber'])
|
||||||
|
) {
|
||||||
$docPageSetup->setFirstPageNumber((int) ($xmlSheet->pageSetup['firstPageNumber']));
|
$docPageSetup->setFirstPageNumber((int) ($xmlSheet->pageSetup['firstPageNumber']));
|
||||||
}
|
}
|
||||||
|
if (isset($xmlSheet->pageSetup['pageOrder'])) {
|
||||||
|
$docPageSetup->setPageOrder((string) $xmlSheet->pageSetup['pageOrder']);
|
||||||
|
}
|
||||||
|
|
||||||
$relAttributes = $xmlSheet->pageSetup->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
$relAttributes = $xmlSheet->pageSetup->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||||
if (isset($relAttributes['id'])) {
|
if (isset($relAttributes['id'])) {
|
||||||
|
@ -84,26 +89,34 @@ class PageSetup extends BaseParserClass
|
||||||
if ($xmlSheet->headerFooter) {
|
if ($xmlSheet->headerFooter) {
|
||||||
$docHeaderFooter = $worksheet->getHeaderFooter();
|
$docHeaderFooter = $worksheet->getHeaderFooter();
|
||||||
|
|
||||||
if (isset($xmlSheet->headerFooter['differentOddEven']) &&
|
if (
|
||||||
self::boolean((string) $xmlSheet->headerFooter['differentOddEven'])) {
|
isset($xmlSheet->headerFooter['differentOddEven']) &&
|
||||||
|
self::boolean((string) $xmlSheet->headerFooter['differentOddEven'])
|
||||||
|
) {
|
||||||
$docHeaderFooter->setDifferentOddEven(true);
|
$docHeaderFooter->setDifferentOddEven(true);
|
||||||
} else {
|
} else {
|
||||||
$docHeaderFooter->setDifferentOddEven(false);
|
$docHeaderFooter->setDifferentOddEven(false);
|
||||||
}
|
}
|
||||||
if (isset($xmlSheet->headerFooter['differentFirst']) &&
|
if (
|
||||||
self::boolean((string) $xmlSheet->headerFooter['differentFirst'])) {
|
isset($xmlSheet->headerFooter['differentFirst']) &&
|
||||||
|
self::boolean((string) $xmlSheet->headerFooter['differentFirst'])
|
||||||
|
) {
|
||||||
$docHeaderFooter->setDifferentFirst(true);
|
$docHeaderFooter->setDifferentFirst(true);
|
||||||
} else {
|
} else {
|
||||||
$docHeaderFooter->setDifferentFirst(false);
|
$docHeaderFooter->setDifferentFirst(false);
|
||||||
}
|
}
|
||||||
if (isset($xmlSheet->headerFooter['scaleWithDoc']) &&
|
if (
|
||||||
!self::boolean((string) $xmlSheet->headerFooter['scaleWithDoc'])) {
|
isset($xmlSheet->headerFooter['scaleWithDoc']) &&
|
||||||
|
!self::boolean((string) $xmlSheet->headerFooter['scaleWithDoc'])
|
||||||
|
) {
|
||||||
$docHeaderFooter->setScaleWithDocument(false);
|
$docHeaderFooter->setScaleWithDocument(false);
|
||||||
} else {
|
} else {
|
||||||
$docHeaderFooter->setScaleWithDocument(true);
|
$docHeaderFooter->setScaleWithDocument(true);
|
||||||
}
|
}
|
||||||
if (isset($xmlSheet->headerFooter['alignWithMargins']) &&
|
if (
|
||||||
!self::boolean((string) $xmlSheet->headerFooter['alignWithMargins'])) {
|
isset($xmlSheet->headerFooter['alignWithMargins']) &&
|
||||||
|
!self::boolean((string) $xmlSheet->headerFooter['alignWithMargins'])
|
||||||
|
) {
|
||||||
$docHeaderFooter->setAlignWithMargins(false);
|
$docHeaderFooter->setAlignWithMargins(false);
|
||||||
} else {
|
} else {
|
||||||
$docHeaderFooter->setAlignWithMargins(true);
|
$docHeaderFooter->setAlignWithMargins(true);
|
||||||
|
|
|
@ -59,15 +59,19 @@ class SheetViewOptions extends BaseParserClass
|
||||||
private function outlines(SimpleXMLElement $sheetPr): void
|
private function outlines(SimpleXMLElement $sheetPr): void
|
||||||
{
|
{
|
||||||
if (isset($sheetPr->outlinePr)) {
|
if (isset($sheetPr->outlinePr)) {
|
||||||
if (isset($sheetPr->outlinePr['summaryRight']) &&
|
if (
|
||||||
!self::boolean((string) $sheetPr->outlinePr['summaryRight'])) {
|
isset($sheetPr->outlinePr['summaryRight']) &&
|
||||||
|
!self::boolean((string) $sheetPr->outlinePr['summaryRight'])
|
||||||
|
) {
|
||||||
$this->worksheet->setShowSummaryRight(false);
|
$this->worksheet->setShowSummaryRight(false);
|
||||||
} else {
|
} else {
|
||||||
$this->worksheet->setShowSummaryRight(true);
|
$this->worksheet->setShowSummaryRight(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($sheetPr->outlinePr['summaryBelow']) &&
|
if (
|
||||||
!self::boolean((string) $sheetPr->outlinePr['summaryBelow'])) {
|
isset($sheetPr->outlinePr['summaryBelow']) &&
|
||||||
|
!self::boolean((string) $sheetPr->outlinePr['summaryBelow'])
|
||||||
|
) {
|
||||||
$this->worksheet->setShowSummaryBelow(false);
|
$this->worksheet->setShowSummaryBelow(false);
|
||||||
} else {
|
} else {
|
||||||
$this->worksheet->setShowSummaryBelow(true);
|
$this->worksheet->setShowSummaryBelow(true);
|
||||||
|
@ -78,8 +82,10 @@ class SheetViewOptions extends BaseParserClass
|
||||||
private function pageSetup(SimpleXMLElement $sheetPr): void
|
private function pageSetup(SimpleXMLElement $sheetPr): void
|
||||||
{
|
{
|
||||||
if (isset($sheetPr->pageSetUpPr)) {
|
if (isset($sheetPr->pageSetUpPr)) {
|
||||||
if (isset($sheetPr->pageSetUpPr['fitToPage']) &&
|
if (
|
||||||
!self::boolean((string) $sheetPr->pageSetUpPr['fitToPage'])) {
|
isset($sheetPr->pageSetUpPr['fitToPage']) &&
|
||||||
|
!self::boolean((string) $sheetPr->pageSetUpPr['fitToPage'])
|
||||||
|
) {
|
||||||
$this->worksheet->getPageSetup()->setFitToPage(false);
|
$this->worksheet->getPageSetup()->setFitToPage(false);
|
||||||
} else {
|
} else {
|
||||||
$this->worksheet->getPageSetup()->setFitToPage(true);
|
$this->worksheet->getPageSetup()->setFitToPage(true);
|
||||||
|
@ -89,9 +95,11 @@ class SheetViewOptions extends BaseParserClass
|
||||||
|
|
||||||
private function sheetFormat(SimpleXMLElement $sheetFormatPr): void
|
private function sheetFormat(SimpleXMLElement $sheetFormatPr): void
|
||||||
{
|
{
|
||||||
if (isset($sheetFormatPr['customHeight']) &&
|
if (
|
||||||
|
isset($sheetFormatPr['customHeight']) &&
|
||||||
self::boolean((string) $sheetFormatPr['customHeight']) &&
|
self::boolean((string) $sheetFormatPr['customHeight']) &&
|
||||||
isset($sheetFormatPr['defaultRowHeight'])) {
|
isset($sheetFormatPr['defaultRowHeight'])
|
||||||
|
) {
|
||||||
$this->worksheet->getDefaultRowDimension()
|
$this->worksheet->getDefaultRowDimension()
|
||||||
->setRowHeight((float) $sheetFormatPr['defaultRowHeight']);
|
->setRowHeight((float) $sheetFormatPr['defaultRowHeight']);
|
||||||
}
|
}
|
||||||
|
@ -101,8 +109,10 @@ class SheetViewOptions extends BaseParserClass
|
||||||
->setWidth((float) $sheetFormatPr['defaultColWidth']);
|
->setWidth((float) $sheetFormatPr['defaultColWidth']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($sheetFormatPr['zeroHeight']) &&
|
if (
|
||||||
((string) $sheetFormatPr['zeroHeight'] === '1')) {
|
isset($sheetFormatPr['zeroHeight']) &&
|
||||||
|
((string) $sheetFormatPr['zeroHeight'] === '1')
|
||||||
|
) {
|
||||||
$this->worksheet->getDefaultRowDimension()->setZeroHeight(true);
|
$this->worksheet->getDefaultRowDimension()->setZeroHeight(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Reader;
|
namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\AddressHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\DefinedName;
|
||||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xml\PageSettings;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
use PhpOffice\PhpSpreadsheet\Settings;
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
|
@ -14,6 +17,8 @@ use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
use SimpleXMLElement;
|
use SimpleXMLElement;
|
||||||
|
|
||||||
|
@ -29,13 +34,6 @@ class Xml extends BaseReader
|
||||||
*/
|
*/
|
||||||
protected $styles = [];
|
protected $styles = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Character set used in the file.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $charSet = 'UTF-8';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Excel2003XML Reader instance.
|
* Create a new Excel2003XML Reader instance.
|
||||||
*/
|
*/
|
||||||
|
@ -45,6 +43,56 @@ class Xml extends BaseReader
|
||||||
$this->securityScanner = XmlScanner::getInstance($this);
|
$this->securityScanner = XmlScanner::getInstance($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private $fileContents = '';
|
||||||
|
|
||||||
|
private static $mappings = [
|
||||||
|
'borderStyle' => [
|
||||||
|
'1continuous' => Border::BORDER_THIN,
|
||||||
|
'1dash' => Border::BORDER_DASHED,
|
||||||
|
'1dashdot' => Border::BORDER_DASHDOT,
|
||||||
|
'1dashdotdot' => Border::BORDER_DASHDOTDOT,
|
||||||
|
'1dot' => Border::BORDER_DOTTED,
|
||||||
|
'1double' => Border::BORDER_DOUBLE,
|
||||||
|
'2continuous' => Border::BORDER_MEDIUM,
|
||||||
|
'2dash' => Border::BORDER_MEDIUMDASHED,
|
||||||
|
'2dashdot' => Border::BORDER_MEDIUMDASHDOT,
|
||||||
|
'2dashdotdot' => Border::BORDER_MEDIUMDASHDOTDOT,
|
||||||
|
'2dot' => Border::BORDER_DOTTED,
|
||||||
|
'2double' => Border::BORDER_DOUBLE,
|
||||||
|
'3continuous' => Border::BORDER_THICK,
|
||||||
|
'3dash' => Border::BORDER_MEDIUMDASHED,
|
||||||
|
'3dashdot' => Border::BORDER_MEDIUMDASHDOT,
|
||||||
|
'3dashdotdot' => Border::BORDER_MEDIUMDASHDOTDOT,
|
||||||
|
'3dot' => Border::BORDER_DOTTED,
|
||||||
|
'3double' => Border::BORDER_DOUBLE,
|
||||||
|
],
|
||||||
|
'fillType' => [
|
||||||
|
'solid' => Fill::FILL_SOLID,
|
||||||
|
'gray75' => Fill::FILL_PATTERN_DARKGRAY,
|
||||||
|
'gray50' => Fill::FILL_PATTERN_MEDIUMGRAY,
|
||||||
|
'gray25' => Fill::FILL_PATTERN_LIGHTGRAY,
|
||||||
|
'gray125' => Fill::FILL_PATTERN_GRAY125,
|
||||||
|
'gray0625' => Fill::FILL_PATTERN_GRAY0625,
|
||||||
|
'horzstripe' => Fill::FILL_PATTERN_DARKHORIZONTAL, // horizontal stripe
|
||||||
|
'vertstripe' => Fill::FILL_PATTERN_DARKVERTICAL, // vertical stripe
|
||||||
|
'reversediagstripe' => Fill::FILL_PATTERN_DARKUP, // reverse diagonal stripe
|
||||||
|
'diagstripe' => Fill::FILL_PATTERN_DARKDOWN, // diagonal stripe
|
||||||
|
'diagcross' => Fill::FILL_PATTERN_DARKGRID, // diagoanl crosshatch
|
||||||
|
'thickdiagcross' => Fill::FILL_PATTERN_DARKTRELLIS, // thick diagonal crosshatch
|
||||||
|
'thinhorzstripe' => Fill::FILL_PATTERN_LIGHTHORIZONTAL,
|
||||||
|
'thinvertstripe' => Fill::FILL_PATTERN_LIGHTVERTICAL,
|
||||||
|
'thinreversediagstripe' => Fill::FILL_PATTERN_LIGHTUP,
|
||||||
|
'thindiagstripe' => Fill::FILL_PATTERN_LIGHTDOWN,
|
||||||
|
'thinhorzcross' => Fill::FILL_PATTERN_LIGHTGRID, // thin horizontal crosshatch
|
||||||
|
'thindiagcross' => Fill::FILL_PATTERN_LIGHTTRELLIS, // thin diagonal crosshatch
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function xmlMappings(): array
|
||||||
|
{
|
||||||
|
return self::$mappings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can the current IReader read the file?
|
* Can the current IReader read the file?
|
||||||
*
|
*
|
||||||
|
@ -70,13 +118,10 @@ class Xml extends BaseReader
|
||||||
];
|
];
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
$this->openFile($pFilename);
|
$data = file_get_contents($pFilename);
|
||||||
$fileHandle = $this->fileHandle;
|
|
||||||
|
|
||||||
// Read sample data (first 2 KB will do)
|
// Why?
|
||||||
$data = fread($fileHandle, 2048);
|
//$data = str_replace("'", '"', $data); // fix headers with single quote
|
||||||
fclose($fileHandle);
|
|
||||||
$data = str_replace("'", '"', $data); // fix headers with single quote
|
|
||||||
|
|
||||||
$valid = true;
|
$valid = true;
|
||||||
foreach ($signature as $match) {
|
foreach ($signature as $match) {
|
||||||
|
@ -89,9 +134,14 @@ class Xml extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve charset encoding
|
// Retrieve charset encoding
|
||||||
if (preg_match('/<?xml.*encoding=[\'"](.*?)[\'"].*?>/um', $data, $matches)) {
|
if (preg_match('/<?xml.*encoding=[\'"](.*?)[\'"].*?>/m', $data, $matches)) {
|
||||||
$this->charSet = strtoupper($matches[1]);
|
$charSet = strtoupper($matches[1]);
|
||||||
|
if (1 == preg_match('/^ISO-8859-\d[\dL]?$/i', $charSet)) {
|
||||||
|
$data = StringHelper::convertEncoding($data, 'UTF-8', $charSet);
|
||||||
|
$data = preg_replace('/(<?xml.*encoding=[\'"]).*?([\'"].*?>)/um', '$1' . 'UTF-8' . '$2', $data, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
$this->fileContents = $data;
|
||||||
|
|
||||||
return $valid;
|
return $valid;
|
||||||
}
|
}
|
||||||
|
@ -107,13 +157,14 @@ class Xml extends BaseReader
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$xml = simplexml_load_string(
|
$xml = simplexml_load_string(
|
||||||
$this->securityScanner->scan(file_get_contents($pFilename)),
|
$this->securityScanner->scan($this->fileContents ?: file_get_contents($pFilename)),
|
||||||
'SimpleXMLElement',
|
'SimpleXMLElement',
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
);
|
);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
throw new Exception('Cannot load invalid XML file: ' . $pFilename, 0, $e);
|
throw new Exception('Cannot load invalid XML file: ' . $pFilename, 0, $e);
|
||||||
}
|
}
|
||||||
|
$this->fileContents = '';
|
||||||
|
|
||||||
return $xml;
|
return $xml;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +192,7 @@ class Xml extends BaseReader
|
||||||
$xml_ss = $xml->children($namespaces['ss']);
|
$xml_ss = $xml->children($namespaces['ss']);
|
||||||
foreach ($xml_ss->Worksheet as $worksheet) {
|
foreach ($xml_ss->Worksheet as $worksheet) {
|
||||||
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
|
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
|
||||||
$worksheetNames[] = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet);
|
$worksheetNames[] = (string) $worksheet_ss['Name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $worksheetNames;
|
return $worksheetNames;
|
||||||
|
@ -157,6 +208,9 @@ class Xml extends BaseReader
|
||||||
public function listWorksheetInfo($pFilename)
|
public function listWorksheetInfo($pFilename)
|
||||||
{
|
{
|
||||||
File::assertFile($pFilename);
|
File::assertFile($pFilename);
|
||||||
|
if (!$this->canRead($pFilename)) {
|
||||||
|
throw new Exception($pFilename . ' is an Invalid Spreadsheet file.');
|
||||||
|
}
|
||||||
|
|
||||||
$worksheetInfo = [];
|
$worksheetInfo = [];
|
||||||
|
|
||||||
|
@ -176,10 +230,9 @@ class Xml extends BaseReader
|
||||||
$tmpInfo['totalRows'] = 0;
|
$tmpInfo['totalRows'] = 0;
|
||||||
$tmpInfo['totalColumns'] = 0;
|
$tmpInfo['totalColumns'] = 0;
|
||||||
|
|
||||||
|
$tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}";
|
||||||
if (isset($worksheet_ss['Name'])) {
|
if (isset($worksheet_ss['Name'])) {
|
||||||
$tmpInfo['worksheetName'] = (string) $worksheet_ss['Name'];
|
$tmpInfo['worksheetName'] = (string) $worksheet_ss['Name'];
|
||||||
} else {
|
|
||||||
$tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($worksheet->Table->Row)) {
|
if (isset($worksheet->Table->Row)) {
|
||||||
|
@ -235,53 +288,23 @@ class Xml extends BaseReader
|
||||||
|
|
||||||
private static function identifyFixedStyleValue($styleList, &$styleAttributeValue)
|
private static function identifyFixedStyleValue($styleList, &$styleAttributeValue)
|
||||||
{
|
{
|
||||||
|
$returnValue = false;
|
||||||
$styleAttributeValue = strtolower($styleAttributeValue);
|
$styleAttributeValue = strtolower($styleAttributeValue);
|
||||||
foreach ($styleList as $style) {
|
foreach ($styleList as $style) {
|
||||||
if ($styleAttributeValue == strtolower($style)) {
|
if ($styleAttributeValue == strtolower($style)) {
|
||||||
$styleAttributeValue = $style;
|
$styleAttributeValue = $style;
|
||||||
|
$returnValue = true;
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return $returnValue;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pixel units to excel width units(units of 1/256th of a character width).
|
|
||||||
*
|
|
||||||
* @param float $pxs
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
protected static function pixel2WidthUnits($pxs)
|
|
||||||
{
|
|
||||||
$UNIT_OFFSET_MAP = [0, 36, 73, 109, 146, 182, 219];
|
|
||||||
|
|
||||||
$widthUnits = 256 * ($pxs / 7);
|
|
||||||
$widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)];
|
|
||||||
|
|
||||||
return $widthUnits;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* excel width units(units of 1/256th of a character width) to pixel units.
|
|
||||||
*
|
|
||||||
* @param float $widthUnits
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
protected static function widthUnits2Pixel($widthUnits)
|
|
||||||
{
|
|
||||||
$pixels = ($widthUnits / 256) * 7;
|
|
||||||
$offsetWidthUnits = $widthUnits % 256;
|
|
||||||
|
|
||||||
return $pixels + round($offsetWidthUnits / (256 / 7));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function hex2str($hex)
|
protected static function hex2str($hex)
|
||||||
{
|
{
|
||||||
return chr(hexdec($hex[1]));
|
return mb_chr((int) hexdec($hex[1]), 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -305,51 +328,52 @@ class Xml extends BaseReader
|
||||||
$docProps = $spreadsheet->getProperties();
|
$docProps = $spreadsheet->getProperties();
|
||||||
if (isset($xml->DocumentProperties[0])) {
|
if (isset($xml->DocumentProperties[0])) {
|
||||||
foreach ($xml->DocumentProperties[0] as $propertyName => $propertyValue) {
|
foreach ($xml->DocumentProperties[0] as $propertyName => $propertyValue) {
|
||||||
|
$stringValue = (string) $propertyValue;
|
||||||
switch ($propertyName) {
|
switch ($propertyName) {
|
||||||
case 'Title':
|
case 'Title':
|
||||||
$docProps->setTitle(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setTitle($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Subject':
|
case 'Subject':
|
||||||
$docProps->setSubject(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setSubject($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Author':
|
case 'Author':
|
||||||
$docProps->setCreator(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setCreator($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Created':
|
case 'Created':
|
||||||
$creationDate = strtotime($propertyValue);
|
$creationDate = strtotime($stringValue);
|
||||||
$docProps->setCreated($creationDate);
|
$docProps->setCreated($creationDate);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'LastAuthor':
|
case 'LastAuthor':
|
||||||
$docProps->setLastModifiedBy(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setLastModifiedBy($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'LastSaved':
|
case 'LastSaved':
|
||||||
$lastSaveDate = strtotime($propertyValue);
|
$lastSaveDate = strtotime($stringValue);
|
||||||
$docProps->setModified($lastSaveDate);
|
$docProps->setModified($lastSaveDate);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Company':
|
case 'Company':
|
||||||
$docProps->setCompany(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setCompany($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Category':
|
case 'Category':
|
||||||
$docProps->setCategory(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setCategory($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Manager':
|
case 'Manager':
|
||||||
$docProps->setManager(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setManager($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Keywords':
|
case 'Keywords':
|
||||||
$docProps->setKeywords(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setKeywords($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Description':
|
case 'Description':
|
||||||
$docProps->setDescription(self::convertStringEncoding($propertyValue, $this->charSet));
|
$docProps->setDescription($stringValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -358,7 +382,7 @@ class Xml extends BaseReader
|
||||||
if (isset($xml->CustomDocumentProperties)) {
|
if (isset($xml->CustomDocumentProperties)) {
|
||||||
foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) {
|
foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) {
|
||||||
$propertyAttributes = $propertyValue->attributes($namespaces['dt']);
|
$propertyAttributes = $propertyValue->attributes($namespaces['dt']);
|
||||||
$propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/', ['self', 'hex2str'], $propertyName);
|
$propertyName = preg_replace_callback('/_x([0-9a-f]{4})_/i', ['self', 'hex2str'], $propertyName);
|
||||||
$propertyType = Properties::PROPERTY_TYPE_UNKNOWN;
|
$propertyType = Properties::PROPERTY_TYPE_UNKNOWN;
|
||||||
switch ((string) $propertyAttributes) {
|
switch ((string) $propertyAttributes) {
|
||||||
case 'string':
|
case 'string':
|
||||||
|
@ -399,8 +423,10 @@ class Xml extends BaseReader
|
||||||
foreach ($xml_ss->Worksheet as $worksheet) {
|
foreach ($xml_ss->Worksheet as $worksheet) {
|
||||||
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
|
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
|
||||||
|
|
||||||
if ((isset($this->loadSheetsOnly)) && (isset($worksheet_ss['Name'])) &&
|
if (
|
||||||
(!in_array($worksheet_ss['Name'], $this->loadSheetsOnly))) {
|
(isset($this->loadSheetsOnly)) && (isset($worksheet_ss['Name'])) &&
|
||||||
|
(!in_array($worksheet_ss['Name'], $this->loadSheetsOnly))
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,13 +434,27 @@ class Xml extends BaseReader
|
||||||
$spreadsheet->createSheet();
|
$spreadsheet->createSheet();
|
||||||
$spreadsheet->setActiveSheetIndex($worksheetID);
|
$spreadsheet->setActiveSheetIndex($worksheetID);
|
||||||
if (isset($worksheet_ss['Name'])) {
|
if (isset($worksheet_ss['Name'])) {
|
||||||
$worksheetName = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet);
|
$worksheetName = (string) $worksheet_ss['Name'];
|
||||||
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
|
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
|
||||||
// formula cells... during the load, all formulae should be correct, and we're simply bringing
|
// formula cells... during the load, all formulae should be correct, and we're simply bringing
|
||||||
// the worksheet name in line with the formula, not the reverse
|
// the worksheet name in line with the formula, not the reverse
|
||||||
$spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false);
|
$spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// locally scoped defined names
|
||||||
|
if (isset($worksheet->Names[0])) {
|
||||||
|
foreach ($worksheet->Names[0] as $definedName) {
|
||||||
|
$definedName_ss = $definedName->attributes($namespaces['ss']);
|
||||||
|
$name = (string) $definedName_ss['Name'];
|
||||||
|
$definedValue = (string) $definedName_ss['RefersTo'];
|
||||||
|
$convertedValue = AddressHelper::convertFormulaToA1($definedValue);
|
||||||
|
if ($convertedValue[0] === '=') {
|
||||||
|
$convertedValue = substr($convertedValue, 1);
|
||||||
|
}
|
||||||
|
$spreadsheet->addDefinedName(DefinedName::createInstance($name, $spreadsheet->getActiveSheet(), $convertedValue, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$columnID = 'A';
|
$columnID = 'A';
|
||||||
if (isset($worksheet->Table->Column)) {
|
if (isset($worksheet->Table->Column)) {
|
||||||
foreach ($worksheet->Table->Column as $columnData) {
|
foreach ($worksheet->Table->Column as $columnData) {
|
||||||
|
@ -457,7 +497,7 @@ class Xml extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($cell_ss['HRef'])) {
|
if (isset($cell_ss['HRef'])) {
|
||||||
$spreadsheet->getActiveSheet()->getCell($cellRange)->getHyperlink()->setUrl($cell_ss['HRef']);
|
$spreadsheet->getActiveSheet()->getCell($cellRange)->getHyperlink()->setUrl((string) $cell_ss['HRef']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) {
|
if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) {
|
||||||
|
@ -474,14 +514,15 @@ class Xml extends BaseReader
|
||||||
$spreadsheet->getActiveSheet()->mergeCells($cellRange);
|
$spreadsheet->getActiveSheet()->mergeCells($cellRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
$cellIsSet = $hasCalculatedValue = false;
|
$hasCalculatedValue = false;
|
||||||
$cellDataFormula = '';
|
$cellDataFormula = '';
|
||||||
if (isset($cell_ss['Formula'])) {
|
if (isset($cell_ss['Formula'])) {
|
||||||
$cellDataFormula = $cell_ss['Formula'];
|
$cellDataFormula = $cell_ss['Formula'];
|
||||||
$hasCalculatedValue = true;
|
$hasCalculatedValue = true;
|
||||||
}
|
}
|
||||||
if (isset($cell->Data)) {
|
if (isset($cell->Data)) {
|
||||||
$cellValue = $cellData = $cell->Data;
|
$cellData = $cell->Data;
|
||||||
|
$cellValue = (string) $cellData;
|
||||||
$type = DataType::TYPE_NULL;
|
$type = DataType::TYPE_NULL;
|
||||||
$cellData_ss = $cellData->attributes($namespaces['ss']);
|
$cellData_ss = $cellData->attributes($namespaces['ss']);
|
||||||
if (isset($cellData_ss['Type'])) {
|
if (isset($cellData_ss['Type'])) {
|
||||||
|
@ -497,7 +538,6 @@ class Xml extends BaseReader
|
||||||
const TYPE_ERROR = 'e';
|
const TYPE_ERROR = 'e';
|
||||||
*/
|
*/
|
||||||
case 'String':
|
case 'String':
|
||||||
$cellValue = self::convertStringEncoding($cellValue, $this->charSet);
|
|
||||||
$type = DataType::TYPE_STRING;
|
$type = DataType::TYPE_STRING;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -516,11 +556,12 @@ class Xml extends BaseReader
|
||||||
break;
|
break;
|
||||||
case 'DateTime':
|
case 'DateTime':
|
||||||
$type = DataType::TYPE_NUMERIC;
|
$type = DataType::TYPE_NUMERIC;
|
||||||
$cellValue = Date::PHPToExcel(strtotime($cellValue));
|
$cellValue = Date::PHPToExcel(strtotime($cellValue . ' UTC'));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Error':
|
case 'Error':
|
||||||
$type = DataType::TYPE_ERROR;
|
$type = DataType::TYPE_ERROR;
|
||||||
|
$hasCalculatedValue = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -529,65 +570,14 @@ class Xml extends BaseReader
|
||||||
if ($hasCalculatedValue) {
|
if ($hasCalculatedValue) {
|
||||||
$type = DataType::TYPE_FORMULA;
|
$type = DataType::TYPE_FORMULA;
|
||||||
$columnNumber = Coordinate::columnIndexFromString($columnID);
|
$columnNumber = Coordinate::columnIndexFromString($columnID);
|
||||||
if (substr($cellDataFormula, 0, 3) == 'of:') {
|
$cellDataFormula = AddressHelper::convertFormulaToA1($cellDataFormula, $rowID, $columnNumber);
|
||||||
$cellDataFormula = substr($cellDataFormula, 3);
|
|
||||||
$temp = explode('"', $cellDataFormula);
|
|
||||||
$key = false;
|
|
||||||
foreach ($temp as &$value) {
|
|
||||||
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
|
||||||
if ($key = !$key) {
|
|
||||||
$value = str_replace(['[.', '.', ']'], '', $value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Convert R1C1 style references to A1 style references (but only when not quoted)
|
|
||||||
$temp = explode('"', $cellDataFormula);
|
|
||||||
$key = false;
|
|
||||||
foreach ($temp as &$value) {
|
|
||||||
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
|
||||||
if ($key = !$key) {
|
|
||||||
preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/', $value, $cellReferences, PREG_SET_ORDER + PREG_OFFSET_CAPTURE);
|
|
||||||
// Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way
|
|
||||||
// through the formula from left to right. Reversing means that we work right to left.through
|
|
||||||
// the formula
|
|
||||||
$cellReferences = array_reverse($cellReferences);
|
|
||||||
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
|
|
||||||
// then modify the formula to use that new reference
|
|
||||||
foreach ($cellReferences as $cellReference) {
|
|
||||||
$rowReference = $cellReference[2][0];
|
|
||||||
// Empty R reference is the current row
|
|
||||||
if ($rowReference == '') {
|
|
||||||
$rowReference = $rowID;
|
|
||||||
}
|
|
||||||
// Bracketed R references are relative to the current row
|
|
||||||
if ($rowReference[0] == '[') {
|
|
||||||
$rowReference = $rowID + trim($rowReference, '[]');
|
|
||||||
}
|
|
||||||
$columnReference = $cellReference[4][0];
|
|
||||||
// Empty C reference is the current column
|
|
||||||
if ($columnReference == '') {
|
|
||||||
$columnReference = $columnNumber;
|
|
||||||
}
|
|
||||||
// Bracketed C references are relative to the current column
|
|
||||||
if ($columnReference[0] == '[') {
|
|
||||||
$columnReference = $columnNumber + trim($columnReference, '[]');
|
|
||||||
}
|
|
||||||
$A1CellReference = Coordinate::stringFromColumnIndex($columnReference) . $rowReference;
|
|
||||||
$value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($value);
|
|
||||||
// Then rebuild the formula string
|
|
||||||
$cellDataFormula = implode('"', $temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$spreadsheet->getActiveSheet()->getCell($columnID . $rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue), $type);
|
$spreadsheet->getActiveSheet()->getCell($columnID . $rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue), $type);
|
||||||
if ($hasCalculatedValue) {
|
if ($hasCalculatedValue) {
|
||||||
$spreadsheet->getActiveSheet()->getCell($columnID . $rowID)->setCalculatedValue($cellValue);
|
$spreadsheet->getActiveSheet()->getCell($columnID . $rowID)->setCalculatedValue($cellValue);
|
||||||
}
|
}
|
||||||
$cellIsSet = $rowHasData = true;
|
$rowHasData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($cell->Comment)) {
|
if (isset($cell->Comment)) {
|
||||||
|
@ -598,15 +588,15 @@ class Xml extends BaseReader
|
||||||
}
|
}
|
||||||
$node = $cell->Comment->Data->asXML();
|
$node = $cell->Comment->Data->asXML();
|
||||||
$annotation = strip_tags($node);
|
$annotation = strip_tags($node);
|
||||||
$spreadsheet->getActiveSheet()->getComment($columnID . $rowID)->setAuthor(self::convertStringEncoding($author, $this->charSet))->setText($this->parseRichText($annotation));
|
$spreadsheet->getActiveSheet()->getComment($columnID . $rowID)->setAuthor($author)->setText($this->parseRichText($annotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($cellIsSet) && (isset($cell_ss['StyleID']))) {
|
if (isset($cell_ss['StyleID'])) {
|
||||||
$style = (string) $cell_ss['StyleID'];
|
$style = (string) $cell_ss['StyleID'];
|
||||||
if ((isset($this->styles[$style])) && (!empty($this->styles[$style]))) {
|
if ((isset($this->styles[$style])) && (!empty($this->styles[$style]))) {
|
||||||
if (!$spreadsheet->getActiveSheet()->cellExists($columnID . $rowID)) {
|
//if (!$spreadsheet->getActiveSheet()->cellExists($columnID . $rowID)) {
|
||||||
$spreadsheet->getActiveSheet()->getCell($columnID . $rowID)->setValue(null);
|
// $spreadsheet->getActiveSheet()->getCell($columnID . $rowID)->setValue(null);
|
||||||
}
|
//}
|
||||||
$spreadsheet->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->styles[$style]);
|
$spreadsheet->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->styles[$style]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,28 +616,39 @@ class Xml extends BaseReader
|
||||||
|
|
||||||
++$rowID;
|
++$rowID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$xmlX = $worksheet->children($namespaces['x']);
|
||||||
|
if (isset($xmlX->WorksheetOptions)) {
|
||||||
|
(new PageSettings($xmlX, $namespaces))->loadPageSettings($spreadsheet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++$worksheetID;
|
++$worksheetID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Globally scoped defined names
|
||||||
|
$activeWorksheet = $spreadsheet->setActiveSheetIndex(0);
|
||||||
|
if (isset($xml->Names[0])) {
|
||||||
|
foreach ($xml->Names[0] as $definedName) {
|
||||||
|
$definedName_ss = $definedName->attributes($namespaces['ss']);
|
||||||
|
$name = (string) $definedName_ss['Name'];
|
||||||
|
$definedValue = (string) $definedName_ss['RefersTo'];
|
||||||
|
$convertedValue = AddressHelper::convertFormulaToA1($definedValue);
|
||||||
|
if ($convertedValue[0] === '=') {
|
||||||
|
$convertedValue = substr($convertedValue, 1);
|
||||||
|
}
|
||||||
|
$spreadsheet->addDefinedName(DefinedName::createInstance($name, $activeWorksheet, $convertedValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return $spreadsheet;
|
return $spreadsheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function convertStringEncoding($string, $charset)
|
|
||||||
{
|
|
||||||
if ($charset != 'UTF-8') {
|
|
||||||
return StringHelper::convertEncoding($string, 'UTF-8', $charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $string;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function parseRichText($is)
|
protected function parseRichText($is)
|
||||||
{
|
{
|
||||||
$value = new RichText();
|
$value = new RichText();
|
||||||
|
|
||||||
$value->createText(self::convertStringEncoding($is, $this->charSet));
|
$value->createText($is);
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
@ -728,29 +729,41 @@ class Xml extends BaseReader
|
||||||
case 'WrapText':
|
case 'WrapText':
|
||||||
$this->styles[$styleID]['alignment']['wrapText'] = true;
|
$this->styles[$styleID]['alignment']['wrapText'] = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'Rotate':
|
||||||
|
$this->styles[$styleID]['alignment']['textRotation'] = $styleAttributeValue;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static $borderPositions = ['top', 'left', 'bottom', 'right'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $styleID
|
* @param $styleID
|
||||||
*/
|
*/
|
||||||
private function parseStyleBorders($styleID, SimpleXMLElement $styleData, array $namespaces): void
|
private function parseStyleBorders($styleID, SimpleXMLElement $styleData, array $namespaces): void
|
||||||
{
|
{
|
||||||
|
$diagonalDirection = '';
|
||||||
|
$borderPosition = '';
|
||||||
foreach ($styleData->Border as $borderStyle) {
|
foreach ($styleData->Border as $borderStyle) {
|
||||||
$borderAttributes = $borderStyle->attributes($namespaces['ss']);
|
$borderAttributes = $borderStyle->attributes($namespaces['ss']);
|
||||||
$thisBorder = [];
|
$thisBorder = [];
|
||||||
|
$style = (string) $borderAttributes->Weight;
|
||||||
|
$style .= strtolower((string) $borderAttributes->LineStyle);
|
||||||
|
$thisBorder['borderStyle'] = self::$mappings['borderStyle'][$style] ?? Border::BORDER_NONE;
|
||||||
foreach ($borderAttributes as $borderStyleKey => $borderStyleValue) {
|
foreach ($borderAttributes as $borderStyleKey => $borderStyleValue) {
|
||||||
switch ($borderStyleKey) {
|
switch ($borderStyleKey) {
|
||||||
case 'LineStyle':
|
|
||||||
$thisBorder['borderStyle'] = Border::BORDER_MEDIUM;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'Weight':
|
|
||||||
break;
|
|
||||||
case 'Position':
|
case 'Position':
|
||||||
$borderPosition = strtolower($borderStyleValue);
|
$borderStyleValue = strtolower((string) $borderStyleValue);
|
||||||
|
if (in_array($borderStyleValue, self::$borderPositions)) {
|
||||||
|
$borderPosition = $borderStyleValue;
|
||||||
|
} elseif ($borderStyleValue == 'diagonalleft') {
|
||||||
|
$diagonalDirection = $diagonalDirection ? Borders::DIAGONAL_BOTH : Borders::DIAGONAL_DOWN;
|
||||||
|
} elseif ($borderStyleValue == 'diagonalright') {
|
||||||
|
$diagonalDirection = $diagonalDirection ? Borders::DIAGONAL_BOTH : Borders::DIAGONAL_UP;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Color':
|
case 'Color':
|
||||||
|
@ -760,20 +773,16 @@ class Xml extends BaseReader
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty($thisBorder)) {
|
if ($borderPosition) {
|
||||||
if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) {
|
|
||||||
$this->styles[$styleID]['borders'][$borderPosition] = $thisBorder;
|
$this->styles[$styleID]['borders'][$borderPosition] = $thisBorder;
|
||||||
}
|
} elseif ($diagonalDirection) {
|
||||||
|
$this->styles[$styleID]['borders']['diagonalDirection'] = $diagonalDirection;
|
||||||
|
$this->styles[$styleID]['borders']['diagonal'] = $thisBorder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static $underlineStyles = [
|
||||||
* @param $styleID
|
|
||||||
*/
|
|
||||||
private function parseStyleFont($styleID, SimpleXMLElement $styleAttributes): void
|
|
||||||
{
|
|
||||||
$underlineStyles = [
|
|
||||||
Font::UNDERLINE_NONE,
|
Font::UNDERLINE_NONE,
|
||||||
Font::UNDERLINE_DOUBLE,
|
Font::UNDERLINE_DOUBLE,
|
||||||
Font::UNDERLINE_DOUBLEACCOUNTING,
|
Font::UNDERLINE_DOUBLEACCOUNTING,
|
||||||
|
@ -781,6 +790,28 @@ class Xml extends BaseReader
|
||||||
Font::UNDERLINE_SINGLEACCOUNTING,
|
Font::UNDERLINE_SINGLEACCOUNTING,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private function parseStyleFontUnderline(string $styleID, string $styleAttributeValue): void
|
||||||
|
{
|
||||||
|
if (self::identifyFixedStyleValue(self::$underlineStyles, $styleAttributeValue)) {
|
||||||
|
$this->styles[$styleID]['font']['underline'] = $styleAttributeValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseStyleFontVerticalAlign(string $styleID, string $styleAttributeValue): void
|
||||||
|
{
|
||||||
|
if ($styleAttributeValue == 'Superscript') {
|
||||||
|
$this->styles[$styleID]['font']['superscript'] = true;
|
||||||
|
}
|
||||||
|
if ($styleAttributeValue == 'Subscript') {
|
||||||
|
$this->styles[$styleID]['font']['subscript'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $styleID
|
||||||
|
*/
|
||||||
|
private function parseStyleFont(string $styleID, SimpleXMLElement $styleAttributes): void
|
||||||
|
{
|
||||||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
|
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
|
||||||
$styleAttributeValue = (string) $styleAttributeValue;
|
$styleAttributeValue = (string) $styleAttributeValue;
|
||||||
switch ($styleAttributeKey) {
|
switch ($styleAttributeKey) {
|
||||||
|
@ -805,9 +836,11 @@ class Xml extends BaseReader
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Underline':
|
case 'Underline':
|
||||||
if (self::identifyFixedStyleValue($underlineStyles, $styleAttributeValue)) {
|
$this->parseStyleFontUnderline($styleID, $styleAttributeValue);
|
||||||
$this->styles[$styleID]['font']['underline'] = $styleAttributeValue;
|
|
||||||
}
|
break;
|
||||||
|
case 'VerticalAlign':
|
||||||
|
$this->parseStyleFontVerticalAlign($styleID, $styleAttributeValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -822,11 +855,17 @@ class Xml extends BaseReader
|
||||||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
|
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
|
||||||
switch ($styleAttributeKey) {
|
switch ($styleAttributeKey) {
|
||||||
case 'Color':
|
case 'Color':
|
||||||
$this->styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue, 1);
|
$this->styles[$styleID]['fill']['endColor']['rgb'] = substr($styleAttributeValue, 1);
|
||||||
|
$this->styles[$styleID]['fill']['startColor']['rgb'] = substr($styleAttributeValue, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'PatternColor':
|
||||||
|
$this->styles[$styleID]['fill']['startColor']['rgb'] = substr($styleAttributeValue, 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Pattern':
|
case 'Pattern':
|
||||||
$this->styles[$styleID]['fill']['fillType'] = strtolower($styleAttributeValue);
|
$lcStyleAttributeValue = strtolower((string) $styleAttributeValue);
|
||||||
|
$this->styles[$styleID]['fill']['fillType'] = self::$mappings['fillType'][$lcStyleAttributeValue] ?? Fill::FILL_NONE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Reader\Xml;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||||
|
use SimpleXMLElement;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class PageSettings
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var stdClass
|
||||||
|
*/
|
||||||
|
private $printSettings;
|
||||||
|
|
||||||
|
public function __construct(SimpleXMLElement $xmlX, array $namespaces)
|
||||||
|
{
|
||||||
|
$printSettings = $this->pageSetup($xmlX, $namespaces, $this->getPrintDefaults());
|
||||||
|
$this->printSettings = $this->printSetup($xmlX, $printSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadPageSettings(Spreadsheet $spreadsheet): void
|
||||||
|
{
|
||||||
|
$spreadsheet->getActiveSheet()->getPageSetup()
|
||||||
|
->setPaperSize($this->printSettings->paperSize)
|
||||||
|
->setOrientation($this->printSettings->orientation)
|
||||||
|
->setScale($this->printSettings->scale)
|
||||||
|
->setVerticalCentered($this->printSettings->verticalCentered)
|
||||||
|
->setHorizontalCentered($this->printSettings->horizontalCentered)
|
||||||
|
->setPageOrder($this->printSettings->printOrder);
|
||||||
|
$spreadsheet->getActiveSheet()->getPageMargins()
|
||||||
|
->setTop($this->printSettings->topMargin)
|
||||||
|
->setHeader($this->printSettings->headerMargin)
|
||||||
|
->setLeft($this->printSettings->leftMargin)
|
||||||
|
->setRight($this->printSettings->rightMargin)
|
||||||
|
->setBottom($this->printSettings->bottomMargin)
|
||||||
|
->setFooter($this->printSettings->footerMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPrintDefaults(): stdClass
|
||||||
|
{
|
||||||
|
return (object) [
|
||||||
|
'paperSize' => 9,
|
||||||
|
'orientation' => PageSetup::ORIENTATION_DEFAULT,
|
||||||
|
'scale' => 100,
|
||||||
|
'horizontalCentered' => false,
|
||||||
|
'verticalCentered' => false,
|
||||||
|
'printOrder' => PageSetup::PAGEORDER_DOWN_THEN_OVER,
|
||||||
|
'topMargin' => 0.75,
|
||||||
|
'headerMargin' => 0.3,
|
||||||
|
'leftMargin' => 0.7,
|
||||||
|
'rightMargin' => 0.7,
|
||||||
|
'bottomMargin' => 0.75,
|
||||||
|
'footerMargin' => 0.3,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function pageSetup(SimpleXMLElement $xmlX, array $namespaces, stdClass $printDefaults): stdClass
|
||||||
|
{
|
||||||
|
if (isset($xmlX->WorksheetOptions->PageSetup)) {
|
||||||
|
foreach ($xmlX->WorksheetOptions->PageSetup as $pageSetupData) {
|
||||||
|
foreach ($pageSetupData as $pageSetupKey => $pageSetupValue) {
|
||||||
|
$pageSetupAttributes = $pageSetupValue->attributes($namespaces['x']);
|
||||||
|
switch ($pageSetupKey) {
|
||||||
|
case 'Layout':
|
||||||
|
$this->setLayout($printDefaults, $pageSetupAttributes);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'Header':
|
||||||
|
$printDefaults->headerMargin = (float) $pageSetupAttributes->Margin ?: 1.0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'Footer':
|
||||||
|
$printDefaults->footerMargin = (float) $pageSetupAttributes->Margin ?: 1.0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'PageMargins':
|
||||||
|
$this->setMargins($printDefaults, $pageSetupAttributes);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $printDefaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function printSetup(SimpleXMLElement $xmlX, stdClass $printDefaults): stdClass
|
||||||
|
{
|
||||||
|
if (isset($xmlX->WorksheetOptions->Print)) {
|
||||||
|
foreach ($xmlX->WorksheetOptions->Print as $printData) {
|
||||||
|
foreach ($printData as $printKey => $printValue) {
|
||||||
|
switch ($printKey) {
|
||||||
|
case 'LeftToRight':
|
||||||
|
$printDefaults->printOrder = PageSetup::PAGEORDER_OVER_THEN_DOWN;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'PaperSizeIndex':
|
||||||
|
$printDefaults->paperSize = (int) $printValue ?: 9;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'Scale':
|
||||||
|
$printDefaults->scale = (int) $printValue ?: 100;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $printDefaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setLayout(stdClass $printDefaults, SimpleXMLElement $pageSetupAttributes): void
|
||||||
|
{
|
||||||
|
$printDefaults->orientation = (string) strtolower($pageSetupAttributes->Orientation) ?: PageSetup::ORIENTATION_PORTRAIT;
|
||||||
|
$printDefaults->horizontalCentered = (bool) $pageSetupAttributes->CenterHorizontal ?: false;
|
||||||
|
$printDefaults->verticalCentered = (bool) $pageSetupAttributes->CenterVertical ?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setMargins(stdClass $printDefaults, SimpleXMLElement $pageSetupAttributes): void
|
||||||
|
{
|
||||||
|
$printDefaults->leftMargin = (float) $pageSetupAttributes->Left ?: 1.0;
|
||||||
|
$printDefaults->rightMargin = (float) $pageSetupAttributes->Right ?: 1.0;
|
||||||
|
$printDefaults->topMargin = (float) $pageSetupAttributes->Top ?: 1.0;
|
||||||
|
$printDefaults->bottomMargin = (float) $pageSetupAttributes->Bottom ?: 1.0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet;
|
namespace PhpOffice\PhpSpreadsheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
@ -68,7 +69,7 @@ class ReferenceHelper
|
||||||
*/
|
*/
|
||||||
public static function columnReverseSort($a, $b)
|
public static function columnReverseSort($a, $b)
|
||||||
{
|
{
|
||||||
return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b);
|
return -strcasecmp(strlen($a) . $a, strlen($b) . $b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +108,7 @@ class ReferenceHelper
|
||||||
[$bc, $br] = sscanf($b, '%[A-Z]%d');
|
[$bc, $br] = sscanf($b, '%[A-Z]%d');
|
||||||
|
|
||||||
if ($ar === $br) {
|
if ($ar === $br) {
|
||||||
return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc);
|
return -strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($ar < $br) ? 1 : -1;
|
return ($ar < $br) ? 1 : -1;
|
||||||
|
@ -129,13 +130,17 @@ class ReferenceHelper
|
||||||
[$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
|
[$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
|
||||||
$cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
|
$cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
|
||||||
// Is cell within the range of rows/columns if we're deleting
|
// Is cell within the range of rows/columns if we're deleting
|
||||||
if ($pNumRows < 0 &&
|
if (
|
||||||
|
$pNumRows < 0 &&
|
||||||
($cellRow >= ($beforeRow + $pNumRows)) &&
|
($cellRow >= ($beforeRow + $pNumRows)) &&
|
||||||
($cellRow < $beforeRow)) {
|
($cellRow < $beforeRow)
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
} elseif ($pNumCols < 0 &&
|
} elseif (
|
||||||
|
$pNumCols < 0 &&
|
||||||
($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) &&
|
($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) &&
|
||||||
($cellColumnIndex < $beforeColumnIndex)) {
|
($cellColumnIndex < $beforeColumnIndex)
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,11 +605,11 @@ class ReferenceHelper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update workbook: named ranges
|
// Update workbook: define names
|
||||||
if (count($pSheet->getParent()->getNamedRanges()) > 0) {
|
if (count($pSheet->getParent()->getDefinedNames()) > 0) {
|
||||||
foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) {
|
foreach ($pSheet->getParent()->getDefinedNames() as $definedName) {
|
||||||
if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) {
|
if ($definedName->getWorksheet()->getHashCode() === $pSheet->getHashCode()) {
|
||||||
$namedRange->setRange($this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows));
|
$definedName->setValue($this->updateCellReference($definedName->getValue(), $pBefore, $pNumCols, $pNumRows));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -754,6 +759,141 @@ class ReferenceHelper
|
||||||
return implode('"', $formulaBlocks);
|
return implode('"', $formulaBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update all cell references within a formula, irrespective of worksheet.
|
||||||
|
*/
|
||||||
|
public function updateFormulaReferencesAnyWorksheet(string $formula = '', int $insertColumns = 0, int $insertRows = 0): string
|
||||||
|
{
|
||||||
|
$formula = $this->updateCellReferencesAllWorksheets($formula, $insertColumns, $insertRows);
|
||||||
|
|
||||||
|
if ($insertColumns !== 0) {
|
||||||
|
$formula = $this->updateColumnRangesAllWorksheets($formula, $insertColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($insertRows !== 0) {
|
||||||
|
$formula = $this->updateRowRangesAllWorksheets($formula, $insertRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateCellReferencesAllWorksheets(string $formula, int $insertColumns, int $insertRows): string
|
||||||
|
{
|
||||||
|
$splitCount = preg_match_all(
|
||||||
|
'/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/mui',
|
||||||
|
$formula,
|
||||||
|
$splitRanges,
|
||||||
|
PREG_OFFSET_CAPTURE
|
||||||
|
);
|
||||||
|
|
||||||
|
$columnLengths = array_map('strlen', array_column($splitRanges[6], 0));
|
||||||
|
$rowLengths = array_map('strlen', array_column($splitRanges[7], 0));
|
||||||
|
$columnOffsets = array_column($splitRanges[6], 1);
|
||||||
|
$rowOffsets = array_column($splitRanges[7], 1);
|
||||||
|
|
||||||
|
$columns = $splitRanges[6];
|
||||||
|
$rows = $splitRanges[7];
|
||||||
|
|
||||||
|
while ($splitCount > 0) {
|
||||||
|
--$splitCount;
|
||||||
|
$columnLength = $columnLengths[$splitCount];
|
||||||
|
$rowLength = $rowLengths[$splitCount];
|
||||||
|
$columnOffset = $columnOffsets[$splitCount];
|
||||||
|
$rowOffset = $rowOffsets[$splitCount];
|
||||||
|
$column = $columns[$splitCount][0];
|
||||||
|
$row = $rows[$splitCount][0];
|
||||||
|
|
||||||
|
if (!empty($column) && $column[0] !== '$') {
|
||||||
|
$column = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($column) + $insertColumns);
|
||||||
|
$formula = substr($formula, 0, $columnOffset) . $column . substr($formula, $columnOffset + $columnLength);
|
||||||
|
}
|
||||||
|
if (!empty($row) && $row[0] !== '$') {
|
||||||
|
$row += $insertRows;
|
||||||
|
$formula = substr($formula, 0, $rowOffset) . $row . substr($formula, $rowOffset + $rowLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateColumnRangesAllWorksheets(string $formula, int $insertColumns): string
|
||||||
|
{
|
||||||
|
$splitCount = preg_match_all(
|
||||||
|
'/' . Calculation::CALCULATION_REGEXP_COLUMNRANGE_RELATIVE . '/mui',
|
||||||
|
$formula,
|
||||||
|
$splitRanges,
|
||||||
|
PREG_OFFSET_CAPTURE
|
||||||
|
);
|
||||||
|
|
||||||
|
$fromColumnLengths = array_map('strlen', array_column($splitRanges[1], 0));
|
||||||
|
$fromColumnOffsets = array_column($splitRanges[1], 1);
|
||||||
|
$toColumnLengths = array_map('strlen', array_column($splitRanges[2], 0));
|
||||||
|
$toColumnOffsets = array_column($splitRanges[2], 1);
|
||||||
|
|
||||||
|
$fromColumns = $splitRanges[1];
|
||||||
|
$toColumns = $splitRanges[2];
|
||||||
|
|
||||||
|
while ($splitCount > 0) {
|
||||||
|
--$splitCount;
|
||||||
|
$fromColumnLength = $fromColumnLengths[$splitCount];
|
||||||
|
$toColumnLength = $toColumnLengths[$splitCount];
|
||||||
|
$fromColumnOffset = $fromColumnOffsets[$splitCount];
|
||||||
|
$toColumnOffset = $toColumnOffsets[$splitCount];
|
||||||
|
$fromColumn = $fromColumns[$splitCount][0];
|
||||||
|
$toColumn = $toColumns[$splitCount][0];
|
||||||
|
|
||||||
|
if (!empty($fromColumn) && $fromColumn[0] !== '$') {
|
||||||
|
$fromColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($fromColumn) + $insertColumns);
|
||||||
|
$formula = substr($formula, 0, $fromColumnOffset) . $fromColumn . substr($formula, $fromColumnOffset + $fromColumnLength);
|
||||||
|
}
|
||||||
|
if (!empty($toColumn) && $toColumn[0] !== '$') {
|
||||||
|
$toColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($toColumn) + $insertColumns);
|
||||||
|
$formula = substr($formula, 0, $toColumnOffset) . $toColumn . substr($formula, $toColumnOffset + $toColumnLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateRowRangesAllWorksheets(string $formula, int $insertRows): string
|
||||||
|
{
|
||||||
|
$splitCount = preg_match_all(
|
||||||
|
'/' . Calculation::CALCULATION_REGEXP_ROWRANGE_RELATIVE . '/mui',
|
||||||
|
$formula,
|
||||||
|
$splitRanges,
|
||||||
|
PREG_OFFSET_CAPTURE
|
||||||
|
);
|
||||||
|
|
||||||
|
$fromRowLengths = array_map('strlen', array_column($splitRanges[1], 0));
|
||||||
|
$fromRowOffsets = array_column($splitRanges[1], 1);
|
||||||
|
$toRowLengths = array_map('strlen', array_column($splitRanges[2], 0));
|
||||||
|
$toRowOffsets = array_column($splitRanges[2], 1);
|
||||||
|
|
||||||
|
$fromRows = $splitRanges[1];
|
||||||
|
$toRows = $splitRanges[2];
|
||||||
|
|
||||||
|
while ($splitCount > 0) {
|
||||||
|
--$splitCount;
|
||||||
|
$fromRowLength = $fromRowLengths[$splitCount];
|
||||||
|
$toRowLength = $toRowLengths[$splitCount];
|
||||||
|
$fromRowOffset = $fromRowOffsets[$splitCount];
|
||||||
|
$toRowOffset = $toRowOffsets[$splitCount];
|
||||||
|
$fromRow = $fromRows[$splitCount][0];
|
||||||
|
$toRow = $toRows[$splitCount][0];
|
||||||
|
|
||||||
|
if (!empty($fromRow) && $fromRow[0] !== '$') {
|
||||||
|
$fromRow += $insertRows;
|
||||||
|
$formula = substr($formula, 0, $fromRowOffset) . $fromRow . substr($formula, $fromRowOffset + $fromRowLength);
|
||||||
|
}
|
||||||
|
if (!empty($toRow) && $toRow[0] !== '$') {
|
||||||
|
$toRow += $insertRows;
|
||||||
|
$formula = substr($formula, 0, $toRowOffset) . $toRow . substr($formula, $toRowOffset + $toRowLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $formula;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update cell reference.
|
* Update cell reference.
|
||||||
*
|
*
|
||||||
|
|
|
@ -5,6 +5,8 @@ namespace PhpOffice\PhpSpreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Renderer\IRenderer;
|
use PhpOffice\PhpSpreadsheet\Chart\Renderer\IRenderer;
|
||||||
use PhpOffice\PhpSpreadsheet\Collection\Memory;
|
use PhpOffice\PhpSpreadsheet\Collection\Memory;
|
||||||
|
use Psr\Http\Client\ClientInterface;
|
||||||
|
use Psr\Http\Message\RequestFactoryInterface;
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
|
|
||||||
class Settings
|
class Settings
|
||||||
|
@ -42,6 +44,18 @@ class Settings
|
||||||
*/
|
*/
|
||||||
private static $cache;
|
private static $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HTTP client implementation to be used for network request.
|
||||||
|
*
|
||||||
|
* @var null|ClientInterface
|
||||||
|
*/
|
||||||
|
private static $httpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var null|RequestFactoryInterface
|
||||||
|
*/
|
||||||
|
private static $requestFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the locale code to use for formula translations and any special formatting.
|
* Set the locale code to use for formula translations and any special formatting.
|
||||||
*
|
*
|
||||||
|
@ -156,4 +170,49 @@ class Settings
|
||||||
|
|
||||||
return self::$cache;
|
return self::$cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the HTTP client implementation to be used for network request.
|
||||||
|
*/
|
||||||
|
public static function setHttpClient(ClientInterface $httpClient, RequestFactoryInterface $requestFactory): void
|
||||||
|
{
|
||||||
|
self::$httpClient = $httpClient;
|
||||||
|
self::$requestFactory = $requestFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unset the HTTP client configuration.
|
||||||
|
*/
|
||||||
|
public static function unsetHttpClient(): void
|
||||||
|
{
|
||||||
|
self::$httpClient = null;
|
||||||
|
self::$requestFactory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTTP client implementation to be used for network request.
|
||||||
|
*/
|
||||||
|
public static function getHttpClient(): ClientInterface
|
||||||
|
{
|
||||||
|
self::assertHttpClient();
|
||||||
|
|
||||||
|
return self::$httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTTP request factory.
|
||||||
|
*/
|
||||||
|
public static function getRequestFactory(): RequestFactoryInterface
|
||||||
|
{
|
||||||
|
self::assertHttpClient();
|
||||||
|
|
||||||
|
return self::$requestFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function assertHttpClient(): void
|
||||||
|
{
|
||||||
|
if (!self::$httpClient || !self::$requestFactory) {
|
||||||
|
throw new Exception('HTTP client must be configured via Settings::setHttpClient() to be able to use WEBSERVICE function.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
|
|
||||||
class CodePage
|
class CodePage
|
||||||
{
|
{
|
||||||
|
public const DEFAULT_CODE_PAGE = 'CP1252';
|
||||||
|
|
||||||
private static $pageArray = [
|
private static $pageArray = [
|
||||||
0 => 'CP1252', // CodePage is not always correctly set when the xls file was saved by Apple's Numbers program
|
0 => 'CP1252', // CodePage is not always correctly set when the xls file was saved by Apple's Numbers program
|
||||||
367 => 'ASCII', // ASCII
|
367 => 'ASCII', // ASCII
|
||||||
|
@ -65,6 +67,11 @@ class CodePage
|
||||||
65001 => 'UTF-8', // Unicode (UTF-8)
|
65001 => 'UTF-8', // Unicode (UTF-8)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public static function validate(string $codePage): bool
|
||||||
|
{
|
||||||
|
return in_array($codePage, self::$pageArray, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert Microsoft Code Page Identifier to Code Page Name which iconv
|
* Convert Microsoft Code Page Identifier to Code Page Name which iconv
|
||||||
* and mbstring understands.
|
* and mbstring understands.
|
||||||
|
|
|
@ -71,8 +71,10 @@ class Date
|
||||||
*/
|
*/
|
||||||
public static function setExcelCalendar($baseDate)
|
public static function setExcelCalendar($baseDate)
|
||||||
{
|
{
|
||||||
if (($baseDate == self::CALENDAR_WINDOWS_1900) ||
|
if (
|
||||||
($baseDate == self::CALENDAR_MAC_1904)) {
|
($baseDate == self::CALENDAR_WINDOWS_1900) ||
|
||||||
|
($baseDate == self::CALENDAR_MAC_1904)
|
||||||
|
) {
|
||||||
self::$excelCalendar = $baseDate;
|
self::$excelCalendar = $baseDate;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -387,6 +389,11 @@ class Date
|
||||||
if ((substr($pFormatCode, 0, 1) == '_') || (substr($pFormatCode, 0, 2) == '0 ')) {
|
if ((substr($pFormatCode, 0, 1) == '_') || (substr($pFormatCode, 0, 2) == '0 ')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Some "special formats" provided in German Excel versions were detected as date time value,
|
||||||
|
// so filter them out here - "\C\H\-00000" (Switzerland) and "\D-00000" (Germany).
|
||||||
|
if (\strpos($pFormatCode, '-00000') !== false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Try checking for any of the date formatting characters that don't appear within square braces
|
// Try checking for any of the date formatting characters that don't appear within square braces
|
||||||
if (preg_match('/(^|\])[^\[]*[' . self::$possibleDateFormatCharacters . ']/i', $pFormatCode)) {
|
if (preg_match('/(^|\])[^\[]*[' . self::$possibleDateFormatCharacters . ']/i', $pFormatCode)) {
|
||||||
// We might also have a format mask containing quoted strings...
|
// We might also have a format mask containing quoted strings...
|
||||||
|
@ -395,8 +402,10 @@ class Date
|
||||||
$segMatcher = false;
|
$segMatcher = false;
|
||||||
foreach (explode('"', $pFormatCode) as $subVal) {
|
foreach (explode('"', $pFormatCode) as $subVal) {
|
||||||
// Only test in alternate array entries (the non-quoted blocks)
|
// Only test in alternate array entries (the non-quoted blocks)
|
||||||
if (($segMatcher = !$segMatcher) &&
|
if (
|
||||||
(preg_match('/(^|\])[^\[]*[' . self::$possibleDateFormatCharacters . ']/i', $subVal))) {
|
($segMatcher = !$segMatcher) &&
|
||||||
|
(preg_match('/(^|\])[^\[]*[' . self::$possibleDateFormatCharacters . ']/i', $subVal))
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,21 +318,25 @@ class Font
|
||||||
// value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font.
|
// value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font.
|
||||||
$columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText));
|
$columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText));
|
||||||
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
|
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Arial':
|
case 'Arial':
|
||||||
// value 8 was set because of experience in different exports at Arial 10 font.
|
// value 8 was set because of experience in different exports at Arial 10 font.
|
||||||
$columnWidth = (int) (8 * StringHelper::countCharacters($columnText));
|
$columnWidth = (int) (8 * StringHelper::countCharacters($columnText));
|
||||||
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
|
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'Verdana':
|
case 'Verdana':
|
||||||
// value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font.
|
// value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font.
|
||||||
$columnWidth = (int) (8 * StringHelper::countCharacters($columnText));
|
$columnWidth = (int) (8 * StringHelper::countCharacters($columnText));
|
||||||
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
|
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// just assume Calibri
|
// just assume Calibri
|
||||||
$columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText));
|
$columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText));
|
||||||
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
|
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue