Compare commits
No commits in common. "php74" and "upstream-3.x" have entirely different histories.
php74
...
upstream-3
@ -1,6 +0,0 @@
|
|||||||
# -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
|
|
||||||
require:
|
|
||||||
nulib/php: ^7.4-dev
|
|
||||||
branch:
|
|
||||||
develop:
|
|
||||||
master:
|
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,10 +0,0 @@
|
|||||||
.~lock*#
|
|
||||||
.*.swp
|
|
||||||
/vendor/
|
|
||||||
|
|
||||||
/.idea/shelf/
|
|
||||||
/.idea/workspace.xml
|
|
||||||
/.idea/httpRequests/
|
|
||||||
/.idea/dataSources/
|
|
||||||
/.idea/dataSources.local.xml
|
|
||||||
/.phpunit.result.cache
|
|
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
12
.idea/inspectionProfiles/Project_Default.xml
generated
12
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,12 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
|
||||||
<option name="processCode" value="true" />
|
|
||||||
<option name="processLiterals" value="true" />
|
|
||||||
<option name="processComments" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
17
.idea/misc.xml
generated
17
.idea/misc.xml
generated
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectInspectionProfilesVisibleTreeState">
|
|
||||||
<entry key="Project Default">
|
|
||||||
<profile-state>
|
|
||||||
<expanded-state>
|
|
||||||
<State />
|
|
||||||
</expanded-state>
|
|
||||||
<selected-state>
|
|
||||||
<State>
|
|
||||||
<id>Angular</id>
|
|
||||||
</State>
|
|
||||||
</selected-state>
|
|
||||||
</profile-state>
|
|
||||||
</entry>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/nulib-spout.iml" filepath="$PROJECT_DIR$/.idea/nulib-spout.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
13
.idea/nulib-spout.iml
generated
13
.idea/nulib-spout.iml
generated
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nulib\" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nulib\ext\" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/upstream-3.x/src" isTestSource="false" packagePrefix="OpenSpout\" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
23
.idea/php-docker-settings.xml
generated
23
.idea/php-docker-settings.xml
generated
@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="PhpDockerContainerSettings">
|
|
||||||
<list>
|
|
||||||
<map>
|
|
||||||
<entry key="125ffb9d-fd5f-4e71-8182-94191665795a">
|
|
||||||
<value>
|
|
||||||
<DockerContainerSettings>
|
|
||||||
<option name="version" value="1" />
|
|
||||||
<option name="volumeBindings">
|
|
||||||
<list>
|
|
||||||
<DockerVolumeBindingImpl>
|
|
||||||
<option name="containerPath" value="/opt/project" />
|
|
||||||
</DockerVolumeBindingImpl>
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</DockerContainerSettings>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</list>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
14
.idea/php-test-framework.xml
generated
14
.idea/php-test-framework.xml
generated
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="PhpTestFrameworkVersionCache">
|
|
||||||
<tools_cache>
|
|
||||||
<tool tool_name="PHPUnit">
|
|
||||||
<cache>
|
|
||||||
<versions>
|
|
||||||
<info id="Local/vendor/autoload.php" version="9.6.21" />
|
|
||||||
</versions>
|
|
||||||
</cache>
|
|
||||||
</tool>
|
|
||||||
</tools_cache>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
107
.idea/php.xml
generated
107
.idea/php.xml
generated
@ -1,107 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="MessDetectorOptionsConfiguration">
|
|
||||||
<option name="transferred" value="true" />
|
|
||||||
</component>
|
|
||||||
<component name="PHPCSFixerOptionsConfiguration">
|
|
||||||
<option name="transferred" value="true" />
|
|
||||||
</component>
|
|
||||||
<component name="PHPCodeSnifferOptionsConfiguration">
|
|
||||||
<option name="highlightLevel" value="WARNING" />
|
|
||||||
<option name="transferred" value="true" />
|
|
||||||
</component>
|
|
||||||
<component name="PhpCSFixer">
|
|
||||||
<phpcsfixer_settings>
|
|
||||||
<PhpCSFixerConfiguration tool_path="$PROJECT_DIR$/vendor/bin/php-cs-fixer" />
|
|
||||||
</phpcsfixer_settings>
|
|
||||||
</component>
|
|
||||||
<component name="PhpIncludePathManager">
|
|
||||||
<include_path>
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/string" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/process" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-phpunit" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/log" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/clue/ndjson-react" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/evenement/evenement" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/promise" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/cache" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/fidry/cpu-core-counter" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/dns" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/child-process" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/event-loop" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/socket" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/stream" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php81" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/nulib/tests" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/nulib/php" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
|
|
||||||
</include_path>
|
|
||||||
</component>
|
|
||||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.4">
|
|
||||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
|
||||||
</component>
|
|
||||||
<component name="PhpStan">
|
|
||||||
<PhpStan_settings>
|
|
||||||
<PhpStanConfiguration tool_path="$PROJECT_DIR$/vendor/bin/phpstan" />
|
|
||||||
</PhpStan_settings>
|
|
||||||
</component>
|
|
||||||
<component name="PhpStanOptionsConfiguration">
|
|
||||||
<option name="transferred" value="true" />
|
|
||||||
</component>
|
|
||||||
<component name="PhpUnit">
|
|
||||||
<phpunit_settings>
|
|
||||||
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" phpunit_phar_path="" />
|
|
||||||
</phpunit_settings>
|
|
||||||
</component>
|
|
||||||
<component name="PsalmOptionsConfiguration">
|
|
||||||
<option name="transferred" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
.idea/phpunit.xml
generated
10
.idea/phpunit.xml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="PHPUnit">
|
|
||||||
<option name="directories">
|
|
||||||
<list>
|
|
||||||
<option value="$PROJECT_DIR$/tests" />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,8 +0,0 @@
|
|||||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
||||||
|
|
||||||
# Chemin vers runphp, e.g sbin/runphp
|
|
||||||
RUNPHP=
|
|
||||||
|
|
||||||
# Si RUNPHP n'est pas défini, les variables suivantes peuvent être définies
|
|
||||||
DIST=d11
|
|
||||||
#REGISTRY=pubdocker.univ-reunion.fr/dist
|
|
25
_merge2php82
25
_merge2php82
@ -1,25 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
||||||
mydir="$(cd "$(dirname -- "$0")"; pwd)"
|
|
||||||
myself="$mydir/$(basename -- "$0")"
|
|
||||||
cwd="$(pwd)"
|
|
||||||
if [ "$1" != --stage2 -o -z "$2" ]; then
|
|
||||||
cp "$myself" /tmp/merge2php82.sh
|
|
||||||
exec /tmp/merge2php82.sh --stage2 "$mydir"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$2" || die
|
|
||||||
if [ -f vendor/nulib/php/load.sh ]; then
|
|
||||||
source ./vendor/nulib/php/load.sh || exit 1
|
|
||||||
else
|
|
||||||
source /etc/nulib.sh || exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
git checkout php82
|
|
||||||
git rebase php74 ||
|
|
||||||
die "Le rebase automatique a échoué. Après avoir résolu les conflits, faire
|
|
||||||
git checkout php74
|
|
||||||
pp -af
|
|
||||||
"
|
|
||||||
git checkout php74
|
|
||||||
pp -af
|
|
@ -1,62 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "nulib/spout",
|
|
||||||
"type": "library",
|
|
||||||
"description": "wrapper pour openspout/openspout",
|
|
||||||
"repositories": [
|
|
||||||
{
|
|
||||||
"type": "path",
|
|
||||||
"url": "../nulib"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "composer",
|
|
||||||
"url": "https://repos.univ-reunion.fr/composer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-php74": "7.4.x-dev",
|
|
||||||
"dev-php82": "8.2.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"replace": {
|
|
||||||
"openspout/openspout": "v3.7.4"
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"nulib/php": "^7.4-dev",
|
|
||||||
"ext-dom": "*",
|
|
||||||
"ext-filter": "*",
|
|
||||||
"ext-libxml": "*",
|
|
||||||
"ext-xmlreader": "*",
|
|
||||||
"ext-zip": "*",
|
|
||||||
"php": "^7.4"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"nulib/tests": "^7.4",
|
|
||||||
"friendsofphp/php-cs-fixer": "^3.4",
|
|
||||||
"phpstan/phpstan": "^1.4",
|
|
||||||
"phpstan/phpstan-phpunit": "^1.0",
|
|
||||||
"ext-zlib": "*"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"nulib\\": "src",
|
|
||||||
"OpenSpout\\": "upstream-3.x/src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"nulib\\ext\\": "tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Jephte Clain",
|
|
||||||
"email": "Jephte.Clain@univ-reunion.fr"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {
|
|
||||||
"allow-plugins": {
|
|
||||||
"infection/extension-installer": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
4583
composer.lock
generated
4583
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,77 +0,0 @@
|
|||||||
diff --git a/src/Writer/WriterAbstract.php b/src/Writer/WriterAbstract.php
|
|
||||||
index fd7c472..a2a5e37 100644
|
|
||||||
--- a/src/Writer/WriterAbstract.php
|
|
||||||
+++ b/src/Writer/WriterAbstract.php
|
|
||||||
@@ -22,6 +22,9 @@ abstract class WriterAbstract implements WriterInterface
|
|
||||||
/** @var resource Pointer to the file/stream we will write to */
|
|
||||||
protected $filePointer;
|
|
||||||
|
|
||||||
+ /** @var bool faut-il garder ouvert le flux quand close() est appelé? */
|
|
||||||
+ protected $dontCloseFilePointer = false;
|
|
||||||
+
|
|
||||||
/** @var bool Indicates whether the writer has been opened or not */
|
|
||||||
protected $isWriterOpened = false;
|
|
||||||
|
|
||||||
@@ -57,6 +60,20 @@ abstract class WriterAbstract implements WriterInterface
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ public function writeToStream($filePointer)
|
|
||||||
+ {
|
|
||||||
+ $this->outputFilePath = null;
|
|
||||||
+
|
|
||||||
+ $this->filePointer = $filePointer;
|
|
||||||
+ $this->dontCloseFilePointer = true;
|
|
||||||
+ $this->throwIfFilePointerIsNotAvailable();
|
|
||||||
+
|
|
||||||
+ $this->openWriter();
|
|
||||||
+ $this->isWriterOpened = true;
|
|
||||||
+
|
|
||||||
+ return $this;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
@@ -177,7 +194,7 @@ abstract class WriterAbstract implements WriterInterface
|
|
||||||
|
|
||||||
$this->closeWriter();
|
|
||||||
|
|
||||||
- if (\is_resource($this->filePointer)) {
|
|
||||||
+ if (!$this->dontCloseFilePointer && \is_resource($this->filePointer)) {
|
|
||||||
$this->globalFunctionsHelper->fclose($this->filePointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/src/Reader/XLSX/Helper/CellValueFormatter.php b/src/Reader/XLSX/Helper/CellValueFormatter.php
|
|
||||||
index 1734fb5..08e5282 100644
|
|
||||||
--- a/src/Reader/XLSX/Helper/CellValueFormatter.php
|
|
||||||
+++ b/src/Reader/XLSX/Helper/CellValueFormatter.php
|
|
||||||
@@ -268,9 +268,13 @@ class CellValueFormatter
|
|
||||||
$dateObj->modify('+'.$secondsRemainder.'seconds');
|
|
||||||
|
|
||||||
if ($this->shouldFormatDates) {
|
|
||||||
- $styleNumberFormatCode = $this->styleManager->getNumberFormatCode($cellStyleId);
|
|
||||||
- $phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode);
|
|
||||||
+ //$styleNumberFormatCode = $this->styleManager->getNumberFormatCode($cellStyleId);
|
|
||||||
+ //$phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode);
|
|
||||||
+ // Toujours utiliser le format français complet
|
|
||||||
+ $phpDateFormat = "d/m/Y H:i:s";
|
|
||||||
$cellValue = $dateObj->format($phpDateFormat);
|
|
||||||
+ // Enlever la composante heure si elle n'existe pas
|
|
||||||
+ $cellValue = preg_replace('/ 00:00:00$/', "", $cellValue);
|
|
||||||
} else {
|
|
||||||
$cellValue = $dateObj;
|
|
||||||
}
|
|
||||||
diff --git a/src/Reader/XLSX/Manager/OptionsManager.php b/src/Reader/XLSX/Manager/OptionsManager.php
|
|
||||||
index b04b92c..5749f65 100644
|
|
||||||
--- a/src/Reader/XLSX/Manager/OptionsManager.php
|
|
||||||
+++ b/src/Reader/XLSX/Manager/OptionsManager.php
|
|
||||||
@@ -29,7 +29,7 @@ class OptionsManager extends OptionsManagerAbstract
|
|
||||||
protected function setDefaultOptions()
|
|
||||||
{
|
|
||||||
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
|
|
||||||
- $this->setOption(Options::SHOULD_FORMAT_DATES, false);
|
|
||||||
+ $this->setOption(Options::SHOULD_FORMAT_DATES, true);
|
|
||||||
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
|
|
||||||
$this->setOption(Options::SHOULD_USE_1904_DATES, false);
|
|
||||||
}
|
|
0
src/.gitignore
vendored
0
src/.gitignore
vendored
@ -1,465 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ext\spout;
|
|
||||||
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\file\tab\AbstractBuilder;
|
|
||||||
use nulib\file\tab\TAbstractBuilder;
|
|
||||||
use nulib\os\path;
|
|
||||||
use nulib\php\func;
|
|
||||||
use nulib\php\nur_func;
|
|
||||||
use nulib\php\time\Date;
|
|
||||||
use nulib\php\time\DateTime;
|
|
||||||
use nulib\ref\ext\spout\ref_builder;
|
|
||||||
use nulib\ref\ext\spout\ref_builder_ods;
|
|
||||||
use nulib\ref\ext\spout\ref_builder_xlsx;
|
|
||||||
use nulib\str;
|
|
||||||
use nulib\web\http;
|
|
||||||
use OpenSpout\Common\Entity\Cell;
|
|
||||||
use OpenSpout\Common\Entity\Style\Border;
|
|
||||||
use OpenSpout\Common\Entity\Style\BorderPart;
|
|
||||||
use OpenSpout\Common\Entity\Style\Style;
|
|
||||||
use OpenSpout\Common\Helper\CellTypeHelper;
|
|
||||||
use OpenSpout\Writer\Common\Creator\WriterEntityFactory;
|
|
||||||
use OpenSpout\Writer\WriterMultiSheetsAbstract;
|
|
||||||
use OpenSpout\Writer\XLSX\Entity\SheetView;
|
|
||||||
|
|
||||||
class SpoutBuilder extends AbstractBuilder {
|
|
||||||
use TAbstractBuilder;
|
|
||||||
|
|
||||||
protected static function apply_params($object, ?array $params, array $refParams) {
|
|
||||||
foreach (array_keys($refParams) as $method) {
|
|
||||||
if (!str::starts_with("->", $method)) continue;
|
|
||||||
$func = func::with([$object, $method]);
|
|
||||||
if (($args = $params[$method] ?? null) !== null) {
|
|
||||||
$func->invoke(cl::with($args));
|
|
||||||
}
|
|
||||||
if (($argss = $params["$method*"] ?? null) !== null) {
|
|
||||||
foreach ($argss as $args) {
|
|
||||||
$func->invoke(cl::with($args));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $object;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function add_border_part(?Border &$border, string $name, ?array $params): void {
|
|
||||||
if ($params === null) return;
|
|
||||||
if ($border === null) $border = new Border();
|
|
||||||
$part = new BorderPart($name);
|
|
||||||
if (($color = $params["color"] ?? null) !== null) {
|
|
||||||
$part->setColor(cl::get(ref_builder::COLORS, $color, $color));
|
|
||||||
}
|
|
||||||
if (($width = $params["width"] ?? null) !== null) $part->setWidth($width);
|
|
||||||
if (($style = $params["style"] ?? null) !== null) $part->setStyle($style);
|
|
||||||
$border->addPart($part);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function set_defaults(?array &$params, string $key, array $defaults): void {
|
|
||||||
if ($params !== null && array_key_exists($key, $params)) {
|
|
||||||
if ($params[$key] === false) $params[$key] = null;
|
|
||||||
else $params[$key] ??= $defaults;
|
|
||||||
} else {
|
|
||||||
$params[$key] ??= $defaults;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function ensure_style(&$style): ?Style {
|
|
||||||
if ($style === null) return null;
|
|
||||||
if ($style instanceof Style) return $style;
|
|
||||||
$cell = $style;
|
|
||||||
$style = new Style();
|
|
||||||
$font = $cell["font"] ?? null;
|
|
||||||
if ($font["bold"] ?? null) $style->setFontBold();
|
|
||||||
if ($font["italic"] ?? null) $style->setFontItalic();
|
|
||||||
if ($font["underline"] ?? null) $style->setFontUnderline();
|
|
||||||
if ($font["strikethrough"] ?? null) $style->setFontStrikethrough();
|
|
||||||
if (($name = $font["name"] ?? null) !== null) $style->setFontName($name);
|
|
||||||
if (($size = $font["size"] ?? null) !== null) $style->setFontSize($size);
|
|
||||||
if (($color = $font["color"] ?? null) !== null) {
|
|
||||||
$style->setFontColor(cl::get(ref_builder::COLORS, $color, $color));
|
|
||||||
}
|
|
||||||
if (($color = $cell["bg_color"] ?? null) !== null) {
|
|
||||||
$style->setBackgroundColor(cl::get(ref_builder::COLORS, $color, $color));
|
|
||||||
}
|
|
||||||
if (($align = $cell["align"] ?? null) !== null) $style->setCellAlignment($align);
|
|
||||||
//if (($align = $cell["valign"] ?? null) !== null) $style->setCellVerticalAlignment($align);
|
|
||||||
if (($wrap = $cell["wrap"] ?? null) !== null) $style->setShouldWrapText($wrap);
|
|
||||||
if (($format = $cell["format"] ?? null) !== null) $style->setFormat($format);
|
|
||||||
if (($border = $cell["border"] ?? null) !== null) {
|
|
||||||
if (is_string($border)) {
|
|
||||||
$parts = explode(" ", $border);
|
|
||||||
$border = [];
|
|
||||||
$styleAll = null;
|
|
||||||
$widthAll = null;
|
|
||||||
$colorAll = null;
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if ($part === "all") {
|
|
||||||
$border["left"] = [];
|
|
||||||
$border["top"] = [];
|
|
||||||
$border["right"] = [];
|
|
||||||
$border["bottom"] = [];
|
|
||||||
} elseif (preg_match('/^(left|top|right|bottom)$/', $part)) {
|
|
||||||
$border[$part] = [];
|
|
||||||
} elseif (preg_match('/^(none|solid|dashed|dotted|double)$/', $part)) {
|
|
||||||
$styleAll = $part;
|
|
||||||
} elseif (preg_match('/^(thin|medium|thick)$/', $part)) {
|
|
||||||
$widthAll = $part;
|
|
||||||
} else {
|
|
||||||
$colorAll = $part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($border as &$part) {
|
|
||||||
if ($styleAll !== null) $part["style"] = $styleAll;
|
|
||||||
if ($widthAll !== null) $part["width"] = $widthAll;
|
|
||||||
if ($colorAll !== null) $part["color"] = $colorAll;
|
|
||||||
}; unset($part);
|
|
||||||
}
|
|
||||||
|
|
||||||
$top = $border["top"] ?? null;
|
|
||||||
$right = $border["right"] ?? null;
|
|
||||||
$bottom = $border["bottom"] ?? null;
|
|
||||||
$left = $border["left"] ?? null;
|
|
||||||
$border = null;
|
|
||||||
self::add_border_part($border, "top", $top);
|
|
||||||
self::add_border_part($border, "right", $right);
|
|
||||||
self::add_border_part($border, "bottom", $bottom);
|
|
||||||
self::add_border_part($border, "left", $left);
|
|
||||||
if ($border !== null) $style->setBorder($border);
|
|
||||||
}
|
|
||||||
return $style;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DATE_FORMAT = "dd/mm/yyyy";
|
|
||||||
|
|
||||||
const DATETIME_FORMAT = "dd/mm/yyyy hh:mm:ss";
|
|
||||||
|
|
||||||
/** @var bool faut-il choisir le type numérique pour une chaine numérique? */
|
|
||||||
const TYPE_NUMERIC = true;
|
|
||||||
|
|
||||||
/** @var bool faut-il choisir le type date pour une chaine au bon format? */
|
|
||||||
const TYPE_DATE = true;
|
|
||||||
|
|
||||||
/** @var array configuration du writer */
|
|
||||||
const SPOUT_PARAMS = null;
|
|
||||||
|
|
||||||
/** @var array configuration de la première feuille */
|
|
||||||
const SHEET_PARAMS = null;
|
|
||||||
|
|
||||||
/** @var string nom de la première feuille */
|
|
||||||
const SHEET_NAME = null;
|
|
||||||
|
|
||||||
/** @var array configuration de la vue de la première feuille */
|
|
||||||
const SHEET_VIEW_PARAMS = null;
|
|
||||||
|
|
||||||
function __construct(?string $output, ?array $params=null) {
|
|
||||||
parent::__construct($output, $params);
|
|
||||||
$ssType = $params["ss_type"] ?? null;
|
|
||||||
if ($ssType === null) {
|
|
||||||
switch (path::ext($this->output)) {
|
|
||||||
case ".ods":
|
|
||||||
$ssType = self::SS_TYPE_ODS;
|
|
||||||
break;
|
|
||||||
case ".xlsx":
|
|
||||||
default:
|
|
||||||
$ssType = self::SS_TYPE_XLSX;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$spoutParams = $params["spout"] ?? static::SPOUT_PARAMS;
|
|
||||||
$spoutParams["default_column_width"] ??= 10.5;
|
|
||||||
self::ensure_style($spoutParams["default_row_style"]);
|
|
||||||
switch ($ssType) {
|
|
||||||
case "ods":
|
|
||||||
case self::SS_TYPE_ODS:
|
|
||||||
$ssType = self::SS_TYPE_ODS;
|
|
||||||
$ssWriter = WriterEntityFactory::createODSWriter();
|
|
||||||
self::apply_params($ssWriter, $spoutParams, ref_builder_ods::PARAMS_SPOUT);
|
|
||||||
break;
|
|
||||||
case "xlsx":
|
|
||||||
case self::SS_TYPE_XLSX:
|
|
||||||
default:
|
|
||||||
$ssType = self::SS_TYPE_XLSX;
|
|
||||||
$ssWriter = WriterEntityFactory::createXLSXWriter();
|
|
||||||
self::apply_params($ssWriter, $spoutParams, ref_builder_xlsx::PARAMS_SPOUT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$defaultColumnWidth = $spoutParams["default_column_width"] ?? null;
|
|
||||||
if ($defaultColumnWidth !== null) $ssWriter->setDefaultColumnWidth($defaultColumnWidth);
|
|
||||||
$defaultRowHeight = $spoutParams["default_row_height"] ?? null;
|
|
||||||
if ($defaultRowHeight !== null) $ssWriter->setDefaultRowHeight($defaultRowHeight);
|
|
||||||
$defaultRowStyle = $spoutParams["default_row_style"] ?? null;
|
|
||||||
if ($defaultRowStyle !== null) $ssWriter->setDefaultRowStyle($defaultRowStyle);
|
|
||||||
$ssWriter->writeToStream($this->getResource());
|
|
||||||
|
|
||||||
$this->ssType = $ssType;
|
|
||||||
$this->ssWriter = $ssWriter;
|
|
||||||
$this->spoutParams = $spoutParams;
|
|
||||||
$this->typeNumeric = boolval($params["type_numeric"] ?? static::TYPE_NUMERIC);
|
|
||||||
$this->typeDate = boolval($params["type_date"] ?? static::TYPE_DATE);
|
|
||||||
|
|
||||||
$sheetParams = $params["sheet"] ?? static::SHEET_PARAMS;
|
|
||||||
$sheetName = $params["sheet_name"] ?? static::SHEET_NAME;
|
|
||||||
if ($sheetName !== null) $sheetParams["->setName"] = $sheetName;
|
|
||||||
$sheetViewParams = $params["sheet_view"] ?? static::SHEET_VIEW_PARAMS;
|
|
||||||
if ($sheetViewParams !== null) $sheetParams["view"] = $sheetViewParams;
|
|
||||||
$this->firstSheet = true;
|
|
||||||
$this->sheetParams = null;
|
|
||||||
$this->setSheet(null, $sheetParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SS_TYPE_ODS = 1, SS_TYPE_XLSX = 2;
|
|
||||||
|
|
||||||
/** @var int type de fichier généré */
|
|
||||||
protected int $ssType;
|
|
||||||
|
|
||||||
protected WriterMultiSheetsAbstract $ssWriter;
|
|
||||||
|
|
||||||
protected ?array $spoutParams;
|
|
||||||
|
|
||||||
protected bool $typeNumeric;
|
|
||||||
|
|
||||||
protected bool $typeDate;
|
|
||||||
|
|
||||||
function setParams(?array $params): self {
|
|
||||||
if ($params !== null) {
|
|
||||||
if (array_key_exists("type_numeric", $params)) {
|
|
||||||
$this->typeNumeric = boolval($params["type_numeric"] ?? static::TYPE_NUMERIC);
|
|
||||||
}
|
|
||||||
if (array_key_exists("type_date", $params)) {
|
|
||||||
$this->typeDate = boolval($params["type_date"] ?? static::TYPE_DATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool $firstSheet;
|
|
||||||
|
|
||||||
protected ?array $sheetParams;
|
|
||||||
|
|
||||||
const STYLE_ROW = 0, STYLE_HEADER = 1;
|
|
||||||
|
|
||||||
protected int $rowStyle;
|
|
||||||
|
|
||||||
protected int $currentRow;
|
|
||||||
|
|
||||||
protected ?bool $differentOddEven = null;
|
|
||||||
|
|
||||||
protected int $oddEvenIndex = 0;
|
|
||||||
|
|
||||||
function setDifferentOddEven(bool $differentOddEven, ?bool $startWithOdd=null): self {
|
|
||||||
$this->differentOddEven = $differentOddEven;
|
|
||||||
if ($differentOddEven && $startWithOdd !== null) $this->oddEvenIndex = $startWithOdd? 1: 0;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|int|null $sheetName
|
|
||||||
*/
|
|
||||||
function setSheet($sheetName, ?array $sheetParams=null): self {
|
|
||||||
$sheet = $params["sheet"] ?? null;
|
|
||||||
$sheetName = $sheetName ?? $sheetParams["sheet_name"] ?? null;
|
|
||||||
$sheetViewParams = $sheetParams["sheet_view"] ?? null;
|
|
||||||
|
|
||||||
if ($sheet !== null) $sheetParams = $sheet;
|
|
||||||
if ($sheetName !== null) $sheetParams["->setName"] = $sheetName;
|
|
||||||
if ($sheetViewParams !== null) $sheetParams["view"] = $sheetViewParams;
|
|
||||||
|
|
||||||
$writer = $this->ssWriter;
|
|
||||||
if ($this->firstSheet) {
|
|
||||||
$this->firstSheet = false;
|
|
||||||
$sheet = $writer->getCurrentSheet();
|
|
||||||
} else {
|
|
||||||
$sheet = $writer->addNewSheetAndMakeItCurrent();
|
|
||||||
$this->wroteHeaders = false;
|
|
||||||
$this->built = false;
|
|
||||||
}
|
|
||||||
$this->rowStyle = self::STYLE_ROW;
|
|
||||||
$this->currentRow = 1;
|
|
||||||
|
|
||||||
switch ($this->ssType) {
|
|
||||||
case self::SS_TYPE_ODS:
|
|
||||||
# appliquer les paramètres de la feuille
|
|
||||||
$this->apply_params($sheet, $sheetParams, ref_builder_ods::PARAMS_SHEET);
|
|
||||||
break;
|
|
||||||
case self::SS_TYPE_XLSX:
|
|
||||||
# appliquer les paramètres de la feuille
|
|
||||||
$this->apply_params($sheet, $sheetParams, ref_builder_xlsx::PARAMS_SHEET);
|
|
||||||
# appliquer les paramètres de la vue de la feuille
|
|
||||||
$sheetViewParams =& $sheetParams["view"];
|
|
||||||
$sheetViewParams["->setFreezeRow"] ??= 2;
|
|
||||||
$sheet->setSheetView(self::apply_params(new SheetView(), $sheetViewParams, ref_builder_xlsx::PARAMS_SHEET_VIEW));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
self::set_defaults($sheetParams, "header_style", [
|
|
||||||
"font" => ["bold" => true],
|
|
||||||
"bg_color" => "gray",
|
|
||||||
]);
|
|
||||||
self::set_defaults($sheetParams, "odd_style", [
|
|
||||||
"wrap" => false,
|
|
||||||
]);
|
|
||||||
self::set_defaults($sheetParams, "even_style", [
|
|
||||||
"bg_color" => "light_gray",
|
|
||||||
"wrap" => false,
|
|
||||||
]);
|
|
||||||
$this->ensure_style($sheetParams["header_style"]);
|
|
||||||
$this->ensure_style($sheetParams["odd_style"]);
|
|
||||||
$this->ensure_style($sheetParams["even_style"]);
|
|
||||||
$this->sheetParams = $sheetParams;
|
|
||||||
|
|
||||||
if ($sheetParams !== null) {
|
|
||||||
if (array_key_exists("schema", $sheetParams)) {
|
|
||||||
$this->schema = $sheetParams["schema"] ?? null;
|
|
||||||
}
|
|
||||||
if (array_key_exists("headers", $sheetParams)) {
|
|
||||||
$this->headers = $sheetParams["headers"] ?? null;
|
|
||||||
}
|
|
||||||
if (array_key_exists("rows", $sheetParams)) {
|
|
||||||
$rows = $sheetParams["rows"] ?? null;
|
|
||||||
if (is_callable($rows)) $rows = $rows();
|
|
||||||
$this->rows = $rows;
|
|
||||||
}
|
|
||||||
if (array_key_exists("cook_func", $sheetParams)) {
|
|
||||||
$cookFunc = $sheetParams["cook_func"] ?? null;
|
|
||||||
$cookCtx = $cookArgs = null;
|
|
||||||
if ($cookFunc !== null) {
|
|
||||||
nur_func::ensure_func($cookFunc, $this, $cookArgs);
|
|
||||||
$cookCtx = nur_func::_prepare($cookFunc);
|
|
||||||
}
|
|
||||||
$this->cookCtx = $cookCtx;
|
|
||||||
$this->cookArgs = $cookArgs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* les colonnes sont indexées sur 0 (e.g A = 0, B = 1, etc.)
|
|
||||||
* Les lignes sont indexées sur 1
|
|
||||||
*/
|
|
||||||
function mergeCells(int $topLeftCol, int $topLeftRow, int $bottomRightCol, int $bottomRightRow): void {
|
|
||||||
$this->ssWriter->mergeCells([$topLeftCol, $topLeftRow], [$bottomRightCol, $bottomRightRow]);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function isNumeric($value): bool {
|
|
||||||
if ($this->typeNumeric && is_numeric($value)) return true;
|
|
||||||
if (!is_string($value) && is_numeric($value)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function isDate(&$value, &$style): bool {
|
|
||||||
if ($value instanceof Date) {
|
|
||||||
$style ??= new Style();
|
|
||||||
$style->setFormat(self::DATE_FORMAT);
|
|
||||||
return true;
|
|
||||||
} elseif ($value instanceof DateTime) {
|
|
||||||
$style ??= new Style();
|
|
||||||
$style->setFormat(self::DATETIME_FORMAT);
|
|
||||||
return true;
|
|
||||||
} elseif (CellTypeHelper::isDateTimeOrDateInterval($value)) {
|
|
||||||
$style ??= new Style();
|
|
||||||
$style->setFormat(self::DATE_FORMAT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!is_string($value) || !$this->typeDate) return false;
|
|
||||||
if (DateTime::isa_datetime($value, true)) {
|
|
||||||
$value = new DateTime($value);
|
|
||||||
$style ??= new Style();
|
|
||||||
$style->setFormat(self::DATETIME_FORMAT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (DateTime::isa_date($value, true)) {
|
|
||||||
$value = new Date($value);
|
|
||||||
$style ??= new Style();
|
|
||||||
$style->setFormat(self::DATE_FORMAT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _write(array $row, ?array $colStyles=null, ?array $rowStyle=null): void {
|
|
||||||
$rowParams = null;
|
|
||||||
if ($rowStyle !== null) {
|
|
||||||
# séparer rowParams (pour configurer l'instance de $row) et $rowStyle
|
|
||||||
# (pour appliquer un style sur la ligne)
|
|
||||||
foreach (array_keys(ref_builder::ROW_PARAMS) as $method) {
|
|
||||||
$value = $rowStyle[$method] ?? null;
|
|
||||||
unset($rowStyle[$method]);
|
|
||||||
if ($value !== null) $rowParams[$method] = $value;
|
|
||||||
}
|
|
||||||
if ($rowStyle === []) $rowStyle = null;
|
|
||||||
}
|
|
||||||
$sheetParams = $this->sheetParams;
|
|
||||||
$headerStyle = $sheetParams["header_style"] ?? null;
|
|
||||||
$oddStyle = $sheetParams["odd_style"] ?? null;
|
|
||||||
$evenStyle = $sheetParams["even_style"] ?? null;
|
|
||||||
$differentOddEven = $this->differentOddEven;
|
|
||||||
$differentOddEven ??= $sheetParams["different_odd_even"] ?? true;
|
|
||||||
|
|
||||||
$cells = [];
|
|
||||||
foreach ($row as $key => $col) {
|
|
||||||
$style = $colStyles[$key] ?? null;
|
|
||||||
self::ensure_style($style);
|
|
||||||
if ($col === null || $col === "") {
|
|
||||||
$type = Cell::TYPE_EMPTY;
|
|
||||||
} elseif ($this->isNumeric($col)) {
|
|
||||||
$type = Cell::TYPE_NUMERIC;
|
|
||||||
} elseif ($this->isDate($col, $style)) {
|
|
||||||
$type = Cell::TYPE_DATE;
|
|
||||||
} else {
|
|
||||||
$type = Cell::TYPE_STRING;
|
|
||||||
}
|
|
||||||
$cell = WriterEntityFactory::createCell($col, $style);
|
|
||||||
$cell->setType($type);
|
|
||||||
$cells[] = $cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->rowStyle === self::STYLE_HEADER) {
|
|
||||||
$rowStyle ??= $headerStyle;
|
|
||||||
} elseif ($differentOddEven && $this->oddEvenIndex % 2 == 0) {
|
|
||||||
$rowStyle ??= $evenStyle;
|
|
||||||
}
|
|
||||||
$rowStyle ??= $oddStyle;
|
|
||||||
self::ensure_style($rowStyle);
|
|
||||||
$row = WriterEntityFactory::createRow($cells, $rowStyle);
|
|
||||||
self::apply_params($row, $rowParams, ref_builder::ROW_PARAMS);
|
|
||||||
|
|
||||||
$mergeCells = $rowParams["merge_cells"] ?? null;
|
|
||||||
$mergeOffset = $rowParams["merge_offset"] ?? 0;
|
|
||||||
if ($mergeCells !== null) {
|
|
||||||
$currentRow = $this->currentRow;
|
|
||||||
foreach ($mergeCells as [$leftCol, $rightCol]) {
|
|
||||||
$this->mergeCells($leftCol + $mergeOffset, $currentRow, $rightCol + $mergeOffset, $currentRow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ssWriter->addRow($row);
|
|
||||||
$this->currentRow++;
|
|
||||||
if ($differentOddEven) $this->oddEvenIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeHeaders(?array $headers=null): void {
|
|
||||||
$this->rowStyle = self::STYLE_HEADER;
|
|
||||||
parent::writeHeaders($headers);
|
|
||||||
$this->rowStyle = self::STYLE_ROW;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _sendContentType(): void {
|
|
||||||
switch (path::ext($this->output)) {
|
|
||||||
case ".ods":
|
|
||||||
$contentType = "application/vnd.oasis.opendocument.spreadsheet";
|
|
||||||
break;
|
|
||||||
case ".xlsx":
|
|
||||||
default:
|
|
||||||
$contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
http::content_type($contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function _checkOk(): bool {
|
|
||||||
$this->ssWriter->close();
|
|
||||||
$this->rewind();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ext\spout;
|
|
||||||
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\file\tab\AbstractReader;
|
|
||||||
use OpenSpout\Reader\Common\Creator\ReaderEntityFactory;
|
|
||||||
|
|
||||||
class SpoutReader extends AbstractReader {
|
|
||||||
/** @var string|int|null nom de la feuille depuis laquelle lire */
|
|
||||||
const WSNAME = null;
|
|
||||||
|
|
||||||
function __construct($input, ?array $params=null) {
|
|
||||||
parent::__construct($input, $params);
|
|
||||||
$this->ssType = $params["ss_type"] ?? null;
|
|
||||||
$this->allSheets = $params["all_sheets"] ?? true;
|
|
||||||
$wsname = static::WSNAME;
|
|
||||||
if ($params !== null && array_key_exists("wsname", $params)) {
|
|
||||||
# spécifié par l'utilisateur: $allSheets = false
|
|
||||||
$this->setWsname($params["wsname"]);
|
|
||||||
} elseif ($wsname !== null) {
|
|
||||||
# valeur non nulle de la classe: $allSheets = false
|
|
||||||
$this->setWsname($wsname);
|
|
||||||
} else {
|
|
||||||
# pas de valeur définie dans la classe, laisser $allSheets à sa valeur
|
|
||||||
# actuelle
|
|
||||||
$this->wsname = null;
|
|
||||||
}
|
|
||||||
$this->includeWsnames = cl::withn($params["include_wsnames"] ?? null);
|
|
||||||
$this->excludeWsnames = cl::withn($params["exclude_wsnames"] ?? null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ?string $ssType;
|
|
||||||
|
|
||||||
/** @var bool faut-il retourner les lignes de toutes les feuilles? */
|
|
||||||
protected bool $allSheets;
|
|
||||||
|
|
||||||
function setAllSheets(bool $allSheets=true): self {
|
|
||||||
$this->allSheets = $allSheets;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array|null si non null, liste de feuilles à inclure. n'est pris en
|
|
||||||
* compte que si $allSheets===true
|
|
||||||
*/
|
|
||||||
protected ?array $includeWsnames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array|null si non null, liste de feuilles à exclure. n'est pris en
|
|
||||||
* compte que si $allSheets===true
|
|
||||||
*/
|
|
||||||
protected ?array $excludeWsnames;
|
|
||||||
|
|
||||||
protected $wsname;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|int|null $wsname l'unique feuille à sélectionner
|
|
||||||
*
|
|
||||||
* NB: appeler cette méthode réinitialise $allSheets à false
|
|
||||||
*/
|
|
||||||
function setWsname($wsname): self {
|
|
||||||
$this->wsname = $wsname;
|
|
||||||
$this->allSheets = true;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getIterator() {
|
|
||||||
switch ($this->ssType) {
|
|
||||||
case "ods":
|
|
||||||
$ss = ReaderEntityFactory::createODSReader();
|
|
||||||
break;
|
|
||||||
case "xlsx":
|
|
||||||
$ss = ReaderEntityFactory::createXLSXReader();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$ss = ReaderEntityFactory::createReaderFromFile($this->input);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$ss->open($this->input);
|
|
||||||
try {
|
|
||||||
$allSheets = $this->allSheets;
|
|
||||||
$includeWsnames = $this->includeWsnames;
|
|
||||||
$excludeWsnames = $this->excludeWsnames;
|
|
||||||
$wsname = $this->wsname;
|
|
||||||
$first = true;
|
|
||||||
foreach ($ss->getSheetIterator() as $ws) {
|
|
||||||
if ($allSheets) {
|
|
||||||
$wsname = $ws->getName();
|
|
||||||
$found = ($includeWsnames === null || in_array($wsname, $includeWsnames))
|
|
||||||
&& ($excludeWsnames === null || !in_array($wsname, $excludeWsnames));
|
|
||||||
} else {
|
|
||||||
$found = $wsname === null || $wsname === $ws->getName();
|
|
||||||
}
|
|
||||||
if ($found) {
|
|
||||||
if ($first) {
|
|
||||||
$first = false;
|
|
||||||
} else {
|
|
||||||
yield null;
|
|
||||||
# on garde le même schéma le cas échéant, mais supprimer headers
|
|
||||||
# pour permettre son recalcul
|
|
||||||
$this->headers = null;
|
|
||||||
}
|
|
||||||
$this->isrc = $this->idest = 0;
|
|
||||||
foreach ($ws->getRowIterator() as $row) {
|
|
||||||
$row = $row->toArray();
|
|
||||||
foreach ($row as &$col) {
|
|
||||||
$this->verifixCol($col);
|
|
||||||
}; unset($col);
|
|
||||||
if ($this->cookRow($row)) {
|
|
||||||
yield $row;
|
|
||||||
$this->idest++;
|
|
||||||
}
|
|
||||||
$this->isrc++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
$ss->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ext\tab;
|
|
||||||
|
|
||||||
use nulib\ext\spout\SpoutBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class SsBuilder: construction d'une feuille de calcul, pour envoi à
|
|
||||||
* l'utilisateur
|
|
||||||
*/
|
|
||||||
class SsBuilder extends SpoutBuilder {
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ext\tab;
|
|
||||||
|
|
||||||
use nulib\ext\spout\SpoutReader;
|
|
||||||
use nulib\file\tab\TAbstractReader;
|
|
||||||
|
|
||||||
class SsReader extends SpoutReader {
|
|
||||||
use TAbstractReader;
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ref\ext\spout;
|
|
||||||
|
|
||||||
use OpenSpout\Common\Entity\Style\Color;
|
|
||||||
|
|
||||||
class ref_builder {
|
|
||||||
const PARAMS = [
|
|
||||||
# Builder
|
|
||||||
"output" => "?string",
|
|
||||||
"schema" => "?array",
|
|
||||||
"headers" => "?array",
|
|
||||||
"use_headers" => "bool",
|
|
||||||
"rows" => "?array",
|
|
||||||
"cook_func" => "?callable",
|
|
||||||
"ss_type" => "?string",
|
|
||||||
# SpoutBuilder
|
|
||||||
"type_numeric" => "bool",
|
|
||||||
"type_date" => "bool",
|
|
||||||
"spout" => self::PARAMS_SPOUT,
|
|
||||||
"sheet" => self::PARAMS_SHEET,
|
|
||||||
"sheet_name" => "?string",
|
|
||||||
"sheet_view" => self::PARAMS_SHEET_VIEW,
|
|
||||||
# TempStream
|
|
||||||
"max_memory" => "?int",
|
|
||||||
"throw_on_error" => "?bool",
|
|
||||||
];
|
|
||||||
|
|
||||||
const PARAMS_SPOUT = [
|
|
||||||
"->setColumnWidth" => ["float", ["int", null]],
|
|
||||||
"->setColumnWidthForRange" => ["int", "int", "int"],
|
|
||||||
"default_column_width" => "float",
|
|
||||||
"default_row_height" => "float",
|
|
||||||
"default_row_style" => self::STYLE,
|
|
||||||
];
|
|
||||||
|
|
||||||
const PARAMS_SHEET = [
|
|
||||||
"view" => self::PARAMS_SHEET_VIEW,
|
|
||||||
"->setName" => ["string"],
|
|
||||||
"->setIsVisible" => ["bool"],
|
|
||||||
"header_style" => self::STYLE,
|
|
||||||
"odd_style" => self::STYLE,
|
|
||||||
"even_style" => self::STYLE,
|
|
||||||
"different_odd_even" => "bool",
|
|
||||||
];
|
|
||||||
|
|
||||||
const PARAMS_SHEET_VIEW = [];
|
|
||||||
|
|
||||||
const ROW_PARAMS = [
|
|
||||||
"->setHeight" => ["float"],
|
|
||||||
"merge_cells" => "array",
|
|
||||||
"merge_offset" => "int",
|
|
||||||
];
|
|
||||||
|
|
||||||
const COLORS = [
|
|
||||||
"black" => Color::BLACK,
|
|
||||||
"white" => Color::WHITE,
|
|
||||||
"red" => Color::RED,
|
|
||||||
"dark_red" => Color::DARK_RED,
|
|
||||||
"orange" => Color::ORANGE,
|
|
||||||
"yellow" => Color::YELLOW,
|
|
||||||
"light_green" => Color::LIGHT_GREEN,
|
|
||||||
"green" => Color::GREEN,
|
|
||||||
"light_blue" => Color::LIGHT_BLUE,
|
|
||||||
"blue" => Color::BLUE,
|
|
||||||
"dark_blue" => Color::DARK_BLUE,
|
|
||||||
"purple" => Color::PURPLE,
|
|
||||||
"light_gray" => "EEEEEE",
|
|
||||||
"gray" => "B2B2B2",
|
|
||||||
];
|
|
||||||
|
|
||||||
const STYLE = [
|
|
||||||
"font" => [
|
|
||||||
"bold" => "bool",
|
|
||||||
"italic" => "bool",
|
|
||||||
"underline" => "bool",
|
|
||||||
"strikethrough" => "bool",
|
|
||||||
"name" => "string",
|
|
||||||
"size" => "int",
|
|
||||||
"color" => "string",
|
|
||||||
],
|
|
||||||
"bg_color" => "string",
|
|
||||||
"align" => "string",
|
|
||||||
"valign" => "string",
|
|
||||||
"wrap" => "bool",
|
|
||||||
"format" => "string",
|
|
||||||
"border" => [
|
|
||||||
"top" => ["color" => "string", "width" => "string", "style" => "string"],
|
|
||||||
"right" => ["color" => "string", "width" => "string", "style" => "string"],
|
|
||||||
"bottom" => ["color" => "string", "width" => "string", "style" => "string"],
|
|
||||||
"left" => ["color" => "string", "width" => "string", "style" => "string"],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ref\ext\spout;
|
|
||||||
|
|
||||||
class ref_builder_ods extends ref_builder {
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\ref\ext\spout;
|
|
||||||
|
|
||||||
class ref_builder_xlsx extends ref_builder {
|
|
||||||
const PARAMS_SHEET = [
|
|
||||||
"view" => self::PARAMS_SHEET_VIEW,
|
|
||||||
# copie de parent::SHEET
|
|
||||||
"->setName" => ["string"],
|
|
||||||
"->setIsVisible" => ["bool"],
|
|
||||||
"header_style" => self::STYLE,
|
|
||||||
"odd_style" => self::STYLE,
|
|
||||||
"even_style" => self::STYLE,
|
|
||||||
"different_odd_even" => "bool",
|
|
||||||
];
|
|
||||||
|
|
||||||
const PARAMS_SHEET_VIEW = [
|
|
||||||
"->setFreezeRow" => ["int"],
|
|
||||||
"->setFreezeColumn" => ["string"],
|
|
||||||
"->setZoomScale" => ["int"],
|
|
||||||
"->setShowFormulas" => ["bool"],
|
|
||||||
"->setShowGridLines" => ["bool"],
|
|
||||||
"->setShowRowColHeaders" => ["bool"],
|
|
||||||
"->setShowZeroes" => ["bool"],
|
|
||||||
"->setRightToLeft" => ["bool"],
|
|
||||||
"->setTabSelected" => ["bool"],
|
|
||||||
"->setShowOutlineSymbols" => ["bool"],
|
|
||||||
"->setDefaultGridColor" => ["bool"],
|
|
||||||
"->setView" => ["string"],
|
|
||||||
"->setTopLeftCell" => ["string"],
|
|
||||||
"->setColorId" => ["int"],
|
|
||||||
"->setZoomScaleNormal" => ["int"],
|
|
||||||
"->setZoomScalePageLayoutView" => ["int"],
|
|
||||||
"->setWorkbookViewId" => ["int"],
|
|
||||||
# copie de parent::PARAMS_SHEET_VIEW
|
|
||||||
];
|
|
||||||
}
|
|
0
tests/.gitignore
vendored
0
tests/.gitignore
vendored
@ -268,13 +268,9 @@ class CellValueFormatter
|
|||||||
$dateObj->modify('+'.$secondsRemainder.'seconds');
|
$dateObj->modify('+'.$secondsRemainder.'seconds');
|
||||||
|
|
||||||
if ($this->shouldFormatDates) {
|
if ($this->shouldFormatDates) {
|
||||||
//$styleNumberFormatCode = $this->styleManager->getNumberFormatCode($cellStyleId);
|
$styleNumberFormatCode = $this->styleManager->getNumberFormatCode($cellStyleId);
|
||||||
//$phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode);
|
$phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode);
|
||||||
// Toujours utiliser le format français complet
|
|
||||||
$phpDateFormat = "d/m/Y H:i:s";
|
|
||||||
$cellValue = $dateObj->format($phpDateFormat);
|
$cellValue = $dateObj->format($phpDateFormat);
|
||||||
// Enlever la composante heure si elle n'existe pas
|
|
||||||
$cellValue = preg_replace('/ 00:00:00$/', "", $cellValue);
|
|
||||||
} else {
|
} else {
|
||||||
$cellValue = $dateObj;
|
$cellValue = $dateObj;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class OptionsManager extends OptionsManagerAbstract
|
|||||||
protected function setDefaultOptions()
|
protected function setDefaultOptions()
|
||||||
{
|
{
|
||||||
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
|
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
|
||||||
$this->setOption(Options::SHOULD_FORMAT_DATES, true);
|
$this->setOption(Options::SHOULD_FORMAT_DATES, false);
|
||||||
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
|
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
|
||||||
$this->setOption(Options::SHOULD_USE_1904_DATES, false);
|
$this->setOption(Options::SHOULD_USE_1904_DATES, false);
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,6 @@ abstract class WriterAbstract implements WriterInterface
|
|||||||
/** @var resource Pointer to the file/stream we will write to */
|
/** @var resource Pointer to the file/stream we will write to */
|
||||||
protected $filePointer;
|
protected $filePointer;
|
||||||
|
|
||||||
/** @var bool faut-il garder ouvert le flux quand close() est appelé? */
|
|
||||||
protected $dontCloseFilePointer = false;
|
|
||||||
|
|
||||||
/** @var bool Indicates whether the writer has been opened or not */
|
/** @var bool Indicates whether the writer has been opened or not */
|
||||||
protected $isWriterOpened = false;
|
protected $isWriterOpened = false;
|
||||||
|
|
||||||
@ -60,20 +57,6 @@ abstract class WriterAbstract implements WriterInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeToStream($filePointer)
|
|
||||||
{
|
|
||||||
$this->outputFilePath = null;
|
|
||||||
|
|
||||||
$this->filePointer = $filePointer;
|
|
||||||
$this->dontCloseFilePointer = true;
|
|
||||||
$this->throwIfFilePointerIsNotAvailable();
|
|
||||||
|
|
||||||
$this->openWriter();
|
|
||||||
$this->isWriterOpened = true;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -194,7 +177,7 @@ abstract class WriterAbstract implements WriterInterface
|
|||||||
|
|
||||||
$this->closeWriter();
|
$this->closeWriter();
|
||||||
|
|
||||||
if (!$this->dontCloseFilePointer && \is_resource($this->filePointer)) {
|
if (\is_resource($this->filePointer)) {
|
||||||
$this->globalFunctionsHelper->fclose($this->filePointer);
|
$this->globalFunctionsHelper->fclose($this->filePointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user