Merge branch 'master' into PHP8-Sane-Property-Names

This commit is contained in:
Adrien Crivelli 2021-10-31 15:25:01 +09:00
commit 69f633420b
No known key found for this signature in database
GPG Key ID: 16D79B903B4B5874
1418 changed files with 82058 additions and 35096 deletions

2
.gitattributes vendored
View File

@ -3,12 +3,12 @@
/.github export-ignore
/.gitignore export-ignore
/.php_cs.dist export-ignore
/.sami.php export-ignore
/.scrutinizer.yml export-ignore
/CHANGELOG.PHPExcel.md export-ignore
/bin export-ignore
/composer.lock export-ignore
/docs export-ignore
/infra export-ignore
/mkdocs.yml export-ignore
/phpunit.xml.dist export-ignore
/samples export-ignore

8
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: monthly
time: "11:00"
open-pull-requests-limit: 10

View File

@ -19,7 +19,7 @@ jobs:
- name: Build API documentation
run: |
curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0-rc/phpDocumentor.phar
curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0/phpDocumentor.phar
php phpDocumentor.phar --directory src/ --target docs/api
- name: Deploy to GithHub Pages

View File

@ -5,6 +5,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
experimental:
- false
php-version:
- '7.2'
- '7.3'
@ -38,13 +40,13 @@ jobs:
- name: Delete composer lock file
id: composer-lock
if: ${{ matrix.php-version == '8.0' || matrix.php-version == '8.1' }}
if: ${{ matrix.php-version == '8.1' }}
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 }}
run: composer update --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"
@ -52,8 +54,10 @@ jobs:
- name: Setup problem matchers for PHPUnit
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Test with PHPUnit
run: ./vendor/bin/phpunit
- name: "Run PHPUnit tests (Experimental: ${{ matrix.experimental }})"
env:
FAILURE_ACTION: "${{ matrix.experimental == true }}"
run: vendor/bin/phpunit --verbose || $FAILURE_ACTION
php-cs-fixer:
runs-on: ubuntu-latest
@ -117,6 +121,68 @@ jobs:
- name: Code style with PHP_CodeSniffer
run: ./vendor/bin/phpcs -q --report=checkstyle | cs2pr
versions:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@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 Version Compatibility check with PHP_CodeSniffer
run: ./vendor/bin/phpcs -q --report-width=200 --report=summary,full src/ --standard=PHPCompatibility --runtime-set testVersion 7.2-
phpstan:
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: Static analysis with PHPStan
run: ./vendor/bin/phpstan analyse
coverage:
runs-on: ubuntu-latest
steps:

3
.gitignore vendored
View File

@ -8,3 +8,6 @@
*.project
/.settings
/.idea
## mkdocs output
/site

View File

@ -160,7 +160,7 @@ return PhpCsFixer\Config::create()
'php_unit_test_annotation' => true,
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_add_missing_param_annotation' => false, // Don't add things that bring no value
'phpdoc_align' => false, // Waste of time
'phpdoc_annotation_without_dot' => true,
'phpdoc_indent' => true,

View File

@ -1518,7 +1518,7 @@ documentation for more information on entering dates into a cell.
### Bugfixes
- PHPExcel->removeSheetByIndex now re-orders sheets after deletion, so no array indexes are lost - @JV
- PHPExcel_Writer_Excel2007_Worksheet::_writeCols() used direct assignment to $pSheet->getColumnDimension('A')->Width instead of $pSheet->getColumnDimension('A')->setWidth() - @JV
- PHPExcel_Writer_Excel2007_Worksheet::_writeCols() used direct assignment to $pSheet->getColumnDimension('A')->Width instead of ~~~~$pSheet->getColumnDimension('A')->setWidth() - @JV
- DocumentProperties used $this->LastModifiedBy instead of $this->_lastModifiedBy. - @JV
### General

View File

@ -8,8 +8,28 @@ and this project adheres to [Semantic Versioning](https://semver.org).
## Unreleased - TBD
### Added
- CSV Reader - Best Guess for Encoding, and Handle Null-string Escape [#1647](https://github.com/PHPOffice/PhpSpreadsheet/issues/1647)
- Ability to set style on named range, and validate input to setSelectedCells.
[Issue #2279](https://github.com/PHPOffice/PhpSpreadsheet/issues/2279)
[PR #2280](https://github.com/PHPOffice/PhpSpreadsheet/pull/2280)
- Process comments in Sylk file.
[Issue #2276](https://github.com/PHPOffice/PhpSpreadsheet/issues/2276)
[PR #2277](https://github.com/PHPOffice/PhpSpreadsheet/pull/2277)
- Addition of Custom Properties to Ods Writer, and 32-bit-safe timestamps for Document Properties.
[PR #2113](https://github.com/PHPOffice/PhpSpreadsheet/pull/2113)
- Added callback to CSV reader to set user-specified defaults for various properties (especially for escape which has a poor PHP-inherited default of backslash which does not correspond with Excel).
[PR #2103](https://github.com/PHPOffice/PhpSpreadsheet/pull/2103)
- Phase 1 of better namespace handling for Xlsx, resolving many open issues.
[PR #2173](https://github.com/PHPOffice/PhpSpreadsheet/pull/2173)
[PR #2204](https://github.com/PHPOffice/PhpSpreadsheet/pull/2204)
[PR #2303](https://github.com/PHPOffice/PhpSpreadsheet/pull/2303)
- Add ability to extract images if source is a URL. [Issue #1997](https://github.com/PHPOffice/PhpSpreadsheet/issues/1997) [PR #2072](https://github.com/PHPOffice/PhpSpreadsheet/pull/2072)
- Support for passing flags in the Reader `load()` and Writer `save()`methods, and through the IOFactory, to set behaviours. [PR #2136](https://github.com/PHPOffice/PhpSpreadsheet/pull/2136)
- See [documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-and-writing-to-file/) for details
- More flexibility in the StringValueBinder to determine what datatypes should be treated as strings [PR #2138](https://github.com/PHPOffice/PhpSpreadsheet/pull/2138)
- Helper class for conversion between css size Units of measure (`px`, `pt`, `pc`, `in`, `cm`, `mm`). [PR #2152](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145)
- Allow Row height and Column Width to be set using different units of measure (`px`, `pt`, `pc`, `in`, `cm`, `mm`), rather than only in points or MS Excel column width units. [PR #2152](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145)
- Ability to stream to an Amazon S3 bucket
[Issue #2249](https://github.com/PHPOffice/PhpSpreadsheet/issues/2249)
- Provided a Size Helper class to validate size values (pt, px, em)
### Changed
@ -18,14 +38,232 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Deprecated
- PHP8.1 will deprecate auto_detect_line_endings. As a result of this change, Csv Reader using PHP8.1+ will no longer be able to handle a Csv with Mac line endings.
### Removed
- Nothing.
### Fixed
- Unexpected format in Xlsx Timestamp
[Issue #2331](https://github.com/PHPOffice/PhpSpreadsheet/issues/2331)
[PR #2332](https://github.com/PHPOffice/PhpSpreadsheet/pull/2332)
- Corrections for HLOOKUP
[Issue #2123](https://github.com/PHPOffice/PhpSpreadsheet/issues/2123)
[PR #2330](https://github.com/PHPOffice/PhpSpreadsheet/pull/2330)
- Corrections for Xlsx Read Comments
[Issue #2316](https://github.com/PHPOffice/PhpSpreadsheet/issues/2316)
[PR #2329](https://github.com/PHPOffice/PhpSpreadsheet/pull/2329)
- Lowercase Calibri font names
[Issue #2273](https://github.com/PHPOffice/PhpSpreadsheet/issues/2273)
[PR #2325](https://github.com/PHPOffice/PhpSpreadsheet/pull/2325)
- isFormula Referencing Sheet with Space in Title
[Issue #2304](https://github.com/PHPOffice/PhpSpreadsheet/issues/2304)
[PR #2306](https://github.com/PHPOffice/PhpSpreadsheet/pull/2306)
- Xls Reader Fatal Error due to Undefined Offset
[Issue #1114](https://github.com/PHPOffice/PhpSpreadsheet/issues/1114)
[PR #2308](https://github.com/PHPOffice/PhpSpreadsheet/pull/2308)
- Permit Csv Reader delimiter to be set to null.
[Issue #2287](https://github.com/PHPOffice/PhpSpreadsheet/issues/2287)
[PR #2288](https://github.com/PHPOffice/PhpSpreadsheet/pull/2288)
- Csv Reader did not handle booleans correctly.
[PR #2232](https://github.com/PHPOffice/PhpSpreadsheet/pull/2232)
- Problems when deleting sheet with local defined name.
[Issue #2266](https://github.com/PHPOffice/PhpSpreadsheet/issues/2266)
[PR #2284](https://github.com/PHPOffice/PhpSpreadsheet/pull/2284)
- Worksheet passwords were not always handled correctly.
[Issue #1897](https://github.com/PHPOffice/PhpSpreadsheet/issues/1897)
[PR #2197](https://github.com/PHPOffice/PhpSpreadsheet/pull/2197)
- Gnumeric Reader will now distinguish between Created and Modified timestamp.
[PR #2133](https://github.com/PHPOffice/PhpSpreadsheet/pull/2133)
- Xls Reader will now handle MACCENTRALEUROPE with or without hyphen.
[Issue #549](https://github.com/PHPOffice/PhpSpreadsheet/issues/549)
[PR #2213](https://github.com/PHPOffice/PhpSpreadsheet/pull/2213)
- Tweaks to input file validation.
[Issue #1718](https://github.com/PHPOffice/PhpSpreadsheet/issues/1718)
[PR #2217](https://github.com/PHPOffice/PhpSpreadsheet/pull/2217)
- Html Reader did not handle comments correctly.
[Issue #2234](https://github.com/PHPOffice/PhpSpreadsheet/issues/2234)
[PR #2235](https://github.com/PHPOffice/PhpSpreadsheet/pull/2235)
- Apache OpenOffice Uses Unexpected Case for General format.
[Issue #2239](https://github.com/PHPOffice/PhpSpreadsheet/issues/2239)
[PR #2242](https://github.com/PHPOffice/PhpSpreadsheet/pull/2242)
- Problems with fraction formatting.
[Issue #2253](https://github.com/PHPOffice/PhpSpreadsheet/issues/2253)
[PR #2254](https://github.com/PHPOffice/PhpSpreadsheet/pull/2254)
- Xlsx Reader had problems reading file with no styles.xml or empty styles.xml.
[Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246)
[PR #2247](https://github.com/PHPOffice/PhpSpreadsheet/pull/2247)
- Xlsx Reader did not read Data Validation flags correctly.
[Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224)
[PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225)
- Better handling of empty arguments in Calculation engine.
[PR #2143](https://github.com/PHPOffice/PhpSpreadsheet/pull/2143)
- Many fixes for Autofilter.
[Issue #2216](https://github.com/PHPOffice/PhpSpreadsheet/issues/2216)
[PR #2141](https://github.com/PHPOffice/PhpSpreadsheet/pull/2141)
[PR #2162](https://github.com/PHPOffice/PhpSpreadsheet/pull/2162)
[PR #2218](https://github.com/PHPOffice/PhpSpreadsheet/pull/2218)
- Locale generator will now use Unix line endings even on Windows.
[Issue #2172](https://github.com/PHPOffice/PhpSpreadsheet/issues/2172)
[PR #2174](https://github.com/PHPOffice/PhpSpreadsheet/pull/2174)
- Support differences in implementation of Text functions between Excel/Ods/Gnumeric.
[PR #2151](https://github.com/PHPOffice/PhpSpreadsheet/pull/2151)
- Fixes to places where PHP8.1 enforces new or previously unenforced restrictions.
[PR #2137](https://github.com/PHPOffice/PhpSpreadsheet/pull/2137)
[PR #2191](https://github.com/PHPOffice/PhpSpreadsheet/pull/2191)
[PR #2231](https://github.com/PHPOffice/PhpSpreadsheet/pull/2231)
- Clone for HashTable was incorrect.
[PR #2130](https://github.com/PHPOffice/PhpSpreadsheet/pull/2130)
- Xlsx Reader was not evaluating Document Security Lock correctly.
[PR #2128](https://github.com/PHPOffice/PhpSpreadsheet/pull/2128)
- Error in COUPNCD handling end of month.
[Issue #2116](https://github.com/PHPOffice/PhpSpreadsheet/issues/2116)
[PR #2119](https://github.com/PHPOffice/PhpSpreadsheet/pull/2119)
- Xls Writer Parser did not handle concatenation operator correctly.
[PR #2080](https://github.com/PHPOffice/PhpSpreadsheet/pull/2080)
- Xlsx Writer did not handle boolean false correctly.
[Issue #2082](https://github.com/PHPOffice/PhpSpreadsheet/issues/2082)
[PR #2087](https://github.com/PHPOffice/PhpSpreadsheet/pull/2087)
- SUM needs to treat invalid strings differently depending on whether they come from a cell or are used as literals.
[Issue #2042](https://github.com/PHPOffice/PhpSpreadsheet/issues/2042)
[PR #2045](https://github.com/PHPOffice/PhpSpreadsheet/pull/2045)
- Html reader could have set illegal coordinates when dealing with embedded tables.
[Issue #2029](https://github.com/PHPOffice/PhpSpreadsheet/issues/2029)
[PR #2032](https://github.com/PHPOffice/PhpSpreadsheet/pull/2032)
- Documentation for printing gridlines was wrong.
[PR #2188](https://github.com/PHPOffice/PhpSpreadsheet/pull/2188)
- Return Value Error - DatabaseAbstruct::buildQuery() return null but must be string [Issue #2158](https://github.com/PHPOffice/PhpSpreadsheet/issues/2158) [PR #2160](https://github.com/PHPOffice/PhpSpreadsheet/pull/2160)
- Xlsx reader not recognize data validations that references another sheet
[Issue #1432](https://github.com/PHPOffice/PhpSpreadsheet/issues/1432)
[Issue #2149](https://github.com/PHPOffice/PhpSpreadsheet/issues/2149)
[PR #2150](https://github.com/PHPOffice/PhpSpreadsheet/pull/2150)
[PR #2265](https://github.com/PHPOffice/PhpSpreadsheet/pull/2265)
- Don't calculate cell width for autosize columns if a cell contains a null or empty string value [Issue #2165](https://github.com/PHPOffice/PhpSpreadsheet/issues/2165) [PR #2167](https://github.com/PHPOffice/PhpSpreadsheet/pull/2167)
- Allow negative interest rate values in a number of the Financial functions (`PPMT()`, `PMT()`, `FV()`, `PV()`, `NPER()`, etc) [Issue #2163](https://github.com/PHPOffice/PhpSpreadsheet/issues/2163) [PR #2164](https://github.com/PHPOffice/PhpSpreadsheet/pull/2164)
- Xls Reader changing grey background to black in Excel template [Issue #2147](Changing grey background to black in Excel template) [PR #2156](https://github.com/PHPOffice/PhpSpreadsheet/pull/2156)
- Column width and Row height styles in the Html Reader when the value includes a unit of measure. [Issue #2145](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145).
- Data Validation flags not set correctly when reading XLSX files. [Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224) [PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225)
- Reading XLSX files without styles.xml throws an exception. [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246)
- Improved performance of `Style::applyFromArray()` when applied to several cells. [PR #1785](https://github.com/PHPOffice/PhpSpreadsheet/issues/1785).
- Improve XLSX parsing speed if no readFilter is applied (again) - [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772)
## 1.18.0 - 2021-05-31
### Added
- Enhancements to CSV Reader, allowing options to be set when using `IOFactory::load()` with a callback to set delimiter, enclosure, charset etc. [PR #2103](https://github.com/PHPOffice/PhpSpreadsheet/pull/2103) - See [documentation](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/docs/topics/reading-and-writing-to-file.md#csv-comma-separated-values) for details.
- Implemented basic AutoFiltering for Ods Reader and Writer [PR #2053](https://github.com/PHPOffice/PhpSpreadsheet/pull/2053)
- Implemented basic AutoFiltering for Gnumeric Reader [PR #2055](https://github.com/PHPOffice/PhpSpreadsheet/pull/2055)
- Improved support for Row and Column ranges in formulae [Issue #1755](https://github.com/PHPOffice/PhpSpreadsheet/issues/1755) [PR #2028](https://github.com/PHPOffice/PhpSpreadsheet/pull/2028)
- Implemented URLENCODE() Web Function
- Implemented the CHITEST(), CHISQ.DIST() and CHISQ.INV() and equivalent Statistical functions, for both left- and right-tailed distributions.
- Support for ActiveSheet and SelectedCells in the ODS Reader and Writer. [PR #1908](https://github.com/PHPOffice/PhpSpreadsheet/pull/1908)
- Support for notContainsText Conditional Style in xlsx [Issue #984](https://github.com/PHPOffice/PhpSpreadsheet/issues/984)
### Changed
- Use of `nb` rather than `no` as the locale code for Norsk Bokmål.
### Deprecated
- All Excel Function implementations in `Calculation\Database`, `Calculation\DateTime`, `Calculation\Engineering`, `Calculation\Financial`, `Calculation\Logical`, `Calculation\LookupRef`, `Calculation\MathTrig`, `Calculation\Statistical`, `Calculation\TextData` and `Calculation\Web` have been moved to dedicated classes for individual functions or groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted.
### Removed
- Use of `nb` rather than `no` as the locale language code for Norsk Bokmål.
### Fixed
- Fixed error in COUPNCD() calculation for end of month [Issue #2116](https://github.com/PHPOffice/PhpSpreadsheet/issues/2116) - [PR #2119](https://github.com/PHPOffice/PhpSpreadsheet/pull/2119)
- Resolve default values when a null argument is passed for HLOOKUP(), VLOOKUP() and ADDRESS() functions [Issue #2120](https://github.com/PHPOffice/PhpSpreadsheet/issues/2120) - [PR #2121](https://github.com/PHPOffice/PhpSpreadsheet/pull/2121)
- Fixed incorrect R1C1 to A1 subtraction formula conversion (`R[-2]C-R[2]C`) [Issue #2076](https://github.com/PHPOffice/PhpSpreadsheet/pull/2076) [PR #2086](https://github.com/PHPOffice/PhpSpreadsheet/pull/2086)
- Correctly handle absolute A1 references when converting to R1C1 format [PR #2060](https://github.com/PHPOffice/PhpSpreadsheet/pull/2060)
- Correct default fill style for conditional without a pattern defined [Issue #2035](https://github.com/PHPOffice/PhpSpreadsheet/issues/2035) [PR #2050](https://github.com/PHPOffice/PhpSpreadsheet/pull/2050)
- Fixed issue where array key check for existince before accessing arrays in Xlsx.php. [PR #1970](https://github.com/PHPOffice/PhpSpreadsheet/pull/1970)
- Fixed issue with quoted strings in number format mask rendered with toFormattedString() [Issue 1972#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1972) [PR #1978](https://github.com/PHPOffice/PhpSpreadsheet/pull/1978)
- Fixed issue with percentage formats in number format mask rendered with toFormattedString() [Issue 1929#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1929) [PR #1928](https://github.com/PHPOffice/PhpSpreadsheet/pull/1928)
- Fixed issue with _ spacing character in number format mask corrupting output from toFormattedString() [Issue 1924#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1924) [PR #1927](https://github.com/PHPOffice/PhpSpreadsheet/pull/1927)
- Fix for [Issue #1887](https://github.com/PHPOffice/PhpSpreadsheet/issues/1887) - Lose Track of Selected Cells After Save
- Fixed issue with Xlsx@listWorksheetInfo not returning any data
- Fixed invalid arguments triggering mb_substr() error in LEFT(), MID() and RIGHT() text functions. [Issue #640](https://github.com/PHPOffice/PhpSpreadsheet/issues/640)
- Fix for [Issue #1916](https://github.com/PHPOffice/PhpSpreadsheet/issues/1916) - Invalid signature check for XML files
- Fix change in `Font::setSize()` behavior for PHP8. [PR #2100](https://github.com/PHPOffice/PhpSpreadsheet/pull/2100)
## 1.17.1 - 2021-03-01
### Added
- Implementation of the Excel `AVERAGEIFS()` functions as part of a restructuring of Database functions and Conditional Statistical functions.
- Support for date values and percentages in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1875](https://github.com/PHPOffice/PhpSpreadsheet/pull/1875)
- Support for booleans, and for wildcard text search in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1876](https://github.com/PHPOffice/PhpSpreadsheet/pull/1876)
- Implemented DataBar for conditional formatting in Xlsx, providing read/write and creation of (type, value, direction, fills, border, axis position, color settings) as DataBar options in Excel. [#1754](https://github.com/PHPOffice/PhpSpreadsheet/pull/1754)
- Alignment for ODS Writer [#1796](https://github.com/PHPOffice/PhpSpreadsheet/issues/1796)
- Basic implementation of the PERMUTATIONA() Statistical Function
### Changed
- Formula functions that previously called PHP functions directly are now processed through the Excel Functions classes; resolving issues with PHP8 stricter typing. [#1789](https://github.com/PHPOffice/PhpSpreadsheet/issues/1789)
The following MathTrig functions are affected:
`ABS()`, `ACOS()`, `ACOSH()`, `ASIN()`, `ASINH()`, `ATAN()`, `ATANH()`,
`COS()`, `COSH()`, `DEGREES()` (rad2deg), `EXP()`, `LN()` (log), `LOG10()`,
`RADIANS()` (deg2rad), `SIN()`, `SINH()`, `SQRT()`, `TAN()`, `TANH()`.
One TextData function is also affected: `REPT()` (str_repeat).
- `formatAsDate` correctly matches language metadata, reverting c55272e
- Formulae that previously crashed on sub function call returning excel error value now return said value.
The following functions are affected `CUMPRINC()`, `CUMIPMT()`, `AMORLINC()`,
`AMORDEGRC()`.
- Adapt some function error return value to match excel's error.
The following functions are affected `PPMT()`, `IPMT()`.
### Deprecated
- Calling many of the Excel formula functions directly rather than through the Calculation Engine.
The logic for these Functions is now being moved out of the categorised `Database`, `DateTime`, `Engineering`, `Financial`, `Logical`, `LookupRef`, `MathTrig`, `Statistical`, `TextData` and `Web` classes into small, dedicated classes for individual functions or related groups of functions.
This makes the logic in these classes easier to maintain; and will reduce the memory footprint required to execute formulae when calling these functions.
### Removed
- Nothing.
### Fixed
- Avoid Duplicate Titles When Reading Multiple HTML Files.[Issue #1823](https://github.com/PHPOffice/PhpSpreadsheet/issues/1823) [PR #1829](https://github.com/PHPOffice/PhpSpreadsheet/pull/1829)
- Fixed issue with Worksheet's `getCell()` method when trying to get a cell by defined name. [#1858](https://github.com/PHPOffice/PhpSpreadsheet/issues/1858)
- Fix possible endless loop in NumberFormat Masks [#1792](https://github.com/PHPOffice/PhpSpreadsheet/issues/1792)
- Fix problem resulting from literal dot inside quotes in number format masks. [PR #1830](https://github.com/PHPOffice/PhpSpreadsheet/pull/1830)
- Resolve Google Sheets Xlsx charts issue. Google Sheets uses oneCellAnchor positioning and does not include *Cache values in the exported Xlsx. [PR #1761](https://github.com/PHPOffice/PhpSpreadsheet/pull/1761)
- Fix for Xlsx Chart axis titles mapping to correct X or Y axis label when only one is present. [PR #1760](https://github.com/PHPOffice/PhpSpreadsheet/pull/1760)
- Fix For Null Exception on ODS Read of Page Settings. [#1772](https://github.com/PHPOffice/PhpSpreadsheet/issues/1772)
- Fix Xlsx reader overriding manually set number format with builtin number format. [PR #1805](https://github.com/PHPOffice/PhpSpreadsheet/pull/1805)
- Fix Xlsx reader cell alignment. [PR #1710](https://github.com/PHPOffice/PhpSpreadsheet/pull/1710)
- Fix for not yet implemented data-types in Open Document writer [Issue #1674](https://github.com/PHPOffice/PhpSpreadsheet/issues/1674)
- Fix XLSX reader when having a corrupt numeric cell data type [PR #1664](https://github.com/phpoffice/phpspreadsheet/pull/1664)
- Fix on `CUMPRINC()`, `CUMIPMT()`, `AMORLINC()`, `AMORDEGRC()` usage. When those functions called one of `YEARFRAC()`, `PPMT()`, `IPMT()` and they would get back an error value (represented as a string), trying to use numeral operands (`+`, `/`, `-`, `*`) on said return value and a number (`float or `int`) would fail.
## 1.16.0 - 2020-12-31
### Added
- CSV Reader - Best Guess for Encoding, and Handle Null-string Escape [#1647](https://github.com/PHPOffice/PhpSpreadsheet/issues/1647)
### Changed
- Updated the CONVERT() function to support all current MS Excel categories and Units of Measure.
### Deprecated
- All Excel Function implementations in `Calculation\Database`, `Calculation\DateTime`, `Calculation\Engineering`, `Calculation\Financial`, `Calculation\Logical`, `Calculation\LookupRef`, `Calculation\MathTrig`, `Calculation\Statistical`, `Calculation\TextData` and `Calculation\Web` have been moved to dedicated classes for individual functions or groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted.
### Removed
- Nothing.
### Fixed
- Fixed issue with absolute path in worksheets' Target. [PR #1769](https://github.com/PHPOffice/PhpSpreadsheet/pull/1769)
- Fix for Xls Reader when SST has a bad length [#1592](https://github.com/PHPOffice/PhpSpreadsheet/issues/1592)
- Resolve Xlsx loader issue whe hyperlinks don't have a destination
- Resolve issues when printer settings resources IDs clash with drawing IDs

View File

@ -9,3 +9,12 @@ If you would like to contribute, here are some notes and guidelines:
- All code changes must be validated by `composer check`
- [Helpful article about forking](https://help.github.com/articles/fork-a-repo/ "Forking a GitHub repository")
- [Helpful article about pull requests](https://help.github.com/articles/using-pull-requests/ "Pull Requests")
## How to release
1. Complete CHANGELOG.md and commit
2. Create an annotated tag
1. `git tag -a 1.2.3`
2. Tag subject must be the version number, eg: `1.2.3`
3. Tag body must be a copy-paste of the changelog entries
3. Push tag with `git push --tags`, GitHub Actions will create a GitHub release automatically

View File

@ -2,12 +2,13 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\DocumentGenerator;
use PhpOffice\PhpSpreadsheetInfra\DocumentGenerator;
require_once 'vendor/autoload.php';
try {
$phpSpreadsheetFunctionsProperty = (new ReflectionClass(Calculation::class))->getProperty('phpSpreadsheetFunctions');
$phpSpreadsheetFunctionsProperty = (new ReflectionClass(Calculation::class))
->getProperty('phpSpreadsheetFunctions');
$phpSpreadsheetFunctionsProperty->setAccessible(true);
$phpSpreadsheetFunctions = $phpSpreadsheetFunctionsProperty->getValue();
ksort($phpSpreadsheetFunctions);

25
bin/generate-locales Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env php
<?php
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheetInfra\LocaleGenerator;
require_once 'vendor/autoload.php';
try {
$phpSpreadsheetFunctionsProperty = (new ReflectionClass(Calculation::class))
->getProperty('phpSpreadsheetFunctions');
$phpSpreadsheetFunctionsProperty->setAccessible(true);
$phpSpreadsheetFunctions = $phpSpreadsheetFunctionsProperty->getValue();
$localeGenerator = new LocaleGenerator(
realpath(__DIR__ . '/../src/PhpSpreadsheet/Calculation/locale/'),
'Translations.xlsx',
$phpSpreadsheetFunctions,
true
);
$localeGenerator->generateLocales();
} catch (\Exception $e) {
fwrite(STDERR, (string) $e);
exit(1);
}

View File

@ -1,7 +1,19 @@
{
"name": "phpoffice/phpspreadsheet",
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"keywords": ["PHP", "OpenXML", "Excel", "xlsx", "xls", "ods", "gnumeric", "spreadsheet"],
"keywords": [
"PHP",
"OpenXML",
"Excel",
"xlsx",
"xls",
"ods",
"gnumeric",
"spreadsheet"
],
"config": {
"sort-packages": true
},
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"type": "library",
"license": "MIT",
@ -29,7 +41,8 @@
"check": [
"php-cs-fixer fix --ansi --dry-run --diff",
"phpcs",
"phpunit --color=always"
"phpunit --color=always",
"phpstan analyse --ansi"
],
"fix": [
"php-cs-fixer fix --ansi"
@ -39,35 +52,38 @@
]
},
"require": {
"php": "^7.2||^8.0",
"php": "^7.2 || ^8.0",
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-fileinfo": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-SimpleXML": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.13",
"maennchen/zipstream-php": "^2.1",
"markbaker/complex": "^1.5||^2.0",
"markbaker/matrix": "^1.2||^2.0",
"psr/simple-cache": "^1.0",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"ezyang/htmlpurifier": "^4.13"
"psr/simple-cache": "^1.0"
},
"require-dev": {
"dompdf/dompdf": "^0.8.5",
"friendsofphp/php-cs-fixer": "^2.16",
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"dompdf/dompdf": "^1.0",
"friendsofphp/php-cs-fixer": "^2.18",
"jpgraph/jpgraph": "^4.0",
"mpdf/mpdf": "^8.0",
"phpcompatibility/php-compatibility": "^9.3",
"phpunit/phpunit": "^8.5||^9.3",
"phpstan/phpstan": "^0.12.82",
"phpstan/phpstan-phpunit": "^0.12.18",
"phpunit/phpunit": "^8.5",
"squizlabs/php_codesniffer": "^3.5",
"tecnickcom/tcpdf": "^6.3"
},
@ -84,7 +100,8 @@
},
"autoload-dev": {
"psr-4": {
"PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests"
"PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests",
"PhpOffice\\PhpSpreadsheetInfra\\": "infra"
}
}
}

1722
composer.lock generated

File diff suppressed because it is too large Load Diff

5
docs/extra/extrajs.js Normal file
View File

@ -0,0 +1,5 @@
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll("table").forEach(function(table) {
table.classList.add("docutils");
});
});

View File

@ -89,7 +89,7 @@ php vendor/phpoffice/phpspreadsheet/samples/Basic/01_Simple.php
## Learn by documentation
For more in-depth documentation, you may read about an [overview of the
For more documentation in depth, you may read about an [overview of the
architecture](./topics/architecture.md),
[creating a spreadsheet](./topics/creating-spreadsheet.md),
[worksheets](./topics/worksheets.md),

View File

@ -1220,13 +1220,13 @@
</tr>
<tr>
<td style="padding-left: 1em;">Merged Cells</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td style="text-align: center; color: green;"></td>
<td style="text-align: center; color: green;"></td>
<td></td>
<td></td>
<td style="text-align: center; color: green;"></td>
<td style="text-align: center; color: green;"></td>
<td>N/A</td>
<td>N/A</td>
<td></td>
<td></td>
<td></td>
@ -1313,13 +1313,13 @@
<td style="text-align: center; color: orange;"></td>
<td style="text-align: center; color: orange;"></td>
<td></td>
<td></td>
<td></td>
<td style="text-align: center; color: orange;"></td>
<td style="text-align: center; color: orange;"></td>
<td></td>
<td></td>
<td style="text-align: center; color: orange;"></td>
<td style="text-align: center; color: orange;"></td>
<td></td>
<td style="text-align: center; color: orange;"></td>
<td></td>
<td></td>
<td></td>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -110,6 +110,11 @@ values beginning with `=` will be converted to a formula. Strings that
aren't numeric, or that don't begin with a leading `=` will be treated
as genuine string values.
Note that a numeric string that begins with a leading zero (that isn't
immediately followed by a decimal separator) will not be converted to a
numeric, so values like phone numbers (e.g. `01615991375``will remain as
strings).
This "conversion" is handled by a cell "value binder", and you can write
custom "value binders" to change the behaviour of these "conversions".
The standard PhpSpreadsheet package also provides an "advanced value
@ -138,8 +143,10 @@ Formats handled by the advanced value binder include:
- When strings contain a newline character (`\n`), then the cell styling is
set to wrap.
You can read more about value binders later in this section of the
documentation.
Basically, it attempts to mimic the behaviour of the MS Excel GUI.
You can read more about value binders [later in this section of the
documentation](#using-value-binders-to-facilitate-data-entry).
### Setting a formula in a Cell
@ -551,8 +558,27 @@ $spreadsheet->getActiveSheet()->setCellValue('A5', 'Date/time value:');
$spreadsheet->getActiveSheet()->setCellValue('B5', '21 December 1983');
```
**Creating your own value binder is easy.** When advanced value binding
is required, you can implement the
`\PhpOffice\PhpSpreadsheet\Cell\IValueBinder` interface or extend the
Alternatively, a `\PhpOffice\PhpSpreadsheet\Cell\StringValueBinder` class is available
if you want to preserve all content as strings. This might be appropriate if you
were loading a file containing values that could be interpreted as numbers (e.g. numbers
with leading sign such as international phone numbers like `+441615579382`), but that
should be retained as strings (non-international phone numbers with leading zeroes are
already maintained as strings).
By default, the StringValueBinder will cast any datatype passed to it into a string. However, there are a number of settings which allow you to specify that certain datatypes shouldn't be cast to strings, but left "as is":
```php
// Set value binder
$stringValueBinder = new \PhpOffice\PhpSpreadsheet\Cell\StringValueBinder();
$stringValueBinder->setNumericConversion(false)
->setBooleanConversion(false)
->setNullConversion(false)
->setFormulaConversion(false);
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( $stringValueBinder );
```
**Creating your own value binder is relatively straightforward.** When more specialised
value binding is required, you can implement the
`\PhpOffice\PhpSpreadsheet\Cell\IValueBinder` interface or extend the existing
`\PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder` or
`\PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder` classes.

View File

@ -251,16 +251,16 @@ $columnFilter->createRule()
);
```
MS Excel uses \* as a wildcard to match any number of characters, and ?
as a wildcard to match a single character. 'U\*' equates to "begins with
a 'U'"; '\*U' equates to "ends with a 'U'"; and '\*U\*' equates to
"contains a 'U'"
MS Excel uses `*` as a wildcard to match any number of characters, and `?`
as a wildcard to match a single character. `U*` equates to "begins with
a 'U'"; `*U` equates to "ends with a 'U'"; and `*U*` equates to
"contains a 'U'".
If you want to match explicitly against a \* or a ? character, you can
escape it with a tilde (\~), so ?\~\*\* would explicitly match for a \*
character as the second character in the cell value, followed by any
If you want to match explicitly against `*` or `?`, you can
escape it with a tilde `~`, so `?~**` would explicitly match for `*`
as the second character in the cell value, followed by any
number of other characters. The only other character that needs escaping
is the \~ itself.
is the `~` itself.
To create a "between" condition, we need to define two rules:
@ -327,14 +327,14 @@ $columnFilter->setFilterType(
```
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 string) but we do specify the dynamic filter
category.
```php
$columnFilter->createRule()
->setRule(
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
NULL,
'',
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE
)
->setRuleType(

View File

@ -71,7 +71,7 @@ library.
### Csv
Comma Separated Value (CSV) file format is a common structuring strategy
for text format files. In CSV flies, each line in the file represents a
for text format files. In CSV files, each line in the file represents a
row of data and (within each line of the file) the different data fields
(or columns) are separated from one another using a comma (`,`). If a
data field contains a comma, then it should be enclosed (typically in

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -1,6 +1,6 @@
# Memory saving
PhpSpreadsheet uses an average of about 1k per cell in your worksheets, so
PhpSpreadsheet uses an average of about 1k per cell (1.6k on 64-bit PHP) in your worksheets, so
large workbooks can quickly use up available memory. Cell caching
provides a mechanism that allows PhpSpreadsheet to maintain the cell
objects in a smaller size of memory, or off-memory (eg: on disk, in APCu,

View File

@ -1,8 +1,7 @@
# Reading and writing to file
As you already know from the [architecture](./architecture.md#readers-and-writers),
reading and writing to a
persisted storage is not possible using the base PhpSpreadsheet classes.
reading and writing to a persisted storage is not possible using the base PhpSpreadsheet classes.
For this purpose, PhpSpreadsheet provides readers and writers, which are
implementations of `\PhpOffice\PhpSpreadsheet\Reader\IReader` and
`\PhpOffice\PhpSpreadsheet\Writer\IWriter`.
@ -139,6 +138,11 @@ $reader->setReadFilter( new MyReadFilter() );
$spreadsheet = $reader->load("06largescale.xlsx");
```
Read Filtering does not renumber cell rows and columns. If you filter to read only rows 100-200, cells that you read will still be numbered A100-A200, not A1-A101. Cells A1-A99 will not be loaded, but if you then try to call `getCell()` for a cell outside your loaded range, then PHPSpreadsheet will create a new cell with a null value.
Methods such as `toArray()` assume that all cells in a spreadsheet has been loaded from A1, so will return null values for rows and columns that fall outside your filter range: it is recommended that you keep track of the range that your filter has requested, and use `rangeToArray()` instead.
### \PhpOffice\PhpSpreadsheet\Writer\Xlsx
#### Writing a spreadsheet
@ -162,6 +166,9 @@ $writer->setPreCalculateFormulas(false);
$writer->save("05featuredemo.xlsx");
```
**Note** Formulas will still be calculated in any column set to be autosized
even if pre-calculated is set to false
#### Office 2003 compatibility pack
Because of a bug in the Office2003 compatibility pack, there can be some
@ -477,6 +484,41 @@ $reader->setSheetIndex(0);
$spreadsheet = $reader->load('sample.csv');
```
You can also set the reader to guess the encoding
rather than calling guessEncoding directly. In this case,
the user-settable fallback encoding is used if nothing else works.
```php
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
$reader->setInputEncoding(\PhpOffice\PhpSpreadsheet\Reader\Csv::GUESS_ENCODING);
$reader->setFallbackEncoding('ISO-8859-2'); // default CP1252 without this statement
$reader->setDelimiter(';');
$reader->setEnclosure('');
$reader->setSheetIndex(0);
$spreadsheet = $reader->load('sample.csv');
```
Finally, you can set a callback to be invoked when the constructor is executed,
either through `new Csv()` or `IOFactory::load`,
and have that callback set the customizable attributes to whatever
defaults are appropriate for your environment.
```php
function constructorCallback(\PhpOffice\PhpSpreadsheet\Reader\Csv $reader): void
{
$reader->setInputEncoding(\PhpOffice\PhpSpreadsheet\Reader\Csv::GUESS_ENCODING);
$reader->setFallbackEncoding('ISO-8859-2');
$reader->setDelimiter(',');
$reader->setEnclosure('"');
// Following represents how Excel behaves better than the default escape character
$reader->setEscapeCharacter((version_compare(PHP_VERSION, '7.4') < 0) ? "\x0" : '');
}
\PhpOffice\PhpSpreadsheet\Reader\Csv::setConstructorCallback('constructorCallback');
$spreadsheet = \PhpSpreadsheet\IOFactory::load('sample.csv');
```
#### Read a specific worksheet
CSV files can only contain one worksheet. Therefore, you can specify
@ -580,6 +622,18 @@ $writer->setUseBOM(true);
$writer->save("05featuredemo.csv");
```
#### Writing CSV files with desired encoding
It can be set to output with the encoding that can be specified by PHP's mb_convert_encoding.
This looks like the following code:
```php
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
$writer->setUseBOM(false);
$writer->setOutputEncoding('SJIS-WIN');
$writer->save("05featuredemo.csv");
```
#### Decimal and thousands separators
If the worksheet you are exporting contains numbers with decimal or
@ -837,8 +891,7 @@ class My_Custom_TCPDF_Writer extends \PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf
#### Writing a spreadsheet
Once you have identified the Renderer that you wish to use for PDF
generation, you can write a .pdf file using the following code:
Once you have identified the Renderer that you wish to use for PDF generation, you can write a .pdf file using the following code:
```php
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet);
@ -850,8 +903,7 @@ first worksheet by default.
#### Write all worksheets
PDF files can contain one or more worksheets. If you want to write all
sheets into a single PDF file, use the following code:
PDF files can contain one or more worksheets. If you want to write all sheets into a single PDF file, use the following code:
```php
$writer->writeAllSheets();
@ -965,3 +1017,64 @@ $spreadhseet = $reader->loadFromString($secondHtmlString, $spreadsheet);
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls');
$writer->save('write.xls');
```
## Reader/Writer Flags
Some Readers and Writers support special "Feature Flags" that need to be explicitly enabled.
An example of this is Charts in a spreadsheet. By default, when you load a spreadsheet that contains Charts, the charts will not be loaded. If all you want to do is read the data in the spreadsheet, then loading charts is an overhead for both speed of loading and memory usage.
However, there are times when you may want to load any charts in the spreadsheet as well as the data. To do so, you need to tell the Reader explicitly to include Charts.
```php
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("05featuredemo.xlsx");
$reader->setIncludeCharts(true);
$reader->load("spreadsheetWithCharts.xlsx");
```
Alternatively, you can specify this in the call to load the spreadsheet:
```php
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("spreadsheetWithCharts.xlsx");
$reader->load("spreadsheetWithCharts.xlsx", $reader::LOAD_WITH_CHARTS);
```
If you wish to use the IOFactory `load()` method rather than instantiating a specific Reader, then you can still pass these flags.
```php
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load("spreadsheetWithCharts.xlsx", \PhpOffice\PhpSpreadsheet\Reader\IReader::LOAD_WITH_CHARTS);
```
Likewise, when saving a file using a Writer, loaded charts wil not be saved unless you explicitly tell the Writer to include them:
```php
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->setIncludeCharts(true);
$writer->save('mySavedFileWithCharts.xlsx');
```
As with the `load()` method, you can also pass flags in the `save()` method:
```php
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save('mySavedFileWithCharts.xlsx', \PhpOffice\PhpSpreadsheet\Writer\IWriter::SAVE_WITH_CHARTS);
```
Currently, the only special "Feature Flag" that is supported in this way is the inclusion of Charts, and only for certain formats.
Readers | LOAD_WITH_CHARTS |
---------|------------------|
Xlsx | YES |
Xls | NO |
Xml | NO |
Ods | NO |
Gnumeric | NO |
Html | N/A |
Slk | N/A |
Csv | N/A |
Writers | SAVE_WITH_CHARTS |
--------|------------------|
Xlsx | YES |
Xls | NO |
Ods | NO |
Html | YES |
Pdf | YES |
Csv | N/A |

View File

@ -324,6 +324,10 @@ to read and process a large workbook in "chunks": an example of this
usage might be when transferring data from an Excel worksheet to a
database.
Read Filtering does not renumber cell rows and columns. If you filter to read only rows 100-200, cells that you read will still be numbered A100-A200, not A1-A101. Cells A1-A99 will not be loaded, but if you then try to call `getCell()` for a cell outside your loaded range, then PHPSpreadsheet will create a new cell with a null value.
Methods such as `toArray()` assume that all cells in a spreadsheet has been loaded from A1, so will return null values for rows and columns that fall outside your filter range: it is recommended that you keep track of the range that your filter has requested, and use `rangeToArray()` instead.
```php
$inputFileType = 'Xls';
$inputFileName = './sampleData/example2.xls';

View File

@ -201,7 +201,7 @@ $spreadsheet->getActiveSheet()->setCellValue('B8',$internalFormula);
```
Currently, formula translation only translates the function names, the
constants TRUE and FALSE, and the function argument separators.
constants TRUE and FALSE, and the function argument separators. Cell addressing using R1C1 formatting is not supported.
At present, the following locale settings are supported:
@ -216,7 +216,7 @@ French | Français | fr
Hungarian | Magyar | hu
Italian | Italiano | it
Dutch | Nederlands | nl
Norwegian | Norsk | no
Norwegian | Norsk Bokmål | nb
Polish | Jezyk polski | pl
Portuguese | Português | pt
Brazilian Portuguese | Português Brasileiro | pt_br
@ -475,7 +475,7 @@ $spreadsheet->getActiveSheet()->setBreak('D10', \PhpOffice\PhpSpreadsheet\Worksh
To show/hide gridlines when printing, use the following code:
```php
$spreadsheet->getActiveSheet()->setShowGridlines(true);
$spreadsheet->getActiveSheet()->setPrintGridlines(true);
```
### Setting rows/columns to repeat at top/left
@ -884,6 +884,44 @@ $spreadsheet->getActiveSheet()
);
```
### DataBar of Conditional formatting
The basics are the same as conditional formatting.
Additional DataBar object to conditional formatting.
For example, the following code will result in the conditional formatting shown in the image.
```php
$conditional = new Conditional();
$conditional->setConditionType(Conditional::CONDITION_DATABAR);
$conditional->setDataBar(new ConditionalDataBar());
$conditional->getDataBar()
->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('num', '2'))
->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max'))
->setColor('FFFF555A');
$ext = $conditional
->getDataBar()
->setConditionalFormattingRuleExt(new ConditionalFormattingRuleExtension())
->getConditionalFormattingRuleExt();
$ext->setCfRule('dataBar');
$ext->setSqref('A1:A5'); // target CellCoordinates
$ext->setDataBarExt(new ConditionalDataBarExtension());
$ext->getDataBarExt()
->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('num', '2'))
->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('autoMax'))
->setMinLength(0)
->setMaxLength(100)
->setBorder(true)
->setDirection('rightToLeft')
->setNegativeBarBorderColorSameAsPositive(false)
->setBorderColor('FFFF555A')
->setNegativeFillColor('FFFF0000')
->setNegativeBorderColor('FFFF0000')
->setAxisColor('FF000000');
```
![10-databar-of-conditional-formatting.png](./images/10-databar-of-conditional-formatting.png)
## Add a comment to a cell
To add a comment to a cell, use the following code. The example below
@ -950,6 +988,9 @@ $security->setLockStructure(true);
$security->setWorkbookPassword("PhpSpreadsheet");
```
Note that there are additional methods setLockRevision and setRevisionsPassword
which apply only to change tracking and history for shared workbooks.
### Worksheet
An example on setting worksheet security:
@ -1063,7 +1104,7 @@ formula is allowed to be maximum 255 characters (not bytes). This sets a
limit on how many items you can have in the string "Item A,Item B,Item
C". Therefore it is normally a better idea to type the item values
directly in some cell range, say A1:A3, and instead use, say,
`$validation->setFormula1('Sheet!$A$1:$A$3')`. Another benefit is that
`$validation->setFormula1('\'Sheet title\'!$A$1:$A$3')`. Another benefit is that
the item values themselves can contain the comma `,` character itself.
If you need data validation on multiple cells, one can clone the
@ -1073,6 +1114,11 @@ ruleset:
$spreadsheet->getActiveSheet()->getCell('B8')->setDataValidation(clone $validation);
```
Alternatively, one can apply the validation to a range of cells:
```php
$validation->setSqref('B5:B1048576');
```
## Setting a column's width
A column's width can be set using the following code:
@ -1081,6 +1127,16 @@ A column's width can be set using the following code:
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(12);
```
If you want to set a column width using a different unit of measure,
then you can do so by telling PhpSpreadsheet what UoM the width value
that you are setting is measured in.
Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches),
`cm` (centimeters) and `mm` (millimeters).
```php
$spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(120, 'pt');
```
If you want PhpSpreadsheet to perform an automatic width calculation,
use the following code. PhpSpreadsheet will approximate the column with
to the width of the widest column value.
@ -1166,6 +1222,16 @@ Excel measures row height in points, where 1 pt is 1/72 of an inch (or
about 0.35mm). The default value is 12.75 pts; and the permitted range
of values is between 0 and 409 pts, where 0 pts is a hidden row.
If you want to set a row height using a different unit of measure,
then you can do so by telling PhpSpreadsheet what UoM the height value
that you are setting is measured in.
Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches),
`cm` (centimeters) and `mm` (millimeters).
```php
$spreadsheet->getActiveSheet()->getRowDimension('10')->setRowHeight(100, 'pt');
```
## Show/hide a row
To set a worksheet''s row visibility, you can use the following code.
@ -1311,9 +1377,11 @@ The following code extracts images from the current active worksheet,
and writes each as a separate file.
```php
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
$i = 0;
foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $drawing) {
if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
if ($drawing instanceof MemoryDrawing) {
ob_start();
call_user_func(
$drawing->getRenderingFunction(),
@ -1322,24 +1390,39 @@ foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $drawing) {
$imageContents = ob_get_contents();
ob_end_clean();
switch ($drawing->getMimeType()) {
case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_PNG :
case MemoryDrawing::MIMETYPE_PNG :
$extension = 'png';
break;
case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_GIF:
case MemoryDrawing::MIMETYPE_GIF:
$extension = 'gif';
break;
case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_JPEG :
case MemoryDrawing::MIMETYPE_JPEG :
$extension = 'jpg';
break;
}
} else {
$zipReader = fopen($drawing->getPath(),'r');
$imageContents = '';
while (!feof($zipReader)) {
$imageContents .= fread($zipReader,1024);
if ($drawing->getPath()) {
// Check if the source is a URL or a file path
if ($drawing->getIsURL()) {
$imageContents = file_get_contents($drawing->getPath());
$filePath = tempnam(sys_get_temp_dir(), 'Drawing');
file_put_contents($filePath , $imageContents);
$mimeType = mime_content_type($filePath);
// You could use the below to find the extension from mime type.
// https://gist.github.com/alexcorvi/df8faecb59e86bee93411f6a7967df2c#gistcomment-2722664
$extension = File::mime2ext($mimeType);
unlink($filePath);
}
else {
$zipReader = fopen($drawing->getPath(),'r');
$imageContents = '';
while (!feof($zipReader)) {
$imageContents .= fread($zipReader,1024);
}
fclose($zipReader);
$extension = $drawing->getExtension();
}
}
fclose($zipReader);
$extension = $drawing->getExtension();
}
$myFileName = '00_Image_'.++$i.'.'.$extension;
file_put_contents($myFileName,$imageContents);
@ -1519,6 +1602,20 @@ Default column width can be set using the following code:
$spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(12);
```
Excel measures column width in its own proprietary units, based on the number
of characters that will be displayed in the default font.
If you want to set the default column width using a different unit of measure,
then you can do so by telling PhpSpreadsheet what UoM the width value
that you are setting is measured in.
Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches),
`cm` (centimeters) and `mm` (millimeters).
```php
$spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(400, 'pt');
```
and PhpSpreadsheet will handle the internal conversion.
## Setting the default row height
Default row height can be set using the following code:
@ -1527,6 +1624,21 @@ Default row height can be set using the following code:
$spreadsheet->getActiveSheet()->getDefaultRowDimension()->setRowHeight(15);
```
Excel measures row height in points, where 1 pt is 1/72 of an inch (or
about 0.35mm). The default value is 12.75 pts; and the permitted range
of values is between 0 and 409 pts, where 0 pts is a hidden row.
If you want to set a row height using a different unit of measure,
then you can do so by telling PhpSpreadsheet what UoM the height value
that you are setting is measured in.
Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches),
`cm` (centimeters) and `mm` (millimeters).
```php
$spreadsheet->getActiveSheet()->getDefaultRowDimension()->setRowHeight(100, 'pt');
```
## Add a GD drawing to a worksheet
There might be a situation where you want to generate an in-memory image

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheet;
namespace PhpOffice\PhpSpreadsheetInfra;
use PhpOffice\PhpSpreadsheet\Calculation\Category;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
@ -19,7 +19,7 @@ class DocumentGenerator
$result .= "\n";
$result .= "## {$categoryConstant}\n";
$result .= "\n";
$lengths = [20, 42];
$lengths = [25, 37];
$result .= self::tableRow($lengths, ['Excel Function', 'PhpSpreadsheet Function']) . "\n";
$result .= self::tableRow($lengths, null) . "\n";
foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) {
@ -78,7 +78,8 @@ class DocumentGenerator
$result = "# Function list by name\n";
$lastAlphabet = null;
foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) {
$lengths = [20, 31, 42];
/** @var string $excelFunction */
$lengths = [25, 31, 37];
if ($lastAlphabet !== $excelFunction[0]) {
$lastAlphabet = $excelFunction[0];
$result .= "\n";

345
infra/LocaleGenerator.php Normal file
View File

@ -0,0 +1,345 @@
<?php
namespace PhpOffice\PhpSpreadsheetInfra;
use Exception;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Column;
use PhpOffice\PhpSpreadsheet\Worksheet\Row;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class LocaleGenerator
{
private const EXCEL_LOCALISATION_WORKSHEET = 'Excel Localisation';
private const EXCEL_FUNCTIONS_WORKSHEET = 'Excel Functions';
private const LOCALE_NAME_ROW = 1;
private const LOCALE_LANGUAGE_NAME_ROW = 2;
private const ENGLISH_LANGUAGE_NAME_ROW = 3;
private const ARGUMENT_SEPARATOR_ROW = 5;
private const ERROR_CODES_FIRST_ROW = 8;
private const FUNCTION_NAME_LIST_FIRST_ROW = 4;
private const ENGLISH_FUNCTION_CATEGORIES_COLUMN = 'A';
private const ENGLISH_REFERENCE_COLUMN = 'B';
private const EOL = "\n"; // not PHP_EOL
/**
* @var string
*/
protected $translationSpreadsheetName;
/**
* @var string
*/
protected $translationBaseFolder;
protected $phpSpreadsheetFunctions;
/**
* @var Spreadsheet
*/
protected $translationSpreadsheet;
protected $verbose;
/**
* @var Worksheet
*/
protected $localeTranslations;
protected $localeLanguageMap = [];
protected $errorCodeMap = [];
/**
* @var Worksheet
*/
private $functionNameTranslations;
protected $functionNameLanguageMap = [];
protected $functionNameMap = [];
public function __construct(
string $translationBaseFolder,
string $translationSpreadsheetName,
array $phpSpreadsheetFunctions,
bool $verbose = false
) {
$this->translationBaseFolder = $translationBaseFolder;
$this->translationSpreadsheetName = $translationSpreadsheetName;
$this->phpSpreadsheetFunctions = $phpSpreadsheetFunctions;
$this->verbose = $verbose;
}
public function generateLocales(): void
{
$this->openTranslationWorkbook();
$this->localeTranslations = $this->getTranslationSheet(self::EXCEL_LOCALISATION_WORKSHEET);
$this->localeLanguageMap = $this->mapLanguageColumns($this->localeTranslations);
$this->mapErrorCodeRows();
$this->functionNameTranslations = $this->getTranslationSheet(self::EXCEL_FUNCTIONS_WORKSHEET);
$this->functionNameLanguageMap = $this->mapLanguageColumns($this->functionNameTranslations);
$this->mapFunctionNameRows();
foreach ($this->localeLanguageMap as $column => $locale) {
$this->buildConfigFileForLocale($column, $locale);
}
foreach ($this->functionNameLanguageMap as $column => $locale) {
$this->buildFunctionsFileForLocale($column, $locale);
}
}
protected function buildConfigFileForLocale($column, $locale): void
{
$language = $this->localeTranslations->getCell($column . self::ENGLISH_LANGUAGE_NAME_ROW)->getValue();
$localeLanguage = $this->localeTranslations->getCell($column . self::LOCALE_LANGUAGE_NAME_ROW)->getValue();
$configFile = $this->openConfigFile($locale, $language, $localeLanguage);
$this->writeConfigArgumentSeparator($configFile, $column);
$this->writeFileSectionHeader($configFile, 'Error Codes');
foreach ($this->errorCodeMap as $errorCode => $row) {
$translationCell = $this->localeTranslations->getCell($column . $row);
$translationValue = $translationCell->getValue();
if (!empty($translationValue)) {
$errorCodeTranslation = "{$errorCode} = {$translationValue}" . self::EOL;
fwrite($configFile, $errorCodeTranslation);
} else {
$errorCodeTranslation = "{$errorCode}" . self::EOL;
fwrite($configFile, $errorCodeTranslation);
$this->log("No {$language} translation available for error code {$errorCode}");
}
}
fclose($configFile);
}
protected function writeConfigArgumentSeparator($configFile, $column): void
{
$translationCell = $this->localeTranslations->getCell($column . self::ARGUMENT_SEPARATOR_ROW);
$localeValue = $translationCell->getValue();
if (!empty($localeValue)) {
$functionTranslation = "ArgumentSeparator = {$localeValue}" . self::EOL;
fwrite($configFile, $functionTranslation);
} else {
$this->log('No Argument Separator defined');
}
}
protected function buildFunctionsFileForLocale($column, $locale): void
{
$language = $this->functionNameTranslations->getCell($column . self::ENGLISH_LANGUAGE_NAME_ROW)->getValue();
$localeLanguage = $this->functionNameTranslations->getCell($column . self::LOCALE_LANGUAGE_NAME_ROW)
->getValue();
$functionFile = $this->openFunctionNameFile($locale, $language, $localeLanguage);
foreach ($this->functionNameMap as $functionName => $row) {
$translationCell = $this->functionNameTranslations->getCell($column . $row);
$translationValue = $translationCell->getValue();
if ($this->isFunctionCategoryEntry($translationCell)) {
$this->writeFileSectionHeader($functionFile, "{$translationValue} ({$functionName})");
} elseif (!array_key_exists($functionName, $this->phpSpreadsheetFunctions)) {
$this->log("Function {$functionName} is not defined in PhpSpreadsheet");
} elseif (!empty($translationValue)) {
$functionTranslation = "{$functionName} = {$translationValue}" . self::EOL;
fwrite($functionFile, $functionTranslation);
} else {
$this->log("No {$language} translation available for function {$functionName}");
}
}
fclose($functionFile);
}
protected function openConfigFile(string $locale, string $language, string $localeLanguage)
{
$this->log("Building locale {$locale} ($language) configuration");
$localeFolder = $this->getLocaleFolder($locale);
$configFileName = realpath($localeFolder . DIRECTORY_SEPARATOR . 'config');
$this->log("Writing locale configuration to {$configFileName}");
$configFile = fopen($configFileName, 'wb');
$this->writeFileHeader($configFile, $localeLanguage, $language, 'locale settings');
return $configFile;
}
protected function openFunctionNameFile(string $locale, string $language, string $localeLanguage)
{
$this->log("Building locale {$locale} ($language) function names");
$localeFolder = $this->getLocaleFolder($locale);
$functionFileName = realpath($localeFolder . DIRECTORY_SEPARATOR . 'functions');
$this->log("Writing local function names to {$functionFileName}");
$functionFile = fopen($functionFileName, 'wb');
$this->writeFileHeader($functionFile, $localeLanguage, $language, 'function name translations');
return $functionFile;
}
protected function getLocaleFolder(string $locale): string
{
$localeFolder = $this->translationBaseFolder .
DIRECTORY_SEPARATOR .
str_replace('_', DIRECTORY_SEPARATOR, $locale);
if (!file_exists($localeFolder) || !is_dir($localeFolder)) {
mkdir($localeFolder, 0777, true);
}
return $localeFolder;
}
protected function writeFileHeader($localeFile, string $localeLanguage, string $language, string $title): void
{
fwrite($localeFile, str_repeat('#', 60) . self::EOL);
fwrite($localeFile, '##' . self::EOL);
fwrite($localeFile, "## PhpSpreadsheet - {$title}" . self::EOL);
fwrite($localeFile, '##' . self::EOL);
fwrite($localeFile, "## {$localeLanguage} ({$language})" . self::EOL);
fwrite($localeFile, '##' . self::EOL);
fwrite($localeFile, str_repeat('#', 60) . self::EOL . self::EOL);
}
protected function writeFileSectionHeader($localeFile, string $header): void
{
fwrite($localeFile, self::EOL . '##' . self::EOL);
fwrite($localeFile, "## {$header}" . self::EOL);
fwrite($localeFile, '##' . self::EOL);
}
protected function openTranslationWorkbook(): void
{
$filepathName = $this->translationBaseFolder . '/' . $this->translationSpreadsheetName;
$this->translationSpreadsheet = IOFactory::load($filepathName);
}
protected function getTranslationSheet(string $sheetName): Worksheet
{
$worksheet = $this->translationSpreadsheet->setActiveSheetIndexByName($sheetName);
if ($worksheet === null) {
throw new Exception("{$sheetName} Worksheet not found");
}
return $worksheet;
}
protected function mapLanguageColumns(Worksheet $translationWorksheet): array
{
$sheetName = $translationWorksheet->getTitle();
$this->log("Mapping Languages for {$sheetName}:");
$baseColumn = self::ENGLISH_REFERENCE_COLUMN;
$languagesList = $translationWorksheet->getColumnIterator(++$baseColumn);
$languageNameMap = [];
foreach ($languagesList as $languageColumn) {
/** @var Column $languageColumn */
$cells = $languageColumn->getCellIterator(self::LOCALE_NAME_ROW, self::LOCALE_NAME_ROW);
$cells->setIterateOnlyExistingCells(true);
foreach ($cells as $cell) {
/** @var Cell $cell */
if ($this->localeCanBeSupported($translationWorksheet, $cell)) {
$languageNameMap[$cell->getColumn()] = $cell->getValue();
$this->log($cell->getColumn() . ' -> ' . $cell->getValue());
}
}
}
return $languageNameMap;
}
protected function localeCanBeSupported(Worksheet $worksheet, Cell $cell): bool
{
if ($worksheet->getTitle() === self::EXCEL_LOCALISATION_WORKSHEET) {
// Only provide support for languages that have a function argument separator defined
// in the localisation worksheet
return !empty(
$worksheet->getCell($cell->getColumn() . self::ARGUMENT_SEPARATOR_ROW)->getValue()
);
}
// If we're processing other worksheets, then language support is determined by whether we included the
// language in the map when we were processing the localisation worksheet (which is always processed first)
return in_array($cell->getValue(), $this->localeLanguageMap, true);
}
protected function mapErrorCodeRows(): void
{
$this->log('Mapping Error Codes:');
$errorList = $this->localeTranslations->getRowIterator(self::ERROR_CODES_FIRST_ROW);
foreach ($errorList as $errorRow) {
/** @var Row $errorList */
$cells = $errorRow->getCellIterator(self::ENGLISH_REFERENCE_COLUMN, self::ENGLISH_REFERENCE_COLUMN);
$cells->setIterateOnlyExistingCells(true);
foreach ($cells as $cell) {
/** @var Cell $cell */
if ($cell->getValue() != '') {
$this->log($cell->getRow() . ' -> ' . $cell->getValue());
$this->errorCodeMap[$cell->getValue()] = $cell->getRow();
}
}
}
}
protected function mapFunctionNameRows(): void
{
$this->log('Mapping Functions:');
$functionList = $this->functionNameTranslations->getRowIterator(self::FUNCTION_NAME_LIST_FIRST_ROW);
foreach ($functionList as $functionRow) {
/** @var Row $functionRow */
$cells = $functionRow->getCellIterator(self::ENGLISH_REFERENCE_COLUMN, self::ENGLISH_REFERENCE_COLUMN);
$cells->setIterateOnlyExistingCells(true);
foreach ($cells as $cell) {
/** @var Cell $cell */
if ($this->isFunctionCategoryEntry($cell)) {
if (!empty($cell->getValue())) {
$this->log('CATEGORY: ' . $cell->getValue());
$this->functionNameMap[$cell->getValue()] = $cell->getRow();
}
continue;
}
if ($cell->getValue() != '') {
if (is_bool($cell->getValue())) {
$this->log($cell->getRow() . ' -> ' . ($cell->getValue() ? 'TRUE' : 'FALSE'));
$this->functionNameMap[($cell->getValue() ? 'TRUE' : 'FALSE')] = $cell->getRow();
} else {
$this->log($cell->getRow() . ' -> ' . $cell->getValue());
$this->functionNameMap[$cell->getValue()] = $cell->getRow();
}
}
}
}
}
private function isFunctionCategoryEntry(Cell $cell): bool
{
$categoryCheckCell = self::ENGLISH_FUNCTION_CATEGORIES_COLUMN . $cell->getRow();
if ($this->functionNameTranslations->getCell($categoryCheckCell)->getValue() != '') {
return true;
}
return false;
}
private function log(string $message): void
{
if ($this->verbose === false) {
return;
}
echo $message, self::EOL;
}
}

View File

@ -5,3 +5,5 @@ edit_uri: edit/master/docs/
theme: readthedocs
extra_css:
- extra/extra.css
extra_javascript:
- extra/extrajs.js

6292
phpstan-baseline.neon Normal file

File diff suppressed because it is too large Load Diff

29
phpstan.neon.dist Normal file
View File

@ -0,0 +1,29 @@
includes:
- phpstan-baseline.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
parameters:
level: max
paths:
- src/
- tests/
parallel:
processTimeout: 300.0
checkMissingIterableValueType: false
ignoreErrors:
- '~^Class GdImage not found\.$~'
- '~^Return typehint of method .* has invalid type GdImage\.$~'
- '~^Property .* has unknown class GdImage as its type\.$~'
- '~^Parameter .* of method .* has invalid typehint type GdImage\.$~'
- '~^Parameter \#1 \$im of function (imagedestroy|imageistruecolor|imagealphablending|imagesavealpha|imagecolortransparent|imagecolorsforindex|imagesavealpha|imagesx|imagesy) expects resource, GdImage\|resource given\.$~'
- '~^Parameter \#2 \$src_im of function imagecopy expects resource, GdImage\|resource given\.$~'
# Accept a bit anything for assert methods
- '~^Parameter \#2 .* of static method PHPUnit\\Framework\\Assert\:\:assert\w+\(\) expects .*, .* given\.$~'
- '~^Method PhpOffice\\PhpSpreadsheetTests\\.*\:\:test.*\(\) has parameter \$args with no typehint specified\.$~'
# Ignore all JpGraph issues
- '~^Constant (MARK_CIRCLE|MARK_CROSS|MARK_DIAMOND|MARK_DTRIANGLE|MARK_FILLEDCIRCLE|MARK_SQUARE|MARK_STAR|MARK_UTRIANGLE|MARK_X|SIDE_RIGHT) not found\.$~'
- '~^Instantiated class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot) not found\.$~'
- '~^Call to method .*\(\) on an unknown class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot)\.$~'
- '~^Access to property .* on an unknown class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot)\.$~'

View File

@ -0,0 +1,100 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
require __DIR__ . '/../Header.php';
// Sample can be slightly off if processing begins just before midnight
// and does not complete till after midnight.
// This possibility is accounted for in unit tests,
// but seems unneccesarily complicated for the sample.
function createSheet(Spreadsheet $spreadsheet, string $rule): void
{
$sheet = $spreadsheet->createSheet();
$sheet->setTitle($rule);
$sheet->getCell('A1')->setValue('Date');
$row = 1;
$date = new DateTime();
$year = (int) $date->format('Y');
$month = (int) $date->format('m');
$day = (int) $date->format('d');
$yearMinus2 = $year - 2;
$sheet->getCell('B1')->setValue("=DATE($year, $month, $day)");
// Each day for two weeks before today through 2 weeks after
for ($dayOffset = -14; $dayOffset < 14; ++$dayOffset) {
++$row;
$sheet->getCell("A$row")->setValue("=B1+($dayOffset)");
}
// First and last day of each month, starting with January 2 years before,
// through December 2 years after.
for ($monthOffset = 0; $monthOffset < 48; ++$monthOffset) {
++$row;
$sheet->getCell("A$row")->setValue("=DATE($yearMinus2, $monthOffset, 1)");
++$row;
$sheet->getCell("A$row")->setValue("=DATE($yearMinus2, $monthOffset + 1, 0)");
}
$sheet->getStyle("A2:A$row")->getNumberFormat()->setFormatCode('yyyy-mm-dd');
$sheet->getStyle('B1')->getNumberFormat()->setFormatCode('yyyy-mm-dd');
$sheet->getColumnDimension('A')->setAutoSize(true);
$sheet->getColumnDimension('B')->setAutoSize(true);
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
$autoFilter->setRange("A1:A$row");
$columnFilter = $autoFilter->getColumn('A');
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
$columnFilter->createRule()
->setRule(
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
'',
$rule
)
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
$sheet->setSelectedCell('B1');
}
// Create new Spreadsheet object
$helper->log('Create new Spreadsheet object');
$spreadsheet = new Spreadsheet();
// Set document properties
$helper->log('Set document properties');
$spreadsheet->getProperties()->setCreator('Owen Leibman')
->setLastModifiedBy('Owen Leibman')
->setTitle('PhpSpreadsheet Test Document')
->setSubject('PhpSpreadsheet Test Document')
->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.')
->setKeywords('office PhpSpreadsheet php')
->setCategory('Test result file');
$ruleNames = [
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2,
Rule::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3,
];
// Create the worksheets
foreach ($ruleNames as $ruleName) {
$helper->log("Add data and filter for $ruleName");
createSheet($spreadsheet, $ruleName);
}
$spreadsheet->removeSheetByIndex(0);
$spreadsheet->setActiveSheetIndex(0);
// Save
$helper->write($spreadsheet, __FILE__);

View File

@ -31,7 +31,8 @@ $spreadsheet->getActiveSheet()->setCellValue('A1', 'Financial Year')
->setCellValue('D1', 'Date')
->setCellValue('E1', 'Sales Value')
->setCellValue('F1', 'Expenditure');
$startYear = $endYear = $currentYear = date('Y');
$dateTime = new DateTime();
$startYear = $endYear = $currentYear = (int) $dateTime->format('Y');
--$startYear;
++$endYear;
@ -52,7 +53,9 @@ $row = 2;
foreach ($years as $year) {
foreach ($periods as $period) {
foreach ($countries as $country) {
$endDays = date('t', mktime(0, 0, 0, $period, 1, (int) $year));
$dateString = sprintf('%04d-%02d-01T00:00:00', $year, $period);
$dateTime = new DateTime($dateString);
$endDays = (int) $dateTime->format('t');
for ($i = 1; $i <= $endDays; ++$i) {
$eDate = Date::formattedPHPToExcel(
$year,
@ -124,10 +127,12 @@ $autoFilter->getColumn('C')
'japan'
)
->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
// Filter the Date column on a filter value of the first day of every period of the current year
// Filter the Date column on a filter value of the last day of every period of the current year
// We us a dateGroup ruletype for this, although it is still a standard filter
foreach ($periods as $period) {
$endDate = date('t', mktime(0, 0, 0, $period, 1, (int) $currentYear));
$dateString = sprintf('%04d-%02d-01T00:00:00', $currentYear, $period);
$dateTime = new DateTime($dateString);
$endDate = (int) $dateTime->format('t');
$autoFilter->getColumn('D')
->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER)

View File

@ -31,7 +31,8 @@ $spreadsheet->getActiveSheet()->setCellValue('A1', 'Financial Year')
->setCellValue('D1', 'Date')
->setCellValue('E1', 'Sales Value')
->setCellValue('F1', 'Expenditure');
$startYear = $endYear = $currentYear = date('Y');
$dateTime = new DateTime();
$startYear = $endYear = $currentYear = (int) $dateTime->format('Y');
--$startYear;
++$endYear;
@ -52,7 +53,9 @@ $row = 2;
foreach ($years as $year) {
foreach ($periods as $period) {
foreach ($countries as $country) {
$endDays = date('t', mktime(0, 0, 0, $period, 1, (int) $year));
$dateString = sprintf('%04d-%02d-01T00:00:00', $year, $period);
$dateTime = new DateTime($dateString);
$endDays = (int) $dateTime->format('t');
for ($i = 1; $i <= $endDays; ++$i) {
$eDate = Date::formattedPHPToExcel(
$year,

View File

@ -31,7 +31,8 @@ $spreadsheet->getActiveSheet()->setCellValue('A1', 'Financial Year')
->setCellValue('D1', 'Date')
->setCellValue('E1', 'Sales Value')
->setCellValue('F1', 'Expenditure');
$startYear = $endYear = $currentYear = date('Y');
$dateTime = new DateTime();
$startYear = $endYear = $currentYear = (int) $dateTime->format('Y');
--$startYear;
++$endYear;
@ -52,7 +53,9 @@ $row = 2;
foreach ($years as $year) {
foreach ($periods as $period) {
foreach ($countries as $country) {
$endDays = date('t', mktime(0, 0, 0, $period, 1, (int) $year));
$dateString = sprintf('%04d-%02d-01T00:00:00', $year, $period);
$dateTime = new DateTime($dateString);
$endDays = (int) $dateTime->format('t');
for ($i = 1; $i <= $endDays; ++$i) {
$eDate = Date::formattedPHPToExcel(
$year,
@ -124,10 +127,12 @@ $autoFilter->getColumn('C')
'japan'
)
->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
// Filter the Date column on a filter value of the first day of every period of the current year
// Filter the Date column on a filter value of the last day of every period of the current year
// We us a dateGroup ruletype for this, although it is still a standard filter
foreach ($periods as $period) {
$endDate = date('t', mktime(0, 0, 0, $period, 1, (int) $currentYear));
$dateString = sprintf('%04d-%02d-01T00:00:00', $currentYear, $period);
$dateTime = new DateTime($dateString);
$endDate = (int) $dateTime->format('t');
$autoFilter->getColumn('D')
->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER)

View File

@ -61,4 +61,4 @@ $spreadsheet->getActiveSheet()
->setTitle('Simple');
// Save
$helper->write($spreadsheet, __FILE__);
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Ods']);

View File

@ -38,7 +38,8 @@ $helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']);
$filenameCSV = $helper->getFilename(__FILE__, 'csv');
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writerCSV */
$writerCSV = new CsvWriter($spreadsheetFromCSV);
$writerCSV->setExcelCompatibility(true);
//$writerCSV->setExcelCompatibility(true);
$writerCSV->setUseBom(true); // because of non-ASCII chars
$callStartTime = microtime(true);
$writerCSV->save($filenameCSV);

View File

@ -31,8 +31,8 @@ $spreadsheet->getActiveSheet()->setCellValue('A1', 'Firstname:')
// Define named ranges
$helper->log('Define named ranges');
$spreadsheet->addNamedRange(new NamedRange('PersonName', $spreadsheet->getActiveSheet(), 'B1'));
$spreadsheet->addNamedRange(new NamedRange('PersonLN', $spreadsheet->getActiveSheet(), 'B2'));
$spreadsheet->addNamedRange(new NamedRange('PersonName', $spreadsheet->getActiveSheet(), '$B$1'));
$spreadsheet->addNamedRange(new NamedRange('PersonLN', $spreadsheet->getActiveSheet(), '$B$2'));
// Rename named ranges
$helper->log('Rename named ranges');

View File

@ -0,0 +1,43 @@
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\Date;
require __DIR__ . '/../Header.php';
$helper->log('Load from Xls template');
$reader = IOFactory::createReader('Xls');
$spreadsheet = $reader->load(__DIR__ . '/../templates/30templatebiff5.xls');
$helper->log('Add new data to the template');
$data = [['title' => 'Excel for dummies',
'price' => 17.99,
'quantity' => 2,
],
['title' => 'PHP for dummies',
'price' => 15.99,
'quantity' => 1,
],
['title' => 'Inside OOP',
'price' => 12.95,
'quantity' => 1,
],
];
$spreadsheet->getActiveSheet()->setCellValue('D1', Date::PHPToExcel(time()));
$baseRow = 5;
foreach ($data as $r => $dataRow) {
$row = $baseRow + $r;
$spreadsheet->getActiveSheet()->insertNewRowBefore($row, 1);
$spreadsheet->getActiveSheet()->setCellValue('A' . $row, $r + 1)
->setCellValue('B' . $row, $dataRow['title'])
->setCellValue('C' . $row, $dataRow['price'])
->setCellValue('D' . $row, $dataRow['quantity'])
->setCellValue('E' . $row, '=C' . $row . '*D' . $row);
}
$spreadsheet->getActiveSheet()->removeRow($baseRow - 1, 1);
// Save
$helper->write($spreadsheet, __FILE__);

View File

@ -30,7 +30,7 @@ for ($col = 1; $col <= 50; ++$col) {
}
}
$d = microtime(true) - $t;
$helper->log('Add data (end) . time: ' . round((string) ($d . 2)) . ' s');
$helper->log('Add data (end) . time: ' . (string) round($d, 2) . ' s');
// Save
$helper->write($spreadsheet, __FILE__);

View File

@ -18,6 +18,10 @@ $helper->logRead('Xlsx', $filename2, $callStartTime);
foreach ($spreadsheet2->getSheetNames() as $sheetName) {
$sheet = $spreadsheet2->getSheetByName($sheetName);
if ($sheet === null) {
continue;
}
$sheet->setTitle($sheet->getTitle() . ' copied');
$spreadsheet1->addExternalSheet($sheet);
}

View File

@ -1,20 +1,35 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Settings;
require __DIR__ . '/../Header.php';
?>
<form action="45_Quadratic_equation_solver.php" method="POST">
Enter the coefficients for the Ax<sup>2</sup> + Bx + C = 0
<table border="0" cellpadding="0" cellspacing="0">
<tr><td><b>A&nbsp;</b></td>
<td><input name="A" type="text" size="8" value="<?php echo (isset($_POST['A'])) ? htmlentities($_POST['A']) : ''; ?>"></td>
<tr>
<td>
<b>A&nbsp;</b>
</td>
<td>
<input name="A" type="text" size="8" value="<?php echo (isset($_POST['A'])) ? htmlentities($_POST['A'], Settings::htmlEntityFlags()) : ''; ?>">
</td>
</tr>
<tr><td><b>B&nbsp;</b></td>
<td><input name="B" type="text" size="8" value="<?php echo (isset($_POST['B'])) ? htmlentities($_POST['B']) : ''; ?>"></td>
<tr>
<td>
<b>B&nbsp;</b>
</td>
<td>
<input name="B" type="text" size="8" value="<?php echo (isset($_POST['B'])) ? htmlentities($_POST['B'], Settings::htmlEntityFlags()) : ''; ?>">
</td>
</tr>
<tr><td><b>C&nbsp;</b></td>
<td><input name="C" type="text" size="8" value="<?php echo (isset($_POST['C'])) ? htmlentities($_POST['C']) : ''; ?>"></td>
<tr>
<td><b>C&nbsp;</b>
</td>
<td>
<input name="C" type="text" size="8" value="<?php echo (isset($_POST['C'])) ? htmlentities($_POST['C'], Settings::htmlEntityFlags()) : ''; ?>">
</td>
</tr>
</table>
<input name="submit" type="submit" value="calculate"><br />

View File

@ -0,0 +1,35 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the accrued interest for a security that pays periodic interest.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Issue Date', DateHelper::getDateValue('01-Jan-2012')],
['First Interest Date', DateHelper::getDateValue('01-Apr-2012')],
['Settlement Date', DateHelper::getDateValue('31-Dec-2013')],
['Annual Coupon Rate', 0.08],
['Par Value', 10000],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B3')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B5')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$worksheet->setCellValue('B10', '=ACCRINT(B1, B2, B3, B4, B5, B6)');
$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B10')->getValue());
$helper->log('ACCRINT() Result is ' . $worksheet->getCell('B10')->getFormattedValue());

View File

@ -0,0 +1,33 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the accrued interest for a security that pays interest at maturity.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Issue Date', DateHelper::getDateValue('01-Jan-2012')],
['Settlement Date', DateHelper::getDateValue('31-Dec-2012')],
['Annual Coupon Rate', 0.08],
['Par Value', 10000],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$worksheet->setCellValue('B6', '=ACCRINTM(B1, B2, B3, B4)');
$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('ACCRINTM() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,38 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Calculation\Financial\Constants as FinancialConstants;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the prorated linear depreciation of an asset for a specified accounting period.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Cost', 150.00],
['Date Purchased', DateHelper::getDateValue('01-Jan-2015')],
['First Period Date', DateHelper::getDateValue('30-Sep-2015')],
['Salvage Value', 20.00],
['Number of Periods', 1],
['Depreciation Rate', 0.20],
['Basis', FinancialConstants::BASIS_DAYS_PER_YEAR_360_EUROPEAN],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('$#,##0.00');
$worksheet->getStyle('B2:B3')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('$#,##0.00');
$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('0.00%');
// Now the formula
$worksheet->setCellValue('B10', '=AMORDEGRC(B1, B2, B3, B4, B5, B6, B7)');
$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B10')->getValue());
$helper->log('AMORDEGRC() Result is ' . $worksheet->getCell('B10')->getFormattedValue());

View File

@ -0,0 +1,38 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Calculation\Financial\Constants as FinancialConstants;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the prorated linear depreciation of an asset for a specified accounting period.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Cost', 150.00],
['Date Purchased', DateHelper::getDateValue('01-Jan-2015')],
['First Period Date', DateHelper::getDateValue('30-Sep-2015')],
['Salvage Value', 20.00],
['Period', 1],
['Depreciation Rate', 0.20],
['Basis', FinancialConstants::BASIS_DAYS_PER_YEAR_360_EUROPEAN],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('$#,##0.00');
$worksheet->getStyle('B2:B3')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('$#,##0.00');
$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('0.00%');
// Now the formula
$worksheet->setCellValue('B10', '=AMORLINC(B1, B2, B3, B4, B5, B6, B7)');
$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B10')->getValue());
$helper->log('AMORLINC() Result is ' . $worksheet->getCell('B10')->getFormattedValue());

View File

@ -0,0 +1,29 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the number of days from the beginning of a coupon\'s period to the settlement date.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Jan-2011')],
['Maturity Date', DateHelper::getDateValue('25-Oct-2012')],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
// Now the formula
$worksheet->setCellValue('B6', '=COUPDAYBS(B1, B2, B3)');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('COUPDAYBS() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,29 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the number of days in the coupon period that contains the settlement date.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Jan-2011')],
['Maturity Date', DateHelper::getDateValue('25-Oct-2012')],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
// Now the formula
$worksheet->setCellValue('B6', '=COUPDAYS(B1, B2, B3)');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('COUPDAYS() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,29 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the number of days from the settlement date to the next coupon date.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Jan-2011')],
['Maturity Date', DateHelper::getDateValue('25-Oct-2012')],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
// Now the formula
$worksheet->setCellValue('B6', '=COUPDAYSNC(B1, B2, B3)');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('COUPDAYSNC() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,30 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the next coupon date, after the settlement date.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Jan-2011')],
['Maturity Date', DateHelper::getDateValue('25-Oct-2012')],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
// Now the formula
$worksheet->setCellValue('B6', '=COUPNCD(B1, B2, B3)');
$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('COUPNCD() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,30 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the number of coupons payable, between a security\'s settlement date and maturity date,');
$helper->log('rounded up to the nearest whole coupon.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Jan-2011')],
['Maturity Date', DateHelper::getDateValue('25-Oct-2012')],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
// Now the formula
$worksheet->setCellValue('B6', '=COUPNUM(B1, B2, B3)');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('COUPNUM() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,30 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the previous coupon date, before the settlement date for a security.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Jan-2011')],
['Maturity Date', DateHelper::getDateValue('25-Oct-2012')],
['Frequency', 4],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
// Now the formula
$worksheet->setCellValue('B6', '=COUPPCD(B1, B2, B3)');
$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$helper->log($worksheet->getCell('B6')->getValue());
$helper->log('COUPPCD() Result is ' . $worksheet->getCell('B6')->getFormattedValue());

View File

@ -0,0 +1,38 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the cumulative interest paid on a loan or investment, between two specified periods.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Interest Rate (per period)', 0.05 / 12],
['Number of Periods', 5 * 12],
['Present Value', 50000],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$baseRow = 5;
for ($year = 1; $year <= 5; ++$year) {
$row = (string) ($baseRow + $year);
$yearStartPeriod = (int) $year * 12 - 11;
$yearEndPeriod = (int) $year * 12;
$worksheet->setCellValue("A{$row}", "Yr {$year}");
$worksheet->setCellValue("B{$row}", "=CUMIPMT(\$B\$1, \$B\$2, \$B\$3, {$yearStartPeriod}, {$yearEndPeriod}, 0)");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("CUMIPMT() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,38 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the cumulative payment on the principal of a loan or investment, between two specified periods.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Interest Rate (per period)', 0.05 / 12],
['Number of Periods', 5 * 12],
['Present Value', 50000],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$baseRow = 5;
for ($year = 1; $year <= 5; ++$year) {
$row = (string) ($baseRow + $year);
$yearStartPeriod = (int) $year * 12 - 11;
$yearEndPeriod = (int) $year * 12;
$worksheet->setCellValue("A{$row}", "Yr {$year}");
$worksheet->setCellValue("B{$row}", "=CUMPRINC(\$B\$1, \$B\$2, \$B\$3, {$yearStartPeriod}, {$yearEndPeriod}, 0)");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("CUMPRINC() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,50 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the depreciation of an asset, using the Fixed Declining Balance Method,');
$helper->log('for each period of the asset\'s lifetime.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Cost Value', 10000],
['Salvage', 1000],
['Life', 5, 'Years'],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$baseRow = 5;
for ($year = 1; $year <= 5; ++$year) {
$row = (string) ($baseRow + $year);
$worksheet->setCellValue("A{$row}", "Depreciation after Yr {$year}");
$worksheet->setCellValue("B{$row}", "=DB(\$B\$1, \$B\$2, \$B\$3, {$year})");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("DB() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}
$helper->log('And with depreciation only starting after 6 months.');
$baseRow = 12;
for ($year = 1; $year <= 6; ++$year) {
$row = (string) ($baseRow + $year);
$worksheet->setCellValue("A{$row}", "Depreciation after Yr {$year}");
$worksheet->setCellValue("B{$row}", "=DB(\$B\$1, \$B\$2, \$B\$3, {$year}, 6)");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("DB() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,36 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the depreciation of an asset, using the Double Declining Balance Method,');
$helper->log('for each period of the asset\'s lifetime.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Cost Value', 10000],
['Salvage', 1000],
['Life', 5, 'Years'],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$baseRow = 5;
for ($year = 1; $year <= 5; ++$year) {
$row = (string) ($baseRow + $year);
$worksheet->setCellValue("A{$row}", "Depreciation after Yr {$year}");
$worksheet->setCellValue("B{$row}", "=DDB(\$B\$1, \$B\$2, \$B\$3, {$year})");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("DDB() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,32 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the the Discount Rate for a security.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Apr-2016')],
['Maturity Date', DateHelper::getDateValue('31-Mar-2021')],
['Par Value', 95.00],
['Redemption Value', 100.00],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$worksheet->getStyle('B3:B4')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$worksheet->setCellValue('B7', '=DISC(B1, B2, B3, B4)');
$worksheet->getStyle('B7')->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell('B7')->getValue());
$helper->log('DISC() Result is ' . $worksheet->getCell('B7')->getFormattedValue());

View File

@ -0,0 +1,30 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the dollar value in fractional notation, into a dollar value expressed as a decimal.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
[1.01, 16],
[1.1, 16],
[1.03, 32],
[1.3, 32],
[1.12, 32],
];
$worksheet->fromArray($arguments, null, 'A1');
// Now the formula
for ($row = 1; $row <= 5; ++$row) {
$worksheet->setCellValue("C{$row}", "=DOLLARDE(A{$row}, B{$row})");
$helper->log($worksheet->getCell("C{$row}")->getValue());
$helper->log('DOLLARDE() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,30 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the dollar value expressed as a decimal number, into a dollar price, expressed as a fraction.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
[1.0625, 16],
[1.625, 16],
[1.09375, 32],
[1.9375, 32],
[1.375, 32],
];
$worksheet->fromArray($arguments, null, 'A1');
// Now the formula
for ($row = 1; $row <= 5; ++$row) {
$worksheet->setCellValue("C{$row}", "=DOLLARFR(A{$row}, B{$row})");
$helper->log($worksheet->getCell("C{$row}")->getValue());
$helper->log('DOLLARFR() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,31 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the effective annual interest rate for a given nominal interest rate and number of');
$helper->log('compounding periods per year.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
[0.10, 4],
[0.10, 2],
[0.025, 2],
];
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B3')->getNumberFormat()->setFormatCode('0.00%');
// Now the formula
for ($row = 1; $row <= 3; ++$row) {
$worksheet->setCellValue("C{$row}", "=EFFECT(A{$row}, B{$row})");
$worksheet->getStyle("C{$row}")->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell("C{$row}")->getValue());
$helper->log('EFFECT() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,36 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the Future Value of an investment with periodic constant payments and a constant interest rate.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Interest Rate', 0.05, 0.10],
['Pament Frequency', 12, 4],
['Duration (Years)', 5, 4],
['Investment', -1000.00, -2000.00],
['Payment Type', 0, 1],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:C1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B4:C4')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$worksheet->setCellValue('B8', '=FV(B1/B2, B3*B2, B4)');
$worksheet->setCellValue('C8', '=FV(C1/C2, C3*C2, C4, null, C5)');
$worksheet->getStyle('B8:C8')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B8')->getValue());
$helper->log('FV() Result is ' . $worksheet->getCell('B8')->getFormattedValue());
$helper->log($worksheet->getCell('C6')->getValue());
$helper->log('FV() Result is ' . $worksheet->getCell('C8')->getFormattedValue());

View File

@ -0,0 +1,36 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the Future Value of an initial principal, after applying a series of compound interest rates.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Principal'],
[10000.00],
[null],
['Schedule'],
[0.05],
[0.05],
[0.035],
[0.035],
[0.035],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('A2')->getNumberFormat()->setFormatCode('$#,##0.00');
$worksheet->getStyle('A5:A9')->getNumberFormat()->setFormatCode('0.00%');
// Now the formula
$worksheet->setCellValue('B1', '=FVSCHEDULE(A2, A5:A9)');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B1')->getValue());
$helper->log('FVSCHEDULE() Result is ' . $worksheet->getCell('B1')->getFormattedValue());

View File

@ -0,0 +1,32 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Helpers as DateHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the interest rate for a fully invested security.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Settlement Date', DateHelper::getDateValue('01-Apr-2005')],
['Maturity Date', DateHelper::getDateValue('31-Mar-2010')],
['Investment', 1000.00],
['Investment', 2125.00],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy');
$worksheet->getStyle('B3:B4')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$worksheet->setCellValue('B7', '=INTRATE(B1, B2, B3, B4)');
$worksheet->getStyle('B7')->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell('B7')->getValue());
$helper->log('INTRATE() Result is ' . $worksheet->getCell('B7')->getFormattedValue());

View File

@ -0,0 +1,37 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the interest payment, during a specific period of a loan or investment that is paid in,');
$helper->log('constant periodic payments, with a constant interest rate.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Interest Rate', 0.05],
['Number of Years', 5],
['Present Value', 50000.00],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$baseRow = 6;
for ($month = 1; $month <= 12; ++$month) {
$row = (string) ($baseRow + $month);
$worksheet->setCellValue("A{$row}", "Payment for Mth {$month}");
$worksheet->setCellValue("B{$row}", "=IPMT(\$B\$1/12, {$month}, \$B\$2*12, \$B\$3)");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("IPMT() Month {$month} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,38 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the Internal Rate of Return for a supplied series of periodic cash flows.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Initial Investment', -100.00],
['Year 1 Income', 20.00],
['Year 2 Income', 24.00, 'IRR after 3 Years'],
['Year 3 Income', 28.80],
['Year 4 Income', 34.56, 'IRR after 5 Years'],
['Year 5 Income', 41.47],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B6')->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
// Now the formula
$worksheet->setCellValue('C4', '=IRR(B1:B4)');
$worksheet->getStyle('C4')->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell('C4')->getValue());
$helper->log('IRR() Result is ' . $worksheet->getCell('C4')->getFormattedValue());
$worksheet->setCellValue('C6', '=IRR(B1:B6)');
$worksheet->getStyle('C6')->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell('C6')->getValue());
$helper->log('IRR() Result is ' . $worksheet->getCell('C6')->getFormattedValue());

View File

@ -0,0 +1,36 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the interest paid during a specific period of a loan or investment.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Interest Rate', 0.05],
['Number of Years', 5],
['Present Value', 50000.00],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$baseRow = 6;
for ($month = 1; $month <= 12; ++$month) {
$row = (string) ($baseRow + $month);
$worksheet->setCellValue("A{$row}", "Payment for Mth {$month}");
$worksheet->setCellValue("B{$row}", "=ISPMT(\$B\$1/12, {$month}, \$B\$2*12, \$B\$3)");
$worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$helper->log($worksheet->getCell("B{$row}")->getValue());
$helper->log("ISPMT() Month {$month} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,42 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the Modified Internal Rate of Return for a supplied series of periodic cash flows.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Initial Investment', -100.00],
['Year 1 Income', 18.00],
['Year 2 Income', 22.50, 'MIRR after 3 Years'],
['Year 3 Income', 28.00],
['Year 4 Income', 35.50, 'MIRR after 5 Years'],
['Year 5 Income', 45.00],
[null],
['Finance Rate', 0.055],
['Re-invest Rate', 0.05],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B6')->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00');
$worksheet->getStyle('B8:B9')->getNumberFormat()->setFormatCode('0.00%');
// Now the formula
$worksheet->setCellValue('C4', '=MIRR(B1:B4, B8, B9)');
$worksheet->getStyle('C4')->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell('C4')->getValue());
$helper->log('MIRR() Result is ' . $worksheet->getCell('C4')->getFormattedValue());
$worksheet->setCellValue('C6', '=MIRR(B1:B6, B8, B9)');
$worksheet->getStyle('C6')->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell('C6')->getValue());
$helper->log('MIRR() Result is ' . $worksheet->getCell('C6')->getFormattedValue());

View File

@ -0,0 +1,31 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the nominal interest rate for a given effective interest rate and number of');
$helper->log('compounding periods per year.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
[0.10, 4],
[0.10, 2],
[0.025, 12],
];
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:B3')->getNumberFormat()->setFormatCode('0.00%');
// Now the formula
for ($row = 1; $row <= 3; ++$row) {
$worksheet->setCellValue("C{$row}", "=NOMINAL(A{$row}, B{$row})");
$worksheet->getStyle("C{$row}")->getNumberFormat()->setFormatCode('0.00%');
$helper->log($worksheet->getCell("C{$row}")->getValue());
$helper->log('NOMINAL() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue());
}

View File

@ -0,0 +1,39 @@
<?php
use PhpOffice\PhpSpreadsheet\Calculation\Financial\Constants as FinancialConstants;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the number of periods required to pay off a loan, for a constant periodic payment');
$helper->log('and a constant interest rate.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Interest Rate', 0.04, 0.06],
['Payments per Year', 1, 4],
['Payment Amount', -6000.00, -2000],
['Present Value', 50000, 60000],
['Future Value', null, 30000],
['Payment Type', null, FinancialConstants::PAYMENT_BEGINNING_OF_PERIOD],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:C1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B3:C5')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
$worksheet->setCellValue('B8', '=NPER(B1/B2, B3, B4)');
$helper->log($worksheet->getCell('B8')->getValue());
$helper->log('NPER() Result is ' . $worksheet->getCell('B8')->getFormattedValue());
$worksheet->setCellValue('C8', '=NPER(C1/C2, C3, C4, C5, C6)');
$helper->log($worksheet->getCell('C8')->getValue());
$helper->log('NPER() Result is ' . $worksheet->getCell('C8')->getFormattedValue());

View File

@ -0,0 +1,43 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the Net Present Value of an investment, based on a supplied discount rate,');
$helper->log('and a series of future payments and income.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Add some data
$arguments = [
['Annual Discount Rate', 0.02, 0.05],
['Initial Investment Cost', -5000.00, -10000],
['Return from Year 1', 800.00, 2000.00],
['Return from Year 2', 950.00, 2400.00],
['Return from Year 3', 1080.00, 2900.00],
['Return from Year 4', 1220.00, 3500.00],
['Return from Year 5', 1500.00, 4100.00],
];
// Some basic formatting for the data
$worksheet->fromArray($arguments, null, 'A1');
$worksheet->getStyle('B1:C1')->getNumberFormat()->setFormatCode('0.00%');
$worksheet->getStyle('B2:C7')->getNumberFormat()->setFormatCode('$#,##0.00');
// Now the formula
// When initial investment is made at the end of the first period
$worksheet->setCellValue('B10', '=NPV(B1, B2:B7)');
$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('B10')->getValue());
$helper->log('NPV() Result is ' . $worksheet->getCell('B10')->getFormattedValue());
// When initial investment is made at the start of the first period
$worksheet->setCellValue('C10', '=NPV(C1, C3:C7) + C2');
$worksheet->getStyle('C10')->getNumberFormat()->setFormatCode('$#,##0.00');
$helper->log($worksheet->getCell('C10')->getValue());
$helper->log('NPV() Result is ' . $worksheet->getCell('C10')->getFormattedValue());

View File

@ -0,0 +1,22 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns a text reference to a single cell in a worksheet.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->getCell('A1')->setValue('=ADDRESS(2,3)');
$worksheet->getCell('A2')->setValue('=ADDRESS(2,3,2)');
$worksheet->getCell('A3')->setValue('=ADDRESS(2,3,2,FALSE)');
$worksheet->getCell('A4')->setValue('=ADDRESS(2,3,1,FALSE,"[Book1]Sheet1")');
$worksheet->getCell('A5')->setValue('=ADDRESS(2,3,1,FALSE,"EXCEL SHEET")');
for ($row = 1; $row <= 5; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,23 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the column index of a cell.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->getCell('A1')->setValue('=COLUMN(C13)');
$worksheet->getCell('A2')->setValue('=COLUMN(E13:G15)');
$worksheet->getCell('F1')->setValue('=COLUMN()');
for ($row = 1; $row <= 2; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}
$cell = $worksheet->getCell('F1');
$helper->log("F1: {$cell->getValue()} => {$cell->getCalculatedValue()}");

View File

@ -0,0 +1,21 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the number of columns in an array or reference.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->getCell('A1')->setValue('=COLUMNS(C1:G4)');
$worksheet->getCell('A2')->setValue('=COLUMNS({1,2,3;4,5,6})');
$worksheet->getCell('A3')->setValue('=ROWS(C1:E4 D3:G5)');
$worksheet->getCell('A4')->setValue('=COLUMNS(1:1)');
for ($row = 1; $row <= 4; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,39 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the row index of a cell.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$data1 = [
['Apples', 'Lemons'],
['Bananas', 'Pears'],
];
$data2 = [
[4, 6],
[5, 3],
[6, 9],
[7, 5],
[8, 3],
];
$worksheet->fromArray($data1, null, 'A1');
$worksheet->fromArray($data2, null, 'C1');
$worksheet->getCell('A11')->setValue('=INDEX(A1:B2, 2, 2)');
$worksheet->getCell('A12')->setValue('=INDEX(A1:B2, 2, 1)');
$worksheet->getCell('A13')->setValue('=INDEX({1,2;3,4}, 0, 2)');
$worksheet->getCell('A14')->setValue('=INDEX(C1:C5, 5)');
$worksheet->getCell('A15')->setValue('=INDEX(C1:D5, 5, 2)');
$worksheet->getCell('A16')->setValue('=SUM(INDEX(C1:D5, 5, 0))');
for ($row = 11; $row <= 16; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,33 @@
<?php
use PhpOffice\PhpSpreadsheet\NamedRange;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the cell specified by a text string.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$data = [
[8, 9, 0],
[3, 4, 5],
[9, 1, 3],
[4, 6, 2],
];
$worksheet->fromArray($data, null, 'C1');
$spreadsheet->addNamedRange(new NamedRange('NAMED_RANGE_FOR_CELL_D4', $worksheet, '="$D$4"'));
$worksheet->getCell('A1')->setValue('=INDIRECT("C1")');
$worksheet->getCell('A2')->setValue('=INDIRECT("D"&4)');
$worksheet->getCell('A3')->setValue('=INDIRECT("E"&ROW())');
$worksheet->getCell('A4')->setValue('=SUM(INDIRECT("$C$4:$E$4"))');
$worksheet->getCell('A5')->setValue('=INDIRECT(NAMED_RANGE_FOR_CELL_D4)');
for ($row = 1; $row <= 5; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,33 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns a cell range that is a specified number of rows and columns from a cell or range of cells.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$data = [
[null, 'Week 1', 'Week 2', 'Week 3', 'Week 4'],
['Sunday', 4500, 2200, 3800, 1500],
['Monday', 5500, 6100, 5200, 4800],
['Tuesday', 7000, 6200, 5000, 7100],
['Wednesday', 8000, 4000, 3900, 7600],
['Thursday', 5900, 5500, 6900, 7100],
['Friday', 4900, 6300, 6900, 5200],
['Saturday', 3500, 3900, 5100, 4100],
];
$worksheet->fromArray($data, null, 'A3');
$worksheet->getCell('H1')->setValue('=OFFSET(A3, 3, 1)');
$worksheet->getCell('H2')->setValue('=SUM(OFFSET(A3, 3, 1, 1, 4))');
$worksheet->getCell('H3')->setValue('=SUM(OFFSET(B3:E3, 3, 0))');
$worksheet->getCell('H4')->setValue('=SUM(OFFSET(E3, 1, -3, 7))');
for ($row = 1; $row <= 4; ++$row) {
$cell = $worksheet->getCell("H{$row}");
$helper->log("H{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,20 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the row index of a cell.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->getCell('A1')->setValue('=ROW(C13)');
$worksheet->getCell('A2')->setValue('=ROW(E19:G21)');
$worksheet->getCell('A3')->setValue('=ROW()');
for ($row = 1; $row <= 3; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,20 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Returns the row index of a cell.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->getCell('A1')->setValue('=ROWS(C1:E4)');
$worksheet->getCell('A2')->setValue('=ROWS({1,2,3;4,5,6})');
$worksheet->getCell('A3')->setValue('=ROWS(C1:E4 D3:G5)');
for ($row = 1; $row <= 3; ++$row) {
$cell = $worksheet->getCell("A{$row}");
$helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -0,0 +1,35 @@
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../../Header.php';
$helper->log('Searches for a value in the top row of a table or an array of values,
and then returns a value in the same column from a row you specify
in the table or array.');
// Create new PhpSpreadsheet object
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$data = [
['ID', 'First Name', 'Last Name', 'Salary'],
[72, 'Emily', 'Smith', 64901, null, 'ID', 53, 66, 56],
[66, 'James', 'Anderson', 70855, null, 'Salary'],
[14, 'Mia', 'Clark', 188657],
[30, 'John', 'Lewis', 97566],
[53, 'Jessica', 'Walker', 58339],
[56, 'Mark', 'Reed', 125180],
[79, 'Richard', 'Lopez', 91632],
];
$worksheet->fromArray($data, null, 'B2');
$worksheet->getCell('H4')->setValue('=VLOOKUP(H3, B3:E9, 4, FALSE)');
$worksheet->getCell('I4')->setValue('=VLOOKUP(I3, B3:E9, 4, FALSE)');
$worksheet->getCell('J4')->setValue('=VLOOKUP(J3, B3:E9, 4, FALSE)');
for ($column = 'H'; $column !== 'K'; ++$column) {
$cell = $worksheet->getCell("{$column}4");
$helper->log("{$column}4: {$cell->getValue()} => {$cell->getCalculatedValue()}");
}

View File

@ -5,6 +5,11 @@ use PhpOffice\PhpSpreadsheet\Settings;
require __DIR__ . '/../Header.php';
if (PHP_VERSION_ID >= 80000) {
$helper->log('Jpgraph no longer runs against PHP8');
exit;
}
// Change these values to select the Rendering library that you wish to use
Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class);

View File

@ -1,6 +1,7 @@
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
require __DIR__ . '/../Header.php';
@ -9,6 +10,6 @@ $helper->log('Loading file ' . pathinfo($inputFileName, PATHINFO_BASENAME) . ' u
try {
$spreadsheet = IOFactory::load($inputFileName);
} catch (InvalidArgumentException $e) {
} catch (ReaderException $e) {
$helper->log('Error loading file "' . pathinfo($inputFileName, PATHINFO_BASENAME) . '": ' . $e->getMessage());
}

View File

@ -1,5 +1,6 @@
<?php
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
require __DIR__ . '/../Header.php';
@ -35,7 +36,7 @@ $helper->log('Write link: ' . $baseUrl);
$drawing->setWorksheet($aSheet);
$filename = tempnam(\PhpOffice\PhpSpreadsheet\Shared\File::sysGetTempDir(), 'phpspreadsheet-test');
$filename = File::temporaryFilename();
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, $inputFileType);
$writer->save($filename);

View File

@ -1,6 +1,7 @@
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\Date;
require __DIR__ . '/../Header.php';
@ -18,9 +19,8 @@ $helper->log('<b>Document Creator: </b>' . $creator);
// Read the Date when the workbook was created (as a PHP timestamp value)
$creationDatestamp = $spreadsheet->getProperties()->getCreated();
// Format the date and time using the standard PHP date() function
$creationDate = date('l, d<\s\up>S</\s\up> F Y', $creationDatestamp);
$creationTime = date('g:i A', $creationDatestamp);
$creationDate = Date::formattedDateTimeFromTimestamp("$creationDatestamp", 'l, d<\s\up>S</\s\up> F Y');
$creationTime = Date::formattedDateTimeFromTimestamp("$creationDatestamp", 'g:i A');
$helper->log('<b>Created On: </b>' . $creationDate . ' at ' . $creationTime);
// Read the name of the last person to modify this workbook
@ -30,8 +30,8 @@ $helper->log('<b>Last Modified By: </b>' . $modifiedBy);
// Read the Date when the workbook was last modified (as a PHP timestamp value)
$modifiedDatestamp = $spreadsheet->getProperties()->getModified();
// Format the date and time using the standard PHP date() function
$modifiedDate = date('l, d<\s\up>S</\s\up> F Y', $modifiedDatestamp);
$modifiedTime = date('g:i A', $modifiedDatestamp);
$modifiedDate = Date::formattedDateTimeFromTimestamp("$modifiedDatestamp", 'l, d<\s\up>S</\s\up> F Y');
$modifiedTime = Date::formattedDateTimeFromTimestamp("$modifiedDatestamp", 'g:i A');
$helper->log('<b>Last Modified On: </b>' . $modifiedDate . ' at ' . $modifiedTime);
// Read the workbook title property

Binary file not shown.

Binary file not shown.

View File

@ -14,7 +14,7 @@
<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>
<LastSaved>2010-09-03T21:48:39Z</LastSaved>
<Category>PHPExcel Xml Reader Test Category</Category>
<Manager>Maarten Balliauw</Manager>
<Company>PHPExcel</Company>

View File

@ -31,7 +31,9 @@ $spreadsheet->getProperties()->setCreator('Maarten Balliauw')
$helper->log('Add some data');
$spreadsheet->setActiveSheetIndex(0);
$spreadsheet->getActiveSheet()->setCellValue('B1', 'Invoice');
$spreadsheet->getActiveSheet()->setCellValue('D1', Date::PHPToExcel(gmmktime(0, 0, 0, date('m'), date('d'), date('Y'))));
$date = new DateTime('now');
$date->setTime(0, 0, 0);
$spreadsheet->getActiveSheet()->setCellValue('D1', Date::PHPToExcel($date));
$spreadsheet->getActiveSheet()->getStyle('D1')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_XLSX15);
$spreadsheet->getActiveSheet()->setCellValue('E1', '#12566');

File diff suppressed because it is too large Load Diff

View File

@ -2,126 +2,11 @@
namespace PhpOffice\PhpSpreadsheet\Calculation;
/**
* @deprecated 1.17.0
*/
class Database
{
/**
* fieldExtract.
*
* Extracts the column ID to use for the data field.
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param mixed $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
*
* @return null|string
*/
private static function fieldExtract($database, $field)
{
$field = strtoupper(Functions::flattenSingleValue($field));
$fieldNames = array_map('strtoupper', array_shift($database));
if (is_numeric($field)) {
$keys = array_keys($fieldNames);
return $keys[$field - 1];
}
$key = array_search($field, $fieldNames);
return ($key) ? $key : null;
}
/**
* filter.
*
* Parses the selection criteria, extracts the database rows that match those criteria, and
* returns that subset of rows.
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return array of mixed
*/
private static function filter($database, $criteria)
{
$fieldNames = array_shift($database);
$criteriaNames = array_shift($criteria);
// Convert the criteria into a set of AND/OR conditions with [:placeholders]
$testConditions = $testValues = [];
$testConditionsCount = 0;
foreach ($criteriaNames as $key => $criteriaName) {
$testCondition = [];
$testConditionCount = 0;
foreach ($criteria as $row => $criterion) {
if ($criterion[$key] > '') {
$testCondition[] = '[:' . $criteriaName . ']' . Functions::ifCondition($criterion[$key]);
++$testConditionCount;
}
}
if ($testConditionCount > 1) {
$testConditions[] = 'OR(' . implode(',', $testCondition) . ')';
++$testConditionsCount;
} elseif ($testConditionCount == 1) {
$testConditions[] = $testCondition[0];
++$testConditionsCount;
}
}
if ($testConditionsCount > 1) {
$testConditionSet = 'AND(' . implode(',', $testConditions) . ')';
} elseif ($testConditionsCount == 1) {
$testConditionSet = $testConditions[0];
}
// Loop through each row of the database
foreach ($database as $dataRow => $dataValues) {
// Substitute actual values from the database row for our [:placeholders]
$testConditionList = $testConditionSet;
foreach ($criteriaNames as $key => $criteriaName) {
$k = array_search($criteriaName, $fieldNames);
if (isset($dataValues[$k])) {
$dataValue = $dataValues[$k];
$dataValue = (is_string($dataValue)) ? Calculation::wrapResult(strtoupper($dataValue)) : $dataValue;
$testConditionList = str_replace('[:' . $criteriaName . ']', $dataValue, $testConditionList);
}
}
// evaluate the criteria against the row data
$result = Calculation::getInstance()->_calculateFormulaValue('=' . $testConditionList);
// If the row failed to meet the criteria, remove it from the database
if (!$result) {
unset($database[$dataRow]);
}
}
return $database;
}
private static function getFilteredColumn($database, $field, $criteria)
{
// reduce the database to a set of rows that match all the criteria
$database = self::filter($database, $criteria);
// extract an array of values for the requested column
$colData = [];
foreach ($database as $row) {
$colData[] = $row[$field];
}
return $colData;
}
/**
* DAVERAGE.
*
@ -130,6 +15,11 @@ class Database
* Excel Function:
* DAVERAGE(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DAverage::evaluate()
* Use the evaluate() method in the Database\DAverage class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -145,19 +35,11 @@ class Database
* the column label in which you specify a condition for the
* column.
*
* @return float|string
* @return null|float|string
*/
public static function DAVERAGE($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::AVERAGE(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DAverage::evaluate($database, $field, $criteria);
}
/**
@ -169,14 +51,16 @@ class Database
* Excel Function:
* DCOUNT(database,[field],criteria)
*
* Excel Function:
* DAVERAGE(database,field,criteria)
* @Deprecated 1.17.0
*
* @see Database\DCount::evaluate()
* Use the evaluate() method in the Database\DCount class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* @param null|int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
@ -194,15 +78,7 @@ class Database
*/
public static function DCOUNT($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::COUNT(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DCount::evaluate($database, $field, $criteria);
}
/**
@ -213,11 +89,16 @@ class Database
* Excel Function:
* DCOUNTA(database,[field],criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DCountA::evaluate()
* Use the evaluate() method in the Database\DCountA class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* @param null|int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
@ -229,29 +110,10 @@ class Database
* column.
*
* @return int
*
* @TODO The field argument is optional. If field is omitted, DCOUNTA counts all records in the
* database that match the criteria.
*/
public static function DCOUNTA($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// reduce the database to a set of rows that match all the criteria
$database = self::filter($database, $criteria);
// extract an array of values for the requested column
$colData = [];
foreach ($database as $row) {
$colData[] = $row[$field];
}
// Return
return Statistical::COUNTA(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DCountA::evaluate($database, $field, $criteria);
}
/**
@ -263,6 +125,11 @@ class Database
* Excel Function:
* DGET(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DGet::evaluate()
* Use the evaluate() method in the Database\DGet class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -282,18 +149,7 @@ class Database
*/
public static function DGET($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
$colData = self::getFilteredColumn($database, $field, $criteria);
if (count($colData) > 1) {
return Functions::NAN();
}
return $colData[0];
return Database\DGet::evaluate($database, $field, $criteria);
}
/**
@ -305,6 +161,11 @@ class Database
* Excel Function:
* DMAX(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DMax::evaluate()
* Use the evaluate() method in the Database\DMax class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -324,15 +185,7 @@ class Database
*/
public static function DMAX($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::MAX(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DMax::evaluate($database, $field, $criteria);
}
/**
@ -344,6 +197,11 @@ class Database
* Excel Function:
* DMIN(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DMin::evaluate()
* Use the evaluate() method in the Database\DMin class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -363,15 +221,7 @@ class Database
*/
public static function DMIN($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::MIN(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DMin::evaluate($database, $field, $criteria);
}
/**
@ -382,6 +232,11 @@ class Database
* Excel Function:
* DPRODUCT(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DProduct::evaluate()
* Use the evaluate() method in the Database\DProduct class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -397,19 +252,11 @@ class Database
* the column label in which you specify a condition for the
* column.
*
* @return float
* @return float|string
*/
public static function DPRODUCT($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return MathTrig::PRODUCT(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DProduct::evaluate($database, $field, $criteria);
}
/**
@ -421,6 +268,11 @@ class Database
* Excel Function:
* DSTDEV(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DStDev::evaluate()
* Use the evaluate() method in the Database\DStDev class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -440,15 +292,7 @@ class Database
*/
public static function DSTDEV($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::STDEV(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DStDev::evaluate($database, $field, $criteria);
}
/**
@ -460,6 +304,11 @@ class Database
* Excel Function:
* DSTDEVP(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DStDevP::evaluate()
* Use the evaluate() method in the Database\DStDevP class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -479,15 +328,7 @@ class Database
*/
public static function DSTDEVP($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::STDEVP(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DStDevP::evaluate($database, $field, $criteria);
}
/**
@ -498,6 +339,11 @@ class Database
* Excel Function:
* DSUM(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DSum::evaluate()
* Use the evaluate() method in the Database\DSum class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -513,19 +359,11 @@ class Database
* the column label in which you specify a condition for the
* column.
*
* @return float
* @return float|string
*/
public static function DSUM($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return MathTrig::SUM(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DSum::evaluate($database, $field, $criteria);
}
/**
@ -537,6 +375,11 @@ class Database
* Excel Function:
* DVAR(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DVar::evaluate()
* Use the evaluate() method in the Database\DVar class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -556,15 +399,7 @@ class Database
*/
public static function DVAR($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::VARFunc(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DVar::evaluate($database, $field, $criteria);
}
/**
@ -576,6 +411,11 @@ class Database
* Excel Function:
* DVARP(database,field,criteria)
*
* @Deprecated 1.17.0
*
* @see Database\DVarP::evaluate()
* Use the evaluate() method in the Database\DVarP class instead
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
@ -595,14 +435,6 @@ class Database
*/
public static function DVARP($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
// Return
return Statistical::VARP(
self::getFilteredColumn($database, $field, $criteria)
);
return Database\DVarP::evaluate($database, $field, $criteria);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages;
class DAverage extends DatabaseAbstract
{
/**
* DAVERAGE.
*
* Averages the values in a column of a list or database that match conditions you specify.
*
* Excel Function:
* DAVERAGE(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return Averages::average(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts;
class DCount extends DatabaseAbstract
{
/**
* DCOUNT.
*
* Counts the cells that contain numbers in a column of a list or database that match conditions
* that you specify.
*
* Excel Function:
* DCOUNT(database,[field],criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param null|int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return int
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
return Counts::COUNT(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts;
class DCountA extends DatabaseAbstract
{
/**
* DCOUNTA.
*
* Counts the nonblank cells in a column of a list or database that match conditions that you specify.
*
* Excel Function:
* DCOUNTA(database,[field],criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return int
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
return Counts::COUNTA(
self::getFilteredColumn($database, $field ?? 0, $criteria)
);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class DGet extends DatabaseAbstract
{
/**
* DGET.
*
* Extracts a single value from a column of a list or database that matches conditions that you
* specify.
*
* Excel Function:
* DGET(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return mixed
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
$columnData = self::getFilteredColumn($database, $field, $criteria);
if (count($columnData) > 1) {
return Functions::NAN();
}
$row = array_pop($columnData);
return array_pop($row);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum;
class DMax extends DatabaseAbstract
{
/**
* DMAX.
*
* Returns the largest number in a column of a list or database that matches conditions you that
* specify.
*
* Excel Function:
* DMAX(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return Maximum::max(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum;
class DMin extends DatabaseAbstract
{
/**
* DMIN.
*
* Returns the smallest number in a column of a list or database that matches conditions you that
* specify.
*
* Excel Function:
* DMIN(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return Minimum::min(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
class DProduct extends DatabaseAbstract
{
/**
* DPRODUCT.
*
* Multiplies the values in a column of a list or database that match conditions that you specify.
*
* Excel Function:
* DPRODUCT(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return MathTrig\Operations::product(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations;
class DStDev extends DatabaseAbstract
{
/**
* DSTDEV.
*
* Estimates the standard deviation of a population based on a sample by using the numbers in a
* column of a list or database that match conditions that you specify.
*
* Excel Function:
* DSTDEV(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return StandardDeviations::STDEV(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations;
class DStDevP extends DatabaseAbstract
{
/**
* DSTDEVP.
*
* Calculates the standard deviation of a population based on the entire population by using the
* numbers in a column of a list or database that match conditions that you specify.
*
* Excel Function:
* DSTDEVP(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return StandardDeviations::STDEVP(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
class DSum extends DatabaseAbstract
{
/**
* DSUM.
*
* Adds the numbers in a column of a list or database that match conditions that you specify.
*
* Excel Function:
* DSUM(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return MathTrig\Sum::sumIgnoringStrings(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances;
class DVar extends DatabaseAbstract
{
/**
* DVAR.
*
* Estimates the variance of a population based on a sample by using the numbers in a column
* of a list or database that match conditions that you specify.
*
* Excel Function:
* DVAR(database,field,criteria)
*
* @param mixed[] $database The range of cells that makes up the list or database.
* A database is a list of related data in which rows of related
* information are records, and columns of data are fields. The
* first row of the list contains labels for each column.
* @param int|string $field Indicates which column is used in the function. Enter the
* column label enclosed between double quotation marks, such as
* "Age" or "Yield," or a number (without quotation marks) that
* represents the position of the column within the list: 1 for
* the first column, 2 for the second column, and so on.
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
* You can use any range for the criteria argument, as long as it
* includes at least one column label and at least one cell below
* the column label in which you specify a condition for the
* column.
*
* @return null|float|string (string if result is an error)
*/
public static function evaluate($database, $field, $criteria)
{
$field = self::fieldExtract($database, $field);
if ($field === null) {
return null;
}
return Variances::VAR(
self::getFilteredColumn($database, $field, $criteria)
);
}
}

Some files were not shown because too many files have changed in this diff Show More