nur-sery/src/ext/spreadsheet/SpoutReader.php

122 lines
3.5 KiB
PHP

<?php
namespace nur\sery\ext\spreadsheet;
use nur\sery\cl;
use nur\sery\file\csv\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->cook($row)) {
yield $row;
$this->idest++;
}
$this->isrc++;
}
}
}
} finally {
$ss->close();
}
}
}