importation nulib/phpss:php74
This commit is contained in:
		
							parent
							
								
									bd9b0027f3
								
							
						
					
					
						commit
						ea95c9a5e6
					
				
							
								
								
									
										0
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1,10 @@ | ||||
| .~lock*# | ||||
| .*.swp | ||||
| /vendor/ | ||||
| 
 | ||||
| /.idea/shelf/ | ||||
| /.idea/workspace.xml | ||||
| /.idea/httpRequests/ | ||||
| /.idea/dataSources/ | ||||
| /.idea/dataSources.local.xml | ||||
| /.phpunit.result.cache | ||||
|  | ||||
							
								
								
									
										17
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| <?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
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | ||||
|   <component name="ProjectModuleManager"> | ||||
|     <modules> | ||||
|       <module fileurl="file://$PROJECT_DIR$/.idea/nulib-phpss.iml" filepath="$PROJECT_DIR$/.idea/nulib-phpss.iml" /> | ||||
|     </modules> | ||||
|   </component> | ||||
| </project> | ||||
							
								
								
									
										12
									
								
								.idea/nulib-phpss.iml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.idea/nulib-phpss.iml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| <?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\ext\" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nulib\ext\" /> | ||||
|       <excludeFolder url="file://$MODULE_DIR$/vendor" /> | ||||
|     </content> | ||||
|     <orderEntry type="inheritedJdk" /> | ||||
|     <orderEntry type="sourceFolder" forTests="false" /> | ||||
|   </component> | ||||
| </module> | ||||
							
								
								
									
										38
									
								
								.idea/php-docker-settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								.idea/php-docker-settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| <?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" /> | ||||
|                     <option name="hostPath" value="$PROJECT_DIR$" /> | ||||
|                   </DockerVolumeBindingImpl> | ||||
|                 </list> | ||||
|               </option> | ||||
|             </DockerContainerSettings> | ||||
|           </value> | ||||
|         </entry> | ||||
|         <entry key="c4cf2564-ed91-488c-a93d-fe2daeae80db"> | ||||
|           <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> | ||||
							
								
								
									
										66
									
								
								.idea/php.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								.idea/php.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| <?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="PhpIncludePathManager"> | ||||
|     <include_path> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/version" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/global-state" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/composer" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/markbaker/complex" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/markbaker/matrix" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/type" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/nikic/php-parser" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpunit/phpunit" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpunit/php-timer" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/psr/http-factory" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/psr/simple-cache" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/psr/http-client" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/psr/http-message" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/theseer/tokenizer" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phar-io/version" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/phar-io/manifest" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/code-unit" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/nulib/php" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/diff" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/complexity" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/environment" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/exporter" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/nulib/tests" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/comparator" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/doctrine/instantiator" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/ezyang/htmlpurifier" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/myclabs/php-enum" /> | ||||
|       <path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" /> | ||||
|     </include_path> | ||||
|   </component> | ||||
|   <component name="PhpProjectSharedConfiguration" php_language_level="7.4" /> | ||||
|   <component name="PhpStanOptionsConfiguration"> | ||||
|     <option name="transferred" value="true" /> | ||||
|   </component> | ||||
|   <component name="PsalmOptionsConfiguration"> | ||||
|     <option name="transferred" value="true" /> | ||||
|   </component> | ||||
| </project> | ||||
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | ||||
|   <component name="VcsDirectoryMappings"> | ||||
|     <mapping directory="" vcs="Git" /> | ||||
|   </component> | ||||
| </project> | ||||
| @ -9,4 +9,4 @@ TAG_PREFIX= | ||||
| TAG_SUFFIX=p74 | ||||
| HOTFIX=hotf74- | ||||
| DIST= | ||||
| NOAUTO= | ||||
| NOAUTO=1 | ||||
|  | ||||
							
								
								
									
										8
									
								
								.runphp.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.runphp.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| # -*- 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 | ||||
							
								
								
									
										5
									
								
								TODO.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								TODO.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| # TODO | ||||
| 
 | ||||
| * [ ] mettre en cohérence avec l'API de nulib/spout (notamment wsname et spout) | ||||
| 
 | ||||
| -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary | ||||
							
								
								
									
										45
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| { | ||||
| 	"name": "nulib/phpss", | ||||
| 	"type": "library", | ||||
| 	"description": "wrapper pour phpoffice/phpspreadsheet", | ||||
| 	"repositories": [ | ||||
| 		{ | ||||
| 			"type": "path", | ||||
| 			"url": "../nulib" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"type": "composer", | ||||
| 			"url": "https://repos.univ-reunion.fr/composer" | ||||
| 		} | ||||
| 	], | ||||
| 	"extra": { | ||||
| 		"branch-alias": { | ||||
| 			"dev-dev74": "7.4.x-dev", | ||||
| 			"dev-dev82": "8.2.x-dev" | ||||
| 		} | ||||
| 	}, | ||||
| 	"require": { | ||||
| 		"nulib/php": "^7.4-dev", | ||||
| 		"phpoffice/phpspreadsheet": "^1.0", | ||||
| 		"php": "^7.4" | ||||
| 	}, | ||||
| 	"require-dev": { | ||||
| 		"nulib/tests": "^7.4" | ||||
| 	}, | ||||
| 	"autoload": { | ||||
| 		"psr-4": { | ||||
| 			"nulib\\ext\\": "src" | ||||
| 		} | ||||
| 	}, | ||||
| 	"autoload-dev": { | ||||
| 		"psr-4": { | ||||
| 			"nulib\\ext\\": "tests" | ||||
| 		} | ||||
| 	}, | ||||
| 	"authors": [ | ||||
| 		{ | ||||
| 			"name": "Jephte Clain", | ||||
| 			"email": "Jephte.Clain@univ-reunion.fr" | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
							
								
								
									
										2857
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2857
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										0
									
								
								src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										112
									
								
								src/phpss/PhpSpreadsheetBuilder.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/phpss/PhpSpreadsheetBuilder.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,112 @@ | ||||
| <?php | ||||
| namespace nulib\ext\phpss; | ||||
| 
 | ||||
| use nulib\file\tab\AbstractBuilder; | ||||
| use nulib\file\tab\TAbstractBuilder; | ||||
| use nulib\os\path; | ||||
| use nulib\web\http; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\IValueBinder; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; | ||||
| use PhpOffice\PhpSpreadsheet\Writer\Ods; | ||||
| use PhpOffice\PhpSpreadsheet\Writer\Xlsx; | ||||
| 
 | ||||
| class PhpSpreadsheetBuilder extends AbstractBuilder { | ||||
|   use TAbstractBuilder; | ||||
| 
 | ||||
|   /** @var string|int|null nom de la feuille dans laquelle écrire */ | ||||
|   const WSNAME = null; | ||||
| 
 | ||||
|   function __construct(?string $output, ?array $params=null) { | ||||
|     parent::__construct($output, $params); | ||||
|     $this->ss = new Spreadsheet(); | ||||
|     $this->valueBinder = new StringValueBinder(); | ||||
|     $this->setWsname($params["wsname"] ?? static::WSNAME); | ||||
|   } | ||||
| 
 | ||||
|   protected Spreadsheet $ss; | ||||
| 
 | ||||
|   protected IValueBinder $valueBinder; | ||||
| 
 | ||||
|   protected ?Worksheet $ws; | ||||
| 
 | ||||
|   protected int $nrow; | ||||
| 
 | ||||
|   const STYLE_ROW = 0, STYLE_HEADER = 1; | ||||
| 
 | ||||
|   protected int $rowStyle; | ||||
| 
 | ||||
|   /** | ||||
|    * @param string|int|null $wsname | ||||
|    */ | ||||
|   function setWsname($wsname): self { | ||||
|     $ss = $this->ss; | ||||
|     $this->ws = null; | ||||
|     $this->nrow = 0; | ||||
|     $this->rowStyle = self::STYLE_ROW; | ||||
| 
 | ||||
|     $ws = wsutils::get_ws($wsname, $ss); | ||||
|     if ($ws === null) { | ||||
|       $ws = $ss->createSheet()->setTitle($wsname); | ||||
|       $this->wroteHeaders = false; | ||||
|     } else { | ||||
|       $maxRow = wsutils::compute_max_coords($ws)[1]; | ||||
|       $this->nrow = $maxRow - 1; | ||||
|       $this->wroteHeaders = $maxRow > 1; | ||||
|     } | ||||
|     $this->ws = $ws; | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   function _write(array $row): void { | ||||
|     $ws = $this->ws; | ||||
|     $styleHeader = $this->rowStyle === self::STYLE_HEADER; | ||||
|     $nrow = ++$this->nrow; | ||||
|     $ncol = 1; | ||||
|     foreach ($row as $col) { | ||||
|       $ws->getCellByColumnAndRow($ncol++, $nrow)->setValue($col, $this->valueBinder); | ||||
|     } | ||||
|     if ($styleHeader) { | ||||
|       $ws->getStyle("$nrow:$nrow")->getFont()->setBold(true); | ||||
|       $maxcol = count($row); | ||||
|       for ($ncol = 1; $ncol <= $maxcol; $ncol++) { | ||||
|         $ws->getColumnDimensionByColumn($ncol)->setAutoSize(true); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   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 { | ||||
|     switch (path::ext($this->output)) { | ||||
|     case ".ods": | ||||
|       $writer = new Ods($this->ss); | ||||
|       break; | ||||
|     case ".xlsx": | ||||
|     default: | ||||
|       $writer = new Xlsx($this->ss); | ||||
|       break; | ||||
|     } | ||||
|     $writer->save($this->getResource()); | ||||
|     $this->rewind(); | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										116
									
								
								src/phpss/PhpSpreadsheetReader.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/phpss/PhpSpreadsheetReader.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | ||||
| <?php | ||||
| namespace nulib\ext\phpss; | ||||
| 
 | ||||
| use nulib\cl; | ||||
| use nulib\file\tab\AbstractReader; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\DataType; | ||||
| use PhpOffice\PhpSpreadsheet\IOFactory; | ||||
| use PhpOffice\PhpSpreadsheet\RichText\RichText; | ||||
| 
 | ||||
| class PhpSpreadsheetReader extends AbstractReader { | ||||
|   const DATETIME_FORMAT = 'dd/mm/yyyy hh:mm:ss'; | ||||
|   const DATE_FORMAT = 'dd/mm/yyyy'; | ||||
|   const TIME_FORMAT = 'hh:mm:ss'; | ||||
|   const FORMAT_MAPPINGS = [ | ||||
|     'mm/dd hh' => self::DATETIME_FORMAT, | ||||
|     'dd/mm hh' => self::DATETIME_FORMAT, | ||||
|     'mm/dd hh:mm' => self::DATETIME_FORMAT, | ||||
|     'dd/mm hh:mm' => self::DATETIME_FORMAT, | ||||
|     'mm/dd hh:mm:ss' => self::DATETIME_FORMAT, | ||||
|     'dd/mm hh:mm:ss' => self::DATETIME_FORMAT, | ||||
|     'mm/dd/yyyy hh' => self::DATETIME_FORMAT, | ||||
|     'dd/mm/yyyy hh' => self::DATETIME_FORMAT, | ||||
|     'mm/dd/yyyy hh:mm' => self::DATETIME_FORMAT, | ||||
|     'dd/mm/yyyy hh:mm' => self::DATETIME_FORMAT, | ||||
|     'mm/dd/yyyy hh:mm:ss' => self::DATETIME_FORMAT, | ||||
|     'dd/mm/yyyy hh:mm:ss' => self::DATETIME_FORMAT, | ||||
|     'yyyy/mm/dd hh' => self::DATETIME_FORMAT, | ||||
|     'yyyy/mm/dd hh:mm' => self::DATETIME_FORMAT, | ||||
|     'yyyy/mm/dd hh:mm:ss' => self::DATETIME_FORMAT, | ||||
| 
 | ||||
|     'mm/dd' => self::DATE_FORMAT, | ||||
|     'dd/mm' => self::DATE_FORMAT, | ||||
|     'mm/dd/yyyy' => self::DATE_FORMAT, | ||||
|     'dd/mm/yyyy' => self::DATE_FORMAT, | ||||
|     'yyyy/mm/dd' => self::DATE_FORMAT, | ||||
|     'mm/yyyy' => self::DATE_FORMAT, | ||||
| 
 | ||||
|     'hh AM/PM' => self::TIME_FORMAT, | ||||
|     'hh:mm AM/PM' => self::TIME_FORMAT, | ||||
|     'hh:mm:ss AM/PM' => self::TIME_FORMAT, | ||||
|     'hh' => self::TIME_FORMAT, | ||||
|     'hh:mm' => self::TIME_FORMAT, | ||||
|     'hh:mm:ss' => self::TIME_FORMAT, | ||||
|     '[hh]:mm:ss' => self::TIME_FORMAT, | ||||
|     'mm:ss' => self::TIME_FORMAT, | ||||
|   ]; | ||||
| 
 | ||||
|   /** @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->wsname = $params["wsname"] ?? static::WSNAME; | ||||
|   } | ||||
| 
 | ||||
|   protected $wsname; | ||||
| 
 | ||||
|   /** | ||||
|    * @param string|int|null $wsname | ||||
|    */ | ||||
|   function setWsname($wsname): self { | ||||
|     $this->wsname = $wsname; | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   function getIterator() { | ||||
|     $ss = IOFactory::load($this->input); | ||||
|     $ws = wsutils::get_ws($this->wsname, $ss); | ||||
| 
 | ||||
|     [$nbCols, $nbRows] = wsutils::compute_max_coords($ws); | ||||
|     $this->isrc = $this->idest = 0; | ||||
|     for ($nrow = 1; $nrow <= $nbRows; $nrow++) { | ||||
|       $row = []; | ||||
|       for ($ncol = 1; $ncol <= $nbCols; $ncol++) { | ||||
|         if ($ws->cellExistsByColumnAndRow($ncol, $nrow)) { | ||||
|           $cell = $ws->getCellByColumnAndRow($ncol, $nrow); | ||||
|           $col = $cell->getValue(); | ||||
|           if ($col instanceof RichText) { | ||||
|             $col = $col->getPlainText(); | ||||
|           } else { | ||||
|             $dataType = $cell->getDataType(); | ||||
|             if ($dataType == DataType::TYPE_NUMERIC || $dataType == DataType::TYPE_FORMULA) { | ||||
|               # si c'est un format date, le forcer à une valeur standard
 | ||||
|               $origFormatCode = $cell->getStyle()->getNumberFormat()->getFormatCode(); | ||||
|               if (strpbrk($origFormatCode, "ymdhs") !== false) { | ||||
|                 $formatCode = $origFormatCode; | ||||
|                 $formatCode = preg_replace('/y+/', "yyyy", $formatCode); | ||||
|                 $formatCode = preg_replace('/m+/', "mm", $formatCode); | ||||
|                 $formatCode = preg_replace('/d+/', "dd", $formatCode); | ||||
|                 $formatCode = preg_replace('/h+/', "hh", $formatCode); | ||||
|                 $formatCode = preg_replace('/s+/', "ss", $formatCode); | ||||
|                 $formatCode = preg_replace('/-+/', "/", $formatCode); | ||||
|                 $formatCode = preg_replace('/\\\\ /', " ", $formatCode); | ||||
|                 $formatCode = preg_replace('/;@$/', "", $formatCode); | ||||
|                 $formatCode = cl::get(self::FORMAT_MAPPINGS, $formatCode, $formatCode); | ||||
|                 if ($formatCode !== $origFormatCode) { | ||||
|                   $cell->getStyle()->getNumberFormat()->setFormatCode($formatCode); | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             $col = $cell->getFormattedValue(); | ||||
|             $this->verifixCol($col); | ||||
|           } | ||||
|         } else { | ||||
|           $col = null; | ||||
|         } | ||||
|         $row[] = $col; | ||||
|       } | ||||
|       if ($this->cookRow($row)) { | ||||
|         yield $row; | ||||
|         $this->idest++; | ||||
|       } | ||||
|       $this->isrc++; | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/phpss/ssutils.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/phpss/ssutils.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| <?php | ||||
| namespace nulib\ext\phpss; | ||||
| 
 | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| 
 | ||||
| class ssutils { | ||||
|   static function each_compute_max_coords(Spreadsheet $ss): array { | ||||
|     $max_coords = []; | ||||
|     foreach ($ss->getAllSheets() as $ws) { | ||||
|       $max_coords[$ws->getTitle()] = wsutils::compute_max_coords($ws); | ||||
|     } | ||||
|     return $max_coords; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										80
									
								
								src/phpss/wsutils.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/phpss/wsutils.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| <?php | ||||
| namespace nulib\ext\phpss; | ||||
| 
 | ||||
| use nulib\ValueException; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\Coordinate; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; | ||||
| 
 | ||||
| class wsutils { | ||||
|   static function get_ws(?string $wsname, Spreadsheet $ss, bool $create=false): ?Worksheet { | ||||
|     if ($wsname == null) { | ||||
|       $ws = $ss->getActiveSheet(); | ||||
|     } elseif (is_numeric($wsname)) { | ||||
|       $sheetCount = $ss->getSheetCount(); | ||||
|       if ($wsname < 1 || $wsname > $sheetCount) { | ||||
|         throw ValueException::invalid_value($wsname, "sheet index"); | ||||
|       } | ||||
|       $ws = $ss->getSheet($wsname - 1); | ||||
|     } else { | ||||
|       $ws = $ss->getSheetByName($wsname); | ||||
|       if ($ws === null) { | ||||
|         if ($create) $ws = $ss->createSheet()->setTitle($wsname); | ||||
|         else throw ValueException::invalid_value($wsname, "sheet name"); | ||||
|       } | ||||
|     } | ||||
|     return $ws; | ||||
|   } | ||||
| 
 | ||||
|   static function get_highest_coords(Worksheet $ws): array { | ||||
|     $highestColumnA = $ws->getHighestColumn(); | ||||
|     $highestCol = Coordinate::columnIndexFromString($highestColumnA); | ||||
|     $highestRow = $ws->getHighestRow(); | ||||
|     return [$highestCol, $highestRow]; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @var int nombre de colonnes/lignes au bout desquels on arrête de chercher | ||||
|    * si on n'a trouvé que des cellules vides. | ||||
|    * | ||||
|    * c'est nécessaire à cause de certains fichiers provenant d'Excel que j'ai | ||||
|    * reçus qui ont jusqu'à 10000 colonne vides et/ou 1048576 lignes vides. un | ||||
|    * algorithme "bête" perd énormément de temps à chercher dans le vide, donnant | ||||
|    * l'impression que le processus a planté. | ||||
|    */ | ||||
|   const MAX_EMPTY_THRESHOLD = 150; | ||||
| 
 | ||||
|   static function compute_max_coords(Worksheet $ws): array { | ||||
|     [$highestCol, $highestRow] = self::get_highest_coords($ws); | ||||
| 
 | ||||
|     $maxCol = 1; | ||||
|     $maxRow = 1; | ||||
|     $maxEmptyRows = self::MAX_EMPTY_THRESHOLD; | ||||
|     for ($row = 1; $row <= $highestRow; $row++) { | ||||
|       $emptyRow = true; | ||||
|       $maxEmptyCols = self::MAX_EMPTY_THRESHOLD; | ||||
|       for ($col = 1; $col <= $highestCol; $col++) { | ||||
|         $value = null; | ||||
|         if ($ws->cellExistsByColumnAndRow($col, $row)) { | ||||
|           $value = $ws->getCellByColumnAndRow($col, $row)->getValue(); | ||||
|         } | ||||
|         if ($value === null) { | ||||
|           $maxEmptyCols--; | ||||
|           if ($maxEmptyCols == 0) break; | ||||
|         } else { | ||||
|           $maxEmptyCols = self::MAX_EMPTY_THRESHOLD; | ||||
|           if ($row > $maxRow) $maxRow = $row; | ||||
|           if ($col > $maxCol) $maxCol = $col; | ||||
|           $emptyRow = false; | ||||
|         } | ||||
|       } | ||||
|       if ($emptyRow) { | ||||
|         $maxEmptyRows--; | ||||
|         if ($maxEmptyRows == 0) break; | ||||
|       } else { | ||||
|         $maxEmptyRows = self::MAX_EMPTY_THRESHOLD; | ||||
|       } | ||||
|     } | ||||
|     return [$maxCol, $maxRow]; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										0
									
								
								tests/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user