modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2024-06-14 07:53:06 +04:00
parent db79a94b1d
commit 0e7c33f22d
4 changed files with 154 additions and 25 deletions

View File

@ -4,8 +4,12 @@ namespace nur\sery\ext\spreadsheet;
use nur\sery\file\csv\AbstractBuilder; use nur\sery\file\csv\AbstractBuilder;
use nur\sery\file\csv\TAbstractBuilder; use nur\sery\file\csv\TAbstractBuilder;
use nur\sery\os\path; use nur\sery\os\path;
use nur\sery\php\time\Date;
use nur\sery\php\time\DateTime;
use nur\sery\web\http; use nur\sery\web\http;
use OpenSpout\Common\Entity\Cell;
use OpenSpout\Common\Entity\Style\Style; use OpenSpout\Common\Entity\Style\Style;
use OpenSpout\Common\Helper\CellTypeHelper;
use OpenSpout\Writer\Common\Creator\WriterEntityFactory; use OpenSpout\Writer\Common\Creator\WriterEntityFactory;
use OpenSpout\Writer\WriterMultiSheetsAbstract; use OpenSpout\Writer\WriterMultiSheetsAbstract;
use OpenSpout\Writer\XLSX\Entity\SheetView; use OpenSpout\Writer\XLSX\Entity\SheetView;
@ -13,28 +17,51 @@ use OpenSpout\Writer\XLSX\Entity\SheetView;
class SpoutBuilder extends AbstractBuilder { class SpoutBuilder extends AbstractBuilder {
use TAbstractBuilder; use TAbstractBuilder;
const DATE_FORMAT = "mm/dd/yyyy";
const DATETIME_FORMAT = "mm/dd/yyyy hh:mm:ss";
/** @var string|int|null nom de la feuille dans laquelle écrire */ /** @var string|int|null nom de la feuille dans laquelle écrire */
const WSNAME = null; const WSNAME = null;
function __construct(?string $output, ?array $params=null) { function __construct(?string $output, ?array $params=null) {
parent::__construct($output, $params); parent::__construct($output, $params);
$ssType = $params["ss_type"] ?? null;
if ($ssType === null) {
switch (path::ext($this->output)) { switch (path::ext($this->output)) {
case ".ods": case ".ods":
$ss = WriterEntityFactory::createODSWriter(); $ssType = "ods";
break; break;
case ".xlsx": case ".xlsx":
default:
$ssType = "xlsx";
break;
}
}
switch ($ssType) {
case "ods":
$ss = WriterEntityFactory::createODSWriter();
break;
case "xlsx":
default: default:
$ss = WriterEntityFactory::createXLSXWriter(); $ss = WriterEntityFactory::createXLSXWriter();
break; break;
} }
$ss->setDefaultColumnWidth(10.5);
$ss->writeToStream($this->getResource()); $ss->writeToStream($this->getResource());
$this->ss = $ss; $this->ss = $ss;
$this->parseNumeric = boolval($params["parse_numeric"] ?? false);
$this->parseDate = boolval($params["parse_date"] ?? true);
$this->firstSheet = true; $this->firstSheet = true;
$this->setWsname($params["wsname"] ?? static::WSNAME); $this->setWsname($params["wsname"] ?? static::WSNAME);
} }
protected WriterMultiSheetsAbstract $ss; protected WriterMultiSheetsAbstract $ss;
protected bool $parseNumeric;
protected bool $parseDate;
const STYLE_ROW = 0, STYLE_HEADER = 1; const STYLE_ROW = 0, STYLE_HEADER = 1;
protected int $rowStyle; protected int $rowStyle;
@ -60,14 +87,53 @@ class SpoutBuilder extends AbstractBuilder {
return $this; return $this;
} }
function _write(array $row): void { protected function isNumeric($value): bool {
$row = WriterEntityFactory::createRowFromArray($row); if ($this->parseNumeric && is_numeric($value)) return true;
if ($this->rowStyle === self::STYLE_HEADER) { if (!is_string($value) && is_numeric($value)) return true;
$row->setStyle((new Style()) return false;
->setFontBold()
);
} }
$this->ss->addRow($row);
protected function isDate(&$value, &$style): bool {
if (CellTypeHelper::isDateTimeOrDateInterval($value)) {
$style = (new Style())->setFormat(self::DATE_FORMAT);
return true;
}
if (!is_string($value)) return false;
if (DateTime::isa_datetime($value, true)) {
$value = new DateTime($value);
$style = (new Style())->setFormat(self::DATETIME_FORMAT);
return true;
}
if (DateTime::isa_date($value, true)) {
$value = new Date($value);
$style = (new Style())->setFormat(self::DATE_FORMAT);
return true;
}
return false;
}
function _write(array $row): void {
$cells = [];
$rowStyle = null;
foreach ($row as $col) {
$style = null;
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 = (new Style())->setFontBold();
}
$this->ss->addRow(WriterEntityFactory::createRow($cells, $rowStyle));
} }
function writeHeaders(?array $headers=null): void { function writeHeaders(?array $headers=null): void {
@ -90,6 +156,7 @@ class SpoutBuilder extends AbstractBuilder {
} }
function _sendFile(): int { function _sendFile(): int {
$this->ss->close();
$this->rewind(); $this->rewind();
$this->sendHeaders(); $this->sendHeaders();
return $this->fpassthru(); return $this->fpassthru();

View File

@ -11,9 +11,12 @@ class SpoutReader extends AbstractReader {
function __construct($input, ?array $params=null) { function __construct($input, ?array $params=null) {
parent::__construct($input, $params); parent::__construct($input, $params);
$this->ssType = $params["ss_type"] ?? null;
$this->wsname = $params["wsname"] ?? static::WSNAME; $this->wsname = $params["wsname"] ?? static::WSNAME;
} }
protected ?string $ssType;
protected $wsname; protected $wsname;
/** /**
@ -25,7 +28,18 @@ class SpoutReader extends AbstractReader {
} }
function getIterator() { function getIterator() {
switch ($this->ssType) {
case "ods":
$ss = ReaderEntityFactory::createODSReader();
break;
case "xlsx":
$ss = ReaderEntityFactory::createXLSXReader();
break;
default:
$ss = ReaderEntityFactory::createReaderFromFile($this->input); $ss = ReaderEntityFactory::createReaderFromFile($this->input);
break;
}
$ss->open($this->input);
try { try {
$found = false; $found = false;
foreach ($ss->getSheetIterator() as $ws) { foreach ($ss->getSheetIterator() as $ws) {

View File

@ -1,30 +1,57 @@
<?php <?php
namespace nur\sery\file\csv; namespace nur\sery\file\csv;
use nur\sery\cl;
use nur\sery\file\web\Upload; use nur\sery\file\web\Upload;
use nur\sery\os\path; use nur\sery\os\path;
use nur\sery\ValueException; use nur\sery\ValueException;
trait TAbstractBuilder { trait TAbstractBuilder {
/** @param Upload|string|array $builder */ /** @param Upload|string|array $builder */
static function with($builder): IBuilder { static function with($builder, ?array $params=null): IBuilder {
if ($builder instanceof self) return $builder; if ($builder instanceof self) return $builder;
$class = null; $class = null;
if ($builder instanceof Upload) { if ($builder instanceof Upload) {
# faire un builder dans le même format que le fichier uploadé # faire un builder dans le même format que le fichier uploadé
if ($builder->isExt(".csv")) $class = CsvBuilder::class; if ($builder->isExt(".csv")) {
else $class = static::class; $class = CsvBuilder::class;
return new $class($builder->name); } else {
$class = static::class;
if ($builder->isExt(".ods")) {
$params["ss_type"] = "ods";
} else {
$params["ss_type"] = "xlsx";
} }
if (is_string($builder)) $builder = ["output" => $builder]; }
if (!is_array($builder)) { return new $class($builder->name, $params);
}
if (is_string($builder)) {
$params["output"] = $builder;
} elseif (is_array($builder)) {
$params = cl::merge($builder, $params);
} elseif ($builder !== null) {
throw ValueException::invalid_type($builder, self::class); throw ValueException::invalid_type($builder, self::class);
} }
$input = $builder["output"] ?? null;
if (is_string($input) && path::ext($input) === ".csv") { $output = $params["output"] ?? null;
$ssType = null;
if (is_string($output)) {
switch (path::ext($output)) {
case ".csv":
$class = CsvBuilder::class; $class = CsvBuilder::class;
break;
case ".ods":
$ssType = "ods";
break;
case ".xlsx":
default:
$ssType = "xlsx";
break;
} }
}
$params["ss_type"] = $ssType;
if ($class === null) $class = static::class; if ($class === null) $class = static::class;
return new $class(null, $builder); return new $class(null, $params);
} }
} }

View File

@ -12,8 +12,16 @@ trait TAbstractReader {
if ($reader instanceof self) return $reader; if ($reader instanceof self) return $reader;
$class = null; $class = null;
if ($reader instanceof Upload) { if ($reader instanceof Upload) {
if ($reader->isExt(".csv")) $class = CsvReader::class; if ($reader->isExt(".csv")) {
else $class = static::class; $class = CsvReader::class;
} else {
$class = static::class;
if ($reader->isExt(".ods")) {
$params["ss_type"] = "ods";
} else {
$params["ss_type"] = "xlsx";
}
}
return new $class($reader->tmpName, $params); return new $class($reader->tmpName, $params);
} }
@ -26,9 +34,22 @@ trait TAbstractReader {
} }
$input = $params["input"] ?? null; $input = $params["input"] ?? null;
if (is_string($input) && path::ext($input) === ".csv") { $ssType = null;
if (is_string($input)) {
switch (path::ext($input)) {
case ".csv":
$class = CsvReader::class; $class = CsvReader::class;
break;
case ".ods":
$ssType = "ods";
break;
case ".xlsx":
default:
$ssType = "xlsx";
break;
} }
}
$params["ss_type"] = $ssType;
if ($class === null) $class = static::class; if ($class === null) $class = static::class;
return new $class(null, $params); return new $class(null, $params);
} }