modifs.mineures sans commentaires
This commit is contained in:
parent
907aba4590
commit
db79a94b1d
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
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\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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _sendFile(): int {
|
||||||
|
switch (path::ext($this->output)) {
|
||||||
|
case ".ods":
|
||||||
|
$writer = new Ods($this->ss);
|
||||||
|
break;
|
||||||
|
case ".xlsx":
|
||||||
|
default:
|
||||||
|
$writer = new Xlsx($this->ss);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$this->rewind();
|
||||||
|
$writer->save($this->getResource());
|
||||||
|
$this->rewind();
|
||||||
|
$this->sendHeaders();
|
||||||
|
return $this->fpassthru();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\ext\spreadsheet;
|
||||||
|
|
||||||
|
use nur\sery\cl;
|
||||||
|
use nur\sery\file\csv\AbstractReader;
|
||||||
|
use nur\sery\file\csv\TAbstractReader;
|
||||||
|
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->cook($row)) {
|
||||||
|
yield $row;
|
||||||
|
$this->idest++;
|
||||||
|
}
|
||||||
|
$this->isrc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
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\web\http;
|
||||||
|
use OpenSpout\Common\Entity\Style\Style;
|
||||||
|
use OpenSpout\Writer\Common\Creator\WriterEntityFactory;
|
||||||
|
use OpenSpout\Writer\WriterMultiSheetsAbstract;
|
||||||
|
use OpenSpout\Writer\XLSX\Entity\SheetView;
|
||||||
|
|
||||||
|
class SpoutBuilder 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);
|
||||||
|
switch (path::ext($this->output)) {
|
||||||
|
case ".ods":
|
||||||
|
$ss = WriterEntityFactory::createODSWriter();
|
||||||
|
break;
|
||||||
|
case ".xlsx":
|
||||||
|
default:
|
||||||
|
$ss = WriterEntityFactory::createXLSXWriter();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$ss->writeToStream($this->getResource());
|
||||||
|
$this->ss = $ss;
|
||||||
|
$this->firstSheet = true;
|
||||||
|
$this->setWsname($params["wsname"] ?? static::WSNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WriterMultiSheetsAbstract $ss;
|
||||||
|
|
||||||
|
const STYLE_ROW = 0, STYLE_HEADER = 1;
|
||||||
|
|
||||||
|
protected int $rowStyle;
|
||||||
|
|
||||||
|
protected bool $firstSheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|int|null $wsname
|
||||||
|
*/
|
||||||
|
function setWsname($wsname): self {
|
||||||
|
$ss = $this->ss;
|
||||||
|
$this->rowStyle = self::STYLE_ROW;
|
||||||
|
if ($this->firstSheet) {
|
||||||
|
$this->firstSheet = false;
|
||||||
|
$ws = $ss->getCurrentSheet();
|
||||||
|
} else {
|
||||||
|
$ws = $ss->addNewSheetAndMakeItCurrent();
|
||||||
|
}
|
||||||
|
if ($wsname !== null) $ws->setName($wsname);
|
||||||
|
$ws->setSheetView((new SheetView())
|
||||||
|
->setFreezeRow(2)
|
||||||
|
);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _write(array $row): void {
|
||||||
|
$row = WriterEntityFactory::createRowFromArray($row);
|
||||||
|
if ($this->rowStyle === self::STYLE_HEADER) {
|
||||||
|
$row->setStyle((new Style())
|
||||||
|
->setFontBold()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->ss->addRow($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _sendFile(): int {
|
||||||
|
$this->rewind();
|
||||||
|
$this->sendHeaders();
|
||||||
|
return $this->fpassthru();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\ext\spreadsheet;
|
||||||
|
|
||||||
|
use nur\sery\file\csv\AbstractReader;
|
||||||
|
use nur\sery\file\csv\TAbstractReader;
|
||||||
|
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->wsname = $params["wsname"] ?? static::WSNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $wsname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|int|null $wsname
|
||||||
|
*/
|
||||||
|
function setWsname($wsname): self {
|
||||||
|
$this->wsname = $wsname;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIterator() {
|
||||||
|
$ss = ReaderEntityFactory::createReaderFromFile($this->input);
|
||||||
|
try {
|
||||||
|
$found = false;
|
||||||
|
foreach ($ss->getSheetIterator() as $ws) {
|
||||||
|
if ($this->wsname === null || $this->wsname === $ws->getName()) {
|
||||||
|
$found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$found) return;
|
||||||
|
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,118 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
namespace nur\sery\ext\spreadsheet;
|
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\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 SsBuilder: construction d'une feuille de calcul, pour envoi à
|
* Class SsBuilder: construction d'une feuille de calcul, pour envoi à
|
||||||
* l'utilisateur
|
* l'utilisateur
|
||||||
*/
|
*/
|
||||||
class SsBuilder extends AbstractBuilder {
|
class SsBuilder extends SpoutBuilder {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _sendFile(): int {
|
|
||||||
switch (path::ext($this->output)) {
|
|
||||||
case ".ods":
|
|
||||||
$writer = new Ods($this->ss);
|
|
||||||
break;
|
|
||||||
case ".xlsx":
|
|
||||||
default:
|
|
||||||
$writer = new Xlsx($this->ss);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$this->rewind();
|
|
||||||
$writer->save($this->getResource());
|
|
||||||
$this->rewind();
|
|
||||||
$this->sendHeaders();
|
|
||||||
return $this->fpassthru();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,119 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
namespace nur\sery\ext\spreadsheet;
|
namespace nur\sery\ext\spreadsheet;
|
||||||
|
|
||||||
use nur\sery\cl;
|
|
||||||
use nur\sery\file\csv\AbstractReader;
|
|
||||||
use nur\sery\file\csv\TAbstractReader;
|
use nur\sery\file\csv\TAbstractReader;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
|
||||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
|
||||||
|
|
||||||
class SsReader extends AbstractReader {
|
class SsReader extends SpoutReader {
|
||||||
use TAbstractReader;
|
use TAbstractReader;
|
||||||
|
|
||||||
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->cook($row)) {
|
|
||||||
yield $row;
|
|
||||||
$this->idest++;
|
|
||||||
}
|
|
||||||
$this->isrc++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue