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

View File

@ -11,9 +11,12 @@ class SpoutReader extends AbstractReader {
function __construct($input, ?array $params=null) {
parent::__construct($input, $params);
$this->ssType = $params["ss_type"] ?? null;
$this->wsname = $params["wsname"] ?? static::WSNAME;
}
protected ?string $ssType;
protected $wsname;
/**
@ -25,7 +28,18 @@ class SpoutReader extends AbstractReader {
}
function getIterator() {
$ss = ReaderEntityFactory::createReaderFromFile($this->input);
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 {
$found = false;
foreach ($ss->getSheetIterator() as $ws) {

View File

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

View File

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