Skip to content

Commit b48232c

Browse files
authored
Merge branch 'master' into Xlsx-Reader_Windows-Folder-Separator-in-Zip
2 parents 235f11b + 00c34e7 commit b48232c

34 files changed

+1340
-123
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org).
99

1010
### Added
1111

12-
- Wizards for defining Number Format masks for Dates and Times. [PR #3458](https://github.com/PHPOffice/PhpSpreadsheet/pull/3458)
12+
- Wizards for defining Number Format masks for Dates and Times, including Durations/Intervals. [PR #3458](https://github.com/PHPOffice/PhpSpreadsheet/pull/3458)
1313
- Specify data type in html tags. [Issue #3444](https://github.com/PHPOffice/PhpSpreadsheet/issues/3444) [PR #3445](https://github.com/PHPOffice/PhpSpreadsheet/pull/3445)
1414

1515
### Changed
1616

17+
- Xlsx Color schemes read in will be written out (previously Excel 2007-2010 Color scheme was always written); manipulation of those schemes before write, including restoring prior behavior, is provided [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476)
1718
- Memory and speed optimisations for Read Filters with Xlsx Files and Shared Formulae. [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474)
1819

1920
### Deprecated

docs/topics/migration-from-PHPExcel.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ automatically your codebase. Assuming your files to be migrated lives
1313
in `src/`, you can run the migration like so:
1414

1515
```sh
16-
composer require rector/rector --dev
16+
composer require rector/rector phpoffice/phpspreadsheet --dev
1717

1818
# this creates rector.php config
1919
vendor/bin/rector init
@@ -41,7 +41,7 @@ vendor/bin/rector process src
4141
```
4242

4343
For more details, see
44-
[RectorPHP blog post](https://getrector.org/blog/2020/04/16/how-to-migrate-from-phpexcel-to-phpspreadsheet-with-rector-in-30-minutes).
44+
[rector-phpoffice](https://github.com/rectorphp/rector-phpoffice).
4545

4646
## Manual changes
4747

samples/Basic/45_Quadratic_equation_solver.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
<?php
22

33
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
4+
use PhpOffice\PhpSpreadsheet\Helper\Sample;
45
use PhpOffice\PhpSpreadsheet\Settings;
56

67
require __DIR__ . '/../Header.php';
8+
9+
$helper = new Sample();
10+
if ($helper->isCli()) {
11+
$helper->log('This example should only be run from a Web Browser' . PHP_EOL);
12+
13+
return;
14+
}
715
?>
816
<form action="45_Quadratic_equation_solver.php" method="POST">
917
Enter the coefficients for the Ax<sup>2</sup> + Bx + C = 0
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
use PhpOffice\PhpSpreadsheet\Chart\Chart;
4+
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
5+
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
6+
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
7+
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
8+
use PhpOffice\PhpSpreadsheet\Chart\Title;
9+
use PhpOffice\PhpSpreadsheet\IOFactory;
10+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
11+
use PhpOffice\PhpSpreadsheet\Theme as SpreadsheetTheme;
12+
13+
require __DIR__ . '/../Header.php';
14+
15+
$spreadsheet = new Spreadsheet();
16+
// same as 33_Chart_create_area, but with 2013+ schemes
17+
$spreadsheet->getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_PLUS_NAME);
18+
$worksheet = $spreadsheet->getActiveSheet();
19+
$worksheet->fromArray(
20+
[
21+
['', 2010, 2011, 2012],
22+
['Q1', 12, 15, 21],
23+
['Q2', 56, 73, 86],
24+
['Q3', 52, 61, 69],
25+
['Q4', 30, 32, 0],
26+
]
27+
);
28+
29+
// Set the Labels for each data series we want to plot
30+
// Datatype
31+
// Cell reference for data
32+
// Format Code
33+
// Number of datapoints in series
34+
// Data values
35+
// Data Marker
36+
$dataSeriesLabels = [
37+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
38+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
39+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
40+
];
41+
// Set the X-Axis Labels
42+
// Datatype
43+
// Cell reference for data
44+
// Format Code
45+
// Number of datapoints in series
46+
// Data values
47+
// Data Marker
48+
$xAxisTickValues = [
49+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
50+
];
51+
// Set the Data values for each data series we want to plot
52+
// Datatype
53+
// Cell reference for data
54+
// Format Code
55+
// Number of datapoints in series
56+
// Data values
57+
// Data Marker
58+
$dataSeriesValues = [
59+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
60+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
61+
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
62+
];
63+
64+
// Build the dataseries
65+
$series = new DataSeries(
66+
DataSeries::TYPE_AREACHART, // plotType
67+
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
68+
range(0, count($dataSeriesValues) - 1), // plotOrder
69+
$dataSeriesLabels, // plotLabel
70+
$xAxisTickValues, // plotCategory
71+
$dataSeriesValues // plotValues
72+
);
73+
74+
// Set the series in the plot area
75+
$plotArea = new PlotArea(null, [$series]);
76+
// Set the chart legend
77+
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
78+
79+
$title = new Title('Test %age-Stacked Area Chart');
80+
$yAxisLabel = new Title('Value ($k)');
81+
82+
// Create the chart
83+
$chart = new Chart(
84+
'chart1', // name
85+
$title, // title
86+
$legend, // legend
87+
$plotArea, // plotArea
88+
true, // plotVisibleOnly
89+
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
90+
null, // xAxisLabel
91+
$yAxisLabel // yAxisLabel
92+
);
93+
94+
// Set the position where the chart should appear in the worksheet
95+
$chart->setTopLeftPosition('A7');
96+
$chart->setBottomRightPosition('H20');
97+
98+
// Add the chart to the worksheet
99+
$worksheet->addChart($chart);
100+
101+
// Save Excel 2007 file
102+
$filename = $helper->getFilename(__FILE__);
103+
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
104+
$writer->setIncludeCharts(true);
105+
$callStartTime = microtime(true);
106+
$writer->save($filename);
107+
$helper->logWrite($writer, $filename, $callStartTime);
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
3+
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
4+
use PhpOffice\PhpSpreadsheet\Helper\Sample;
5+
use PhpOffice\PhpSpreadsheet\Settings;
6+
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
7+
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard;
8+
9+
require __DIR__ . '/../../Header.php';
10+
11+
$helper = new Sample();
12+
if ($helper->isCli()) {
13+
$helper->log('This example should only be run from a Web Browser' . PHP_EOL);
14+
15+
return;
16+
}
17+
18+
$currencies = [
19+
'$' => 'US Dollars ($)',
20+
'' => 'Euro (€)',
21+
'¥' => 'Japanese Yen (¥)',
22+
'£' => 'Pound Sterling (£)',
23+
'' => 'Rupee (₹)',
24+
'' => 'Rouble (₽)',
25+
];
26+
27+
?>
28+
<form action=Accounting.php method="POST">
29+
<div class="mb-3 row">
30+
<label for="number" class="col-sm-2 col-form-label">Sample Number Value</label>
31+
<div class="col-sm-10">
32+
<input name="number" type="text" size="8" value="<?php echo (isset($_POST['number'])) ? htmlentities($_POST['number'], Settings::htmlEntityFlags()) : '1234.5678'; ?>">
33+
</div>
34+
</div>
35+
<div class="mb-3 row">
36+
<hr />
37+
</div>
38+
<div class="mb-3 row">
39+
<label for="currency" class="col-sm-2 col-form-label">Currency</label>
40+
<div class="col-sm-10">
41+
<select name="currency" class="form-select">
42+
<?php foreach ($currencies as $currencySymbol => $currencyName) {
43+
echo "<option value=\"{$currencySymbol}\" " . ((isset($_POST['currency']) && $_POST['currency'] === $currencySymbol) ? 'selected' : '') . ">{$currencyName}</option>", PHP_EOL;
44+
} ?>
45+
</select>
46+
</div>
47+
</div>
48+
<div class="mb-3 row">
49+
<label for="decimals" class="col-sm-2 col-form-label">Decimal Places</label>
50+
<div class="col-sm-10">
51+
<input name="decimals" type="number" size="2" min="0" max="14" value="<?php echo (isset($_POST['decimals'])) ? htmlentities($_POST['decimals'], Settings::htmlEntityFlags()) : '2'; ?>">
52+
</div>
53+
</div>
54+
<div class="mb-3 row">
55+
<label for="thousands" class="col-sm-2 col-form-label">Use Thousands Separator</label>
56+
<div class="col-sm-10">
57+
<input name="thousands" type="checkbox" <?php echo (isset($_POST['thousands'])) ? 'value="on"' : ''; ?> <?php echo (isset($_POST['thousands'])) ? 'checked' : ''; ?>>
58+
</div>
59+
</div>
60+
<div class="mb-3 row">
61+
<label for="position" class="col-sm-2 col-form-label">Currency Position</label>
62+
<div class="col-sm-10">
63+
<input name="position" type="radio" value="1" <?php echo ((isset($_POST['position']) === false) || (isset($_POST['position']) && $_POST['position'] === '1')) ? 'checked' : ''; ?>>Leading
64+
<input name="position" type="radio" value="0" <?php echo (isset($_POST['position']) && $_POST['position'] === '0') ? 'checked' : ''; ?>>Trailing
65+
</div>
66+
</div>
67+
<div class="mb-3 row">
68+
<label for="spacing" class="col-sm-2 col-form-label">Currency Spacing</label>
69+
<div class="col-sm-10">
70+
<input name="spacing" type="radio" value="1" <?php echo (isset($_POST['spacing']) && $_POST['spacing'] === '1') ? 'checked' : ''; ?>>Yes
71+
<input name="spacing" type="radio" value="0" <?php echo ((isset($_POST['spacing']) === false) || (isset($_POST['spacing']) && $_POST['spacing'] === '0')) ? 'checked' : ''; ?>>No
72+
</div>
73+
</div>
74+
<div class="mb-3 row">
75+
<div class="col-sm-10">
76+
<input class="btn btn-primary" name="submit" type="submit" value="Display Mask"><br />
77+
</div>
78+
</div>
79+
</form>
80+
81+
<?php
82+
/** If the user has submitted the form, then we need to use the wizard to build a mask and display the result */
83+
if (isset($_POST['submit'])) {
84+
if (!is_numeric($_POST['number'])) {
85+
$helper->log('The Sample Number Value must be numeric');
86+
} elseif (!is_numeric($_POST['decimals']) || strpos($_POST['decimals'], '.') !== false || (int) $_POST['decimals'] < 0) {
87+
$helper->log('The Decimal Places value must be positive integer');
88+
} else {
89+
try {
90+
$wizard = new Wizard\Accounting($_POST['currency'], $_POST['decimals'], isset($_POST['thousands']), (bool) $_POST['position'], (bool) $_POST['spacing']);
91+
$mask = $wizard->format();
92+
$example = (string) NumberFormat::toFormattedString((float) $_POST['number'], $mask);
93+
$helper->log('<hr /><b>Code:</b><br />');
94+
$helper->log('use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard;');
95+
$helper->log(
96+
"\$mask = Wizard\\Accounting('{$_POST['currency']}', {$_POST['decimals']}, Wizard\\Number::" .
97+
(isset($_POST['thousands']) ? 'WITH_THOUSANDS_SEPARATOR' : 'WITHOUT_THOUSANDS_SEPARATOR') .
98+
', Wizard\Currency::' . (((bool) $_POST['position']) ? 'LEADING_SYMBOL' : 'TRAILING_SYMBOL') .
99+
', Wizard\Currency::' . (((bool) $_POST['spacing']) ? 'SYMBOL_WITH_SPACING' : 'SYMBOL_WITHOUT_SPACING') .
100+
');<br />'
101+
);
102+
$helper->log('echo (string) $mask;');
103+
$helper->log('<hr /><b>Mask:</b><br />');
104+
$helper->log($mask . '<br />');
105+
$helper->log('<br /><b>Example:</b><br />');
106+
$helper->log($example);
107+
} catch (SpreadsheetException $e) {
108+
$helper->log("Exception: {$e->getMessage()}");
109+
}
110+
}
111+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
3+
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
4+
use PhpOffice\PhpSpreadsheet\Helper\Sample;
5+
use PhpOffice\PhpSpreadsheet\Settings;
6+
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
7+
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard;
8+
9+
require __DIR__ . '/../../Header.php';
10+
11+
$helper = new Sample();
12+
if ($helper->isCli()) {
13+
$helper->log('This example should only be run from a Web Browser' . PHP_EOL);
14+
15+
return;
16+
}
17+
18+
$currencies = [
19+
'$' => 'US Dollars ($)',
20+
'' => 'Euro (€)',
21+
'¥' => 'Japanese Yen (¥)',
22+
'£' => 'Pound Sterling (£)',
23+
'' => 'Rupee (₹)',
24+
'' => 'Rouble (₽)',
25+
];
26+
27+
?>
28+
<form action="Currency.php" method="POST">
29+
<div class="mb-3 row">
30+
<label for="number" class="col-sm-2 col-form-label">Sample Number Value</label>
31+
<div class="col-sm-10">
32+
<input name="number" type="text" size="8" value="<?php echo (isset($_POST['number'])) ? htmlentities($_POST['number'], Settings::htmlEntityFlags()) : '1234.5678'; ?>">
33+
</div>
34+
</div>
35+
<div class="mb-3 row">
36+
<hr />
37+
</div>
38+
<div class="mb-3 row">
39+
<label for="currency" class="col-sm-2 col-form-label">Currency</label>
40+
<div class="col-sm-10">
41+
<select name="currency" class="form-select">
42+
<?php foreach ($currencies as $currencySymbol => $currencyName) {
43+
echo "<option value=\"{$currencySymbol}\" " . ((isset($_POST['currency']) && $_POST['currency'] === $currencySymbol) ? 'selected' : '') . ">{$currencyName}</option>", PHP_EOL;
44+
} ?>
45+
</select>
46+
</div>
47+
</div>
48+
<div class="mb-3 row">
49+
<label for="decimals" class="col-sm-2 col-form-label">Decimal Places</label>
50+
<div class="col-sm-10">
51+
<input name="decimals" type="number" size="2" min="0" max="14" value="<?php echo (isset($_POST['decimals'])) ? htmlentities($_POST['decimals'], Settings::htmlEntityFlags()) : '2'; ?>">
52+
</div>
53+
</div>
54+
<div class="mb-3 row">
55+
<label for="thousands" class="col-sm-2 col-form-label">Use Thousands Separator</label>
56+
<div class="col-sm-10">
57+
<input name="thousands" type="checkbox" <?php echo (isset($_POST['thousands'])) ? 'value="on"' : ''; ?> <?php echo (isset($_POST['thousands'])) ? 'checked' : ''; ?>>
58+
</div>
59+
</div>
60+
<div class="mb-3 row">
61+
<label for="position" class="col-sm-2 col-form-label">Currency Position</label>
62+
<div class="col-sm-10">
63+
<input name="position" type="radio" value="1" <?php echo ((isset($_POST['position']) === false) || (isset($_POST['position']) && $_POST['position'] === '1')) ? 'checked' : ''; ?>>Leading
64+
<input name="position" type="radio" value="0" <?php echo (isset($_POST['position']) && $_POST['position'] === '0') ? 'checked' : ''; ?>>Trailing
65+
</div>
66+
</div>
67+
<div class="mb-3 row">
68+
<label for="spacing" class="col-sm-2 col-form-label">Currency Spacing</label>
69+
<div class="col-sm-10">
70+
<input name="spacing" type="radio" value="1" <?php echo (isset($_POST['spacing']) && $_POST['spacing'] === '1') ? 'checked' : ''; ?>>Yes
71+
<input name="spacing" type="radio" value="0" <?php echo ((isset($_POST['spacing']) === false) || (isset($_POST['spacing']) && $_POST['spacing'] === '0')) ? 'checked' : ''; ?>>No
72+
</div>
73+
</div>
74+
<div class="mb-3 row">
75+
<div class="col-sm-10">
76+
<input class="btn btn-primary" name="submit" type="submit" value="Display Mask"><br />
77+
</div>
78+
</div>
79+
</form>
80+
81+
<?php
82+
/** If the user has submitted the form, then we need to use the wizard to build a mask and display the result */
83+
if (isset($_POST['submit'])) {
84+
if (!is_numeric($_POST['number'])) {
85+
$helper->log('The Sample Number Value must be numeric');
86+
} elseif (!is_numeric($_POST['decimals']) || strpos($_POST['decimals'], '.') !== false || (int) $_POST['decimals'] < 0) {
87+
$helper->log('The Decimal Places value must be positive integer');
88+
} else {
89+
try {
90+
$wizard = new Wizard\Currency($_POST['currency'], $_POST['decimals'], isset($_POST['thousands']), (bool) $_POST['position'], (bool) $_POST['spacing']);
91+
$mask = $wizard->format();
92+
$example = (string) NumberFormat::toFormattedString((float) $_POST['number'], $mask);
93+
$helper->log('<hr /><b>Code:</b><br />');
94+
$helper->log('use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard;');
95+
$helper->log(
96+
"\$mask = Wizard\\Currency('{$_POST['currency']}', {$_POST['decimals']}, Wizard\\Number::" .
97+
(isset($_POST['thousands']) ? 'WITH_THOUSANDS_SEPARATOR' : 'WITHOUT_THOUSANDS_SEPARATOR') .
98+
', Wizard\Currency::' . (((bool) $_POST['position']) ? 'LEADING_SYMBOL' : 'TRAILING_SYMBOL') .
99+
', Wizard\Currency::' . (((bool) $_POST['spacing']) ? 'SYMBOL_WITH_SPACING' : 'SYMBOL_WITHOUT_SPACING') .
100+
');<br />'
101+
);
102+
$helper->log('echo (string) $mask;');
103+
$helper->log('<hr /><b>Mask:</b><br />');
104+
$helper->log($mask . '<br />');
105+
$helper->log('<br /><b>Example:</b><br />');
106+
$helper->log($example);
107+
} catch (SpreadsheetException $e) {
108+
$helper->log("Exception: {$e->getMessage()}");
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)