modifs.mineures sans commentaires
This commit is contained in:
parent
db79a94b1d
commit
0e7c33f22d
|
@ -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);
|
||||||
switch (path::ext($this->output)) {
|
$ssType = $params["ss_type"] ?? null;
|
||||||
case ".ods":
|
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();
|
$ss = WriterEntityFactory::createODSWriter();
|
||||||
break;
|
break;
|
||||||
case ".xlsx":
|
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()
|
}
|
||||||
);
|
|
||||||
|
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 {
|
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();
|
||||||
|
|
|
@ -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() {
|
||||||
$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 {
|
try {
|
||||||
$found = false;
|
$found = false;
|
||||||
foreach ($ss->getSheetIterator() as $ws) {
|
foreach ($ss->getSheetIterator() as $ws) {
|
||||||
|
|
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
throw ValueException::invalid_type($builder, self::class);
|
||||||
}
|
}
|
||||||
$input = $builder["output"] ?? null;
|
|
||||||
if (is_string($input) && path::ext($input) === ".csv") {
|
$output = $params["output"] ?? null;
|
||||||
$class = CsvBuilder::class;
|
$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;
|
if ($class === null) $class = static::class;
|
||||||
return new $class(null, $builder);
|
return new $class(null, $params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
$class = CsvReader::class;
|
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;
|
if ($class === null) $class = static::class;
|
||||||
return new $class(null, $params);
|
return new $class(null, $params);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue