commitall
This commit is contained in:
148
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/BaseWriter.php
vendored
Normal file
148
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/BaseWriter.php
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
abstract class BaseWriter implements IWriter
|
||||
{
|
||||
/**
|
||||
* Write charts that are defined in the workbook?
|
||||
* Identifies whether the Writer should write definitions for any charts that exist in the PhpSpreadsheet object.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $includeCharts = false;
|
||||
|
||||
/**
|
||||
* Pre-calculate formulas
|
||||
* Forces PhpSpreadsheet to recalculate all formulae in a workbook when saving, so that the pre-calculated values are
|
||||
* immediately available to MS Excel or other office spreadsheet viewer when opening the file.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $preCalculateFormulas = true;
|
||||
|
||||
/**
|
||||
* Use disk caching where possible?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $useDiskCaching = false;
|
||||
|
||||
/**
|
||||
* Disk caching directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $diskCachingDirectory = './';
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
protected $fileHandle;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $shouldCloseFile;
|
||||
|
||||
public function getIncludeCharts()
|
||||
{
|
||||
return $this->includeCharts;
|
||||
}
|
||||
|
||||
public function setIncludeCharts($includeCharts)
|
||||
{
|
||||
$this->includeCharts = (bool) $includeCharts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPreCalculateFormulas()
|
||||
{
|
||||
return $this->preCalculateFormulas;
|
||||
}
|
||||
|
||||
public function setPreCalculateFormulas($precalculateFormulas)
|
||||
{
|
||||
$this->preCalculateFormulas = (bool) $precalculateFormulas;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUseDiskCaching()
|
||||
{
|
||||
return $this->useDiskCaching;
|
||||
}
|
||||
|
||||
public function setUseDiskCaching($useDiskCache, $cacheDirectory = null)
|
||||
{
|
||||
$this->useDiskCaching = $useDiskCache;
|
||||
|
||||
if ($cacheDirectory !== null) {
|
||||
if (is_dir($cacheDirectory)) {
|
||||
$this->diskCachingDirectory = $cacheDirectory;
|
||||
} else {
|
||||
throw new Exception("Directory does not exist: $cacheDirectory");
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDiskCachingDirectory()
|
||||
{
|
||||
return $this->diskCachingDirectory;
|
||||
}
|
||||
|
||||
protected function processFlags(int $flags): void
|
||||
{
|
||||
if (((bool) ($flags & self::SAVE_WITH_CHARTS)) === true) {
|
||||
$this->setIncludeCharts(true);
|
||||
}
|
||||
if (((bool) ($flags & self::DISABLE_PRECALCULATE_FORMULAE)) === true) {
|
||||
$this->setPreCalculateFormulas(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open file handle.
|
||||
*
|
||||
* @param resource|string $filename
|
||||
*/
|
||||
public function openFileHandle($filename): void
|
||||
{
|
||||
if (is_resource($filename)) {
|
||||
$this->fileHandle = $filename;
|
||||
$this->shouldCloseFile = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$mode = 'wb';
|
||||
$scheme = parse_url($filename, PHP_URL_SCHEME);
|
||||
if ($scheme === 's3') {
|
||||
// @codeCoverageIgnoreStart
|
||||
$mode = 'w';
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$fileHandle = $filename ? fopen($filename, $mode) : false;
|
||||
if ($fileHandle === false) {
|
||||
throw new Exception('Could not open file "' . $filename . '" for writing.');
|
||||
}
|
||||
|
||||
$this->fileHandle = $fileHandle;
|
||||
$this->shouldCloseFile = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close file handle only if we opened it ourselves.
|
||||
*/
|
||||
protected function maybeCloseFileHandle(): void
|
||||
{
|
||||
if ($this->shouldCloseFile) {
|
||||
if (!fclose($this->fileHandle)) {
|
||||
throw new Exception('Could not close file after writing.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
326
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php
vendored
Normal file
326
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
class Csv extends BaseWriter
|
||||
{
|
||||
/**
|
||||
* PhpSpreadsheet object.
|
||||
*
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
/**
|
||||
* Delimiter.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $delimiter = ',';
|
||||
|
||||
/**
|
||||
* Enclosure.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $enclosure = '"';
|
||||
|
||||
/**
|
||||
* Line ending.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $lineEnding = PHP_EOL;
|
||||
|
||||
/**
|
||||
* Sheet index to write.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $sheetIndex = 0;
|
||||
|
||||
/**
|
||||
* Whether to write a UTF8 BOM.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $useBOM = false;
|
||||
|
||||
/**
|
||||
* Whether to write a Separator line as the first line of the file
|
||||
* sep=x.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $includeSeparatorLine = false;
|
||||
|
||||
/**
|
||||
* Whether to write a fully Excel compatible CSV file.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $excelCompatibility = false;
|
||||
|
||||
/**
|
||||
* Output encoding.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $outputEncoding = '';
|
||||
|
||||
/**
|
||||
* Create a new CSV.
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param resource|string $filename
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
$this->processFlags($flags);
|
||||
|
||||
// Fetch sheet
|
||||
$sheet = $this->spreadsheet->getSheet($this->sheetIndex);
|
||||
|
||||
$saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
|
||||
$saveArrayReturnType = Calculation::getArrayReturnType();
|
||||
Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE);
|
||||
|
||||
// Open file
|
||||
$this->openFileHandle($filename);
|
||||
|
||||
if ($this->excelCompatibility) {
|
||||
$this->setUseBOM(true); // Enforce UTF-8 BOM Header
|
||||
$this->setIncludeSeparatorLine(true); // Set separator line
|
||||
$this->setEnclosure('"'); // Set enclosure to "
|
||||
$this->setDelimiter(';'); // Set delimiter to a semi-colon
|
||||
$this->setLineEnding("\r\n");
|
||||
}
|
||||
|
||||
if ($this->useBOM) {
|
||||
// Write the UTF-8 BOM code if required
|
||||
fwrite($this->fileHandle, "\xEF\xBB\xBF");
|
||||
}
|
||||
|
||||
if ($this->includeSeparatorLine) {
|
||||
// Write the separator line if required
|
||||
fwrite($this->fileHandle, 'sep=' . $this->getDelimiter() . $this->lineEnding);
|
||||
}
|
||||
|
||||
// Identify the range that we need to extract from the worksheet
|
||||
$maxCol = $sheet->getHighestDataColumn();
|
||||
$maxRow = $sheet->getHighestDataRow();
|
||||
|
||||
// Write rows to file
|
||||
for ($row = 1; $row <= $maxRow; ++$row) {
|
||||
// Convert the row to an array...
|
||||
$cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas);
|
||||
// ... and write to the file
|
||||
$this->writeLine($this->fileHandle, $cellsArray[0]);
|
||||
}
|
||||
|
||||
$this->maybeCloseFileHandle();
|
||||
Calculation::setArrayReturnType($saveArrayReturnType);
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
}
|
||||
|
||||
public function getDelimiter(): string
|
||||
{
|
||||
return $this->delimiter;
|
||||
}
|
||||
|
||||
public function setDelimiter(string $delimiter): self
|
||||
{
|
||||
$this->delimiter = $delimiter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEnclosure(): string
|
||||
{
|
||||
return $this->enclosure;
|
||||
}
|
||||
|
||||
public function setEnclosure(string $enclosure = '"'): self
|
||||
{
|
||||
$this->enclosure = $enclosure;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLineEnding(): string
|
||||
{
|
||||
return $this->lineEnding;
|
||||
}
|
||||
|
||||
public function setLineEnding(string $lineEnding): self
|
||||
{
|
||||
$this->lineEnding = $lineEnding;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether BOM should be used.
|
||||
*/
|
||||
public function getUseBOM(): bool
|
||||
{
|
||||
return $this->useBOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether BOM should be used, typically when non-ASCII characters are used.
|
||||
*/
|
||||
public function setUseBOM(bool $useBOM): self
|
||||
{
|
||||
$this->useBOM = $useBOM;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether a separator line should be included.
|
||||
*/
|
||||
public function getIncludeSeparatorLine(): bool
|
||||
{
|
||||
return $this->includeSeparatorLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether a separator line should be included as the first line of the file.
|
||||
*/
|
||||
public function setIncludeSeparatorLine(bool $includeSeparatorLine): self
|
||||
{
|
||||
$this->includeSeparatorLine = $includeSeparatorLine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the file should be saved with full Excel Compatibility.
|
||||
*/
|
||||
public function getExcelCompatibility(): bool
|
||||
{
|
||||
return $this->excelCompatibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the file should be saved with full Excel Compatibility.
|
||||
*
|
||||
* @param bool $excelCompatibility Set the file to be written as a fully Excel compatible csv file
|
||||
* Note that this overrides other settings such as useBOM, enclosure and delimiter
|
||||
*/
|
||||
public function setExcelCompatibility(bool $excelCompatibility): self
|
||||
{
|
||||
$this->excelCompatibility = $excelCompatibility;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSheetIndex(): int
|
||||
{
|
||||
return $this->sheetIndex;
|
||||
}
|
||||
|
||||
public function setSheetIndex(int $sheetIndex): self
|
||||
{
|
||||
$this->sheetIndex = $sheetIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOutputEncoding(): string
|
||||
{
|
||||
return $this->outputEncoding;
|
||||
}
|
||||
|
||||
public function setOutputEncoding(string $outputEnconding): self
|
||||
{
|
||||
$this->outputEncoding = $outputEnconding;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @var bool */
|
||||
private $enclosureRequired = true;
|
||||
|
||||
public function setEnclosureRequired(bool $value): self
|
||||
{
|
||||
$this->enclosureRequired = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEnclosureRequired(): bool
|
||||
{
|
||||
return $this->enclosureRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert boolean to TRUE/FALSE; otherwise return element cast to string.
|
||||
*
|
||||
* @param mixed $element
|
||||
*/
|
||||
private static function elementToString($element): string
|
||||
{
|
||||
if (is_bool($element)) {
|
||||
return $element ? 'TRUE' : 'FALSE';
|
||||
}
|
||||
|
||||
return (string) $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write line to CSV file.
|
||||
*
|
||||
* @param resource $fileHandle PHP filehandle
|
||||
* @param array $values Array containing values in a row
|
||||
*/
|
||||
private function writeLine($fileHandle, array $values): void
|
||||
{
|
||||
// No leading delimiter
|
||||
$delimiter = '';
|
||||
|
||||
// Build the line
|
||||
$line = '';
|
||||
|
||||
foreach ($values as $element) {
|
||||
$element = self::elementToString($element);
|
||||
// Add delimiter
|
||||
$line .= $delimiter;
|
||||
$delimiter = $this->delimiter;
|
||||
// Escape enclosures
|
||||
$enclosure = $this->enclosure;
|
||||
if ($enclosure) {
|
||||
// If enclosure is not required, use enclosure only if
|
||||
// element contains newline, delimiter, or enclosure.
|
||||
if (!$this->enclosureRequired && strpbrk($element, "$delimiter$enclosure\n") === false) {
|
||||
$enclosure = '';
|
||||
} else {
|
||||
$element = str_replace($enclosure, $enclosure . $enclosure, $element);
|
||||
}
|
||||
}
|
||||
// Add enclosed string
|
||||
$line .= $enclosure . $element . $enclosure;
|
||||
}
|
||||
|
||||
// Add line ending
|
||||
$line .= $this->lineEnding;
|
||||
|
||||
// Write to file
|
||||
if ($this->outputEncoding != '') {
|
||||
$line = mb_convert_encoding($line, $this->outputEncoding);
|
||||
}
|
||||
fwrite($fileHandle, /** @scrutinizer ignore-type */ $line);
|
||||
}
|
||||
}
|
9
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Exception.php
vendored
Normal file
9
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Exception.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
|
||||
class Exception extends PhpSpreadsheetException
|
||||
{
|
||||
}
|
1860
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php
vendored
Normal file
1860
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
98
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/IWriter.php
vendored
Normal file
98
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/IWriter.php
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
interface IWriter
|
||||
{
|
||||
public const SAVE_WITH_CHARTS = 1;
|
||||
|
||||
public const DISABLE_PRECALCULATE_FORMULAE = 2;
|
||||
|
||||
/**
|
||||
* IWriter constructor.
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet The spreadsheet that we want to save using this Writer
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet);
|
||||
|
||||
/**
|
||||
* Write charts in workbook?
|
||||
* If this is true, then the Writer will write definitions for any charts that exist in the PhpSpreadsheet object.
|
||||
* If false (the default) it will ignore any charts defined in the PhpSpreadsheet object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIncludeCharts();
|
||||
|
||||
/**
|
||||
* Set write charts in workbook
|
||||
* Set to true, to advise the Writer to include any charts that exist in the PhpSpreadsheet object.
|
||||
* Set to false (the default) to ignore charts.
|
||||
*
|
||||
* @param bool $includeCharts
|
||||
*
|
||||
* @return IWriter
|
||||
*/
|
||||
public function setIncludeCharts($includeCharts);
|
||||
|
||||
/**
|
||||
* Get Pre-Calculate Formulas flag
|
||||
* If this is true (the default), then the writer will recalculate all formulae in a workbook when saving,
|
||||
* so that the pre-calculated values are immediately available to MS Excel or other office spreadsheet
|
||||
* viewer when opening the file
|
||||
* If false, then formulae are not calculated on save. This is faster for saving in PhpSpreadsheet, but slower
|
||||
* when opening the resulting file in MS Excel, because Excel has to recalculate the formulae itself.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getPreCalculateFormulas();
|
||||
|
||||
/**
|
||||
* Set Pre-Calculate Formulas
|
||||
* Set to true (the default) to advise the Writer to calculate all formulae on save
|
||||
* Set to false to prevent precalculation of formulae on save.
|
||||
*
|
||||
* @param bool $precalculateFormulas Pre-Calculate Formulas?
|
||||
*
|
||||
* @return IWriter
|
||||
*/
|
||||
public function setPreCalculateFormulas($precalculateFormulas);
|
||||
|
||||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param resource|string $filename Name of the file to save
|
||||
* @param int $flags Flags that can change the behaviour of the Writer:
|
||||
* self::SAVE_WITH_CHARTS Save any charts that are defined (if the Writer supports Charts)
|
||||
* self::DISABLE_PRECALCULATE_FORMULAE Don't Precalculate formulae before saving the file
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void;
|
||||
|
||||
/**
|
||||
* Get use disk caching where possible?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseDiskCaching();
|
||||
|
||||
/**
|
||||
* Set use disk caching where possible?
|
||||
*
|
||||
* @param bool $useDiskCache
|
||||
* @param string $cacheDirectory Disk caching directory
|
||||
*
|
||||
* @return IWriter
|
||||
*/
|
||||
public function setUseDiskCaching($useDiskCache, $cacheDirectory = null);
|
||||
|
||||
/**
|
||||
* Get disk caching directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDiskCachingDirectory();
|
||||
}
|
199
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php
vendored
Normal file
199
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Content;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Meta;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\MetaInf;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Settings;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Styles;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails;
|
||||
use ZipStream\Exception\OverflowException;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
class Ods extends BaseWriter
|
||||
{
|
||||
/**
|
||||
* Private PhpSpreadsheet.
|
||||
*
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
private $spreadSheet;
|
||||
|
||||
/**
|
||||
* @var Content
|
||||
*/
|
||||
private $writerPartContent;
|
||||
|
||||
/**
|
||||
* @var Meta
|
||||
*/
|
||||
private $writerPartMeta;
|
||||
|
||||
/**
|
||||
* @var MetaInf
|
||||
*/
|
||||
private $writerPartMetaInf;
|
||||
|
||||
/**
|
||||
* @var Mimetype
|
||||
*/
|
||||
private $writerPartMimetype;
|
||||
|
||||
/**
|
||||
* @var Settings
|
||||
*/
|
||||
private $writerPartSettings;
|
||||
|
||||
/**
|
||||
* @var Styles
|
||||
*/
|
||||
private $writerPartStyles;
|
||||
|
||||
/**
|
||||
* @var Thumbnails
|
||||
*/
|
||||
private $writerPartThumbnails;
|
||||
|
||||
/**
|
||||
* Create a new Ods.
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->setSpreadsheet($spreadsheet);
|
||||
|
||||
$this->writerPartContent = new Content($this);
|
||||
$this->writerPartMeta = new Meta($this);
|
||||
$this->writerPartMetaInf = new MetaInf($this);
|
||||
$this->writerPartMimetype = new Mimetype($this);
|
||||
$this->writerPartSettings = new Settings($this);
|
||||
$this->writerPartStyles = new Styles($this);
|
||||
$this->writerPartThumbnails = new Thumbnails($this);
|
||||
}
|
||||
|
||||
public function getWriterPartContent(): Content
|
||||
{
|
||||
return $this->writerPartContent;
|
||||
}
|
||||
|
||||
public function getWriterPartMeta(): Meta
|
||||
{
|
||||
return $this->writerPartMeta;
|
||||
}
|
||||
|
||||
public function getWriterPartMetaInf(): MetaInf
|
||||
{
|
||||
return $this->writerPartMetaInf;
|
||||
}
|
||||
|
||||
public function getWriterPartMimetype(): Mimetype
|
||||
{
|
||||
return $this->writerPartMimetype;
|
||||
}
|
||||
|
||||
public function getWriterPartSettings(): Settings
|
||||
{
|
||||
return $this->writerPartSettings;
|
||||
}
|
||||
|
||||
public function getWriterPartStyles(): Styles
|
||||
{
|
||||
return $this->writerPartStyles;
|
||||
}
|
||||
|
||||
public function getWriterPartThumbnails(): Thumbnails
|
||||
{
|
||||
return $this->writerPartThumbnails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param resource|string $filename
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
if (!$this->spreadSheet) {
|
||||
throw new WriterException('PhpSpreadsheet object unassigned.');
|
||||
}
|
||||
|
||||
$this->processFlags($flags);
|
||||
|
||||
// garbage collect
|
||||
$this->spreadSheet->garbageCollect();
|
||||
|
||||
$this->openFileHandle($filename);
|
||||
|
||||
$zip = $this->createZip();
|
||||
|
||||
$zip->addFile('META-INF/manifest.xml', $this->getWriterPartMetaInf()->write());
|
||||
$zip->addFile('Thumbnails/thumbnail.png', $this->getWriterPartthumbnails()->write());
|
||||
// Settings always need to be written before Content; Styles after Content
|
||||
$zip->addFile('settings.xml', $this->getWriterPartsettings()->write());
|
||||
$zip->addFile('content.xml', $this->getWriterPartcontent()->write());
|
||||
$zip->addFile('meta.xml', $this->getWriterPartmeta()->write());
|
||||
$zip->addFile('mimetype', $this->getWriterPartmimetype()->write());
|
||||
$zip->addFile('styles.xml', $this->getWriterPartstyles()->write());
|
||||
|
||||
// Close file
|
||||
try {
|
||||
$zip->finish();
|
||||
} catch (OverflowException $e) {
|
||||
throw new WriterException('Could not close resource.');
|
||||
}
|
||||
|
||||
$this->maybeCloseFileHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create zip object.
|
||||
*
|
||||
* @return ZipStream
|
||||
*/
|
||||
private function createZip()
|
||||
{
|
||||
// Try opening the ZIP file
|
||||
if (!is_resource($this->fileHandle)) {
|
||||
throw new WriterException('Could not open resource for writing.');
|
||||
}
|
||||
|
||||
// Create new ZIP stream
|
||||
$options = new Archive();
|
||||
$options->setEnableZip64(false);
|
||||
$options->setOutputStream($this->fileHandle);
|
||||
|
||||
return new ZipStream(null, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Spreadsheet object.
|
||||
*
|
||||
* @return Spreadsheet
|
||||
*/
|
||||
public function getSpreadsheet()
|
||||
{
|
||||
if ($this->spreadSheet !== null) {
|
||||
return $this->spreadSheet;
|
||||
}
|
||||
|
||||
throw new WriterException('No PhpSpreadsheet assigned.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Spreadsheet object.
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet PhpSpreadsheet object
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSpreadsheet(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadSheet = $spreadsheet;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
66
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/AutoFilters.php
vendored
Normal file
66
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/AutoFilters.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class AutoFilters
|
||||
{
|
||||
/**
|
||||
* @var XMLWriter
|
||||
*/
|
||||
private $objWriter;
|
||||
|
||||
/**
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
public function __construct(XMLWriter $objWriter, Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->objWriter = $objWriter;
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
}
|
||||
|
||||
/** @var mixed */
|
||||
private static $scrutinizerFalse = false;
|
||||
|
||||
public function write(): void
|
||||
{
|
||||
$wrapperWritten = self::$scrutinizerFalse;
|
||||
$sheetCount = $this->spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$worksheet = $this->spreadsheet->getSheet($i);
|
||||
$autofilter = $worksheet->getAutoFilter();
|
||||
if ($autofilter !== null && !empty($autofilter->getRange())) {
|
||||
if ($wrapperWritten === false) {
|
||||
$this->objWriter->startElement('table:database-ranges');
|
||||
$wrapperWritten = true;
|
||||
}
|
||||
$this->objWriter->startElement('table:database-range');
|
||||
$this->objWriter->writeAttribute('table:orientation', 'column');
|
||||
$this->objWriter->writeAttribute('table:display-filter-buttons', 'true');
|
||||
$this->objWriter->writeAttribute(
|
||||
'table:target-range-address',
|
||||
$this->formatRange($worksheet, $autofilter)
|
||||
);
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
if ($wrapperWritten === true) {
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
protected function formatRange(Worksheet $worksheet, Autofilter $autofilter): string
|
||||
{
|
||||
$title = $worksheet->getTitle();
|
||||
$range = $autofilter->getRange();
|
||||
|
||||
return "'{$title}'.{$range}";
|
||||
}
|
||||
}
|
30
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php
vendored
Normal file
30
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods\Cell;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
|
||||
/**
|
||||
* @author Alexander Pervakov <frost-nzcr4@jagmort.com>
|
||||
*/
|
||||
class Comment
|
||||
{
|
||||
public static function write(XMLWriter $objWriter, Cell $cell): void
|
||||
{
|
||||
$comments = $cell->getWorksheet()->getComments();
|
||||
if (!isset($comments[$cell->getCoordinate()])) {
|
||||
return;
|
||||
}
|
||||
$comment = $comments[$cell->getCoordinate()];
|
||||
|
||||
$objWriter->startElement('office:annotation');
|
||||
$objWriter->writeAttribute('svg:width', $comment->getWidth());
|
||||
$objWriter->writeAttribute('svg:height', $comment->getHeight());
|
||||
$objWriter->writeAttribute('svg:x', $comment->getMarginLeft());
|
||||
$objWriter->writeAttribute('svg:y', $comment->getMarginTop());
|
||||
$objWriter->writeElement('dc:creator', $comment->getAuthor());
|
||||
$objWriter->writeElement('text:p', $comment->getText()->getPlainText());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
262
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Style.php
vendored
Normal file
262
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Style.php
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods\Cell;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Helper\Dimension;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style as CellStyle;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\ColumnDimension;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class Style
|
||||
{
|
||||
public const CELL_STYLE_PREFIX = 'ce';
|
||||
public const COLUMN_STYLE_PREFIX = 'co';
|
||||
public const ROW_STYLE_PREFIX = 'ro';
|
||||
public const TABLE_STYLE_PREFIX = 'ta';
|
||||
|
||||
private $writer;
|
||||
|
||||
public function __construct(XMLWriter $writer)
|
||||
{
|
||||
$this->writer = $writer;
|
||||
}
|
||||
|
||||
private function mapHorizontalAlignment(string $horizontalAlignment): string
|
||||
{
|
||||
switch ($horizontalAlignment) {
|
||||
case Alignment::HORIZONTAL_CENTER:
|
||||
case Alignment::HORIZONTAL_CENTER_CONTINUOUS:
|
||||
case Alignment::HORIZONTAL_DISTRIBUTED:
|
||||
return 'center';
|
||||
case Alignment::HORIZONTAL_RIGHT:
|
||||
return 'end';
|
||||
case Alignment::HORIZONTAL_FILL:
|
||||
case Alignment::HORIZONTAL_JUSTIFY:
|
||||
return 'justify';
|
||||
}
|
||||
|
||||
return 'start';
|
||||
}
|
||||
|
||||
private function mapVerticalAlignment(string $verticalAlignment): string
|
||||
{
|
||||
switch ($verticalAlignment) {
|
||||
case Alignment::VERTICAL_TOP:
|
||||
return 'top';
|
||||
case Alignment::VERTICAL_CENTER:
|
||||
return 'middle';
|
||||
case Alignment::VERTICAL_DISTRIBUTED:
|
||||
case Alignment::VERTICAL_JUSTIFY:
|
||||
return 'automatic';
|
||||
}
|
||||
|
||||
return 'bottom';
|
||||
}
|
||||
|
||||
private function writeFillStyle(Fill $fill): void
|
||||
{
|
||||
switch ($fill->getFillType()) {
|
||||
case Fill::FILL_SOLID:
|
||||
$this->writer->writeAttribute('fo:background-color', sprintf(
|
||||
'#%s',
|
||||
strtolower($fill->getStartColor()->getRGB())
|
||||
));
|
||||
|
||||
break;
|
||||
case Fill::FILL_GRADIENT_LINEAR:
|
||||
case Fill::FILL_GRADIENT_PATH:
|
||||
/// TODO :: To be implemented
|
||||
break;
|
||||
case Fill::FILL_NONE:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private function writeCellProperties(CellStyle $style): void
|
||||
{
|
||||
// Align
|
||||
$hAlign = $style->getAlignment()->getHorizontal();
|
||||
$vAlign = $style->getAlignment()->getVertical();
|
||||
$wrap = $style->getAlignment()->getWrapText();
|
||||
|
||||
$this->writer->startElement('style:table-cell-properties');
|
||||
if (!empty($vAlign) || $wrap) {
|
||||
if (!empty($vAlign)) {
|
||||
$vAlign = $this->mapVerticalAlignment($vAlign);
|
||||
$this->writer->writeAttribute('style:vertical-align', $vAlign);
|
||||
}
|
||||
if ($wrap) {
|
||||
$this->writer->writeAttribute('fo:wrap-option', 'wrap');
|
||||
}
|
||||
}
|
||||
$this->writer->writeAttribute('style:rotation-align', 'none');
|
||||
|
||||
// Fill
|
||||
if ($fill = $style->getFill()) {
|
||||
$this->writeFillStyle($fill);
|
||||
}
|
||||
|
||||
$this->writer->endElement();
|
||||
|
||||
if (!empty($hAlign)) {
|
||||
$hAlign = $this->mapHorizontalAlignment($hAlign);
|
||||
$this->writer->startElement('style:paragraph-properties');
|
||||
$this->writer->writeAttribute('fo:text-align', $hAlign);
|
||||
$this->writer->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
protected function mapUnderlineStyle(Font $font): string
|
||||
{
|
||||
switch ($font->getUnderline()) {
|
||||
case Font::UNDERLINE_DOUBLE:
|
||||
case Font::UNDERLINE_DOUBLEACCOUNTING:
|
||||
return'double';
|
||||
case Font::UNDERLINE_SINGLE:
|
||||
case Font::UNDERLINE_SINGLEACCOUNTING:
|
||||
return'single';
|
||||
}
|
||||
|
||||
return 'none';
|
||||
}
|
||||
|
||||
protected function writeTextProperties(CellStyle $style): void
|
||||
{
|
||||
// Font
|
||||
$this->writer->startElement('style:text-properties');
|
||||
|
||||
$font = $style->getFont();
|
||||
|
||||
if ($font->getBold()) {
|
||||
$this->writer->writeAttribute('fo:font-weight', 'bold');
|
||||
$this->writer->writeAttribute('style:font-weight-complex', 'bold');
|
||||
$this->writer->writeAttribute('style:font-weight-asian', 'bold');
|
||||
}
|
||||
|
||||
if ($font->getItalic()) {
|
||||
$this->writer->writeAttribute('fo:font-style', 'italic');
|
||||
}
|
||||
|
||||
if ($color = $font->getColor()) {
|
||||
$this->writer->writeAttribute('fo:color', sprintf('#%s', $color->getRGB()));
|
||||
}
|
||||
|
||||
if ($family = $font->getName()) {
|
||||
$this->writer->writeAttribute('fo:font-family', $family);
|
||||
}
|
||||
|
||||
if ($size = $font->getSize()) {
|
||||
$this->writer->writeAttribute('fo:font-size', sprintf('%.1Fpt', $size));
|
||||
}
|
||||
|
||||
if ($font->getUnderline() && $font->getUnderline() !== Font::UNDERLINE_NONE) {
|
||||
$this->writer->writeAttribute('style:text-underline-style', 'solid');
|
||||
$this->writer->writeAttribute('style:text-underline-width', 'auto');
|
||||
$this->writer->writeAttribute('style:text-underline-color', 'font-color');
|
||||
|
||||
$underline = $this->mapUnderlineStyle($font);
|
||||
$this->writer->writeAttribute('style:text-underline-type', $underline);
|
||||
}
|
||||
|
||||
$this->writer->endElement(); // Close style:text-properties
|
||||
}
|
||||
|
||||
protected function writeColumnProperties(ColumnDimension $columnDimension): void
|
||||
{
|
||||
$this->writer->startElement('style:table-column-properties');
|
||||
$this->writer->writeAttribute(
|
||||
'style:column-width',
|
||||
round($columnDimension->getWidth(Dimension::UOM_CENTIMETERS), 3) . 'cm'
|
||||
);
|
||||
$this->writer->writeAttribute('fo:break-before', 'auto');
|
||||
|
||||
// End
|
||||
$this->writer->endElement(); // Close style:table-column-properties
|
||||
}
|
||||
|
||||
public function writeColumnStyles(ColumnDimension $columnDimension, int $sheetId): void
|
||||
{
|
||||
$this->writer->startElement('style:style');
|
||||
$this->writer->writeAttribute('style:family', 'table-column');
|
||||
$this->writer->writeAttribute(
|
||||
'style:name',
|
||||
sprintf('%s_%d_%d', self::COLUMN_STYLE_PREFIX, $sheetId, $columnDimension->getColumnNumeric())
|
||||
);
|
||||
|
||||
$this->writeColumnProperties($columnDimension);
|
||||
|
||||
// End
|
||||
$this->writer->endElement(); // Close style:style
|
||||
}
|
||||
|
||||
protected function writeRowProperties(RowDimension $rowDimension): void
|
||||
{
|
||||
$this->writer->startElement('style:table-row-properties');
|
||||
$this->writer->writeAttribute(
|
||||
'style:row-height',
|
||||
round($rowDimension->getRowHeight(Dimension::UOM_CENTIMETERS), 3) . 'cm'
|
||||
);
|
||||
$this->writer->writeAttribute('style:use-optimal-row-height', 'false');
|
||||
$this->writer->writeAttribute('fo:break-before', 'auto');
|
||||
|
||||
// End
|
||||
$this->writer->endElement(); // Close style:table-row-properties
|
||||
}
|
||||
|
||||
public function writeRowStyles(RowDimension $rowDimension, int $sheetId): void
|
||||
{
|
||||
$this->writer->startElement('style:style');
|
||||
$this->writer->writeAttribute('style:family', 'table-row');
|
||||
$this->writer->writeAttribute(
|
||||
'style:name',
|
||||
sprintf('%s_%d_%d', self::ROW_STYLE_PREFIX, $sheetId, $rowDimension->getRowIndex())
|
||||
);
|
||||
|
||||
$this->writeRowProperties($rowDimension);
|
||||
|
||||
// End
|
||||
$this->writer->endElement(); // Close style:style
|
||||
}
|
||||
|
||||
public function writeTableStyle(Worksheet $worksheet, int $sheetId): void
|
||||
{
|
||||
$this->writer->startElement('style:style');
|
||||
$this->writer->writeAttribute('style:family', 'table');
|
||||
$this->writer->writeAttribute(
|
||||
'style:name',
|
||||
sprintf('%s%d', self::TABLE_STYLE_PREFIX, $sheetId)
|
||||
);
|
||||
|
||||
$this->writer->startElement('style:table-properties');
|
||||
|
||||
$this->writer->writeAttribute(
|
||||
'table:display',
|
||||
$worksheet->getSheetState() === Worksheet::SHEETSTATE_VISIBLE ? 'true' : 'false'
|
||||
);
|
||||
|
||||
$this->writer->endElement(); // Close style:table-properties
|
||||
$this->writer->endElement(); // Close style:style
|
||||
}
|
||||
|
||||
public function write(CellStyle $style): void
|
||||
{
|
||||
$this->writer->startElement('style:style');
|
||||
$this->writer->writeAttribute('style:name', self::CELL_STYLE_PREFIX . $style->getIndex());
|
||||
$this->writer->writeAttribute('style:family', 'table-cell');
|
||||
$this->writer->writeAttribute('style:parent-style-name', 'Default');
|
||||
|
||||
// Alignment, fill colour, etc
|
||||
$this->writeCellProperties($style);
|
||||
|
||||
// style:text-properties
|
||||
$this->writeTextProperties($style);
|
||||
|
||||
// End
|
||||
$this->writer->endElement(); // Close style:style
|
||||
}
|
||||
}
|
335
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php
vendored
Normal file
335
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Row;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\RowCellIterator;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Cell\Comment;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Cell\Style;
|
||||
|
||||
/**
|
||||
* @author Alexander Pervakov <frost-nzcr4@jagmort.com>
|
||||
*/
|
||||
class Content extends WriterPart
|
||||
{
|
||||
const NUMBER_COLS_REPEATED_MAX = 1024;
|
||||
const NUMBER_ROWS_REPEATED_MAX = 1048576;
|
||||
|
||||
private $formulaConvertor;
|
||||
|
||||
/**
|
||||
* Set parent Ods writer.
|
||||
*/
|
||||
public function __construct(Ods $writer)
|
||||
{
|
||||
parent::__construct($writer);
|
||||
|
||||
$this->formulaConvertor = new Formula($this->getParentWriter()->getSpreadsheet()->getDefinedNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write content.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8');
|
||||
|
||||
// Content
|
||||
$objWriter->startElement('office:document-content');
|
||||
$objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
|
||||
$objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
|
||||
$objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
|
||||
$objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
|
||||
$objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
|
||||
$objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
|
||||
$objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
$objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
|
||||
$objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
|
||||
$objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
|
||||
$objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0');
|
||||
$objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
|
||||
$objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0');
|
||||
$objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0');
|
||||
$objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML');
|
||||
$objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0');
|
||||
$objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0');
|
||||
$objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
|
||||
$objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer');
|
||||
$objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc');
|
||||
$objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events');
|
||||
$objWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms');
|
||||
$objWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
|
||||
$objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
||||
$objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report');
|
||||
$objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2');
|
||||
$objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
|
||||
$objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
|
||||
$objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table');
|
||||
$objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0');
|
||||
$objWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0');
|
||||
$objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/');
|
||||
$objWriter->writeAttribute('office:version', '1.2');
|
||||
|
||||
$objWriter->writeElement('office:scripts');
|
||||
$objWriter->writeElement('office:font-face-decls');
|
||||
|
||||
// Styles XF
|
||||
$objWriter->startElement('office:automatic-styles');
|
||||
$this->writeXfStyles($objWriter, $this->getParentWriter()->getSpreadsheet());
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('office:body');
|
||||
$objWriter->startElement('office:spreadsheet');
|
||||
$objWriter->writeElement('table:calculation-settings');
|
||||
|
||||
$this->writeSheets($objWriter);
|
||||
|
||||
(new AutoFilters($objWriter, $this->getParentWriter()->getSpreadsheet()))->write();
|
||||
// Defined names (ranges and formulae)
|
||||
(new NamedExpressions($objWriter, $this->getParentWriter()->getSpreadsheet(), $this->formulaConvertor))->write();
|
||||
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write sheets.
|
||||
*/
|
||||
private function writeSheets(XMLWriter $objWriter): void
|
||||
{
|
||||
$spreadsheet = $this->getParentWriter()->getSpreadsheet(); /** @var Spreadsheet $spreadsheet */
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($sheetIndex = 0; $sheetIndex < $sheetCount; ++$sheetIndex) {
|
||||
$objWriter->startElement('table:table');
|
||||
$objWriter->writeAttribute('table:name', $spreadsheet->getSheet($sheetIndex)->getTitle());
|
||||
$objWriter->writeAttribute('table:style-name', Style::TABLE_STYLE_PREFIX . (string) ($sheetIndex + 1));
|
||||
$objWriter->writeElement('office:forms');
|
||||
foreach ($spreadsheet->getSheet($sheetIndex)->getColumnDimensions() as $columnDimension) {
|
||||
$objWriter->startElement('table:table-column');
|
||||
$objWriter->writeAttribute(
|
||||
'table:style-name',
|
||||
sprintf('%s_%d_%d', Style::COLUMN_STYLE_PREFIX, $sheetIndex, $columnDimension->getColumnNumeric())
|
||||
);
|
||||
$objWriter->writeAttribute('table:default-cell-style-name', 'ce0');
|
||||
// $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$this->writeRows($objWriter, $spreadsheet->getSheet($sheetIndex), $sheetIndex);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write rows of the specified sheet.
|
||||
*/
|
||||
private function writeRows(XMLWriter $objWriter, Worksheet $sheet, int $sheetIndex): void
|
||||
{
|
||||
$numberRowsRepeated = self::NUMBER_ROWS_REPEATED_MAX;
|
||||
$span_row = 0;
|
||||
$rows = $sheet->getRowIterator();
|
||||
foreach ($rows as $row) {
|
||||
$cellIterator = $row->getCellIterator();
|
||||
--$numberRowsRepeated;
|
||||
if ($cellIterator->valid()) {
|
||||
$objWriter->startElement('table:table-row');
|
||||
if ($span_row) {
|
||||
if ($span_row > 1) {
|
||||
$objWriter->writeAttribute('table:number-rows-repeated', $span_row);
|
||||
}
|
||||
$objWriter->startElement('table:table-cell');
|
||||
$objWriter->writeAttribute('table:number-columns-repeated', (string) self::NUMBER_COLS_REPEATED_MAX);
|
||||
$objWriter->endElement();
|
||||
$span_row = 0;
|
||||
} else {
|
||||
if ($sheet->getRowDimension($row->getRowIndex())->getRowHeight() > 0) {
|
||||
$objWriter->writeAttribute(
|
||||
'table:style-name',
|
||||
sprintf('%s_%d_%d', Style::ROW_STYLE_PREFIX, $sheetIndex, $row->getRowIndex())
|
||||
);
|
||||
}
|
||||
$this->writeCells($objWriter, $cellIterator);
|
||||
}
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
++$span_row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write cells of the specified row.
|
||||
*/
|
||||
private function writeCells(XMLWriter $objWriter, RowCellIterator $cells): void
|
||||
{
|
||||
$numberColsRepeated = self::NUMBER_COLS_REPEATED_MAX;
|
||||
$prevColumn = -1;
|
||||
foreach ($cells as $cell) {
|
||||
/** @var \PhpOffice\PhpSpreadsheet\Cell\Cell $cell */
|
||||
$column = Coordinate::columnIndexFromString($cell->getColumn()) - 1;
|
||||
|
||||
$this->writeCellSpan($objWriter, $column, $prevColumn);
|
||||
$objWriter->startElement('table:table-cell');
|
||||
$this->writeCellMerge($objWriter, $cell);
|
||||
|
||||
// Style XF
|
||||
$style = $cell->getXfIndex();
|
||||
if ($style !== null) {
|
||||
$objWriter->writeAttribute('table:style-name', Style::CELL_STYLE_PREFIX . $style);
|
||||
}
|
||||
|
||||
switch ($cell->getDataType()) {
|
||||
case DataType::TYPE_BOOL:
|
||||
$objWriter->writeAttribute('office:value-type', 'boolean');
|
||||
$objWriter->writeAttribute('office:value', $cell->getValue());
|
||||
$objWriter->writeElement('text:p', $cell->getValue());
|
||||
|
||||
break;
|
||||
case DataType::TYPE_ERROR:
|
||||
$objWriter->writeAttribute('table:formula', 'of:=#NULL!');
|
||||
$objWriter->writeAttribute('office:value-type', 'string');
|
||||
$objWriter->writeAttribute('office:string-value', '');
|
||||
$objWriter->writeElement('text:p', '#NULL!');
|
||||
|
||||
break;
|
||||
case DataType::TYPE_FORMULA:
|
||||
$formulaValue = $cell->getValue();
|
||||
if ($this->getParentWriter()->getPreCalculateFormulas()) {
|
||||
try {
|
||||
$formulaValue = $cell->getCalculatedValue();
|
||||
} catch (Exception $e) {
|
||||
// don't do anything
|
||||
}
|
||||
}
|
||||
$objWriter->writeAttribute('table:formula', $this->formulaConvertor->convertFormula($cell->getValue()));
|
||||
if (is_numeric($formulaValue)) {
|
||||
$objWriter->writeAttribute('office:value-type', 'float');
|
||||
} else {
|
||||
$objWriter->writeAttribute('office:value-type', 'string');
|
||||
}
|
||||
$objWriter->writeAttribute('office:value', $formulaValue);
|
||||
$objWriter->writeElement('text:p', $formulaValue);
|
||||
|
||||
break;
|
||||
case DataType::TYPE_NUMERIC:
|
||||
$objWriter->writeAttribute('office:value-type', 'float');
|
||||
$objWriter->writeAttribute('office:value', $cell->getValue());
|
||||
$objWriter->writeElement('text:p', $cell->getValue());
|
||||
|
||||
break;
|
||||
case DataType::TYPE_INLINE:
|
||||
// break intentionally omitted
|
||||
case DataType::TYPE_STRING:
|
||||
$objWriter->writeAttribute('office:value-type', 'string');
|
||||
$objWriter->writeElement('text:p', $cell->getValue());
|
||||
|
||||
break;
|
||||
}
|
||||
Comment::write($objWriter, $cell);
|
||||
$objWriter->endElement();
|
||||
$prevColumn = $column;
|
||||
}
|
||||
|
||||
$numberColsRepeated = $numberColsRepeated - $prevColumn - 1;
|
||||
if ($numberColsRepeated > 0) {
|
||||
if ($numberColsRepeated > 1) {
|
||||
$objWriter->startElement('table:table-cell');
|
||||
$objWriter->writeAttribute('table:number-columns-repeated', $numberColsRepeated);
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
$objWriter->writeElement('table:table-cell');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write span.
|
||||
*
|
||||
* @param int $curColumn
|
||||
* @param int $prevColumn
|
||||
*/
|
||||
private function writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn): void
|
||||
{
|
||||
$diff = $curColumn - $prevColumn - 1;
|
||||
if (1 === $diff) {
|
||||
$objWriter->writeElement('table:table-cell');
|
||||
} elseif ($diff > 1) {
|
||||
$objWriter->startElement('table:table-cell');
|
||||
$objWriter->writeAttribute('table:number-columns-repeated', $diff);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write XF cell styles.
|
||||
*/
|
||||
private function writeXfStyles(XMLWriter $writer, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
$styleWriter = new Style($writer);
|
||||
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$worksheet = $spreadsheet->getSheet($i);
|
||||
$styleWriter->writeTableStyle($worksheet, $i + 1);
|
||||
|
||||
$worksheet->calculateColumnWidths();
|
||||
foreach ($worksheet->getColumnDimensions() as $columnDimension) {
|
||||
if ($columnDimension->getWidth() !== -1.0) {
|
||||
$styleWriter->writeColumnStyles($columnDimension, $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$worksheet = $spreadsheet->getSheet($i);
|
||||
foreach ($worksheet->getRowDimensions() as $rowDimension) {
|
||||
if ($rowDimension->getRowHeight() > 0.0) {
|
||||
$styleWriter->writeRowStyles($rowDimension, $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($spreadsheet->getCellXfCollection() as $style) {
|
||||
$styleWriter->write($style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write attributes for merged cell.
|
||||
*/
|
||||
private function writeCellMerge(XMLWriter $objWriter, Cell $cell): void
|
||||
{
|
||||
if (!$cell->isMergeRangeValueCell()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mergeRange = Coordinate::splitRange($cell->getMergeRange());
|
||||
[$startCell, $endCell] = $mergeRange[0];
|
||||
$start = Coordinate::coordinateFromString($startCell);
|
||||
$end = Coordinate::coordinateFromString($endCell);
|
||||
$columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1;
|
||||
$rowSpan = ((int) $end[1]) - ((int) $start[1]) + 1;
|
||||
|
||||
$objWriter->writeAttribute('table:number-columns-spanned', (string) $columnSpan);
|
||||
$objWriter->writeAttribute('table:number-rows-spanned', (string) $rowSpan);
|
||||
}
|
||||
}
|
119
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Formula.php
vendored
Normal file
119
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Formula.php
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\DefinedName;
|
||||
|
||||
class Formula
|
||||
{
|
||||
private $definedNames = [];
|
||||
|
||||
/**
|
||||
* @param DefinedName[] $definedNames
|
||||
*/
|
||||
public function __construct(array $definedNames)
|
||||
{
|
||||
foreach ($definedNames as $definedName) {
|
||||
$this->definedNames[] = $definedName->getName();
|
||||
}
|
||||
}
|
||||
|
||||
public function convertFormula(string $formula, string $worksheetName = ''): string
|
||||
{
|
||||
$formula = $this->convertCellReferences($formula, $worksheetName);
|
||||
$formula = $this->convertDefinedNames($formula);
|
||||
|
||||
if (substr($formula, 0, 1) !== '=') {
|
||||
$formula = '=' . $formula;
|
||||
}
|
||||
|
||||
return 'of:' . $formula;
|
||||
}
|
||||
|
||||
private function convertDefinedNames(string $formula): string
|
||||
{
|
||||
$splitCount = preg_match_all(
|
||||
'/' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '/mui',
|
||||
$formula,
|
||||
$splitRanges,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
$lengths = array_map('strlen', array_column($splitRanges[0], 0));
|
||||
$offsets = array_column($splitRanges[0], 1);
|
||||
$values = array_column($splitRanges[0], 0);
|
||||
|
||||
while ($splitCount > 0) {
|
||||
--$splitCount;
|
||||
$length = $lengths[$splitCount];
|
||||
$offset = $offsets[$splitCount];
|
||||
$value = $values[$splitCount];
|
||||
|
||||
if (in_array($value, $this->definedNames, true)) {
|
||||
$formula = substr($formula, 0, $offset) . '$$' . $value . substr($formula, $offset + $length);
|
||||
}
|
||||
}
|
||||
|
||||
return $formula;
|
||||
}
|
||||
|
||||
private function convertCellReferences(string $formula, string $worksheetName): string
|
||||
{
|
||||
$splitCount = preg_match_all(
|
||||
'/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/mui',
|
||||
$formula,
|
||||
$splitRanges,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
$lengths = array_map('strlen', array_column($splitRanges[0], 0));
|
||||
$offsets = array_column($splitRanges[0], 1);
|
||||
|
||||
$worksheets = $splitRanges[2];
|
||||
$columns = $splitRanges[6];
|
||||
$rows = $splitRanges[7];
|
||||
|
||||
// Replace any commas in the formula with semi-colons for Ods
|
||||
// If by chance there are commas in worksheet names, then they will be "fixed" again in the loop
|
||||
// because we've already extracted worksheet names with our preg_match_all()
|
||||
$formula = str_replace(',', ';', $formula);
|
||||
while ($splitCount > 0) {
|
||||
--$splitCount;
|
||||
$length = $lengths[$splitCount];
|
||||
$offset = $offsets[$splitCount];
|
||||
$worksheet = $worksheets[$splitCount][0];
|
||||
$column = $columns[$splitCount][0];
|
||||
$row = $rows[$splitCount][0];
|
||||
|
||||
$newRange = '';
|
||||
if (empty($worksheet)) {
|
||||
if (($offset === 0) || ($formula[$offset - 1] !== ':')) {
|
||||
// We need a worksheet
|
||||
$worksheet = $worksheetName;
|
||||
}
|
||||
} else {
|
||||
$worksheet = str_replace("''", "'", trim($worksheet, "'"));
|
||||
}
|
||||
if (!empty($worksheet)) {
|
||||
$newRange = "['" . str_replace("'", "''", $worksheet) . "'";
|
||||
} elseif (substr($formula, $offset - 1, 1) !== ':') {
|
||||
$newRange = '[';
|
||||
}
|
||||
$newRange .= '.';
|
||||
|
||||
if (!empty($column)) {
|
||||
$newRange .= $column;
|
||||
}
|
||||
if (!empty($row)) {
|
||||
$newRange .= $row;
|
||||
}
|
||||
// close the wrapping [] unless this is the first part of a range
|
||||
$newRange .= substr($formula, $offset + $length, 1) !== ':' ? ']' : '';
|
||||
|
||||
$formula = substr($formula, 0, $offset) . $newRange . substr($formula, $offset + $length);
|
||||
}
|
||||
|
||||
return $formula;
|
||||
}
|
||||
}
|
122
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Meta.php
vendored
Normal file
122
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Meta.php
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
class Meta extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write meta.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
$spreadsheet = $this->getParentWriter()->getSpreadsheet();
|
||||
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8');
|
||||
|
||||
// Meta
|
||||
$objWriter->startElement('office:document-meta');
|
||||
|
||||
$objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
|
||||
$objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
$objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
|
||||
$objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
|
||||
$objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
|
||||
$objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
|
||||
$objWriter->writeAttribute('office:version', '1.2');
|
||||
|
||||
$objWriter->startElement('office:meta');
|
||||
|
||||
$objWriter->writeElement('meta:initial-creator', $spreadsheet->getProperties()->getCreator());
|
||||
$objWriter->writeElement('dc:creator', $spreadsheet->getProperties()->getCreator());
|
||||
$created = $spreadsheet->getProperties()->getCreated();
|
||||
$date = Date::dateTimeFromTimestamp("$created");
|
||||
$date->setTimeZone(Date::getDefaultOrLocalTimeZone());
|
||||
$objWriter->writeElement('meta:creation-date', $date->format(DATE_W3C));
|
||||
$created = $spreadsheet->getProperties()->getModified();
|
||||
$date = Date::dateTimeFromTimestamp("$created");
|
||||
$date->setTimeZone(Date::getDefaultOrLocalTimeZone());
|
||||
$objWriter->writeElement('dc:date', $date->format(DATE_W3C));
|
||||
$objWriter->writeElement('dc:title', $spreadsheet->getProperties()->getTitle());
|
||||
$objWriter->writeElement('dc:description', $spreadsheet->getProperties()->getDescription());
|
||||
$objWriter->writeElement('dc:subject', $spreadsheet->getProperties()->getSubject());
|
||||
$objWriter->writeElement('meta:keyword', $spreadsheet->getProperties()->getKeywords());
|
||||
// Don't know if this changed over time, but the keywords are all
|
||||
// in a single declaration now.
|
||||
//$keywords = explode(' ', $spreadsheet->getProperties()->getKeywords());
|
||||
//foreach ($keywords as $keyword) {
|
||||
// $objWriter->writeElement('meta:keyword', $keyword);
|
||||
//}
|
||||
|
||||
//<meta:document-statistic meta:table-count="XXX" meta:cell-count="XXX" meta:object-count="XXX"/>
|
||||
$objWriter->startElement('meta:user-defined');
|
||||
$objWriter->writeAttribute('meta:name', 'Company');
|
||||
$objWriter->writeRaw($spreadsheet->getProperties()->getCompany());
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('meta:user-defined');
|
||||
$objWriter->writeAttribute('meta:name', 'category');
|
||||
$objWriter->writeRaw($spreadsheet->getProperties()->getCategory());
|
||||
$objWriter->endElement();
|
||||
|
||||
self::writeDocPropsCustom($objWriter, $spreadsheet);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
private static function writeDocPropsCustom(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
$customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
|
||||
foreach ($customPropertyList as $key => $customProperty) {
|
||||
$propertyValue = $spreadsheet->getProperties()->getCustomPropertyValue($customProperty);
|
||||
$propertyType = $spreadsheet->getProperties()->getCustomPropertyType($customProperty);
|
||||
|
||||
$objWriter->startElement('meta:user-defined');
|
||||
$objWriter->writeAttribute('meta:name', $customProperty);
|
||||
|
||||
switch ($propertyType) {
|
||||
case Properties::PROPERTY_TYPE_INTEGER:
|
||||
case Properties::PROPERTY_TYPE_FLOAT:
|
||||
$objWriter->writeAttribute('meta:value-type', 'float');
|
||||
$objWriter->writeRawData($propertyValue);
|
||||
|
||||
break;
|
||||
case Properties::PROPERTY_TYPE_BOOLEAN:
|
||||
$objWriter->writeAttribute('meta:value-type', 'boolean');
|
||||
$objWriter->writeRawData($propertyValue ? 'true' : 'false');
|
||||
|
||||
break;
|
||||
case Properties::PROPERTY_TYPE_DATE:
|
||||
$objWriter->writeAttribute('meta:value-type', 'date');
|
||||
$dtobj = Date::dateTimeFromTimestamp($propertyValue ?? 0);
|
||||
$objWriter->writeRawData($dtobj->format(DATE_W3C));
|
||||
|
||||
break;
|
||||
default:
|
||||
$objWriter->writeRawData($propertyValue);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
}
|
60
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/MetaInf.php
vendored
Normal file
60
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/MetaInf.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
|
||||
class MetaInf extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write META-INF/manifest.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8');
|
||||
|
||||
// Manifest
|
||||
$objWriter->startElement('manifest:manifest');
|
||||
$objWriter->writeAttribute('xmlns:manifest', 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0');
|
||||
$objWriter->writeAttribute('manifest:version', '1.2');
|
||||
|
||||
$objWriter->startElement('manifest:file-entry');
|
||||
$objWriter->writeAttribute('manifest:full-path', '/');
|
||||
$objWriter->writeAttribute('manifest:version', '1.2');
|
||||
$objWriter->writeAttribute('manifest:media-type', 'application/vnd.oasis.opendocument.spreadsheet');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('manifest:file-entry');
|
||||
$objWriter->writeAttribute('manifest:full-path', 'meta.xml');
|
||||
$objWriter->writeAttribute('manifest:media-type', 'text/xml');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('manifest:file-entry');
|
||||
$objWriter->writeAttribute('manifest:full-path', 'settings.xml');
|
||||
$objWriter->writeAttribute('manifest:media-type', 'text/xml');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('manifest:file-entry');
|
||||
$objWriter->writeAttribute('manifest:full-path', 'content.xml');
|
||||
$objWriter->writeAttribute('manifest:media-type', 'text/xml');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('manifest:file-entry');
|
||||
$objWriter->writeAttribute('manifest:full-path', 'Thumbnails/thumbnail.png');
|
||||
$objWriter->writeAttribute('manifest:media-type', 'image/png');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('manifest:file-entry');
|
||||
$objWriter->writeAttribute('manifest:full-path', 'styles.xml');
|
||||
$objWriter->writeAttribute('manifest:media-type', 'text/xml');
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
}
|
16
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Mimetype.php
vendored
Normal file
16
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Mimetype.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
class Mimetype extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write mimetype to plain text format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
return 'application/vnd.oasis.opendocument.spreadsheet';
|
||||
}
|
||||
}
|
140
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/NamedExpressions.php
vendored
Normal file
140
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/NamedExpressions.php
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\DefinedName;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class NamedExpressions
|
||||
{
|
||||
/** @var XMLWriter */
|
||||
private $objWriter;
|
||||
|
||||
/** @var Spreadsheet */
|
||||
private $spreadsheet;
|
||||
|
||||
/** @var Formula */
|
||||
private $formulaConvertor;
|
||||
|
||||
public function __construct(XMLWriter $objWriter, Spreadsheet $spreadsheet, Formula $formulaConvertor)
|
||||
{
|
||||
$this->objWriter = $objWriter;
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
$this->formulaConvertor = $formulaConvertor;
|
||||
}
|
||||
|
||||
public function write(): string
|
||||
{
|
||||
$this->objWriter->startElement('table:named-expressions');
|
||||
$this->writeExpressions();
|
||||
$this->objWriter->endElement();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function writeExpressions(): void
|
||||
{
|
||||
$definedNames = $this->spreadsheet->getDefinedNames();
|
||||
|
||||
foreach ($definedNames as $definedName) {
|
||||
if ($definedName->isFormula()) {
|
||||
$this->objWriter->startElement('table:named-expression');
|
||||
$this->writeNamedFormula($definedName, $this->spreadsheet->getActiveSheet());
|
||||
} else {
|
||||
$this->objWriter->startElement('table:named-range');
|
||||
$this->writeNamedRange($definedName);
|
||||
}
|
||||
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
private function writeNamedFormula(DefinedName $definedName, Worksheet $defaultWorksheet): void
|
||||
{
|
||||
$title = ($definedName->getWorksheet() !== null) ? $definedName->getWorksheet()->getTitle() : $defaultWorksheet->getTitle();
|
||||
$this->objWriter->writeAttribute('table:name', $definedName->getName());
|
||||
$this->objWriter->writeAttribute(
|
||||
'table:expression',
|
||||
$this->formulaConvertor->convertFormula($definedName->getValue(), $title)
|
||||
);
|
||||
$this->objWriter->writeAttribute('table:base-cell-address', $this->convertAddress(
|
||||
$definedName,
|
||||
"'" . $title . "'!\$A\$1"
|
||||
));
|
||||
}
|
||||
|
||||
private function writeNamedRange(DefinedName $definedName): void
|
||||
{
|
||||
$baseCell = '$A$1';
|
||||
$ws = $definedName->getWorksheet();
|
||||
if ($ws !== null) {
|
||||
$baseCell = "'" . $ws->getTitle() . "'!$baseCell";
|
||||
}
|
||||
$this->objWriter->writeAttribute('table:name', $definedName->getName());
|
||||
$this->objWriter->writeAttribute('table:base-cell-address', $this->convertAddress(
|
||||
$definedName,
|
||||
$baseCell
|
||||
));
|
||||
$this->objWriter->writeAttribute('table:cell-range-address', $this->convertAddress($definedName, $definedName->getValue()));
|
||||
}
|
||||
|
||||
private function convertAddress(DefinedName $definedName, string $address): string
|
||||
{
|
||||
$splitCount = preg_match_all(
|
||||
'/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/mui',
|
||||
$address,
|
||||
$splitRanges,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
$lengths = array_map('strlen', array_column($splitRanges[0], 0));
|
||||
$offsets = array_column($splitRanges[0], 1);
|
||||
|
||||
$worksheets = $splitRanges[2];
|
||||
$columns = $splitRanges[6];
|
||||
$rows = $splitRanges[7];
|
||||
|
||||
while ($splitCount > 0) {
|
||||
--$splitCount;
|
||||
$length = $lengths[$splitCount];
|
||||
$offset = $offsets[$splitCount];
|
||||
$worksheet = $worksheets[$splitCount][0];
|
||||
$column = $columns[$splitCount][0];
|
||||
$row = $rows[$splitCount][0];
|
||||
|
||||
$newRange = '';
|
||||
if (empty($worksheet)) {
|
||||
if (($offset === 0) || ($address[$offset - 1] !== ':')) {
|
||||
// We need a worksheet
|
||||
$ws = $definedName->getWorksheet();
|
||||
if ($ws !== null) {
|
||||
$worksheet = $ws->getTitle();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$worksheet = str_replace("''", "'", trim($worksheet, "'"));
|
||||
}
|
||||
if (!empty($worksheet)) {
|
||||
$newRange = "'" . str_replace("'", "''", $worksheet) . "'.";
|
||||
}
|
||||
|
||||
if (!empty($column)) {
|
||||
$newRange .= $column;
|
||||
}
|
||||
if (!empty($row)) {
|
||||
$newRange .= $row;
|
||||
}
|
||||
|
||||
$address = substr($address, 0, $offset) . $newRange . substr($address, $offset + $length);
|
||||
}
|
||||
|
||||
if (substr($address, 0, 1) === '=') {
|
||||
$address = substr($address, 1);
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
}
|
152
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Settings.php
vendored
Normal file
152
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Settings.php
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\CellAddress;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class Settings extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write settings.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8');
|
||||
|
||||
// Settings
|
||||
$objWriter->startElement('office:document-settings');
|
||||
$objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
|
||||
$objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
$objWriter->writeAttribute('xmlns:config', 'urn:oasis:names:tc:opendocument:xmlns:config:1.0');
|
||||
$objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
|
||||
$objWriter->writeAttribute('office:version', '1.2');
|
||||
|
||||
$objWriter->startElement('office:settings');
|
||||
$objWriter->startElement('config:config-item-set');
|
||||
$objWriter->writeAttribute('config:name', 'ooo:view-settings');
|
||||
$objWriter->startElement('config:config-item-map-indexed');
|
||||
$objWriter->writeAttribute('config:name', 'Views');
|
||||
$objWriter->startElement('config:config-item-map-entry');
|
||||
$spreadsheet = $this->getParentWriter()->getSpreadsheet();
|
||||
|
||||
$objWriter->startElement('config:config-item');
|
||||
$objWriter->writeAttribute('config:name', 'ViewId');
|
||||
$objWriter->writeAttribute('config:type', 'string');
|
||||
$objWriter->text('view1');
|
||||
$objWriter->endElement(); // ViewId
|
||||
$objWriter->startElement('config:config-item-map-named');
|
||||
|
||||
$this->writeAllWorksheetSettings($objWriter, $spreadsheet);
|
||||
|
||||
$wstitle = $spreadsheet->getActiveSheet()->getTitle();
|
||||
$objWriter->startElement('config:config-item');
|
||||
$objWriter->writeAttribute('config:name', 'ActiveTable');
|
||||
$objWriter->writeAttribute('config:type', 'string');
|
||||
$objWriter->text($wstitle);
|
||||
$objWriter->endElement(); // config:config-item ActiveTable
|
||||
|
||||
$objWriter->endElement(); // config:config-item-map-entry
|
||||
$objWriter->endElement(); // config:config-item-map-indexed Views
|
||||
$objWriter->endElement(); // config:config-item-set ooo:view-settings
|
||||
$objWriter->startElement('config:config-item-set');
|
||||
$objWriter->writeAttribute('config:name', 'ooo:configuration-settings');
|
||||
$objWriter->endElement(); // config:config-item-set ooo:configuration-settings
|
||||
$objWriter->endElement(); // office:settings
|
||||
$objWriter->endElement(); // office:document-settings
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
private function writeAllWorksheetSettings(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
$objWriter->writeAttribute('config:name', 'Tables');
|
||||
|
||||
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
|
||||
$this->writeWorksheetSettings($objWriter, $worksheet);
|
||||
}
|
||||
|
||||
$objWriter->endElement(); // config:config-item-map-entry Tables
|
||||
}
|
||||
|
||||
private function writeWorksheetSettings(XMLWriter $objWriter, Worksheet $worksheet): void
|
||||
{
|
||||
$objWriter->startElement('config:config-item-map-entry');
|
||||
$objWriter->writeAttribute('config:name', $worksheet->getTitle());
|
||||
|
||||
$this->writeSelectedCells($objWriter, $worksheet);
|
||||
if ($worksheet->getFreezePane() !== null) {
|
||||
$this->writeFreezePane($objWriter, $worksheet);
|
||||
}
|
||||
|
||||
$objWriter->endElement(); // config:config-item-map-entry Worksheet
|
||||
}
|
||||
|
||||
private function writeSelectedCells(XMLWriter $objWriter, Worksheet $worksheet): void
|
||||
{
|
||||
$selected = $worksheet->getSelectedCells();
|
||||
if (preg_match('/^([a-z]+)([0-9]+)/i', $selected, $matches) === 1) {
|
||||
$colSel = Coordinate::columnIndexFromString($matches[1]) - 1;
|
||||
$rowSel = (int) $matches[2] - 1;
|
||||
$objWriter->startElement('config:config-item');
|
||||
$objWriter->writeAttribute('config:name', 'CursorPositionX');
|
||||
$objWriter->writeAttribute('config:type', 'int');
|
||||
$objWriter->text((string) $colSel);
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('config:config-item');
|
||||
$objWriter->writeAttribute('config:name', 'CursorPositionY');
|
||||
$objWriter->writeAttribute('config:type', 'int');
|
||||
$objWriter->text((string) $rowSel);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
private function writeSplitValue(XMLWriter $objWriter, string $splitMode, string $type, string $value): void
|
||||
{
|
||||
$objWriter->startElement('config:config-item');
|
||||
$objWriter->writeAttribute('config:name', $splitMode);
|
||||
$objWriter->writeAttribute('config:type', $type);
|
||||
$objWriter->text($value);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
private function writeFreezePane(XMLWriter $objWriter, Worksheet $worksheet): void
|
||||
{
|
||||
$freezePane = CellAddress::fromCellAddress($worksheet->getFreezePane());
|
||||
if ($freezePane->cellAddress() === 'A1') {
|
||||
return;
|
||||
}
|
||||
|
||||
$columnId = $freezePane->columnId();
|
||||
$columnName = $freezePane->columnName();
|
||||
$row = $freezePane->rowId();
|
||||
|
||||
$this->writeSplitValue($objWriter, 'HorizontalSplitMode', 'short', '2');
|
||||
$this->writeSplitValue($objWriter, 'HorizontalSplitPosition', 'int', (string) ($columnId - 1));
|
||||
$this->writeSplitValue($objWriter, 'PositionLeft', 'short', '0');
|
||||
$this->writeSplitValue($objWriter, 'PositionRight', 'short', (string) ($columnId - 1));
|
||||
|
||||
for ($column = 'A'; $column !== $columnName; ++$column) {
|
||||
$worksheet->getColumnDimension($column)->setAutoSize(true);
|
||||
}
|
||||
|
||||
$this->writeSplitValue($objWriter, 'VerticalSplitMode', 'short', '2');
|
||||
$this->writeSplitValue($objWriter, 'VerticalSplitPosition', 'int', (string) ($row - 1));
|
||||
$this->writeSplitValue($objWriter, 'PositionTop', 'short', '0');
|
||||
$this->writeSplitValue($objWriter, 'PositionBottom', 'short', (string) ($row - 1));
|
||||
|
||||
$this->writeSplitValue($objWriter, 'ActiveSplitRange', 'short', '3');
|
||||
}
|
||||
}
|
65
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Styles.php
vendored
Normal file
65
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Styles.php
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
|
||||
class Styles extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write styles.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8');
|
||||
|
||||
// Content
|
||||
$objWriter->startElement('office:document-styles');
|
||||
$objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
|
||||
$objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
|
||||
$objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
|
||||
$objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
|
||||
$objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
|
||||
$objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
|
||||
$objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
$objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
|
||||
$objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
|
||||
$objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
|
||||
$objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0');
|
||||
$objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
|
||||
$objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0');
|
||||
$objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0');
|
||||
$objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML');
|
||||
$objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0');
|
||||
$objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0');
|
||||
$objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
|
||||
$objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer');
|
||||
$objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc');
|
||||
$objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events');
|
||||
$objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report');
|
||||
$objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2');
|
||||
$objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
|
||||
$objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
|
||||
$objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table');
|
||||
$objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/');
|
||||
$objWriter->writeAttribute('office:version', '1.2');
|
||||
|
||||
$objWriter->writeElement('office:font-face-decls');
|
||||
$objWriter->writeElement('office:styles');
|
||||
$objWriter->writeElement('office:automatic-styles');
|
||||
$objWriter->writeElement('office:master-styles');
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
}
|
16
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Thumbnails.php
vendored
Normal file
16
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Thumbnails.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
class Thumbnails extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write Thumbnails/thumbnail.png to PNG format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function write(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
35
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/WriterPart.php
vendored
Normal file
35
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/WriterPart.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods;
|
||||
|
||||
abstract class WriterPart
|
||||
{
|
||||
/**
|
||||
* Parent Ods object.
|
||||
*
|
||||
* @var Ods
|
||||
*/
|
||||
private $parentWriter;
|
||||
|
||||
/**
|
||||
* Get Ods writer.
|
||||
*
|
||||
* @return Ods
|
||||
*/
|
||||
public function getParentWriter()
|
||||
{
|
||||
return $this->parentWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parent Ods writer.
|
||||
*/
|
||||
public function __construct(Ods $writer)
|
||||
{
|
||||
$this->parentWriter = $writer;
|
||||
}
|
||||
|
||||
abstract public function write(): string;
|
||||
}
|
251
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php
vendored
Normal file
251
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
abstract class Pdf extends Html
|
||||
{
|
||||
/**
|
||||
* Temporary storage directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tempDir = '';
|
||||
|
||||
/**
|
||||
* Font.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $font = 'freesans';
|
||||
|
||||
/**
|
||||
* Orientation (Over-ride).
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
protected $orientation;
|
||||
|
||||
/**
|
||||
* Paper size (Over-ride).
|
||||
*
|
||||
* @var ?int
|
||||
*/
|
||||
protected $paperSize;
|
||||
|
||||
/**
|
||||
* Paper Sizes xRef List.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $paperSizes = [
|
||||
PageSetup::PAPERSIZE_LETTER => 'LETTER', // (8.5 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_LETTER_SMALL => 'LETTER', // (8.5 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_TABLOID => [792.00, 1224.00], // (11 in. by 17 in.)
|
||||
PageSetup::PAPERSIZE_LEDGER => [1224.00, 792.00], // (17 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_LEGAL => 'LEGAL', // (8.5 in. by 14 in.)
|
||||
PageSetup::PAPERSIZE_STATEMENT => [396.00, 612.00], // (5.5 in. by 8.5 in.)
|
||||
PageSetup::PAPERSIZE_EXECUTIVE => 'EXECUTIVE', // (7.25 in. by 10.5 in.)
|
||||
PageSetup::PAPERSIZE_A3 => 'A3', // (297 mm by 420 mm)
|
||||
PageSetup::PAPERSIZE_A4 => 'A4', // (210 mm by 297 mm)
|
||||
PageSetup::PAPERSIZE_A4_SMALL => 'A4', // (210 mm by 297 mm)
|
||||
PageSetup::PAPERSIZE_A5 => 'A5', // (148 mm by 210 mm)
|
||||
PageSetup::PAPERSIZE_B4 => 'B4', // (250 mm by 353 mm)
|
||||
PageSetup::PAPERSIZE_B5 => 'B5', // (176 mm by 250 mm)
|
||||
PageSetup::PAPERSIZE_FOLIO => 'FOLIO', // (8.5 in. by 13 in.)
|
||||
PageSetup::PAPERSIZE_QUARTO => [609.45, 779.53], // (215 mm by 275 mm)
|
||||
PageSetup::PAPERSIZE_STANDARD_1 => [720.00, 1008.00], // (10 in. by 14 in.)
|
||||
PageSetup::PAPERSIZE_STANDARD_2 => [792.00, 1224.00], // (11 in. by 17 in.)
|
||||
PageSetup::PAPERSIZE_NOTE => 'LETTER', // (8.5 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_NO9_ENVELOPE => [279.00, 639.00], // (3.875 in. by 8.875 in.)
|
||||
PageSetup::PAPERSIZE_NO10_ENVELOPE => [297.00, 684.00], // (4.125 in. by 9.5 in.)
|
||||
PageSetup::PAPERSIZE_NO11_ENVELOPE => [324.00, 747.00], // (4.5 in. by 10.375 in.)
|
||||
PageSetup::PAPERSIZE_NO12_ENVELOPE => [342.00, 792.00], // (4.75 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_NO14_ENVELOPE => [360.00, 828.00], // (5 in. by 11.5 in.)
|
||||
PageSetup::PAPERSIZE_C => [1224.00, 1584.00], // (17 in. by 22 in.)
|
||||
PageSetup::PAPERSIZE_D => [1584.00, 2448.00], // (22 in. by 34 in.)
|
||||
PageSetup::PAPERSIZE_E => [2448.00, 3168.00], // (34 in. by 44 in.)
|
||||
PageSetup::PAPERSIZE_DL_ENVELOPE => [311.81, 623.62], // (110 mm by 220 mm)
|
||||
PageSetup::PAPERSIZE_C5_ENVELOPE => 'C5', // (162 mm by 229 mm)
|
||||
PageSetup::PAPERSIZE_C3_ENVELOPE => 'C3', // (324 mm by 458 mm)
|
||||
PageSetup::PAPERSIZE_C4_ENVELOPE => 'C4', // (229 mm by 324 mm)
|
||||
PageSetup::PAPERSIZE_C6_ENVELOPE => 'C6', // (114 mm by 162 mm)
|
||||
PageSetup::PAPERSIZE_C65_ENVELOPE => [323.15, 649.13], // (114 mm by 229 mm)
|
||||
PageSetup::PAPERSIZE_B4_ENVELOPE => 'B4', // (250 mm by 353 mm)
|
||||
PageSetup::PAPERSIZE_B5_ENVELOPE => 'B5', // (176 mm by 250 mm)
|
||||
PageSetup::PAPERSIZE_B6_ENVELOPE => [498.90, 354.33], // (176 mm by 125 mm)
|
||||
PageSetup::PAPERSIZE_ITALY_ENVELOPE => [311.81, 651.97], // (110 mm by 230 mm)
|
||||
PageSetup::PAPERSIZE_MONARCH_ENVELOPE => [279.00, 540.00], // (3.875 in. by 7.5 in.)
|
||||
PageSetup::PAPERSIZE_6_3_4_ENVELOPE => [261.00, 468.00], // (3.625 in. by 6.5 in.)
|
||||
PageSetup::PAPERSIZE_US_STANDARD_FANFOLD => [1071.00, 792.00], // (14.875 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_GERMAN_STANDARD_FANFOLD => [612.00, 864.00], // (8.5 in. by 12 in.)
|
||||
PageSetup::PAPERSIZE_GERMAN_LEGAL_FANFOLD => 'FOLIO', // (8.5 in. by 13 in.)
|
||||
PageSetup::PAPERSIZE_ISO_B4 => 'B4', // (250 mm by 353 mm)
|
||||
PageSetup::PAPERSIZE_JAPANESE_DOUBLE_POSTCARD => [566.93, 419.53], // (200 mm by 148 mm)
|
||||
PageSetup::PAPERSIZE_STANDARD_PAPER_1 => [648.00, 792.00], // (9 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_STANDARD_PAPER_2 => [720.00, 792.00], // (10 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_STANDARD_PAPER_3 => [1080.00, 792.00], // (15 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_INVITE_ENVELOPE => [623.62, 623.62], // (220 mm by 220 mm)
|
||||
PageSetup::PAPERSIZE_LETTER_EXTRA_PAPER => [667.80, 864.00], // (9.275 in. by 12 in.)
|
||||
PageSetup::PAPERSIZE_LEGAL_EXTRA_PAPER => [667.80, 1080.00], // (9.275 in. by 15 in.)
|
||||
PageSetup::PAPERSIZE_TABLOID_EXTRA_PAPER => [841.68, 1296.00], // (11.69 in. by 18 in.)
|
||||
PageSetup::PAPERSIZE_A4_EXTRA_PAPER => [668.98, 912.76], // (236 mm by 322 mm)
|
||||
PageSetup::PAPERSIZE_LETTER_TRANSVERSE_PAPER => [595.80, 792.00], // (8.275 in. by 11 in.)
|
||||
PageSetup::PAPERSIZE_A4_TRANSVERSE_PAPER => 'A4', // (210 mm by 297 mm)
|
||||
PageSetup::PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER => [667.80, 864.00], // (9.275 in. by 12 in.)
|
||||
PageSetup::PAPERSIZE_SUPERA_SUPERA_A4_PAPER => [643.46, 1009.13], // (227 mm by 356 mm)
|
||||
PageSetup::PAPERSIZE_SUPERB_SUPERB_A3_PAPER => [864.57, 1380.47], // (305 mm by 487 mm)
|
||||
PageSetup::PAPERSIZE_LETTER_PLUS_PAPER => [612.00, 913.68], // (8.5 in. by 12.69 in.)
|
||||
PageSetup::PAPERSIZE_A4_PLUS_PAPER => [595.28, 935.43], // (210 mm by 330 mm)
|
||||
PageSetup::PAPERSIZE_A5_TRANSVERSE_PAPER => 'A5', // (148 mm by 210 mm)
|
||||
PageSetup::PAPERSIZE_JIS_B5_TRANSVERSE_PAPER => [515.91, 728.50], // (182 mm by 257 mm)
|
||||
PageSetup::PAPERSIZE_A3_EXTRA_PAPER => [912.76, 1261.42], // (322 mm by 445 mm)
|
||||
PageSetup::PAPERSIZE_A5_EXTRA_PAPER => [493.23, 666.14], // (174 mm by 235 mm)
|
||||
PageSetup::PAPERSIZE_ISO_B5_EXTRA_PAPER => [569.76, 782.36], // (201 mm by 276 mm)
|
||||
PageSetup::PAPERSIZE_A2_PAPER => 'A2', // (420 mm by 594 mm)
|
||||
PageSetup::PAPERSIZE_A3_TRANSVERSE_PAPER => 'A3', // (297 mm by 420 mm)
|
||||
PageSetup::PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER => [912.76, 1261.42], // (322 mm by 445 mm)
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new PDF Writer instance.
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet Spreadsheet object
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
parent::__construct($spreadsheet);
|
||||
//$this->setUseInlineCss(true);
|
||||
$this->tempDir = File::sysGetTempDir() . '/phpsppdf';
|
||||
$this->isPdf = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Font.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFont()
|
||||
{
|
||||
return $this->font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set font. Examples:
|
||||
* 'arialunicid0-chinese-simplified'
|
||||
* 'arialunicid0-chinese-traditional'
|
||||
* 'arialunicid0-korean'
|
||||
* 'arialunicid0-japanese'.
|
||||
*
|
||||
* @param string $fontName
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFont($fontName)
|
||||
{
|
||||
$this->font = $fontName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paper Size.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getPaperSize()
|
||||
{
|
||||
return $this->paperSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Paper Size.
|
||||
*
|
||||
* @param int $paperSize Paper size see PageSetup::PAPERSIZE_*
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPaperSize($paperSize)
|
||||
{
|
||||
$this->paperSize = $paperSize;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Orientation.
|
||||
*/
|
||||
public function getOrientation(): ?string
|
||||
{
|
||||
return $this->orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Orientation.
|
||||
*
|
||||
* @param string $orientation Page orientation see PageSetup::ORIENTATION_*
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setOrientation($orientation)
|
||||
{
|
||||
$this->orientation = $orientation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get temporary storage directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTempDir()
|
||||
{
|
||||
return $this->tempDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set temporary storage directory.
|
||||
*
|
||||
* @param string $temporaryDirectory Temporary storage directory
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setTempDir($temporaryDirectory)
|
||||
{
|
||||
if (is_dir($temporaryDirectory)) {
|
||||
$this->tempDir = $temporaryDirectory;
|
||||
} else {
|
||||
throw new WriterException("Directory does not exist: $temporaryDirectory");
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Spreadsheet to PDF file, pre-save.
|
||||
*
|
||||
* @param string $filename Name of the file to save as
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
protected function prepareForSave($filename)
|
||||
{
|
||||
// Open file
|
||||
$this->openFileHandle($filename);
|
||||
|
||||
return $this->fileHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save PhpSpreadsheet to PDF file, post-save.
|
||||
*/
|
||||
protected function restoreStateAfterSave(): void
|
||||
{
|
||||
$this->maybeCloseFileHandle();
|
||||
}
|
||||
}
|
60
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Dompdf.php
vendored
Normal file
60
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Dompdf.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Pdf;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Pdf;
|
||||
|
||||
class Dompdf extends Pdf
|
||||
{
|
||||
/**
|
||||
* embed images, or link to images.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $embedImages = true;
|
||||
|
||||
/**
|
||||
* Gets the implementation of external PDF library that should be used.
|
||||
*
|
||||
* @return \Dompdf\Dompdf implementation
|
||||
*/
|
||||
protected function createExternalWriterInstance()
|
||||
{
|
||||
return new \Dompdf\Dompdf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Spreadsheet to file.
|
||||
*
|
||||
* @param string $filename Name of the file to save as
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
$fileHandle = parent::prepareForSave($filename);
|
||||
|
||||
// Check for paper size and page orientation
|
||||
$setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
|
||||
$orientation = $this->getOrientation() ?? $setup->getOrientation();
|
||||
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
|
||||
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
|
||||
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();
|
||||
if (is_array($paperSize) && count($paperSize) === 2) {
|
||||
$paperSize = [0.0, 0.0, $paperSize[0], $paperSize[1]];
|
||||
}
|
||||
|
||||
$orientation = ($orientation == 'L') ? 'landscape' : 'portrait';
|
||||
|
||||
// Create PDF
|
||||
$pdf = $this->createExternalWriterInstance();
|
||||
$pdf->setPaper($paperSize, $orientation);
|
||||
|
||||
$pdf->loadHtml($this->generateHTMLAll());
|
||||
$pdf->render();
|
||||
|
||||
// Write to file
|
||||
fwrite($fileHandle, $pdf->output() ?? '');
|
||||
|
||||
parent::restoreStateAfterSave();
|
||||
}
|
||||
}
|
93
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php
vendored
Normal file
93
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Pdf;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Html;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Pdf;
|
||||
|
||||
class Mpdf extends Pdf
|
||||
{
|
||||
/** @var bool */
|
||||
protected $isMPdf = true;
|
||||
|
||||
/**
|
||||
* Gets the implementation of external PDF library that should be used.
|
||||
*
|
||||
* @param array $config Configuration array
|
||||
*
|
||||
* @return \Mpdf\Mpdf implementation
|
||||
*/
|
||||
protected function createExternalWriterInstance($config)
|
||||
{
|
||||
return new \Mpdf\Mpdf($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Spreadsheet to file.
|
||||
*
|
||||
* @param string $filename Name of the file to save as
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
$fileHandle = parent::prepareForSave($filename);
|
||||
|
||||
// Check for paper size and page orientation
|
||||
$setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
|
||||
$orientation = $this->getOrientation() ?? $setup->getOrientation();
|
||||
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
|
||||
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
|
||||
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();
|
||||
|
||||
// Create PDF
|
||||
$config = ['tempDir' => $this->tempDir . '/mpdf'];
|
||||
$pdf = $this->createExternalWriterInstance($config);
|
||||
$ortmp = $orientation;
|
||||
$pdf->_setPageSize($paperSize, $ortmp);
|
||||
$pdf->DefOrientation = $orientation;
|
||||
$pdf->AddPageByArray([
|
||||
'orientation' => $orientation,
|
||||
'margin-left' => $this->inchesToMm($this->spreadsheet->getActiveSheet()->getPageMargins()->getLeft()),
|
||||
'margin-right' => $this->inchesToMm($this->spreadsheet->getActiveSheet()->getPageMargins()->getRight()),
|
||||
'margin-top' => $this->inchesToMm($this->spreadsheet->getActiveSheet()->getPageMargins()->getTop()),
|
||||
'margin-bottom' => $this->inchesToMm($this->spreadsheet->getActiveSheet()->getPageMargins()->getBottom()),
|
||||
]);
|
||||
|
||||
// Document info
|
||||
$pdf->SetTitle($this->spreadsheet->getProperties()->getTitle());
|
||||
$pdf->SetAuthor($this->spreadsheet->getProperties()->getCreator());
|
||||
$pdf->SetSubject($this->spreadsheet->getProperties()->getSubject());
|
||||
$pdf->SetKeywords($this->spreadsheet->getProperties()->getKeywords());
|
||||
$pdf->SetCreator($this->spreadsheet->getProperties()->getCreator());
|
||||
|
||||
$html = $this->generateHTMLAll();
|
||||
$bodyLocation = strpos($html, Html::BODY_LINE);
|
||||
// Make sure first data presented to Mpdf includes body tag
|
||||
// so that Mpdf doesn't parse it as content. Issue 2432.
|
||||
if ($bodyLocation !== false) {
|
||||
$bodyLocation += strlen(Html::BODY_LINE);
|
||||
$pdf->WriteHTML(substr($html, 0, $bodyLocation));
|
||||
$html = substr($html, $bodyLocation);
|
||||
}
|
||||
foreach (\array_chunk(\explode(PHP_EOL, $html), 1000) as $lines) {
|
||||
$pdf->WriteHTML(\implode(PHP_EOL, $lines));
|
||||
}
|
||||
|
||||
// Write to file
|
||||
fwrite($fileHandle, $pdf->Output('', 'S'));
|
||||
|
||||
parent::restoreStateAfterSave();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inches to mm.
|
||||
*
|
||||
* @param float $inches
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function inchesToMm($inches)
|
||||
{
|
||||
return $inches * 25.4;
|
||||
}
|
||||
}
|
84
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php
vendored
Normal file
84
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Pdf;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Pdf;
|
||||
|
||||
class Tcpdf extends Pdf
|
||||
{
|
||||
/**
|
||||
* Create a new PDF Writer instance.
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet Spreadsheet object
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
parent::__construct($spreadsheet);
|
||||
$this->setUseInlineCss(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation of external PDF library that should be used.
|
||||
*
|
||||
* @param string $orientation Page orientation
|
||||
* @param string $unit Unit measure
|
||||
* @param array|string $paperSize Paper size
|
||||
*
|
||||
* @return \TCPDF implementation
|
||||
*/
|
||||
protected function createExternalWriterInstance($orientation, $unit, $paperSize)
|
||||
{
|
||||
return new \TCPDF($orientation, $unit, $paperSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Spreadsheet to file.
|
||||
*
|
||||
* @param string $filename Name of the file to save as
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
$fileHandle = parent::prepareForSave($filename);
|
||||
|
||||
// Default PDF paper size
|
||||
$paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.)
|
||||
|
||||
// Check for paper size and page orientation
|
||||
$setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
|
||||
$orientation = $this->getOrientation() ?? $setup->getOrientation();
|
||||
$orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
|
||||
$printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
|
||||
$paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();
|
||||
$printMargins = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageMargins();
|
||||
|
||||
// Create PDF
|
||||
$pdf = $this->createExternalWriterInstance($orientation, 'pt', $paperSize);
|
||||
$pdf->setFontSubsetting(false);
|
||||
// Set margins, converting inches to points (using 72 dpi)
|
||||
$pdf->SetMargins($printMargins->getLeft() * 72, $printMargins->getTop() * 72, $printMargins->getRight() * 72);
|
||||
$pdf->SetAutoPageBreak(true, $printMargins->getBottom() * 72);
|
||||
|
||||
$pdf->setPrintHeader(false);
|
||||
$pdf->setPrintFooter(false);
|
||||
|
||||
$pdf->AddPage();
|
||||
|
||||
// Set the appropriate font
|
||||
$pdf->SetFont($this->getFont());
|
||||
$pdf->writeHTML($this->generateHTMLAll());
|
||||
|
||||
// Document info
|
||||
$pdf->SetTitle($this->spreadsheet->getProperties()->getTitle());
|
||||
$pdf->SetAuthor($this->spreadsheet->getProperties()->getCreator());
|
||||
$pdf->SetSubject($this->spreadsheet->getProperties()->getSubject());
|
||||
$pdf->SetKeywords($this->spreadsheet->getProperties()->getKeywords());
|
||||
$pdf->SetCreator($this->spreadsheet->getProperties()->getCreator());
|
||||
|
||||
// Write to file
|
||||
fwrite($fileHandle, $pdf->output('', 'S'));
|
||||
|
||||
parent::restoreStateAfterSave();
|
||||
}
|
||||
}
|
918
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php
vendored
Normal file
918
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php
vendored
Normal file
@ -0,0 +1,918 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\Run;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\OLE;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\Root;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls\Parser;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls\Worksheet;
|
||||
|
||||
class Xls extends BaseWriter
|
||||
{
|
||||
/**
|
||||
* PhpSpreadsheet object.
|
||||
*
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
/**
|
||||
* Total number of shared strings in workbook.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $strTotal = 0;
|
||||
|
||||
/**
|
||||
* Number of unique shared strings in workbook.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $strUnique = 0;
|
||||
|
||||
/**
|
||||
* Array of unique shared strings in workbook.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $strTable = [];
|
||||
|
||||
/**
|
||||
* Color cache. Mapping between RGB value and color index.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $colors;
|
||||
|
||||
/**
|
||||
* Formula parser.
|
||||
*
|
||||
* @var Parser
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* Identifier clusters for drawings. Used in MSODRAWINGGROUP record.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $IDCLs;
|
||||
|
||||
/**
|
||||
* Basic OLE object summary information.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $summaryInformation;
|
||||
|
||||
/**
|
||||
* Extended OLE object document summary information.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $documentSummaryInformation;
|
||||
|
||||
/**
|
||||
* @var Workbook
|
||||
*/
|
||||
private $writerWorkbook;
|
||||
|
||||
/**
|
||||
* @var Worksheet[]
|
||||
*/
|
||||
private $writerWorksheets;
|
||||
|
||||
/**
|
||||
* Create a new Xls Writer.
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet PhpSpreadsheet object
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
|
||||
$this->parser = new Xls\Parser($spreadsheet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Spreadsheet to file.
|
||||
*
|
||||
* @param resource|string $filename
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
$this->processFlags($flags);
|
||||
|
||||
// garbage collect
|
||||
$this->spreadsheet->garbageCollect();
|
||||
|
||||
$saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
|
||||
$saveDateReturnType = Functions::getReturnDateType();
|
||||
Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
|
||||
|
||||
// initialize colors array
|
||||
$this->colors = [];
|
||||
|
||||
// Initialise workbook writer
|
||||
$this->writerWorkbook = new Xls\Workbook($this->spreadsheet, $this->strTotal, $this->strUnique, $this->strTable, $this->colors, $this->parser);
|
||||
|
||||
// Initialise worksheet writers
|
||||
$countSheets = $this->spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $countSheets; ++$i) {
|
||||
$this->writerWorksheets[$i] = new Xls\Worksheet($this->strTotal, $this->strUnique, $this->strTable, $this->colors, $this->parser, $this->preCalculateFormulas, $this->spreadsheet->getSheet($i));
|
||||
}
|
||||
|
||||
// build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
|
||||
$this->buildWorksheetEschers();
|
||||
$this->buildWorkbookEscher();
|
||||
|
||||
// add 15 identical cell style Xfs
|
||||
// for now, we use the first cellXf instead of cellStyleXf
|
||||
$cellXfCollection = $this->spreadsheet->getCellXfCollection();
|
||||
for ($i = 0; $i < 15; ++$i) {
|
||||
$this->writerWorkbook->addXfWriter($cellXfCollection[0], true);
|
||||
}
|
||||
|
||||
// add all the cell Xfs
|
||||
foreach ($this->spreadsheet->getCellXfCollection() as $style) {
|
||||
$this->writerWorkbook->addXfWriter($style, false);
|
||||
}
|
||||
|
||||
// add fonts from rich text eleemnts
|
||||
for ($i = 0; $i < $countSheets; ++$i) {
|
||||
foreach ($this->writerWorksheets[$i]->phpSheet->getCellCollection()->getCoordinates() as $coordinate) {
|
||||
/** @var Cell $cell */
|
||||
$cell = $this->writerWorksheets[$i]->phpSheet->getCellCollection()->get($coordinate);
|
||||
$cVal = $cell->getValue();
|
||||
if ($cVal instanceof RichText) {
|
||||
$elements = $cVal->getRichTextElements();
|
||||
foreach ($elements as $element) {
|
||||
if ($element instanceof Run) {
|
||||
$font = $element->getFont();
|
||||
$this->writerWorksheets[$i]->fontHashIndex[$font->getHashCode()] = $this->writerWorkbook->addFont($font);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialize OLE file
|
||||
$workbookStreamName = 'Workbook';
|
||||
$OLE = new File(OLE::ascToUcs($workbookStreamName));
|
||||
|
||||
// Write the worksheet streams before the global workbook stream,
|
||||
// because the byte sizes of these are needed in the global workbook stream
|
||||
$worksheetSizes = [];
|
||||
for ($i = 0; $i < $countSheets; ++$i) {
|
||||
$this->writerWorksheets[$i]->close();
|
||||
$worksheetSizes[] = $this->writerWorksheets[$i]->_datasize;
|
||||
}
|
||||
|
||||
// add binary data for global workbook stream
|
||||
$OLE->append($this->writerWorkbook->writeWorkbook($worksheetSizes));
|
||||
|
||||
// add binary data for sheet streams
|
||||
for ($i = 0; $i < $countSheets; ++$i) {
|
||||
$OLE->append($this->writerWorksheets[$i]->getData());
|
||||
}
|
||||
|
||||
$this->documentSummaryInformation = $this->writeDocumentSummaryInformation();
|
||||
// initialize OLE Document Summary Information
|
||||
if (isset($this->documentSummaryInformation) && !empty($this->documentSummaryInformation)) {
|
||||
$OLE_DocumentSummaryInformation = new File(OLE::ascToUcs(chr(5) . 'DocumentSummaryInformation'));
|
||||
$OLE_DocumentSummaryInformation->append($this->documentSummaryInformation);
|
||||
}
|
||||
|
||||
$this->summaryInformation = $this->writeSummaryInformation();
|
||||
// initialize OLE Summary Information
|
||||
if (isset($this->summaryInformation) && !empty($this->summaryInformation)) {
|
||||
$OLE_SummaryInformation = new File(OLE::ascToUcs(chr(5) . 'SummaryInformation'));
|
||||
$OLE_SummaryInformation->append($this->summaryInformation);
|
||||
}
|
||||
|
||||
// define OLE Parts
|
||||
$arrRootData = [$OLE];
|
||||
// initialize OLE Properties file
|
||||
if (isset($OLE_SummaryInformation)) {
|
||||
$arrRootData[] = $OLE_SummaryInformation;
|
||||
}
|
||||
// initialize OLE Extended Properties file
|
||||
if (isset($OLE_DocumentSummaryInformation)) {
|
||||
$arrRootData[] = $OLE_DocumentSummaryInformation;
|
||||
}
|
||||
|
||||
$time = $this->spreadsheet->getProperties()->getModified();
|
||||
$root = new Root($time, $time, $arrRootData);
|
||||
// save the OLE file
|
||||
$this->openFileHandle($filename);
|
||||
$root->save($this->fileHandle);
|
||||
$this->maybeCloseFileHandle();
|
||||
|
||||
Functions::setReturnDateType($saveDateReturnType);
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Worksheet Escher objects.
|
||||
*/
|
||||
private function buildWorksheetEschers(): void
|
||||
{
|
||||
// 1-based index to BstoreContainer
|
||||
$blipIndex = 0;
|
||||
$lastReducedSpId = 0;
|
||||
$lastSpId = 0;
|
||||
|
||||
foreach ($this->spreadsheet->getAllsheets() as $sheet) {
|
||||
// sheet index
|
||||
$sheetIndex = $sheet->getParent()->getIndex($sheet);
|
||||
|
||||
// check if there are any shapes for this sheet
|
||||
$filterRange = $sheet->getAutoFilter()->getRange();
|
||||
if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// create intermediate Escher object
|
||||
$escher = new Escher();
|
||||
|
||||
// dgContainer
|
||||
$dgContainer = new DgContainer();
|
||||
|
||||
// set the drawing index (we use sheet index + 1)
|
||||
$dgId = $sheet->getParent()->getIndex($sheet) + 1;
|
||||
$dgContainer->setDgId($dgId);
|
||||
$escher->setDgContainer($dgContainer);
|
||||
|
||||
// spgrContainer
|
||||
$spgrContainer = new SpgrContainer();
|
||||
$dgContainer->setSpgrContainer($spgrContainer);
|
||||
|
||||
// add one shape which is the group shape
|
||||
$spContainer = new SpContainer();
|
||||
$spContainer->setSpgr(true);
|
||||
$spContainer->setSpType(0);
|
||||
$spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
|
||||
$spgrContainer->addChild($spContainer);
|
||||
|
||||
// add the shapes
|
||||
|
||||
$countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet
|
||||
|
||||
foreach ($sheet->getDrawingCollection() as $drawing) {
|
||||
++$blipIndex;
|
||||
|
||||
++$countShapes[$sheetIndex];
|
||||
|
||||
// add the shape
|
||||
$spContainer = new SpContainer();
|
||||
|
||||
// set the shape type
|
||||
$spContainer->setSpType(0x004B);
|
||||
// set the shape flag
|
||||
$spContainer->setSpFlag(0x02);
|
||||
|
||||
// set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
|
||||
$reducedSpId = $countShapes[$sheetIndex];
|
||||
$spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
|
||||
$spContainer->setSpId($spId);
|
||||
|
||||
// keep track of last reducedSpId
|
||||
$lastReducedSpId = $reducedSpId;
|
||||
|
||||
// keep track of last spId
|
||||
$lastSpId = $spId;
|
||||
|
||||
// set the BLIP index
|
||||
$spContainer->setOPT(0x4104, $blipIndex);
|
||||
|
||||
// set coordinates and offsets, client anchor
|
||||
$coordinates = $drawing->getCoordinates();
|
||||
$offsetX = $drawing->getOffsetX();
|
||||
$offsetY = $drawing->getOffsetY();
|
||||
$width = $drawing->getWidth();
|
||||
$height = $drawing->getHeight();
|
||||
|
||||
$twoAnchor = \PhpOffice\PhpSpreadsheet\Shared\Xls::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
|
||||
|
||||
$spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
|
||||
$spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
|
||||
$spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
|
||||
$spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
|
||||
$spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
|
||||
$spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
|
||||
|
||||
$spgrContainer->addChild($spContainer);
|
||||
}
|
||||
|
||||
// AutoFilters
|
||||
if (!empty($filterRange)) {
|
||||
$rangeBounds = Coordinate::rangeBoundaries($filterRange);
|
||||
$iNumColStart = $rangeBounds[0][0];
|
||||
$iNumColEnd = $rangeBounds[1][0];
|
||||
|
||||
$iInc = $iNumColStart;
|
||||
while ($iInc <= $iNumColEnd) {
|
||||
++$countShapes[$sheetIndex];
|
||||
|
||||
// create an Drawing Object for the dropdown
|
||||
$oDrawing = new BaseDrawing();
|
||||
// get the coordinates of drawing
|
||||
$cDrawing = Coordinate::stringFromColumnIndex($iInc) . $rangeBounds[0][1];
|
||||
$oDrawing->setCoordinates($cDrawing);
|
||||
$oDrawing->setWorksheet($sheet);
|
||||
|
||||
// add the shape
|
||||
$spContainer = new SpContainer();
|
||||
// set the shape type
|
||||
$spContainer->setSpType(0x00C9);
|
||||
// set the shape flag
|
||||
$spContainer->setSpFlag(0x01);
|
||||
|
||||
// set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
|
||||
$reducedSpId = $countShapes[$sheetIndex];
|
||||
$spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
|
||||
$spContainer->setSpId($spId);
|
||||
|
||||
// keep track of last reducedSpId
|
||||
$lastReducedSpId = $reducedSpId;
|
||||
|
||||
// keep track of last spId
|
||||
$lastSpId = $spId;
|
||||
|
||||
$spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
|
||||
$spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
|
||||
$spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
|
||||
$spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
|
||||
$spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint
|
||||
|
||||
// set coordinates and offsets, client anchor
|
||||
$endCoordinates = Coordinate::stringFromColumnIndex($iInc);
|
||||
$endCoordinates .= $rangeBounds[0][1] + 1;
|
||||
|
||||
$spContainer->setStartCoordinates($cDrawing);
|
||||
$spContainer->setStartOffsetX(0);
|
||||
$spContainer->setStartOffsetY(0);
|
||||
$spContainer->setEndCoordinates($endCoordinates);
|
||||
$spContainer->setEndOffsetX(0);
|
||||
$spContainer->setEndOffsetY(0);
|
||||
|
||||
$spgrContainer->addChild($spContainer);
|
||||
++$iInc;
|
||||
}
|
||||
}
|
||||
|
||||
// identifier clusters, used for workbook Escher object
|
||||
$this->IDCLs[$dgId] = $lastReducedSpId;
|
||||
|
||||
// set last shape index
|
||||
$dgContainer->setLastSpId($lastSpId);
|
||||
|
||||
// set the Escher object
|
||||
$this->writerWorksheets[$sheetIndex]->setEscher($escher);
|
||||
}
|
||||
}
|
||||
|
||||
private function processMemoryDrawing(BstoreContainer &$bstoreContainer, MemoryDrawing $drawing, string $renderingFunctionx): void
|
||||
{
|
||||
switch ($renderingFunctionx) {
|
||||
case MemoryDrawing::RENDERING_JPEG:
|
||||
$blipType = BSE::BLIPTYPE_JPEG;
|
||||
$renderingFunction = 'imagejpeg';
|
||||
|
||||
break;
|
||||
default:
|
||||
$blipType = BSE::BLIPTYPE_PNG;
|
||||
$renderingFunction = 'imagepng';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
call_user_func($renderingFunction, $drawing->getImageResource());
|
||||
$blipData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$blip = new Blip();
|
||||
$blip->setData($blipData);
|
||||
|
||||
$BSE = new BSE();
|
||||
$BSE->setBlipType($blipType);
|
||||
$BSE->setBlip($blip);
|
||||
|
||||
$bstoreContainer->addBSE($BSE);
|
||||
}
|
||||
|
||||
private function processDrawing(BstoreContainer &$bstoreContainer, Drawing $drawing): void
|
||||
{
|
||||
$blipType = null;
|
||||
$blipData = '';
|
||||
$filename = $drawing->getPath();
|
||||
|
||||
[$imagesx, $imagesy, $imageFormat] = getimagesize($filename);
|
||||
|
||||
switch ($imageFormat) {
|
||||
case 1: // GIF, not supported by BIFF8, we convert to PNG
|
||||
$blipType = BSE::BLIPTYPE_PNG;
|
||||
$newImage = @imagecreatefromgif($filename);
|
||||
if ($newImage === false) {
|
||||
throw new Exception("Unable to create image from $filename");
|
||||
}
|
||||
ob_start();
|
||||
imagepng($newImage);
|
||||
$blipData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
break;
|
||||
case 2: // JPEG
|
||||
$blipType = BSE::BLIPTYPE_JPEG;
|
||||
$blipData = file_get_contents($filename);
|
||||
|
||||
break;
|
||||
case 3: // PNG
|
||||
$blipType = BSE::BLIPTYPE_PNG;
|
||||
$blipData = file_get_contents($filename);
|
||||
|
||||
break;
|
||||
case 6: // Windows DIB (BMP), we convert to PNG
|
||||
$blipType = BSE::BLIPTYPE_PNG;
|
||||
$newImage = @imagecreatefrombmp($filename);
|
||||
if ($newImage === false) {
|
||||
throw new Exception("Unable to create image from $filename");
|
||||
}
|
||||
ob_start();
|
||||
imagepng($newImage);
|
||||
$blipData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
break;
|
||||
}
|
||||
if ($blipData) {
|
||||
$blip = new Blip();
|
||||
$blip->setData($blipData);
|
||||
|
||||
$BSE = new BSE();
|
||||
$BSE->setBlipType($blipType);
|
||||
$BSE->setBlip($blip);
|
||||
|
||||
$bstoreContainer->addBSE($BSE);
|
||||
}
|
||||
}
|
||||
|
||||
private function processBaseDrawing(BstoreContainer &$bstoreContainer, BaseDrawing $drawing): void
|
||||
{
|
||||
if ($drawing instanceof Drawing) {
|
||||
$this->processDrawing($bstoreContainer, $drawing);
|
||||
} elseif ($drawing instanceof MemoryDrawing) {
|
||||
$this->processMemoryDrawing($bstoreContainer, $drawing, $drawing->getRenderingFunction());
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForDrawings(): bool
|
||||
{
|
||||
// any drawings in this workbook?
|
||||
$found = false;
|
||||
foreach ($this->spreadsheet->getAllSheets() as $sheet) {
|
||||
if (count($sheet->getDrawingCollection()) > 0) {
|
||||
$found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Escher object corresponding to the MSODRAWINGGROUP record.
|
||||
*/
|
||||
private function buildWorkbookEscher(): void
|
||||
{
|
||||
// nothing to do if there are no drawings
|
||||
if (!$this->checkForDrawings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we reach here, then there are drawings in the workbook
|
||||
$escher = new Escher();
|
||||
|
||||
// dggContainer
|
||||
$dggContainer = new DggContainer();
|
||||
$escher->setDggContainer($dggContainer);
|
||||
|
||||
// set IDCLs (identifier clusters)
|
||||
$dggContainer->setIDCLs($this->IDCLs);
|
||||
|
||||
// this loop is for determining maximum shape identifier of all drawing
|
||||
$spIdMax = 0;
|
||||
$totalCountShapes = 0;
|
||||
$countDrawings = 0;
|
||||
|
||||
foreach ($this->spreadsheet->getAllsheets() as $sheet) {
|
||||
$sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
|
||||
|
||||
$addCount = 0;
|
||||
foreach ($sheet->getDrawingCollection() as $drawing) {
|
||||
$addCount = 1;
|
||||
++$sheetCountShapes;
|
||||
++$totalCountShapes;
|
||||
|
||||
$spId = $sheetCountShapes | ($this->spreadsheet->getIndex($sheet) + 1) << 10;
|
||||
$spIdMax = max($spId, $spIdMax);
|
||||
}
|
||||
$countDrawings += $addCount;
|
||||
}
|
||||
|
||||
$dggContainer->setSpIdMax($spIdMax + 1);
|
||||
$dggContainer->setCDgSaved($countDrawings);
|
||||
$dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
|
||||
|
||||
// bstoreContainer
|
||||
$bstoreContainer = new BstoreContainer();
|
||||
$dggContainer->setBstoreContainer($bstoreContainer);
|
||||
|
||||
// the BSE's (all the images)
|
||||
foreach ($this->spreadsheet->getAllsheets() as $sheet) {
|
||||
foreach ($sheet->getDrawingCollection() as $drawing) {
|
||||
$this->processBaseDrawing($bstoreContainer, $drawing);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Escher object
|
||||
$this->writerWorkbook->setEscher($escher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the OLE Part for DocumentSummary Information.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function writeDocumentSummaryInformation()
|
||||
{
|
||||
// offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
|
||||
$data = pack('v', 0xFFFE);
|
||||
// offset: 2; size: 2;
|
||||
$data .= pack('v', 0x0000);
|
||||
// offset: 4; size: 2; OS version
|
||||
$data .= pack('v', 0x0106);
|
||||
// offset: 6; size: 2; OS indicator
|
||||
$data .= pack('v', 0x0002);
|
||||
// offset: 8; size: 16
|
||||
$data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
|
||||
// offset: 24; size: 4; section count
|
||||
$data .= pack('V', 0x0001);
|
||||
|
||||
// offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae
|
||||
$data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9);
|
||||
// offset: 44; size: 4; offset of the start
|
||||
$data .= pack('V', 0x30);
|
||||
|
||||
// SECTION
|
||||
$dataSection = [];
|
||||
$dataSection_NumProps = 0;
|
||||
$dataSection_Summary = '';
|
||||
$dataSection_Content = '';
|
||||
|
||||
// GKPIDDSI_CODEPAGE: CodePage
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x01],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
|
||||
'data' => ['data' => 1252],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
|
||||
// GKPIDDSI_CATEGORY : Category
|
||||
$dataProp = $this->spreadsheet->getProperties()->getCategory();
|
||||
if ($dataProp) {
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x02],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x1E],
|
||||
'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
}
|
||||
// GKPIDDSI_VERSION :Version of the application that wrote the property storage
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x17],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x03],
|
||||
'data' => ['pack' => 'V', 'data' => 0x000C0000],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
// GKPIDDSI_SCALE : FALSE
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x0B],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x0B],
|
||||
'data' => ['data' => false],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
// GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x10],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x0B],
|
||||
'data' => ['data' => false],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
// GKPIDDSI_SHAREDOC : FALSE
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x13],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x0B],
|
||||
'data' => ['data' => false],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
// GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x16],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x0B],
|
||||
'data' => ['data' => false],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
|
||||
// GKPIDDSI_DOCSPARTS
|
||||
// MS-OSHARED p75 (2.3.3.2.2.1)
|
||||
// Structure is VtVecUnalignedLpstrValue (2.3.3.1.9)
|
||||
// cElements
|
||||
$dataProp = pack('v', 0x0001);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
// array of UnalignedLpstr
|
||||
// cch
|
||||
$dataProp .= pack('v', 0x000A);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
// value
|
||||
$dataProp .= 'Worksheet' . chr(0);
|
||||
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x0D],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x101E],
|
||||
'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
|
||||
// GKPIDDSI_HEADINGPAIR
|
||||
// VtVecHeadingPairValue
|
||||
// cElements
|
||||
$dataProp = pack('v', 0x0002);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
// Array of vtHeadingPair
|
||||
// vtUnalignedString - headingString
|
||||
// stringType
|
||||
$dataProp .= pack('v', 0x001E);
|
||||
// padding
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
// UnalignedLpstr
|
||||
// cch
|
||||
$dataProp .= pack('v', 0x0013);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
// value
|
||||
$dataProp .= 'Feuilles de calcul';
|
||||
// vtUnalignedString - headingParts
|
||||
// wType : 0x0003 = 32 bit signed integer
|
||||
$dataProp .= pack('v', 0x0300);
|
||||
// padding
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
// value
|
||||
$dataProp .= pack('v', 0x0100);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
$dataProp .= pack('v', 0x0000);
|
||||
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x0C],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x100C],
|
||||
'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
|
||||
// 4 Section Length
|
||||
// 4 Property count
|
||||
// 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4))
|
||||
$dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
|
||||
foreach ($dataSection as $dataProp) {
|
||||
// Summary
|
||||
$dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
|
||||
// Offset
|
||||
$dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
|
||||
// DataType
|
||||
$dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
|
||||
// Data
|
||||
if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
|
||||
$dataSection_Content .= pack('V', $dataProp['data']['data']);
|
||||
|
||||
$dataSection_Content_Offset += 4 + 4;
|
||||
} elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
|
||||
$dataSection_Content .= pack('V', $dataProp['data']['data']);
|
||||
|
||||
$dataSection_Content_Offset += 4 + 4;
|
||||
} elseif ($dataProp['type']['data'] == 0x0B) { // Boolean
|
||||
$dataSection_Content .= pack('V', (int) $dataProp['data']['data']);
|
||||
$dataSection_Content_Offset += 4 + 4;
|
||||
} elseif ($dataProp['type']['data'] == 0x1E) { // null-terminated string prepended by dword string length
|
||||
// Null-terminated string
|
||||
$dataProp['data']['data'] .= chr(0);
|
||||
++$dataProp['data']['length'];
|
||||
// Complete the string with null string for being a %4
|
||||
$dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
|
||||
$dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
|
||||
|
||||
$dataSection_Content .= pack('V', $dataProp['data']['length']);
|
||||
$dataSection_Content .= $dataProp['data']['data'];
|
||||
|
||||
$dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
|
||||
// Condition below can never be true
|
||||
//} elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
|
||||
// $dataSection_Content .= $dataProp['data']['data'];
|
||||
|
||||
// $dataSection_Content_Offset += 4 + 8;
|
||||
} else {
|
||||
$dataSection_Content .= $dataProp['data']['data'];
|
||||
|
||||
$dataSection_Content_Offset += 4 + $dataProp['data']['length'];
|
||||
}
|
||||
}
|
||||
// Now $dataSection_Content_Offset contains the size of the content
|
||||
|
||||
// section header
|
||||
// offset: $secOffset; size: 4; section length
|
||||
// + x Size of the content (summary + content)
|
||||
$data .= pack('V', $dataSection_Content_Offset);
|
||||
// offset: $secOffset+4; size: 4; property count
|
||||
$data .= pack('V', $dataSection_NumProps);
|
||||
// Section Summary
|
||||
$data .= $dataSection_Summary;
|
||||
// Section Content
|
||||
$data .= $dataSection_Content;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int $dataProp
|
||||
*/
|
||||
private function writeSummaryPropOle($dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata): void
|
||||
{
|
||||
if ($dataProp) {
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => $sumdata],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => $typdata], // null-terminated string prepended by dword string length
|
||||
'data' => ['data' => OLE::localDateToOLE($dataProp)],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
}
|
||||
}
|
||||
|
||||
private function writeSummaryProp(string $dataProp, int &$dataSection_NumProps, array &$dataSection, int $sumdata, int $typdata): void
|
||||
{
|
||||
if ($dataProp) {
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => $sumdata],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => $typdata], // null-terminated string prepended by dword string length
|
||||
'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the OLE Part for Summary Information.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function writeSummaryInformation()
|
||||
{
|
||||
// offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
|
||||
$data = pack('v', 0xFFFE);
|
||||
// offset: 2; size: 2;
|
||||
$data .= pack('v', 0x0000);
|
||||
// offset: 4; size: 2; OS version
|
||||
$data .= pack('v', 0x0106);
|
||||
// offset: 6; size: 2; OS indicator
|
||||
$data .= pack('v', 0x0002);
|
||||
// offset: 8; size: 16
|
||||
$data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
|
||||
// offset: 24; size: 4; section count
|
||||
$data .= pack('V', 0x0001);
|
||||
|
||||
// offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9
|
||||
$data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3);
|
||||
// offset: 44; size: 4; offset of the start
|
||||
$data .= pack('V', 0x30);
|
||||
|
||||
// SECTION
|
||||
$dataSection = [];
|
||||
$dataSection_NumProps = 0;
|
||||
$dataSection_Summary = '';
|
||||
$dataSection_Content = '';
|
||||
|
||||
// CodePage : CP-1252
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x01],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
|
||||
'data' => ['data' => 1252],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
|
||||
$props = $this->spreadsheet->getProperties();
|
||||
$this->writeSummaryProp($props->getTitle(), $dataSection_NumProps, $dataSection, 0x02, 0x1e);
|
||||
$this->writeSummaryProp($props->getSubject(), $dataSection_NumProps, $dataSection, 0x03, 0x1e);
|
||||
$this->writeSummaryProp($props->getCreator(), $dataSection_NumProps, $dataSection, 0x04, 0x1e);
|
||||
$this->writeSummaryProp($props->getKeywords(), $dataSection_NumProps, $dataSection, 0x05, 0x1e);
|
||||
$this->writeSummaryProp($props->getDescription(), $dataSection_NumProps, $dataSection, 0x06, 0x1e);
|
||||
$this->writeSummaryProp($props->getLastModifiedBy(), $dataSection_NumProps, $dataSection, 0x08, 0x1e);
|
||||
$this->writeSummaryPropOle($props->getCreated(), $dataSection_NumProps, $dataSection, 0x0c, 0x40);
|
||||
$this->writeSummaryPropOle($props->getModified(), $dataSection_NumProps, $dataSection, 0x0d, 0x40);
|
||||
|
||||
// Security
|
||||
$dataSection[] = [
|
||||
'summary' => ['pack' => 'V', 'data' => 0x13],
|
||||
'offset' => ['pack' => 'V'],
|
||||
'type' => ['pack' => 'V', 'data' => 0x03], // 4 byte signed integer
|
||||
'data' => ['data' => 0x00],
|
||||
];
|
||||
++$dataSection_NumProps;
|
||||
|
||||
// 4 Section Length
|
||||
// 4 Property count
|
||||
// 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4))
|
||||
$dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
|
||||
foreach ($dataSection as $dataProp) {
|
||||
// Summary
|
||||
$dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
|
||||
// Offset
|
||||
$dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
|
||||
// DataType
|
||||
$dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
|
||||
// Data
|
||||
if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
|
||||
$dataSection_Content .= pack('V', $dataProp['data']['data']);
|
||||
|
||||
$dataSection_Content_Offset += 4 + 4;
|
||||
} elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
|
||||
$dataSection_Content .= pack('V', $dataProp['data']['data']);
|
||||
|
||||
$dataSection_Content_Offset += 4 + 4;
|
||||
} elseif ($dataProp['type']['data'] == 0x1E) { // null-terminated string prepended by dword string length
|
||||
// Null-terminated string
|
||||
$dataProp['data']['data'] .= chr(0);
|
||||
++$dataProp['data']['length'];
|
||||
// Complete the string with null string for being a %4
|
||||
$dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
|
||||
$dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
|
||||
|
||||
$dataSection_Content .= pack('V', $dataProp['data']['length']);
|
||||
$dataSection_Content .= $dataProp['data']['data'];
|
||||
|
||||
$dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
|
||||
} elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
|
||||
$dataSection_Content .= $dataProp['data']['data'];
|
||||
|
||||
$dataSection_Content_Offset += 4 + 8;
|
||||
}
|
||||
// Data Type Not Used at the moment
|
||||
}
|
||||
// Now $dataSection_Content_Offset contains the size of the content
|
||||
|
||||
// section header
|
||||
// offset: $secOffset; size: 4; section length
|
||||
// + x Size of the content (summary + content)
|
||||
$data .= pack('V', $dataSection_Content_Offset);
|
||||
// offset: $secOffset+4; size: 4; property count
|
||||
$data .= pack('V', $dataSection_NumProps);
|
||||
// Section Summary
|
||||
$data .= $dataSection_Summary;
|
||||
// Section Content
|
||||
$data .= $dataSection_Content;
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
224
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/BIFFwriter.php
vendored
Normal file
224
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/BIFFwriter.php
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
// Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class):
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// * Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
|
||||
// *
|
||||
// * The majority of this is _NOT_ my code. I simply ported it from the
|
||||
// * PERL Spreadsheet::WriteExcel module.
|
||||
// *
|
||||
// * The author of the Spreadsheet::WriteExcel module is John McNamara
|
||||
// * <jmcnamara@cpan.org>
|
||||
// *
|
||||
// * I _DO_ maintain this code, and John McNamara has nothing to do with the
|
||||
// * porting of this code to PHP. Any questions directly related to this
|
||||
// * class library should be directed to me.
|
||||
// *
|
||||
// * License Information:
|
||||
// *
|
||||
// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
|
||||
// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
|
||||
// *
|
||||
// * This library is free software; you can redistribute it and/or
|
||||
// * modify it under the terms of the GNU Lesser General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2.1 of the License, or (at your option) any later version.
|
||||
// *
|
||||
// * This library is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// * Lesser General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU Lesser General Public
|
||||
// * License along with this library; if not, write to the Free Software
|
||||
// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// */
|
||||
class BIFFwriter
|
||||
{
|
||||
/**
|
||||
* The byte order of this architecture. 0 => little endian, 1 => big endian.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private static $byteOrder;
|
||||
|
||||
/**
|
||||
* The string containing the data of the BIFF stream.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
public $_data;
|
||||
|
||||
/**
|
||||
* The size of the data in bytes. Should be the same as strlen($this->_data).
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $_datasize;
|
||||
|
||||
/**
|
||||
* The maximum length for a BIFF record (excluding record header and length field). See addContinue().
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @see addContinue()
|
||||
*/
|
||||
private $limit = 8224;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_data = '';
|
||||
$this->_datasize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the byte order and store it as class data to avoid
|
||||
* recalculating it for each call to new().
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getByteOrder()
|
||||
{
|
||||
if (!isset(self::$byteOrder)) {
|
||||
// Check if "pack" gives the required IEEE 64bit float
|
||||
$teststr = pack('d', 1.2345);
|
||||
$number = pack('C8', 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
|
||||
if ($number == $teststr) {
|
||||
$byte_order = 0; // Little Endian
|
||||
} elseif ($number == strrev($teststr)) {
|
||||
$byte_order = 1; // Big Endian
|
||||
} else {
|
||||
// Give up. I'll fix this in a later version.
|
||||
throw new WriterException('Required floating point format not supported on this platform.');
|
||||
}
|
||||
self::$byteOrder = $byte_order;
|
||||
}
|
||||
|
||||
return self::$byteOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* General storage function.
|
||||
*
|
||||
* @param string $data binary data to append
|
||||
*/
|
||||
protected function append($data): void
|
||||
{
|
||||
if (strlen($data) - 4 > $this->limit) {
|
||||
$data = $this->addContinue($data);
|
||||
}
|
||||
$this->_data .= $data;
|
||||
$this->_datasize += strlen($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* General storage function like append, but returns string instead of modifying $this->_data.
|
||||
*
|
||||
* @param string $data binary data to write
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function writeData($data)
|
||||
{
|
||||
if (strlen($data) - 4 > $this->limit) {
|
||||
$data = $this->addContinue($data);
|
||||
}
|
||||
$this->_datasize += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes Excel BOF record to indicate the beginning of a stream or
|
||||
* sub-stream in the BIFF file.
|
||||
*
|
||||
* @param int $type type of BIFF file to write: 0x0005 Workbook,
|
||||
* 0x0010 Worksheet
|
||||
*/
|
||||
protected function storeBof($type): void
|
||||
{
|
||||
$record = 0x0809; // Record identifier (BIFF5-BIFF8)
|
||||
$length = 0x0010;
|
||||
|
||||
// by inspection of real files, MS Office Excel 2007 writes the following
|
||||
$unknown = pack('VV', 0x000100D1, 0x00000406);
|
||||
|
||||
$build = 0x0DBB; // Excel 97
|
||||
$year = 0x07CC; // Excel 97
|
||||
|
||||
$version = 0x0600; // BIFF8
|
||||
|
||||
$header = pack('vv', $record, $length);
|
||||
$data = pack('vvvv', $version, $type, $build, $year);
|
||||
$this->append($header . $data . $unknown);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes Excel EOF record to indicate the end of a BIFF stream.
|
||||
*/
|
||||
protected function storeEof(): void
|
||||
{
|
||||
$record = 0x000A; // Record identifier
|
||||
$length = 0x0000; // Number of bytes to follow
|
||||
|
||||
$header = pack('vv', $record, $length);
|
||||
$this->append($header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes Excel EOF record to indicate the end of a BIFF stream.
|
||||
*/
|
||||
public function writeEof()
|
||||
{
|
||||
$record = 0x000A; // Record identifier
|
||||
$length = 0x0000; // Number of bytes to follow
|
||||
$header = pack('vv', $record, $length);
|
||||
|
||||
return $this->writeData($header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
|
||||
* Excel 97 the limit is 8228 bytes. Records that are longer than these limits
|
||||
* must be split up into CONTINUE blocks.
|
||||
*
|
||||
* This function takes a long BIFF record and inserts CONTINUE records as
|
||||
* necessary.
|
||||
*
|
||||
* @param string $data The original binary data to be written
|
||||
*
|
||||
* @return string A very convenient string of continue blocks
|
||||
*/
|
||||
private function addContinue($data)
|
||||
{
|
||||
$limit = $this->limit;
|
||||
$record = 0x003C; // Record identifier
|
||||
|
||||
// The first 2080/8224 bytes remain intact. However, we have to change
|
||||
// the length field of the record.
|
||||
$tmp = substr($data, 0, 2) . pack('v', $limit) . substr($data, 4, $limit);
|
||||
|
||||
$header = pack('vv', $record, $limit); // Headers for continue records
|
||||
|
||||
// Retrieve chunks of 2080/8224 bytes +4 for the header.
|
||||
$data_length = strlen($data);
|
||||
for ($i = $limit + 4; $i < ($data_length - $limit); $i += $limit) {
|
||||
$tmp .= $header;
|
||||
$tmp .= substr($data, $i, $limit);
|
||||
}
|
||||
|
||||
// Retrieve the last chunk of data
|
||||
$header = pack('vv', $record, strlen($data) - $i);
|
||||
$tmp .= $header;
|
||||
$tmp .= substr($data, $i);
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
}
|
78
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/CellDataValidation.php
vendored
Normal file
78
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/CellDataValidation.php
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
|
||||
|
||||
class CellDataValidation
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected static $validationTypeMap = [
|
||||
DataValidation::TYPE_NONE => 0x00,
|
||||
DataValidation::TYPE_WHOLE => 0x01,
|
||||
DataValidation::TYPE_DECIMAL => 0x02,
|
||||
DataValidation::TYPE_LIST => 0x03,
|
||||
DataValidation::TYPE_DATE => 0x04,
|
||||
DataValidation::TYPE_TIME => 0x05,
|
||||
DataValidation::TYPE_TEXTLENGTH => 0x06,
|
||||
DataValidation::TYPE_CUSTOM => 0x07,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected static $errorStyleMap = [
|
||||
DataValidation::STYLE_STOP => 0x00,
|
||||
DataValidation::STYLE_WARNING => 0x01,
|
||||
DataValidation::STYLE_INFORMATION => 0x02,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected static $operatorMap = [
|
||||
DataValidation::OPERATOR_BETWEEN => 0x00,
|
||||
DataValidation::OPERATOR_NOTBETWEEN => 0x01,
|
||||
DataValidation::OPERATOR_EQUAL => 0x02,
|
||||
DataValidation::OPERATOR_NOTEQUAL => 0x03,
|
||||
DataValidation::OPERATOR_GREATERTHAN => 0x04,
|
||||
DataValidation::OPERATOR_LESSTHAN => 0x05,
|
||||
DataValidation::OPERATOR_GREATERTHANOREQUAL => 0x06,
|
||||
DataValidation::OPERATOR_LESSTHANOREQUAL => 0x07,
|
||||
];
|
||||
|
||||
public static function type(DataValidation $dataValidation): int
|
||||
{
|
||||
$validationType = $dataValidation->getType();
|
||||
|
||||
if (is_string($validationType) && array_key_exists($validationType, self::$validationTypeMap)) {
|
||||
return self::$validationTypeMap[$validationType];
|
||||
}
|
||||
|
||||
return self::$validationTypeMap[DataValidation::TYPE_NONE];
|
||||
}
|
||||
|
||||
public static function errorStyle(DataValidation $dataValidation): int
|
||||
{
|
||||
$errorStyle = $dataValidation->getErrorStyle();
|
||||
|
||||
if (is_string($errorStyle) && array_key_exists($errorStyle, self::$errorStyleMap)) {
|
||||
return self::$errorStyleMap[$errorStyle];
|
||||
}
|
||||
|
||||
return self::$errorStyleMap[DataValidation::STYLE_STOP];
|
||||
}
|
||||
|
||||
public static function operator(DataValidation $dataValidation): int
|
||||
{
|
||||
$operator = $dataValidation->getOperator();
|
||||
|
||||
if (is_string($operator) && array_key_exists($operator, self::$operatorMap)) {
|
||||
return self::$operatorMap[$operator];
|
||||
}
|
||||
|
||||
return self::$operatorMap[DataValidation::OPERATOR_BETWEEN];
|
||||
}
|
||||
}
|
76
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ConditionalHelper.php
vendored
Normal file
76
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ConditionalHelper.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
|
||||
|
||||
class ConditionalHelper
|
||||
{
|
||||
/**
|
||||
* Formula parser.
|
||||
*
|
||||
* @var Parser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $condition;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $cellRange;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $size;
|
||||
|
||||
public function __construct(Parser $parser)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $condition
|
||||
*/
|
||||
public function processCondition($condition, string $cellRange): void
|
||||
{
|
||||
$this->condition = $condition;
|
||||
$this->cellRange = $cellRange;
|
||||
|
||||
if (is_int($condition) || is_float($condition)) {
|
||||
$this->size = ($condition <= 65535 ? 3 : 0x0000);
|
||||
$this->tokens = pack('Cv', 0x1E, $condition);
|
||||
} else {
|
||||
try {
|
||||
$formula = Wizard\WizardAbstract::reverseAdjustCellRef((string) $condition, $cellRange);
|
||||
$this->parser->parse($formula);
|
||||
$this->tokens = $this->parser->toReversePolish();
|
||||
$this->size = strlen($this->tokens ?? '');
|
||||
} catch (PhpSpreadsheetException $e) {
|
||||
// In the event of a parser error with a formula value, we set the expression to ptgInt + 0
|
||||
$this->tokens = pack('Cv', 0x1E, 0);
|
||||
$this->size = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function tokens(): ?string
|
||||
{
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
public function size(): int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
}
|
28
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ErrorCode.php
vendored
Normal file
28
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ErrorCode.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
class ErrorCode
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected static $errorCodeMap = [
|
||||
'#NULL!' => 0x00,
|
||||
'#DIV/0!' => 0x07,
|
||||
'#VALUE!' => 0x0F,
|
||||
'#REF!' => 0x17,
|
||||
'#NAME?' => 0x1D,
|
||||
'#NUM!' => 0x24,
|
||||
'#N/A' => 0x2A,
|
||||
];
|
||||
|
||||
public static function error(string $errorCode): int
|
||||
{
|
||||
if (array_key_exists($errorCode, self::$errorCodeMap)) {
|
||||
return self::$errorCodeMap[$errorCode];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
508
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php
vendored
Normal file
508
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php
vendored
Normal file
@ -0,0 +1,508 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip;
|
||||
|
||||
class Escher
|
||||
{
|
||||
/**
|
||||
* The object we are writing.
|
||||
*/
|
||||
private $object;
|
||||
|
||||
/**
|
||||
* The written binary data.
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Shape offsets. Positions in binary stream where a new shape record begins.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $spOffsets;
|
||||
|
||||
/**
|
||||
* Shape types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $spTypes;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $object
|
||||
*/
|
||||
public function __construct($object)
|
||||
{
|
||||
$this->object = $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the object to be written.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// initialize
|
||||
$this->data = '';
|
||||
|
||||
switch (get_class($this->object)) {
|
||||
case \PhpOffice\PhpSpreadsheet\Shared\Escher::class:
|
||||
if ($dggContainer = $this->object->getDggContainer()) {
|
||||
$writer = new self($dggContainer);
|
||||
$this->data = $writer->close();
|
||||
} elseif ($dgContainer = $this->object->getDgContainer()) {
|
||||
$writer = new self($dgContainer);
|
||||
$this->data = $writer->close();
|
||||
$this->spOffsets = $writer->getSpOffsets();
|
||||
$this->spTypes = $writer->getSpTypes();
|
||||
}
|
||||
|
||||
break;
|
||||
case DggContainer::class:
|
||||
// this is a container record
|
||||
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
// write the dgg
|
||||
$recVer = 0x0;
|
||||
$recInstance = 0x0000;
|
||||
$recType = 0xF006;
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
// dgg data
|
||||
$dggData =
|
||||
pack(
|
||||
'VVVV',
|
||||
$this->object->getSpIdMax(), // maximum shape identifier increased by one
|
||||
$this->object->getCDgSaved() + 1, // number of file identifier clusters increased by one
|
||||
$this->object->getCSpSaved(),
|
||||
$this->object->getCDgSaved() // count total number of drawings saved
|
||||
);
|
||||
|
||||
// add file identifier clusters (one per drawing)
|
||||
$IDCLs = $this->object->getIDCLs();
|
||||
|
||||
foreach ($IDCLs as $dgId => $maxReducedSpId) {
|
||||
$dggData .= pack('VV', $dgId, $maxReducedSpId + 1);
|
||||
}
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, strlen($dggData));
|
||||
$innerData .= $header . $dggData;
|
||||
|
||||
// write the bstoreContainer
|
||||
if ($bstoreContainer = $this->object->getBstoreContainer()) {
|
||||
$writer = new self($bstoreContainer);
|
||||
$innerData .= $writer->close();
|
||||
}
|
||||
|
||||
// write the record
|
||||
$recVer = 0xF;
|
||||
$recInstance = 0x0000;
|
||||
$recType = 0xF000;
|
||||
$length = strlen($innerData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header . $innerData;
|
||||
|
||||
break;
|
||||
case BstoreContainer::class:
|
||||
// this is a container record
|
||||
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
// treat the inner data
|
||||
if ($BSECollection = $this->object->getBSECollection()) {
|
||||
foreach ($BSECollection as $BSE) {
|
||||
$writer = new self($BSE);
|
||||
$innerData .= $writer->close();
|
||||
}
|
||||
}
|
||||
|
||||
// write the record
|
||||
$recVer = 0xF;
|
||||
$recInstance = count($this->object->getBSECollection());
|
||||
$recType = 0xF001;
|
||||
$length = strlen($innerData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header . $innerData;
|
||||
|
||||
break;
|
||||
case BSE::class:
|
||||
// this is a semi-container record
|
||||
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
// here we treat the inner data
|
||||
if ($blip = $this->object->getBlip()) {
|
||||
$writer = new self($blip);
|
||||
$innerData .= $writer->close();
|
||||
}
|
||||
|
||||
// initialize
|
||||
$data = '';
|
||||
|
||||
$btWin32 = $this->object->getBlipType();
|
||||
$btMacOS = $this->object->getBlipType();
|
||||
$data .= pack('CC', $btWin32, $btMacOS);
|
||||
|
||||
$rgbUid = pack('VVVV', 0, 0, 0, 0); // todo
|
||||
$data .= $rgbUid;
|
||||
|
||||
$tag = 0;
|
||||
$size = strlen($innerData);
|
||||
$cRef = 1;
|
||||
$foDelay = 0; //todo
|
||||
$unused1 = 0x0;
|
||||
$cbName = 0x0;
|
||||
$unused2 = 0x0;
|
||||
$unused3 = 0x0;
|
||||
$data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3);
|
||||
|
||||
$data .= $innerData;
|
||||
|
||||
// write the record
|
||||
$recVer = 0x2;
|
||||
$recInstance = $this->object->getBlipType();
|
||||
$recType = 0xF007;
|
||||
$length = strlen($data);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header;
|
||||
|
||||
$this->data .= $data;
|
||||
|
||||
break;
|
||||
case Blip::class:
|
||||
// this is an atom record
|
||||
|
||||
// write the record
|
||||
switch ($this->object->getParent()->getBlipType()) {
|
||||
case BSE::BLIPTYPE_JPEG:
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
$rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
|
||||
$innerData .= $rgbUid1;
|
||||
|
||||
$tag = 0xFF; // todo
|
||||
$innerData .= pack('C', $tag);
|
||||
|
||||
$innerData .= $this->object->getData();
|
||||
|
||||
$recVer = 0x0;
|
||||
$recInstance = 0x46A;
|
||||
$recType = 0xF01D;
|
||||
$length = strlen($innerData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header;
|
||||
|
||||
$this->data .= $innerData;
|
||||
|
||||
break;
|
||||
case BSE::BLIPTYPE_PNG:
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
$rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
|
||||
$innerData .= $rgbUid1;
|
||||
|
||||
$tag = 0xFF; // todo
|
||||
$innerData .= pack('C', $tag);
|
||||
|
||||
$innerData .= $this->object->getData();
|
||||
|
||||
$recVer = 0x0;
|
||||
$recInstance = 0x6E0;
|
||||
$recType = 0xF01E;
|
||||
$length = strlen($innerData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header;
|
||||
|
||||
$this->data .= $innerData;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case DgContainer::class:
|
||||
// this is a container record
|
||||
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
// write the dg
|
||||
$recVer = 0x0;
|
||||
$recInstance = $this->object->getDgId();
|
||||
$recType = 0xF008;
|
||||
$length = 8;
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
// number of shapes in this drawing (including group shape)
|
||||
$countShapes = count($this->object->getSpgrContainer()->getChildren());
|
||||
$innerData .= $header . pack('VV', $countShapes, $this->object->getLastSpId());
|
||||
|
||||
// write the spgrContainer
|
||||
if ($spgrContainer = $this->object->getSpgrContainer()) {
|
||||
$writer = new self($spgrContainer);
|
||||
$innerData .= $writer->close();
|
||||
|
||||
// get the shape offsets relative to the spgrContainer record
|
||||
$spOffsets = $writer->getSpOffsets();
|
||||
$spTypes = $writer->getSpTypes();
|
||||
|
||||
// save the shape offsets relative to dgContainer
|
||||
foreach ($spOffsets as &$spOffset) {
|
||||
$spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes)
|
||||
}
|
||||
|
||||
$this->spOffsets = $spOffsets;
|
||||
$this->spTypes = $spTypes;
|
||||
}
|
||||
|
||||
// write the record
|
||||
$recVer = 0xF;
|
||||
$recInstance = 0x0000;
|
||||
$recType = 0xF002;
|
||||
$length = strlen($innerData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header . $innerData;
|
||||
|
||||
break;
|
||||
case SpgrContainer::class:
|
||||
// this is a container record
|
||||
|
||||
// initialize
|
||||
$innerData = '';
|
||||
|
||||
// initialize spape offsets
|
||||
$totalSize = 8;
|
||||
$spOffsets = [];
|
||||
$spTypes = [];
|
||||
|
||||
// treat the inner data
|
||||
foreach ($this->object->getChildren() as $spContainer) {
|
||||
$writer = new self($spContainer);
|
||||
$spData = $writer->close();
|
||||
$innerData .= $spData;
|
||||
|
||||
// save the shape offsets (where new shape records begin)
|
||||
$totalSize += strlen($spData);
|
||||
$spOffsets[] = $totalSize;
|
||||
|
||||
$spTypes = array_merge($spTypes, $writer->getSpTypes());
|
||||
}
|
||||
|
||||
// write the record
|
||||
$recVer = 0xF;
|
||||
$recInstance = 0x0000;
|
||||
$recType = 0xF003;
|
||||
$length = strlen($innerData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header . $innerData;
|
||||
$this->spOffsets = $spOffsets;
|
||||
$this->spTypes = $spTypes;
|
||||
|
||||
break;
|
||||
case SpContainer::class:
|
||||
// initialize
|
||||
$data = '';
|
||||
|
||||
// build the data
|
||||
|
||||
// write group shape record, if necessary?
|
||||
if ($this->object->getSpgr()) {
|
||||
$recVer = 0x1;
|
||||
$recInstance = 0x0000;
|
||||
$recType = 0xF009;
|
||||
$length = 0x00000010;
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$data .= $header . pack('VVVV', 0, 0, 0, 0);
|
||||
}
|
||||
$this->spTypes[] = ($this->object->getSpType());
|
||||
|
||||
// write the shape record
|
||||
$recVer = 0x2;
|
||||
$recInstance = $this->object->getSpType(); // shape type
|
||||
$recType = 0xF00A;
|
||||
$length = 0x00000008;
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$data .= $header . pack('VV', $this->object->getSpId(), $this->object->getSpgr() ? 0x0005 : 0x0A00);
|
||||
|
||||
// the options
|
||||
if ($this->object->getOPTCollection()) {
|
||||
$optData = '';
|
||||
|
||||
$recVer = 0x3;
|
||||
$recInstance = count($this->object->getOPTCollection());
|
||||
$recType = 0xF00B;
|
||||
foreach ($this->object->getOPTCollection() as $property => $value) {
|
||||
$optData .= pack('vV', $property, $value);
|
||||
}
|
||||
$length = strlen($optData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
$data .= $header . $optData;
|
||||
}
|
||||
|
||||
// the client anchor
|
||||
if ($this->object->getStartCoordinates()) {
|
||||
$recVer = 0x0;
|
||||
$recInstance = 0x0;
|
||||
$recType = 0xF010;
|
||||
|
||||
// start coordinates
|
||||
[$column, $row] = Coordinate::indexesFromString($this->object->getStartCoordinates());
|
||||
$c1 = $column - 1;
|
||||
$r1 = $row - 1;
|
||||
|
||||
// start offsetX
|
||||
$startOffsetX = $this->object->getStartOffsetX();
|
||||
|
||||
// start offsetY
|
||||
$startOffsetY = $this->object->getStartOffsetY();
|
||||
|
||||
// end coordinates
|
||||
[$column, $row] = Coordinate::indexesFromString($this->object->getEndCoordinates());
|
||||
$c2 = $column - 1;
|
||||
$r2 = $row - 1;
|
||||
|
||||
// end offsetX
|
||||
$endOffsetX = $this->object->getEndOffsetX();
|
||||
|
||||
// end offsetY
|
||||
$endOffsetY = $this->object->getEndOffsetY();
|
||||
|
||||
$clientAnchorData = pack('vvvvvvvvv', $this->object->getSpFlag(), $c1, $startOffsetX, $r1, $startOffsetY, $c2, $endOffsetX, $r2, $endOffsetY);
|
||||
|
||||
$length = strlen($clientAnchorData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
$data .= $header . $clientAnchorData;
|
||||
}
|
||||
|
||||
// the client data, just empty for now
|
||||
if (!$this->object->getSpgr()) {
|
||||
$clientDataData = '';
|
||||
|
||||
$recVer = 0x0;
|
||||
$recInstance = 0x0;
|
||||
$recType = 0xF011;
|
||||
|
||||
$length = strlen($clientDataData);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
$data .= $header . $clientDataData;
|
||||
}
|
||||
|
||||
// write the record
|
||||
$recVer = 0xF;
|
||||
$recInstance = 0x0000;
|
||||
$recType = 0xF004;
|
||||
$length = strlen($data);
|
||||
|
||||
$recVerInstance = $recVer;
|
||||
$recVerInstance |= $recInstance << 4;
|
||||
|
||||
$header = pack('vvV', $recVerInstance, $recType, $length);
|
||||
|
||||
$this->data = $header . $data;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shape offsets.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSpOffsets()
|
||||
{
|
||||
return $this->spOffsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shape types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSpTypes()
|
||||
{
|
||||
return $this->spTypes;
|
||||
}
|
||||
}
|
146
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Font.php
vendored
Normal file
146
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Font.php
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
|
||||
class Font
|
||||
{
|
||||
/**
|
||||
* Color index.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $colorIndex;
|
||||
|
||||
/**
|
||||
* Font.
|
||||
*
|
||||
* @var \PhpOffice\PhpSpreadsheet\Style\Font
|
||||
*/
|
||||
private $font;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(\PhpOffice\PhpSpreadsheet\Style\Font $font)
|
||||
{
|
||||
$this->colorIndex = 0x7FFF;
|
||||
$this->font = $font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color index.
|
||||
*
|
||||
* @param int $colorIndex
|
||||
*/
|
||||
public function setColorIndex($colorIndex): void
|
||||
{
|
||||
$this->colorIndex = $colorIndex;
|
||||
}
|
||||
|
||||
/** @var int */
|
||||
private static $notImplemented = 0;
|
||||
|
||||
/**
|
||||
* Get font record data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function writeFont()
|
||||
{
|
||||
$font_outline = self::$notImplemented;
|
||||
$font_shadow = self::$notImplemented;
|
||||
|
||||
$icv = $this->colorIndex; // Index to color palette
|
||||
if ($this->font->getSuperscript()) {
|
||||
$sss = 1;
|
||||
} elseif ($this->font->getSubscript()) {
|
||||
$sss = 2;
|
||||
} else {
|
||||
$sss = 0;
|
||||
}
|
||||
$bFamily = 0; // Font family
|
||||
$bCharSet = \PhpOffice\PhpSpreadsheet\Shared\Font::getCharsetFromFontName((string) $this->font->getName()); // Character set
|
||||
|
||||
$record = 0x31; // Record identifier
|
||||
$reserved = 0x00; // Reserved
|
||||
$grbit = 0x00; // Font attributes
|
||||
if ($this->font->getItalic()) {
|
||||
$grbit |= 0x02;
|
||||
}
|
||||
if ($this->font->getStrikethrough()) {
|
||||
$grbit |= 0x08;
|
||||
}
|
||||
if ($font_outline) {
|
||||
$grbit |= 0x10;
|
||||
}
|
||||
if ($font_shadow) {
|
||||
$grbit |= 0x20;
|
||||
}
|
||||
|
||||
$data = pack(
|
||||
'vvvvvCCCC',
|
||||
// Fontsize (in twips)
|
||||
$this->font->getSize() * 20,
|
||||
$grbit,
|
||||
// Colour
|
||||
$icv,
|
||||
// Font weight
|
||||
self::mapBold($this->font->getBold()),
|
||||
// Superscript/Subscript
|
||||
$sss,
|
||||
self::mapUnderline((string) $this->font->getUnderline()),
|
||||
$bFamily,
|
||||
$bCharSet,
|
||||
$reserved
|
||||
);
|
||||
$data .= StringHelper::UTF8toBIFF8UnicodeShort((string) $this->font->getName());
|
||||
|
||||
$length = strlen($data);
|
||||
$header = pack('vv', $record, $length);
|
||||
|
||||
return $header . $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map to BIFF5-BIFF8 codes for bold.
|
||||
*/
|
||||
private static function mapBold(?bool $bold): int
|
||||
{
|
||||
if ($bold === true) {
|
||||
return 0x2BC; // 700 = Bold font weight
|
||||
}
|
||||
|
||||
return 0x190; // 400 = Normal font weight
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of BIFF2-BIFF8 codes for underline styles.
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
private static $mapUnderline = [
|
||||
\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_NONE => 0x00,
|
||||
\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE => 0x01,
|
||||
\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE => 0x02,
|
||||
\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLEACCOUNTING => 0x21,
|
||||
\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLEACCOUNTING => 0x22,
|
||||
];
|
||||
|
||||
/**
|
||||
* Map underline.
|
||||
*
|
||||
* @param string $underline
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function mapUnderline($underline)
|
||||
{
|
||||
if (isset(self::$mapUnderline[$underline])) {
|
||||
return self::$mapUnderline[$underline];
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
}
|
1489
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php
vendored
Normal file
1489
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
59
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellAlignment.php
vendored
Normal file
59
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellAlignment.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls\Style;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
|
||||
class CellAlignment
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private static $horizontalMap = [
|
||||
Alignment::HORIZONTAL_GENERAL => 0,
|
||||
Alignment::HORIZONTAL_LEFT => 1,
|
||||
Alignment::HORIZONTAL_RIGHT => 3,
|
||||
Alignment::HORIZONTAL_CENTER => 2,
|
||||
Alignment::HORIZONTAL_CENTER_CONTINUOUS => 6,
|
||||
Alignment::HORIZONTAL_JUSTIFY => 5,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private static $verticalMap = [
|
||||
Alignment::VERTICAL_BOTTOM => 2,
|
||||
Alignment::VERTICAL_TOP => 0,
|
||||
Alignment::VERTICAL_CENTER => 1,
|
||||
Alignment::VERTICAL_JUSTIFY => 3,
|
||||
];
|
||||
|
||||
public static function horizontal(Alignment $alignment): int
|
||||
{
|
||||
$horizontalAlignment = $alignment->getHorizontal();
|
||||
|
||||
if (is_string($horizontalAlignment) && array_key_exists($horizontalAlignment, self::$horizontalMap)) {
|
||||
return self::$horizontalMap[$horizontalAlignment];
|
||||
}
|
||||
|
||||
return self::$horizontalMap[Alignment::HORIZONTAL_GENERAL];
|
||||
}
|
||||
|
||||
public static function wrap(Alignment $alignment): int
|
||||
{
|
||||
$wrap = $alignment->getWrapText();
|
||||
|
||||
return ($wrap === true) ? 1 : 0;
|
||||
}
|
||||
|
||||
public static function vertical(Alignment $alignment): int
|
||||
{
|
||||
$verticalAlignment = $alignment->getVertical();
|
||||
|
||||
if (is_string($verticalAlignment) && array_key_exists($verticalAlignment, self::$verticalMap)) {
|
||||
return self::$verticalMap[$verticalAlignment];
|
||||
}
|
||||
|
||||
return self::$verticalMap[Alignment::VERTICAL_BOTTOM];
|
||||
}
|
||||
}
|
39
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellBorder.php
vendored
Normal file
39
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellBorder.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls\Style;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
|
||||
class CellBorder
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected static $styleMap = [
|
||||
Border::BORDER_NONE => 0x00,
|
||||
Border::BORDER_THIN => 0x01,
|
||||
Border::BORDER_MEDIUM => 0x02,
|
||||
Border::BORDER_DASHED => 0x03,
|
||||
Border::BORDER_DOTTED => 0x04,
|
||||
Border::BORDER_THICK => 0x05,
|
||||
Border::BORDER_DOUBLE => 0x06,
|
||||
Border::BORDER_HAIR => 0x07,
|
||||
Border::BORDER_MEDIUMDASHED => 0x08,
|
||||
Border::BORDER_DASHDOT => 0x09,
|
||||
Border::BORDER_MEDIUMDASHDOT => 0x0A,
|
||||
Border::BORDER_DASHDOTDOT => 0x0B,
|
||||
Border::BORDER_MEDIUMDASHDOTDOT => 0x0C,
|
||||
Border::BORDER_SLANTDASHDOT => 0x0D,
|
||||
];
|
||||
|
||||
public static function style(Border $border): int
|
||||
{
|
||||
$borderStyle = $border->getBorderStyle();
|
||||
|
||||
if (is_string($borderStyle) && array_key_exists($borderStyle, self::$styleMap)) {
|
||||
return self::$styleMap[$borderStyle];
|
||||
}
|
||||
|
||||
return self::$styleMap[Border::BORDER_NONE];
|
||||
}
|
||||
}
|
46
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellFill.php
vendored
Normal file
46
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellFill.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls\Style;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
|
||||
class CellFill
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected static $fillStyleMap = [
|
||||
Fill::FILL_NONE => 0x00,
|
||||
Fill::FILL_SOLID => 0x01,
|
||||
Fill::FILL_PATTERN_MEDIUMGRAY => 0x02,
|
||||
Fill::FILL_PATTERN_DARKGRAY => 0x03,
|
||||
Fill::FILL_PATTERN_LIGHTGRAY => 0x04,
|
||||
Fill::FILL_PATTERN_DARKHORIZONTAL => 0x05,
|
||||
Fill::FILL_PATTERN_DARKVERTICAL => 0x06,
|
||||
Fill::FILL_PATTERN_DARKDOWN => 0x07,
|
||||
Fill::FILL_PATTERN_DARKUP => 0x08,
|
||||
Fill::FILL_PATTERN_DARKGRID => 0x09,
|
||||
Fill::FILL_PATTERN_DARKTRELLIS => 0x0A,
|
||||
Fill::FILL_PATTERN_LIGHTHORIZONTAL => 0x0B,
|
||||
Fill::FILL_PATTERN_LIGHTVERTICAL => 0x0C,
|
||||
Fill::FILL_PATTERN_LIGHTDOWN => 0x0D,
|
||||
Fill::FILL_PATTERN_LIGHTUP => 0x0E,
|
||||
Fill::FILL_PATTERN_LIGHTGRID => 0x0F,
|
||||
Fill::FILL_PATTERN_LIGHTTRELLIS => 0x10,
|
||||
Fill::FILL_PATTERN_GRAY125 => 0x11,
|
||||
Fill::FILL_PATTERN_GRAY0625 => 0x12,
|
||||
Fill::FILL_GRADIENT_LINEAR => 0x00, // does not exist in BIFF8
|
||||
Fill::FILL_GRADIENT_PATH => 0x00, // does not exist in BIFF8
|
||||
];
|
||||
|
||||
public static function style(Fill $fill): int
|
||||
{
|
||||
$fillStyle = $fill->getFillType();
|
||||
|
||||
if (is_string($fillStyle) && array_key_exists($fillStyle, self::$fillStyleMap)) {
|
||||
return self::$fillStyleMap[$fillStyle];
|
||||
}
|
||||
|
||||
return self::$fillStyleMap[Fill::FILL_NONE];
|
||||
}
|
||||
}
|
90
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/ColorMap.php
vendored
Normal file
90
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/ColorMap.php
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls\Style;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||
|
||||
class ColorMap
|
||||
{
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private static $colorMap = [
|
||||
'#000000' => 0x08,
|
||||
'#FFFFFF' => 0x09,
|
||||
'#FF0000' => 0x0A,
|
||||
'#00FF00' => 0x0B,
|
||||
'#0000FF' => 0x0C,
|
||||
'#FFFF00' => 0x0D,
|
||||
'#FF00FF' => 0x0E,
|
||||
'#00FFFF' => 0x0F,
|
||||
'#800000' => 0x10,
|
||||
'#008000' => 0x11,
|
||||
'#000080' => 0x12,
|
||||
'#808000' => 0x13,
|
||||
'#800080' => 0x14,
|
||||
'#008080' => 0x15,
|
||||
'#C0C0C0' => 0x16,
|
||||
'#808080' => 0x17,
|
||||
'#9999FF' => 0x18,
|
||||
'#993366' => 0x19,
|
||||
'#FFFFCC' => 0x1A,
|
||||
'#CCFFFF' => 0x1B,
|
||||
'#660066' => 0x1C,
|
||||
'#FF8080' => 0x1D,
|
||||
'#0066CC' => 0x1E,
|
||||
'#CCCCFF' => 0x1F,
|
||||
// '#000080' => 0x20,
|
||||
// '#FF00FF' => 0x21,
|
||||
// '#FFFF00' => 0x22,
|
||||
// '#00FFFF' => 0x23,
|
||||
// '#800080' => 0x24,
|
||||
// '#800000' => 0x25,
|
||||
// '#008080' => 0x26,
|
||||
// '#0000FF' => 0x27,
|
||||
'#00CCFF' => 0x28,
|
||||
// '#CCFFFF' => 0x29,
|
||||
'#CCFFCC' => 0x2A,
|
||||
'#FFFF99' => 0x2B,
|
||||
'#99CCFF' => 0x2C,
|
||||
'#FF99CC' => 0x2D,
|
||||
'#CC99FF' => 0x2E,
|
||||
'#FFCC99' => 0x2F,
|
||||
'#3366FF' => 0x30,
|
||||
'#33CCCC' => 0x31,
|
||||
'#99CC00' => 0x32,
|
||||
'#FFCC00' => 0x33,
|
||||
'#FF9900' => 0x34,
|
||||
'#FF6600' => 0x35,
|
||||
'#666699' => 0x36,
|
||||
'#969696' => 0x37,
|
||||
'#003366' => 0x38,
|
||||
'#339966' => 0x39,
|
||||
'#003300' => 0x3A,
|
||||
'#333300' => 0x3B,
|
||||
'#993300' => 0x3C,
|
||||
// '#993366' => 0x3D,
|
||||
'#333399' => 0x3E,
|
||||
'#333333' => 0x3F,
|
||||
];
|
||||
|
||||
public static function lookup(Color $color, int $defaultIndex = 0x00): int
|
||||
{
|
||||
$colorRgb = $color->getRGB();
|
||||
if (is_string($colorRgb) && array_key_exists("#{$colorRgb}", self::$colorMap)) {
|
||||
return self::$colorMap["#{$colorRgb}"];
|
||||
}
|
||||
|
||||
// TODO Try and map RGB value to nearest colour within the define pallette
|
||||
// $red = Color::getRed($colorRgb, false);
|
||||
// $green = Color::getGreen($colorRgb, false);
|
||||
// $blue = Color::getBlue($colorRgb, false);
|
||||
|
||||
// $paletteSpace = 3;
|
||||
// $newColor = ($red * $paletteSpace / 256) * ($paletteSpace * $paletteSpace) +
|
||||
// ($green * $paletteSpace / 256) * $paletteSpace +
|
||||
// ($blue * $paletteSpace / 256);
|
||||
|
||||
return $defaultIndex;
|
||||
}
|
||||
}
|
1193
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php
vendored
Normal file
1193
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3230
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php
vendored
Normal file
3230
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
418
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Xf.php
vendored
Normal file
418
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Xf.php
vendored
Normal file
@ -0,0 +1,418 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls\Style\CellAlignment;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls\Style\CellBorder;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls\Style\CellFill;
|
||||
|
||||
// Original file header of PEAR::Spreadsheet_Excel_Writer_Format (used as the base for this class):
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// /*
|
||||
// * Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
|
||||
// *
|
||||
// * The majority of this is _NOT_ my code. I simply ported it from the
|
||||
// * PERL Spreadsheet::WriteExcel module.
|
||||
// *
|
||||
// * The author of the Spreadsheet::WriteExcel module is John McNamara
|
||||
// * <jmcnamara@cpan.org>
|
||||
// *
|
||||
// * I _DO_ maintain this code, and John McNamara has nothing to do with the
|
||||
// * porting of this code to PHP. Any questions directly related to this
|
||||
// * class library should be directed to me.
|
||||
// *
|
||||
// * License Information:
|
||||
// *
|
||||
// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
|
||||
// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
|
||||
// *
|
||||
// * This library is free software; you can redistribute it and/or
|
||||
// * modify it under the terms of the GNU Lesser General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2.1 of the License, or (at your option) any later version.
|
||||
// *
|
||||
// * This library is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// * Lesser General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU Lesser General Public
|
||||
// * License along with this library; if not, write to the Free Software
|
||||
// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// */
|
||||
class Xf
|
||||
{
|
||||
/**
|
||||
* Style XF or a cell XF ?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isStyleXf;
|
||||
|
||||
/**
|
||||
* Index to the FONT record. Index 4 does not exist.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $fontIndex;
|
||||
|
||||
/**
|
||||
* An index (2 bytes) to a FORMAT record (number format).
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $numberFormatIndex;
|
||||
|
||||
/**
|
||||
* 1 bit, apparently not used.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $textJustLast;
|
||||
|
||||
/**
|
||||
* The cell's foreground color.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $foregroundColor;
|
||||
|
||||
/**
|
||||
* The cell's background color.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $backgroundColor;
|
||||
|
||||
/**
|
||||
* Color of the bottom border of the cell.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $bottomBorderColor;
|
||||
|
||||
/**
|
||||
* Color of the top border of the cell.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $topBorderColor;
|
||||
|
||||
/**
|
||||
* Color of the left border of the cell.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $leftBorderColor;
|
||||
|
||||
/**
|
||||
* Color of the right border of the cell.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $rightBorderColor;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $diag;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $diagColor;
|
||||
|
||||
/**
|
||||
* @var Style
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Style $style The XF format
|
||||
*/
|
||||
public function __construct(Style $style)
|
||||
{
|
||||
$this->isStyleXf = false;
|
||||
$this->fontIndex = 0;
|
||||
|
||||
$this->numberFormatIndex = 0;
|
||||
|
||||
$this->textJustLast = 0;
|
||||
|
||||
$this->foregroundColor = 0x40;
|
||||
$this->backgroundColor = 0x41;
|
||||
|
||||
$this->diag = 0;
|
||||
|
||||
$this->bottomBorderColor = 0x40;
|
||||
$this->topBorderColor = 0x40;
|
||||
$this->leftBorderColor = 0x40;
|
||||
$this->rightBorderColor = 0x40;
|
||||
$this->diagColor = 0x40;
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an Excel BIFF XF record (style or cell).
|
||||
*
|
||||
* @return string The XF record
|
||||
*/
|
||||
public function writeXf()
|
||||
{
|
||||
// Set the type of the XF record and some of the attributes.
|
||||
if ($this->isStyleXf) {
|
||||
$style = 0xFFF5;
|
||||
} else {
|
||||
$style = self::mapLocked($this->style->getProtection()->getLocked());
|
||||
$style |= self::mapHidden($this->style->getProtection()->getHidden()) << 1;
|
||||
}
|
||||
|
||||
// Flags to indicate if attributes have been set.
|
||||
$atr_num = ($this->numberFormatIndex != 0) ? 1 : 0;
|
||||
$atr_fnt = ($this->fontIndex != 0) ? 1 : 0;
|
||||
$atr_alc = ((int) $this->style->getAlignment()->getWrapText()) ? 1 : 0;
|
||||
$atr_bdr = (CellBorder::style($this->style->getBorders()->getBottom()) ||
|
||||
CellBorder::style($this->style->getBorders()->getTop()) ||
|
||||
CellBorder::style($this->style->getBorders()->getLeft()) ||
|
||||
CellBorder::style($this->style->getBorders()->getRight())) ? 1 : 0;
|
||||
$atr_pat = ($this->foregroundColor != 0x40) ? 1 : 0;
|
||||
$atr_pat = ($this->backgroundColor != 0x41) ? 1 : $atr_pat;
|
||||
$atr_pat = CellFill::style($this->style->getFill()) ? 1 : $atr_pat;
|
||||
$atr_prot = self::mapLocked($this->style->getProtection()->getLocked())
|
||||
| self::mapHidden($this->style->getProtection()->getHidden());
|
||||
|
||||
// Zero the default border colour if the border has not been set.
|
||||
if (CellBorder::style($this->style->getBorders()->getBottom()) == 0) {
|
||||
$this->bottomBorderColor = 0;
|
||||
}
|
||||
if (CellBorder::style($this->style->getBorders()->getTop()) == 0) {
|
||||
$this->topBorderColor = 0;
|
||||
}
|
||||
if (CellBorder::style($this->style->getBorders()->getRight()) == 0) {
|
||||
$this->rightBorderColor = 0;
|
||||
}
|
||||
if (CellBorder::style($this->style->getBorders()->getLeft()) == 0) {
|
||||
$this->leftBorderColor = 0;
|
||||
}
|
||||
if (CellBorder::style($this->style->getBorders()->getDiagonal()) == 0) {
|
||||
$this->diagColor = 0;
|
||||
}
|
||||
|
||||
$record = 0x00E0; // Record identifier
|
||||
$length = 0x0014; // Number of bytes to follow
|
||||
|
||||
$ifnt = $this->fontIndex; // Index to FONT record
|
||||
$ifmt = $this->numberFormatIndex; // Index to FORMAT record
|
||||
|
||||
// Alignment
|
||||
$align = CellAlignment::horizontal($this->style->getAlignment());
|
||||
$align |= CellAlignment::wrap($this->style->getAlignment()) << 3;
|
||||
$align |= CellAlignment::vertical($this->style->getAlignment()) << 4;
|
||||
$align |= $this->textJustLast << 7;
|
||||
|
||||
$used_attrib = $atr_num << 2;
|
||||
$used_attrib |= $atr_fnt << 3;
|
||||
$used_attrib |= $atr_alc << 4;
|
||||
$used_attrib |= $atr_bdr << 5;
|
||||
$used_attrib |= $atr_pat << 6;
|
||||
$used_attrib |= $atr_prot << 7;
|
||||
|
||||
$icv = $this->foregroundColor; // fg and bg pattern colors
|
||||
$icv |= $this->backgroundColor << 7;
|
||||
|
||||
$border1 = CellBorder::style($this->style->getBorders()->getLeft()); // Border line style and color
|
||||
$border1 |= CellBorder::style($this->style->getBorders()->getRight()) << 4;
|
||||
$border1 |= CellBorder::style($this->style->getBorders()->getTop()) << 8;
|
||||
$border1 |= CellBorder::style($this->style->getBorders()->getBottom()) << 12;
|
||||
$border1 |= $this->leftBorderColor << 16;
|
||||
$border1 |= $this->rightBorderColor << 23;
|
||||
|
||||
$diagonalDirection = $this->style->getBorders()->getDiagonalDirection();
|
||||
$diag_tl_to_rb = $diagonalDirection == Borders::DIAGONAL_BOTH
|
||||
|| $diagonalDirection == Borders::DIAGONAL_DOWN;
|
||||
$diag_tr_to_lb = $diagonalDirection == Borders::DIAGONAL_BOTH
|
||||
|| $diagonalDirection == Borders::DIAGONAL_UP;
|
||||
$border1 |= $diag_tl_to_rb << 30;
|
||||
$border1 |= $diag_tr_to_lb << 31;
|
||||
|
||||
$border2 = $this->topBorderColor; // Border color
|
||||
$border2 |= $this->bottomBorderColor << 7;
|
||||
$border2 |= $this->diagColor << 14;
|
||||
$border2 |= CellBorder::style($this->style->getBorders()->getDiagonal()) << 21;
|
||||
$border2 |= CellFill::style($this->style->getFill()) << 26;
|
||||
|
||||
$header = pack('vv', $record, $length);
|
||||
|
||||
//BIFF8 options: identation, shrinkToFit and text direction
|
||||
$biff8_options = $this->style->getAlignment()->getIndent();
|
||||
$biff8_options |= (int) $this->style->getAlignment()->getShrinkToFit() << 4;
|
||||
|
||||
$data = pack('vvvC', $ifnt, $ifmt, $style, $align);
|
||||
$data .= pack('CCC', self::mapTextRotation($this->style->getAlignment()->getTextRotation()), $biff8_options, $used_attrib);
|
||||
$data .= pack('VVv', $border1, $border2, $icv);
|
||||
|
||||
return $header . $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a style XF ?
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setIsStyleXf($value): void
|
||||
{
|
||||
$this->isStyleXf = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's bottom border color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setBottomColor($colorIndex): void
|
||||
{
|
||||
$this->bottomBorderColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's top border color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setTopColor($colorIndex): void
|
||||
{
|
||||
$this->topBorderColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's left border color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setLeftColor($colorIndex): void
|
||||
{
|
||||
$this->leftBorderColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's right border color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setRightColor($colorIndex): void
|
||||
{
|
||||
$this->rightBorderColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's diagonal border color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setDiagColor($colorIndex): void
|
||||
{
|
||||
$this->diagColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's foreground color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setFgColor($colorIndex): void
|
||||
{
|
||||
$this->foregroundColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell's background color.
|
||||
*
|
||||
* @param int $colorIndex Color index
|
||||
*/
|
||||
public function setBgColor($colorIndex): void
|
||||
{
|
||||
$this->backgroundColor = $colorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the index to the number format record
|
||||
* It can be date, time, currency, etc...
|
||||
*
|
||||
* @param int $numberFormatIndex Index to format record
|
||||
*/
|
||||
public function setNumberFormatIndex($numberFormatIndex): void
|
||||
{
|
||||
$this->numberFormatIndex = $numberFormatIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the font index.
|
||||
*
|
||||
* @param int $value Font index, note that value 4 does not exist
|
||||
*/
|
||||
public function setFontIndex($value): void
|
||||
{
|
||||
$this->fontIndex = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map to BIFF8 codes for text rotation angle.
|
||||
*
|
||||
* @param int $textRotation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function mapTextRotation($textRotation)
|
||||
{
|
||||
if ($textRotation >= 0) {
|
||||
return $textRotation;
|
||||
}
|
||||
if ($textRotation == Alignment::TEXTROTATION_STACK_PHPSPREADSHEET) {
|
||||
return Alignment::TEXTROTATION_STACK_EXCEL;
|
||||
}
|
||||
|
||||
return 90 - $textRotation;
|
||||
}
|
||||
|
||||
private const LOCK_ARRAY = [
|
||||
Protection::PROTECTION_INHERIT => 1,
|
||||
Protection::PROTECTION_PROTECTED => 1,
|
||||
Protection::PROTECTION_UNPROTECTED => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* Map locked values.
|
||||
*
|
||||
* @param string $locked
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function mapLocked($locked)
|
||||
{
|
||||
return array_key_exists($locked, self::LOCK_ARRAY) ? self::LOCK_ARRAY[$locked] : 1;
|
||||
}
|
||||
|
||||
private const HIDDEN_ARRAY = [
|
||||
Protection::PROTECTION_INHERIT => 0,
|
||||
Protection::PROTECTION_PROTECTED => 1,
|
||||
Protection::PROTECTION_UNPROTECTED => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* Map hidden.
|
||||
*
|
||||
* @param string $hidden
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function mapHidden($hidden)
|
||||
{
|
||||
return array_key_exists($hidden, self::HIDDEN_ARRAY) ? self::HIDDEN_ARRAY[$hidden] : 0;
|
||||
}
|
||||
}
|
755
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php
vendored
Normal file
755
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php
vendored
Normal file
@ -0,0 +1,755 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\HashTable;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing as WorksheetDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Comments;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\ContentTypes;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\DocProps;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Drawing;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsRibbon;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsVBA;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Style;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Table;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Theme;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Workbook;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet;
|
||||
use ZipArchive;
|
||||
use ZipStream\Exception\OverflowException;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
class Xlsx extends BaseWriter
|
||||
{
|
||||
/**
|
||||
* Office2003 compatibility.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $office2003compatibility = false;
|
||||
|
||||
/**
|
||||
* Private Spreadsheet.
|
||||
*
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
private $spreadSheet;
|
||||
|
||||
/**
|
||||
* Private string table.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $stringTable = [];
|
||||
|
||||
/**
|
||||
* Private unique Conditional HashTable.
|
||||
*
|
||||
* @var HashTable<Conditional>
|
||||
*/
|
||||
private $stylesConditionalHashTable;
|
||||
|
||||
/**
|
||||
* Private unique Style HashTable.
|
||||
*
|
||||
* @var HashTable<\PhpOffice\PhpSpreadsheet\Style\Style>
|
||||
*/
|
||||
private $styleHashTable;
|
||||
|
||||
/**
|
||||
* Private unique Fill HashTable.
|
||||
*
|
||||
* @var HashTable<Fill>
|
||||
*/
|
||||
private $fillHashTable;
|
||||
|
||||
/**
|
||||
* Private unique \PhpOffice\PhpSpreadsheet\Style\Font HashTable.
|
||||
*
|
||||
* @var HashTable<Font>
|
||||
*/
|
||||
private $fontHashTable;
|
||||
|
||||
/**
|
||||
* Private unique Borders HashTable.
|
||||
*
|
||||
* @var HashTable<Borders>
|
||||
*/
|
||||
private $bordersHashTable;
|
||||
|
||||
/**
|
||||
* Private unique NumberFormat HashTable.
|
||||
*
|
||||
* @var HashTable<NumberFormat>
|
||||
*/
|
||||
private $numFmtHashTable;
|
||||
|
||||
/**
|
||||
* Private unique \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable.
|
||||
*
|
||||
* @var HashTable<BaseDrawing>
|
||||
*/
|
||||
private $drawingHashTable;
|
||||
|
||||
/**
|
||||
* Private handle for zip stream.
|
||||
*
|
||||
* @var ZipStream
|
||||
*/
|
||||
private $zip;
|
||||
|
||||
/**
|
||||
* @var Chart
|
||||
*/
|
||||
private $writerPartChart;
|
||||
|
||||
/**
|
||||
* @var Comments
|
||||
*/
|
||||
private $writerPartComments;
|
||||
|
||||
/**
|
||||
* @var ContentTypes
|
||||
*/
|
||||
private $writerPartContentTypes;
|
||||
|
||||
/**
|
||||
* @var DocProps
|
||||
*/
|
||||
private $writerPartDocProps;
|
||||
|
||||
/**
|
||||
* @var Drawing
|
||||
*/
|
||||
private $writerPartDrawing;
|
||||
|
||||
/**
|
||||
* @var Rels
|
||||
*/
|
||||
private $writerPartRels;
|
||||
|
||||
/**
|
||||
* @var RelsRibbon
|
||||
*/
|
||||
private $writerPartRelsRibbon;
|
||||
|
||||
/**
|
||||
* @var RelsVBA
|
||||
*/
|
||||
private $writerPartRelsVBA;
|
||||
|
||||
/**
|
||||
* @var StringTable
|
||||
*/
|
||||
private $writerPartStringTable;
|
||||
|
||||
/**
|
||||
* @var Style
|
||||
*/
|
||||
private $writerPartStyle;
|
||||
|
||||
/**
|
||||
* @var Theme
|
||||
*/
|
||||
private $writerPartTheme;
|
||||
|
||||
/**
|
||||
* @var Table
|
||||
*/
|
||||
private $writerPartTable;
|
||||
|
||||
/**
|
||||
* @var Workbook
|
||||
*/
|
||||
private $writerPartWorkbook;
|
||||
|
||||
/**
|
||||
* @var Worksheet
|
||||
*/
|
||||
private $writerPartWorksheet;
|
||||
|
||||
/**
|
||||
* Create a new Xlsx Writer.
|
||||
*/
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Assign PhpSpreadsheet
|
||||
$this->setSpreadsheet($spreadsheet);
|
||||
|
||||
$this->writerPartChart = new Chart($this);
|
||||
$this->writerPartComments = new Comments($this);
|
||||
$this->writerPartContentTypes = new ContentTypes($this);
|
||||
$this->writerPartDocProps = new DocProps($this);
|
||||
$this->writerPartDrawing = new Drawing($this);
|
||||
$this->writerPartRels = new Rels($this);
|
||||
$this->writerPartRelsRibbon = new RelsRibbon($this);
|
||||
$this->writerPartRelsVBA = new RelsVBA($this);
|
||||
$this->writerPartStringTable = new StringTable($this);
|
||||
$this->writerPartStyle = new Style($this);
|
||||
$this->writerPartTheme = new Theme($this);
|
||||
$this->writerPartTable = new Table($this);
|
||||
$this->writerPartWorkbook = new Workbook($this);
|
||||
$this->writerPartWorksheet = new Worksheet($this);
|
||||
|
||||
// Set HashTable variables
|
||||
// @phpstan-ignore-next-line
|
||||
$this->bordersHashTable = new HashTable();
|
||||
// @phpstan-ignore-next-line
|
||||
$this->drawingHashTable = new HashTable();
|
||||
// @phpstan-ignore-next-line
|
||||
$this->fillHashTable = new HashTable();
|
||||
// @phpstan-ignore-next-line
|
||||
$this->fontHashTable = new HashTable();
|
||||
// @phpstan-ignore-next-line
|
||||
$this->numFmtHashTable = new HashTable();
|
||||
// @phpstan-ignore-next-line
|
||||
$this->styleHashTable = new HashTable();
|
||||
// @phpstan-ignore-next-line
|
||||
$this->stylesConditionalHashTable = new HashTable();
|
||||
}
|
||||
|
||||
public function getWriterPartChart(): Chart
|
||||
{
|
||||
return $this->writerPartChart;
|
||||
}
|
||||
|
||||
public function getWriterPartComments(): Comments
|
||||
{
|
||||
return $this->writerPartComments;
|
||||
}
|
||||
|
||||
public function getWriterPartContentTypes(): ContentTypes
|
||||
{
|
||||
return $this->writerPartContentTypes;
|
||||
}
|
||||
|
||||
public function getWriterPartDocProps(): DocProps
|
||||
{
|
||||
return $this->writerPartDocProps;
|
||||
}
|
||||
|
||||
public function getWriterPartDrawing(): Drawing
|
||||
{
|
||||
return $this->writerPartDrawing;
|
||||
}
|
||||
|
||||
public function getWriterPartRels(): Rels
|
||||
{
|
||||
return $this->writerPartRels;
|
||||
}
|
||||
|
||||
public function getWriterPartRelsRibbon(): RelsRibbon
|
||||
{
|
||||
return $this->writerPartRelsRibbon;
|
||||
}
|
||||
|
||||
public function getWriterPartRelsVBA(): RelsVBA
|
||||
{
|
||||
return $this->writerPartRelsVBA;
|
||||
}
|
||||
|
||||
public function getWriterPartStringTable(): StringTable
|
||||
{
|
||||
return $this->writerPartStringTable;
|
||||
}
|
||||
|
||||
public function getWriterPartStyle(): Style
|
||||
{
|
||||
return $this->writerPartStyle;
|
||||
}
|
||||
|
||||
public function getWriterPartTheme(): Theme
|
||||
{
|
||||
return $this->writerPartTheme;
|
||||
}
|
||||
|
||||
public function getWriterPartTable(): Table
|
||||
{
|
||||
return $this->writerPartTable;
|
||||
}
|
||||
|
||||
public function getWriterPartWorkbook(): Workbook
|
||||
{
|
||||
return $this->writerPartWorkbook;
|
||||
}
|
||||
|
||||
public function getWriterPartWorksheet(): Worksheet
|
||||
{
|
||||
return $this->writerPartWorksheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param resource|string $filename
|
||||
*/
|
||||
public function save($filename, int $flags = 0): void
|
||||
{
|
||||
$this->processFlags($flags);
|
||||
|
||||
// garbage collect
|
||||
$this->pathNames = [];
|
||||
$this->spreadSheet->garbageCollect();
|
||||
|
||||
$saveDebugLog = Calculation::getInstance($this->spreadSheet)->getDebugLog()->getWriteDebugLog();
|
||||
Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog(false);
|
||||
$saveDateReturnType = Functions::getReturnDateType();
|
||||
Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
|
||||
|
||||
// Create string lookup table
|
||||
$this->stringTable = [];
|
||||
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
|
||||
$this->stringTable = $this->getWriterPartStringTable()->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable);
|
||||
}
|
||||
|
||||
// Create styles dictionaries
|
||||
$this->styleHashTable->addFromSource($this->getWriterPartStyle()->allStyles($this->spreadSheet));
|
||||
$this->stylesConditionalHashTable->addFromSource($this->getWriterPartStyle()->allConditionalStyles($this->spreadSheet));
|
||||
$this->fillHashTable->addFromSource($this->getWriterPartStyle()->allFills($this->spreadSheet));
|
||||
$this->fontHashTable->addFromSource($this->getWriterPartStyle()->allFonts($this->spreadSheet));
|
||||
$this->bordersHashTable->addFromSource($this->getWriterPartStyle()->allBorders($this->spreadSheet));
|
||||
$this->numFmtHashTable->addFromSource($this->getWriterPartStyle()->allNumberFormats($this->spreadSheet));
|
||||
|
||||
// Create drawing dictionary
|
||||
$this->drawingHashTable->addFromSource($this->getWriterPartDrawing()->allDrawings($this->spreadSheet));
|
||||
|
||||
$zipContent = [];
|
||||
// Add [Content_Types].xml to ZIP file
|
||||
$zipContent['[Content_Types].xml'] = $this->getWriterPartContentTypes()->writeContentTypes($this->spreadSheet, $this->includeCharts);
|
||||
|
||||
//if hasMacros, add the vbaProject.bin file, Certificate file(if exists)
|
||||
if ($this->spreadSheet->hasMacros()) {
|
||||
$macrosCode = $this->spreadSheet->getMacrosCode();
|
||||
if ($macrosCode !== null) {
|
||||
// we have the code ?
|
||||
$zipContent['xl/vbaProject.bin'] = $macrosCode; //allways in 'xl', allways named vbaProject.bin
|
||||
if ($this->spreadSheet->hasMacrosCertificate()) {
|
||||
//signed macros ?
|
||||
// Yes : add the certificate file and the related rels file
|
||||
$zipContent['xl/vbaProjectSignature.bin'] = $this->spreadSheet->getMacrosCertificate();
|
||||
$zipContent['xl/_rels/vbaProject.bin.rels'] = $this->getWriterPartRelsVBA()->writeVBARelationships();
|
||||
}
|
||||
}
|
||||
}
|
||||
//a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels)
|
||||
if ($this->spreadSheet->hasRibbon()) {
|
||||
$tmpRibbonTarget = $this->spreadSheet->getRibbonXMLData('target');
|
||||
$tmpRibbonTarget = is_string($tmpRibbonTarget) ? $tmpRibbonTarget : '';
|
||||
$zipContent[$tmpRibbonTarget] = $this->spreadSheet->getRibbonXMLData('data');
|
||||
if ($this->spreadSheet->hasRibbonBinObjects()) {
|
||||
$tmpRootPath = dirname($tmpRibbonTarget) . '/';
|
||||
$ribbonBinObjects = $this->spreadSheet->getRibbonBinObjects('data'); //the files to write
|
||||
if (is_array($ribbonBinObjects)) {
|
||||
foreach ($ribbonBinObjects as $aPath => $aContent) {
|
||||
$zipContent[$tmpRootPath . $aPath] = $aContent;
|
||||
}
|
||||
}
|
||||
//the rels for files
|
||||
$zipContent[$tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels'] = $this->getWriterPartRelsRibbon()->writeRibbonRelationships($this->spreadSheet);
|
||||
}
|
||||
}
|
||||
|
||||
// Add relationships to ZIP file
|
||||
$zipContent['_rels/.rels'] = $this->getWriterPartRels()->writeRelationships($this->spreadSheet);
|
||||
$zipContent['xl/_rels/workbook.xml.rels'] = $this->getWriterPartRels()->writeWorkbookRelationships($this->spreadSheet);
|
||||
|
||||
// Add document properties to ZIP file
|
||||
$zipContent['docProps/app.xml'] = $this->getWriterPartDocProps()->writeDocPropsApp($this->spreadSheet);
|
||||
$zipContent['docProps/core.xml'] = $this->getWriterPartDocProps()->writeDocPropsCore($this->spreadSheet);
|
||||
$customPropertiesPart = $this->getWriterPartDocProps()->writeDocPropsCustom($this->spreadSheet);
|
||||
if ($customPropertiesPart !== null) {
|
||||
$zipContent['docProps/custom.xml'] = $customPropertiesPart;
|
||||
}
|
||||
|
||||
// Add theme to ZIP file
|
||||
$zipContent['xl/theme/theme1.xml'] = $this->getWriterPartTheme()->writeTheme();
|
||||
|
||||
// Add string table to ZIP file
|
||||
$zipContent['xl/sharedStrings.xml'] = $this->getWriterPartStringTable()->writeStringTable($this->stringTable);
|
||||
|
||||
// Add styles to ZIP file
|
||||
$zipContent['xl/styles.xml'] = $this->getWriterPartStyle()->writeStyles($this->spreadSheet);
|
||||
|
||||
// Add workbook to ZIP file
|
||||
$zipContent['xl/workbook.xml'] = $this->getWriterPartWorkbook()->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas);
|
||||
|
||||
$chartCount = 0;
|
||||
// Add worksheets
|
||||
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
|
||||
$zipContent['xl/worksheets/sheet' . ($i + 1) . '.xml'] = $this->getWriterPartWorksheet()->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts);
|
||||
if ($this->includeCharts) {
|
||||
$charts = $this->spreadSheet->getSheet($i)->getChartCollection();
|
||||
if (count($charts) > 0) {
|
||||
foreach ($charts as $chart) {
|
||||
$zipContent['xl/charts/chart' . ($chartCount + 1) . '.xml'] = $this->getWriterPartChart()->writeChart($chart, $this->preCalculateFormulas);
|
||||
++$chartCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$chartRef1 = 0;
|
||||
$tableRef1 = 1;
|
||||
// Add worksheet relationships (drawings, ...)
|
||||
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
|
||||
// Add relationships
|
||||
$zipContent['xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels'] = $this->getWriterPartRels()->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts, $tableRef1);
|
||||
|
||||
// Add unparsedLoadedData
|
||||
$sheetCodeName = $this->spreadSheet->getSheet($i)->getCodeName();
|
||||
$unparsedLoadedData = $this->spreadSheet->getUnparsedLoadedData();
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'] as $ctrlProp) {
|
||||
$zipContent[$ctrlProp['filePath']] = $ctrlProp['content'];
|
||||
}
|
||||
}
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'] as $ctrlProp) {
|
||||
$zipContent[$ctrlProp['filePath']] = $ctrlProp['content'];
|
||||
}
|
||||
}
|
||||
|
||||
$drawings = $this->spreadSheet->getSheet($i)->getDrawingCollection();
|
||||
$drawingCount = count($drawings);
|
||||
if ($this->includeCharts) {
|
||||
$chartCount = $this->spreadSheet->getSheet($i)->getChartCount();
|
||||
}
|
||||
|
||||
// Add drawing and image relationship parts
|
||||
if (($drawingCount > 0) || ($chartCount > 0)) {
|
||||
// Drawing relationships
|
||||
$zipContent['xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels'] = $this->getWriterPartRels()->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts);
|
||||
|
||||
// Drawings
|
||||
$zipContent['xl/drawings/drawing' . ($i + 1) . '.xml'] = $this->getWriterPartDrawing()->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts);
|
||||
} elseif (isset($unparsedLoadedData['sheets'][$sheetCodeName]['drawingAlternateContents'])) {
|
||||
// Drawings
|
||||
$zipContent['xl/drawings/drawing' . ($i + 1) . '.xml'] = $this->getWriterPartDrawing()->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts);
|
||||
}
|
||||
|
||||
// Add unparsed drawings
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['Drawings'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['Drawings'] as $relId => $drawingXml) {
|
||||
$drawingFile = array_search($relId, $unparsedLoadedData['sheets'][$sheetCodeName]['drawingOriginalIds']);
|
||||
if ($drawingFile !== false) {
|
||||
//$drawingFile = ltrim($drawingFile, '.');
|
||||
//$zipContent['xl' . $drawingFile] = $drawingXml;
|
||||
$zipContent['xl/drawings/drawing' . ($i + 1) . '.xml'] = $drawingXml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add comment relationship parts
|
||||
if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) {
|
||||
// VML Comments relationships
|
||||
$zipContent['xl/drawings/_rels/vmlDrawing' . ($i + 1) . '.vml.rels'] = $this->getWriterPartRels()->writeVMLDrawingRelationships($this->spreadSheet->getSheet($i));
|
||||
|
||||
// VML Comments
|
||||
$zipContent['xl/drawings/vmlDrawing' . ($i + 1) . '.vml'] = $this->getWriterPartComments()->writeVMLComments($this->spreadSheet->getSheet($i));
|
||||
|
||||
// Comments
|
||||
$zipContent['xl/comments' . ($i + 1) . '.xml'] = $this->getWriterPartComments()->writeComments($this->spreadSheet->getSheet($i));
|
||||
|
||||
// Media
|
||||
foreach ($this->spreadSheet->getSheet($i)->getComments() as $comment) {
|
||||
if ($comment->hasBackgroundImage()) {
|
||||
$image = $comment->getBackgroundImage();
|
||||
$zipContent['xl/media/' . $image->getMediaFilename()] = $this->processDrawing($image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add unparsed relationship parts
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'] as $vmlDrawing) {
|
||||
$zipContent[$vmlDrawing['filePath']] = $vmlDrawing['content'];
|
||||
}
|
||||
}
|
||||
|
||||
// Add header/footer relationship parts
|
||||
if (count($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
|
||||
// VML Drawings
|
||||
$zipContent['xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml'] = $this->getWriterPartDrawing()->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i));
|
||||
|
||||
// VML Drawing relationships
|
||||
$zipContent['xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels'] = $this->getWriterPartRels()->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i));
|
||||
|
||||
// Media
|
||||
foreach ($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) {
|
||||
$zipContent['xl/media/' . $image->getIndexedFilename()] = file_get_contents($image->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
// Add Table parts
|
||||
$tables = $this->spreadSheet->getSheet($i)->getTableCollection();
|
||||
foreach ($tables as $table) {
|
||||
$zipContent['xl/tables/table' . $tableRef1 . '.xml'] = $this->getWriterPartTable()->writeTable($table, $tableRef1++);
|
||||
}
|
||||
}
|
||||
|
||||
// Add media
|
||||
for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) {
|
||||
if ($this->getDrawingHashTable()->getByIndex($i) instanceof WorksheetDrawing) {
|
||||
$imageContents = null;
|
||||
$imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath();
|
||||
if (strpos($imagePath, 'zip://') !== false) {
|
||||
$imagePath = substr($imagePath, 6);
|
||||
$imagePathSplitted = explode('#', $imagePath);
|
||||
|
||||
$imageZip = new ZipArchive();
|
||||
$imageZip->open($imagePathSplitted[0]);
|
||||
$imageContents = $imageZip->getFromName($imagePathSplitted[1]);
|
||||
$imageZip->close();
|
||||
unset($imageZip);
|
||||
} else {
|
||||
$imageContents = file_get_contents($imagePath);
|
||||
}
|
||||
|
||||
$zipContent['xl/media/' . $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()] = $imageContents;
|
||||
} elseif ($this->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) {
|
||||
ob_start();
|
||||
/** @var callable */
|
||||
$callable = $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction();
|
||||
call_user_func(
|
||||
$callable,
|
||||
$this->getDrawingHashTable()->getByIndex($i)->getImageResource()
|
||||
);
|
||||
$imageContents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$zipContent['xl/media/' . $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()] = $imageContents;
|
||||
}
|
||||
}
|
||||
|
||||
Functions::setReturnDateType($saveDateReturnType);
|
||||
Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
|
||||
$this->openFileHandle($filename);
|
||||
|
||||
$options = new Archive();
|
||||
$options->setEnableZip64(false);
|
||||
$options->setOutputStream($this->fileHandle);
|
||||
|
||||
$this->zip = new ZipStream(null, $options);
|
||||
|
||||
$this->addZipFiles($zipContent);
|
||||
|
||||
// Close file
|
||||
try {
|
||||
$this->zip->finish();
|
||||
} catch (OverflowException $e) {
|
||||
throw new WriterException('Could not close resource.');
|
||||
}
|
||||
|
||||
$this->maybeCloseFileHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Spreadsheet object.
|
||||
*
|
||||
* @return Spreadsheet
|
||||
*/
|
||||
public function getSpreadsheet()
|
||||
{
|
||||
return $this->spreadSheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Spreadsheet object.
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet PhpSpreadsheet object
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSpreadsheet(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadSheet = $spreadsheet;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string table.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getStringTable()
|
||||
{
|
||||
return $this->stringTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Style HashTable.
|
||||
*
|
||||
* @return HashTable<\PhpOffice\PhpSpreadsheet\Style\Style>
|
||||
*/
|
||||
public function getStyleHashTable()
|
||||
{
|
||||
return $this->styleHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Conditional HashTable.
|
||||
*
|
||||
* @return HashTable<Conditional>
|
||||
*/
|
||||
public function getStylesConditionalHashTable()
|
||||
{
|
||||
return $this->stylesConditionalHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Fill HashTable.
|
||||
*
|
||||
* @return HashTable<Fill>
|
||||
*/
|
||||
public function getFillHashTable()
|
||||
{
|
||||
return $this->fillHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get \PhpOffice\PhpSpreadsheet\Style\Font HashTable.
|
||||
*
|
||||
* @return HashTable<Font>
|
||||
*/
|
||||
public function getFontHashTable()
|
||||
{
|
||||
return $this->fontHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Borders HashTable.
|
||||
*
|
||||
* @return HashTable<Borders>
|
||||
*/
|
||||
public function getBordersHashTable()
|
||||
{
|
||||
return $this->bordersHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NumberFormat HashTable.
|
||||
*
|
||||
* @return HashTable<NumberFormat>
|
||||
*/
|
||||
public function getNumFmtHashTable()
|
||||
{
|
||||
return $this->numFmtHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable.
|
||||
*
|
||||
* @return HashTable<BaseDrawing>
|
||||
*/
|
||||
public function getDrawingHashTable()
|
||||
{
|
||||
return $this->drawingHashTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Office2003 compatibility.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getOffice2003Compatibility()
|
||||
{
|
||||
return $this->office2003compatibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Office2003 compatibility.
|
||||
*
|
||||
* @param bool $office2003compatibility Office2003 compatibility?
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffice2003Compatibility($office2003compatibility)
|
||||
{
|
||||
$this->office2003compatibility = $office2003compatibility;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
private $pathNames = [];
|
||||
|
||||
private function addZipFile(string $path, string $content): void
|
||||
{
|
||||
if (!in_array($path, $this->pathNames)) {
|
||||
$this->pathNames[] = $path;
|
||||
$this->zip->addFile($path, $content);
|
||||
}
|
||||
}
|
||||
|
||||
private function addZipFiles(array $zipContent): void
|
||||
{
|
||||
foreach ($zipContent as $path => $content) {
|
||||
$this->addZipFile($path, $content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
private function processDrawing(WorksheetDrawing $drawing)
|
||||
{
|
||||
$data = null;
|
||||
$filename = $drawing->getPath();
|
||||
$imageData = getimagesize($filename);
|
||||
|
||||
if (!empty($imageData)) {
|
||||
switch ($imageData[2]) {
|
||||
case 1: // GIF, not supported by BIFF8, we convert to PNG
|
||||
$image = imagecreatefromgif($filename);
|
||||
if ($image !== false) {
|
||||
ob_start();
|
||||
imagepng($image);
|
||||
$data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2: // JPEG
|
||||
$data = file_get_contents($filename);
|
||||
|
||||
break;
|
||||
|
||||
case 3: // PNG
|
||||
$data = file_get_contents($filename);
|
||||
|
||||
break;
|
||||
|
||||
case 6: // Windows DIB (BMP), we convert to PNG
|
||||
$image = imagecreatefrombmp($filename);
|
||||
if ($image !== false) {
|
||||
ob_start();
|
||||
imagepng($image);
|
||||
$data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
125
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/AutoFilter.php
vendored
Normal file
125
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/AutoFilter.php
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as ActualWorksheet;
|
||||
|
||||
class AutoFilter extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write AutoFilter.
|
||||
*/
|
||||
public static function writeAutoFilter(XMLWriter $objWriter, ActualWorksheet $worksheet): void
|
||||
{
|
||||
$autoFilterRange = $worksheet->getAutoFilter()->getRange();
|
||||
if (!empty($autoFilterRange)) {
|
||||
// autoFilter
|
||||
$objWriter->startElement('autoFilter');
|
||||
|
||||
// Strip any worksheet reference from the filter coordinates
|
||||
$range = Coordinate::splitRange($autoFilterRange);
|
||||
$range = $range[0];
|
||||
// Strip any worksheet ref
|
||||
[$ws, $range[0]] = ActualWorksheet::extractSheetTitle($range[0], true);
|
||||
$range = implode(':', $range);
|
||||
|
||||
$objWriter->writeAttribute('ref', str_replace('$', '', $range));
|
||||
|
||||
$columns = $worksheet->getAutoFilter()->getColumns();
|
||||
if (count($columns) > 0) {
|
||||
foreach ($columns as $columnID => $column) {
|
||||
$colId = $worksheet->getAutoFilter()->getColumnOffset($columnID);
|
||||
self::writeAutoFilterColumn($objWriter, $column, $colId);
|
||||
}
|
||||
}
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write AutoFilter's filterColumn.
|
||||
*/
|
||||
public static function writeAutoFilterColumn(XMLWriter $objWriter, Column $column, int $colId): void
|
||||
{
|
||||
$rules = $column->getRules();
|
||||
if (count($rules) > 0) {
|
||||
$objWriter->startElement('filterColumn');
|
||||
$objWriter->writeAttribute('colId', "$colId");
|
||||
|
||||
$objWriter->startElement($column->getFilterType());
|
||||
if ($column->getJoin() == Column::AUTOFILTER_COLUMN_JOIN_AND) {
|
||||
$objWriter->writeAttribute('and', '1');
|
||||
}
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
self::writeAutoFilterColumnRule($column, $rule, $objWriter);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write AutoFilter's filterColumn Rule.
|
||||
*/
|
||||
private static function writeAutoFilterColumnRule(Column $column, Rule $rule, XMLWriter $objWriter): void
|
||||
{
|
||||
if (
|
||||
($column->getFilterType() === Column::AUTOFILTER_FILTERTYPE_FILTER) &&
|
||||
($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_EQUAL) &&
|
||||
($rule->getValue() === '')
|
||||
) {
|
||||
// Filter rule for Blanks
|
||||
$objWriter->writeAttribute('blank', '1');
|
||||
} elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) {
|
||||
// Dynamic Filter Rule
|
||||
$objWriter->writeAttribute('type', $rule->getGrouping());
|
||||
$val = $column->getAttribute('val');
|
||||
if ($val !== null) {
|
||||
$objWriter->writeAttribute('val', "$val");
|
||||
}
|
||||
$maxVal = $column->getAttribute('maxVal');
|
||||
if ($maxVal !== null) {
|
||||
$objWriter->writeAttribute('maxVal', "$maxVal");
|
||||
}
|
||||
} elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) {
|
||||
// Top 10 Filter Rule
|
||||
$ruleValue = $rule->getValue();
|
||||
if (!is_array($ruleValue)) {
|
||||
$objWriter->writeAttribute('val', "$ruleValue");
|
||||
}
|
||||
$objWriter->writeAttribute('percent', (($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0'));
|
||||
$objWriter->writeAttribute('top', (($rule->getGrouping() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1' : '0'));
|
||||
} else {
|
||||
// Filter, DateGroupItem or CustomFilter
|
||||
$objWriter->startElement($rule->getRuleType());
|
||||
|
||||
if ($rule->getOperator() !== Rule::AUTOFILTER_COLUMN_RULE_EQUAL) {
|
||||
$objWriter->writeAttribute('operator', $rule->getOperator());
|
||||
}
|
||||
if ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DATEGROUP) {
|
||||
// Date Group filters
|
||||
$ruleValue = $rule->getValue();
|
||||
if (is_array($ruleValue)) {
|
||||
foreach ($ruleValue as $key => $value) {
|
||||
$objWriter->writeAttribute($key, "$value");
|
||||
}
|
||||
}
|
||||
$objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping());
|
||||
} else {
|
||||
$ruleValue = $rule->getValue();
|
||||
if (!is_array($ruleValue)) {
|
||||
$objWriter->writeAttribute('val', "$ruleValue");
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
}
|
1772
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php
vendored
Normal file
1772
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
236
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php
vendored
Normal file
236
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Comment;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
|
||||
class Comments extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write comments to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Comments cache
|
||||
$comments = $worksheet->getComments();
|
||||
|
||||
// Authors cache
|
||||
$authors = [];
|
||||
$authorId = 0;
|
||||
foreach ($comments as $comment) {
|
||||
if (!isset($authors[$comment->getAuthor()])) {
|
||||
$authors[$comment->getAuthor()] = $authorId++;
|
||||
}
|
||||
}
|
||||
|
||||
// comments
|
||||
$objWriter->startElement('comments');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
|
||||
|
||||
// Loop through authors
|
||||
$objWriter->startElement('authors');
|
||||
foreach ($authors as $author => $index) {
|
||||
$objWriter->writeElement('author', $author);
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
// Loop through comments
|
||||
$objWriter->startElement('commentList');
|
||||
foreach ($comments as $key => $value) {
|
||||
$this->writeComment($objWriter, $key, $value, $authors);
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write comment to XML format.
|
||||
*
|
||||
* @param string $cellReference Cell reference
|
||||
* @param Comment $comment Comment
|
||||
* @param array $authors Array of authors
|
||||
*/
|
||||
private function writeComment(XMLWriter $objWriter, $cellReference, Comment $comment, array $authors): void
|
||||
{
|
||||
// comment
|
||||
$objWriter->startElement('comment');
|
||||
$objWriter->writeAttribute('ref', $cellReference);
|
||||
$objWriter->writeAttribute('authorId', $authors[$comment->getAuthor()]);
|
||||
|
||||
// text
|
||||
$objWriter->startElement('text');
|
||||
$this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $comment->getText());
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write VML comments to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeVMLComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Comments cache
|
||||
$comments = $worksheet->getComments();
|
||||
|
||||
// xml
|
||||
$objWriter->startElement('xml');
|
||||
$objWriter->writeAttribute('xmlns:v', Namespaces::URN_VML);
|
||||
$objWriter->writeAttribute('xmlns:o', Namespaces::URN_MSOFFICE);
|
||||
$objWriter->writeAttribute('xmlns:x', Namespaces::URN_EXCEL);
|
||||
|
||||
// o:shapelayout
|
||||
$objWriter->startElement('o:shapelayout');
|
||||
$objWriter->writeAttribute('v:ext', 'edit');
|
||||
|
||||
// o:idmap
|
||||
$objWriter->startElement('o:idmap');
|
||||
$objWriter->writeAttribute('v:ext', 'edit');
|
||||
$objWriter->writeAttribute('data', '1');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:shapetype
|
||||
$objWriter->startElement('v:shapetype');
|
||||
$objWriter->writeAttribute('id', '_x0000_t202');
|
||||
$objWriter->writeAttribute('coordsize', '21600,21600');
|
||||
$objWriter->writeAttribute('o:spt', '202');
|
||||
$objWriter->writeAttribute('path', 'm,l,21600r21600,l21600,xe');
|
||||
|
||||
// v:stroke
|
||||
$objWriter->startElement('v:stroke');
|
||||
$objWriter->writeAttribute('joinstyle', 'miter');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:path
|
||||
$objWriter->startElement('v:path');
|
||||
$objWriter->writeAttribute('gradientshapeok', 't');
|
||||
$objWriter->writeAttribute('o:connecttype', 'rect');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Loop through comments
|
||||
foreach ($comments as $key => $value) {
|
||||
$this->writeVMLComment($objWriter, $key, $value);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write VML comment to XML format.
|
||||
*
|
||||
* @param string $cellReference Cell reference, eg: 'A1'
|
||||
* @param Comment $comment Comment
|
||||
*/
|
||||
private function writeVMLComment(XMLWriter $objWriter, $cellReference, Comment $comment): void
|
||||
{
|
||||
// Metadata
|
||||
[$column, $row] = Coordinate::indexesFromString($cellReference);
|
||||
$id = 1024 + $column + $row;
|
||||
$id = substr("$id", 0, 4);
|
||||
|
||||
// v:shape
|
||||
$objWriter->startElement('v:shape');
|
||||
$objWriter->writeAttribute('id', '_x0000_s' . $id);
|
||||
$objWriter->writeAttribute('type', '#_x0000_t202');
|
||||
$objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $comment->getMarginLeft() . ';margin-top:' . $comment->getMarginTop() . ';width:' . $comment->getWidth() . ';height:' . $comment->getHeight() . ';z-index:1;visibility:' . ($comment->getVisible() ? 'visible' : 'hidden'));
|
||||
$objWriter->writeAttribute('fillcolor', '#' . $comment->getFillColor()->getRGB());
|
||||
$objWriter->writeAttribute('o:insetmode', 'auto');
|
||||
|
||||
// v:fill
|
||||
$objWriter->startElement('v:fill');
|
||||
$objWriter->writeAttribute('color2', '#' . $comment->getFillColor()->getRGB());
|
||||
if ($comment->hasBackgroundImage()) {
|
||||
$bgImage = $comment->getBackgroundImage();
|
||||
$objWriter->writeAttribute('o:relid', 'rId' . $bgImage->getImageIndex());
|
||||
$objWriter->writeAttribute('o:title', $bgImage->getName());
|
||||
$objWriter->writeAttribute('type', 'frame');
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:shadow
|
||||
$objWriter->startElement('v:shadow');
|
||||
$objWriter->writeAttribute('on', 't');
|
||||
$objWriter->writeAttribute('color', 'black');
|
||||
$objWriter->writeAttribute('obscured', 't');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:path
|
||||
$objWriter->startElement('v:path');
|
||||
$objWriter->writeAttribute('o:connecttype', 'none');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:textbox
|
||||
$objWriter->startElement('v:textbox');
|
||||
$objWriter->writeAttribute('style', 'mso-direction-alt:auto');
|
||||
|
||||
// div
|
||||
$objWriter->startElement('div');
|
||||
$objWriter->writeAttribute('style', 'text-align:left');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// x:ClientData
|
||||
$objWriter->startElement('x:ClientData');
|
||||
$objWriter->writeAttribute('ObjectType', 'Note');
|
||||
|
||||
// x:MoveWithCells
|
||||
$objWriter->writeElement('x:MoveWithCells', '');
|
||||
|
||||
// x:SizeWithCells
|
||||
$objWriter->writeElement('x:SizeWithCells', '');
|
||||
|
||||
// x:AutoFill
|
||||
$objWriter->writeElement('x:AutoFill', 'False');
|
||||
|
||||
// x:Row
|
||||
$objWriter->writeElement('x:Row', (string) ($row - 1));
|
||||
|
||||
// x:Column
|
||||
$objWriter->writeElement('x:Column', (string) ($column - 1));
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
266
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php
vendored
Normal file
266
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
class ContentTypes extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write content types to XML format.
|
||||
*
|
||||
* @param bool $includeCharts Flag indicating if we should include drawing details for charts
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeContentTypes(Spreadsheet $spreadsheet, $includeCharts = false)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Types
|
||||
$objWriter->startElement('Types');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::CONTENT_TYPES);
|
||||
|
||||
// Theme
|
||||
$this->writeOverrideContentType($objWriter, '/xl/theme/theme1.xml', 'application/vnd.openxmlformats-officedocument.theme+xml');
|
||||
|
||||
// Styles
|
||||
$this->writeOverrideContentType($objWriter, '/xl/styles.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml');
|
||||
|
||||
// Rels
|
||||
$this->writeDefaultContentType($objWriter, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');
|
||||
|
||||
// XML
|
||||
$this->writeDefaultContentType($objWriter, 'xml', 'application/xml');
|
||||
|
||||
// VML
|
||||
$this->writeDefaultContentType($objWriter, 'vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing');
|
||||
|
||||
// Workbook
|
||||
if ($spreadsheet->hasMacros()) { //Macros in workbook ?
|
||||
// Yes : not standard content but "macroEnabled"
|
||||
$this->writeOverrideContentType($objWriter, '/xl/workbook.xml', 'application/vnd.ms-excel.sheet.macroEnabled.main+xml');
|
||||
//... and define a new type for the VBA project
|
||||
// Better use Override, because we can use 'bin' also for xl\printerSettings\printerSettings1.bin
|
||||
$this->writeOverrideContentType($objWriter, '/xl/vbaProject.bin', 'application/vnd.ms-office.vbaProject');
|
||||
if ($spreadsheet->hasMacrosCertificate()) {
|
||||
// signed macros ?
|
||||
// Yes : add needed information
|
||||
$this->writeOverrideContentType($objWriter, '/xl/vbaProjectSignature.bin', 'application/vnd.ms-office.vbaProjectSignature');
|
||||
}
|
||||
} else {
|
||||
// no macros in workbook, so standard type
|
||||
$this->writeOverrideContentType($objWriter, '/xl/workbook.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml');
|
||||
}
|
||||
|
||||
// DocProps
|
||||
$this->writeOverrideContentType($objWriter, '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-properties+xml');
|
||||
|
||||
$this->writeOverrideContentType($objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml');
|
||||
|
||||
$customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
|
||||
if (!empty($customPropertyList)) {
|
||||
$this->writeOverrideContentType($objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml');
|
||||
}
|
||||
|
||||
// Worksheets
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$this->writeOverrideContentType($objWriter, '/xl/worksheets/sheet' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml');
|
||||
}
|
||||
|
||||
// Shared strings
|
||||
$this->writeOverrideContentType($objWriter, '/xl/sharedStrings.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml');
|
||||
|
||||
// Table
|
||||
$table = 1;
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$tableCount = $spreadsheet->getSheet($i)->getTableCollection()->count();
|
||||
|
||||
for ($t = 1; $t <= $tableCount; ++$t) {
|
||||
$this->writeOverrideContentType($objWriter, '/xl/tables/table' . $table++ . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml');
|
||||
}
|
||||
}
|
||||
|
||||
// Add worksheet relationship content types
|
||||
$unparsedLoadedData = $spreadsheet->getUnparsedLoadedData();
|
||||
$chart = 1;
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$drawings = $spreadsheet->getSheet($i)->getDrawingCollection();
|
||||
$drawingCount = count($drawings);
|
||||
$chartCount = ($includeCharts) ? $spreadsheet->getSheet($i)->getChartCount() : 0;
|
||||
$hasUnparsedDrawing = isset($unparsedLoadedData['sheets'][$spreadsheet->getSheet($i)->getCodeName()]['drawingOriginalIds']);
|
||||
|
||||
// We need a drawing relationship for the worksheet if we have either drawings or charts
|
||||
if (($drawingCount > 0) || ($chartCount > 0) || $hasUnparsedDrawing) {
|
||||
$this->writeOverrideContentType($objWriter, '/xl/drawings/drawing' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.drawing+xml');
|
||||
}
|
||||
|
||||
// If we have charts, then we need a chart relationship for every individual chart
|
||||
if ($chartCount > 0) {
|
||||
for ($c = 0; $c < $chartCount; ++$c) {
|
||||
$this->writeOverrideContentType($objWriter, '/xl/charts/chart' . $chart++ . '.xml', 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Comments
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
if (count($spreadsheet->getSheet($i)->getComments()) > 0) {
|
||||
$this->writeOverrideContentType($objWriter, '/xl/comments' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml');
|
||||
}
|
||||
}
|
||||
|
||||
// Add media content-types
|
||||
$aMediaContentTypes = [];
|
||||
$mediaCount = $this->getParentWriter()->getDrawingHashTable()->count();
|
||||
for ($i = 0; $i < $mediaCount; ++$i) {
|
||||
$extension = '';
|
||||
$mimeType = '';
|
||||
|
||||
if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing) {
|
||||
$extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension());
|
||||
$mimeType = $this->getImageMimeType($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath());
|
||||
} elseif ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) {
|
||||
$extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType());
|
||||
$extension = explode('/', $extension);
|
||||
$extension = $extension[1];
|
||||
|
||||
$mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType();
|
||||
}
|
||||
|
||||
if (!isset($aMediaContentTypes[$extension])) {
|
||||
$aMediaContentTypes[$extension] = $mimeType;
|
||||
|
||||
$this->writeDefaultContentType($objWriter, $extension, $mimeType);
|
||||
}
|
||||
}
|
||||
if ($spreadsheet->hasRibbonBinObjects()) {
|
||||
// Some additional objects in the ribbon ?
|
||||
// we need to write "Extension" but not already write for media content
|
||||
$tabRibbonTypes = array_diff($spreadsheet->getRibbonBinObjects('types') ?? [], array_keys($aMediaContentTypes));
|
||||
foreach ($tabRibbonTypes as $aRibbonType) {
|
||||
$mimeType = 'image/.' . $aRibbonType; //we wrote $mimeType like customUI Editor
|
||||
$this->writeDefaultContentType($objWriter, $aRibbonType, $mimeType);
|
||||
}
|
||||
}
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
if (count($spreadsheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
|
||||
foreach ($spreadsheet->getSheet($i)->getHeaderFooter()->getImages() as $image) {
|
||||
if (!isset($aMediaContentTypes[strtolower($image->getExtension())])) {
|
||||
$aMediaContentTypes[strtolower($image->getExtension())] = $this->getImageMimeType($image->getPath());
|
||||
|
||||
$this->writeDefaultContentType($objWriter, strtolower($image->getExtension()), $aMediaContentTypes[strtolower($image->getExtension())]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($spreadsheet->getSheet($i)->getComments()) > 0) {
|
||||
foreach ($spreadsheet->getSheet($i)->getComments() as $comment) {
|
||||
if (!$comment->hasBackgroundImage()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$bgImage = $comment->getBackgroundImage();
|
||||
$bgImageExtentionKey = strtolower($bgImage->getImageFileExtensionForSave(false));
|
||||
|
||||
if (!isset($aMediaContentTypes[$bgImageExtentionKey])) {
|
||||
$aMediaContentTypes[$bgImageExtentionKey] = $bgImage->getImageMimeType();
|
||||
|
||||
$this->writeDefaultContentType($objWriter, $bgImageExtentionKey, $aMediaContentTypes[$bgImageExtentionKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unparsed defaults
|
||||
if (isset($unparsedLoadedData['default_content_types'])) {
|
||||
foreach ($unparsedLoadedData['default_content_types'] as $extName => $contentType) {
|
||||
$this->writeDefaultContentType($objWriter, $extName, $contentType);
|
||||
}
|
||||
}
|
||||
|
||||
// unparsed overrides
|
||||
if (isset($unparsedLoadedData['override_content_types'])) {
|
||||
foreach ($unparsedLoadedData['override_content_types'] as $partName => $overrideType) {
|
||||
$this->writeOverrideContentType($objWriter, $partName, $overrideType);
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image mime type.
|
||||
*
|
||||
* @param string $filename Filename
|
||||
*
|
||||
* @return string Mime Type
|
||||
*/
|
||||
private function getImageMimeType($filename)
|
||||
{
|
||||
if (File::fileExists($filename)) {
|
||||
$image = getimagesize($filename);
|
||||
|
||||
return image_type_to_mime_type((is_array($image) && count($image) >= 3) ? $image[2] : 0);
|
||||
}
|
||||
|
||||
throw new WriterException("File $filename does not exist");
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Default content type.
|
||||
*
|
||||
* @param string $partName Part name
|
||||
* @param string $contentType Content type
|
||||
*/
|
||||
private function writeDefaultContentType(XMLWriter $objWriter, $partName, $contentType): void
|
||||
{
|
||||
if ($partName != '' && $contentType != '') {
|
||||
// Write content type
|
||||
$objWriter->startElement('Default');
|
||||
$objWriter->writeAttribute('Extension', $partName);
|
||||
$objWriter->writeAttribute('ContentType', $contentType);
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
throw new WriterException('Invalid parameters passed.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Override content type.
|
||||
*
|
||||
* @param string $partName Part name
|
||||
* @param string $contentType Content type
|
||||
*/
|
||||
private function writeOverrideContentType(XMLWriter $objWriter, $partName, $contentType): void
|
||||
{
|
||||
if ($partName != '' && $contentType != '') {
|
||||
// Write content type
|
||||
$objWriter->startElement('Override');
|
||||
$objWriter->writeAttribute('PartName', $partName);
|
||||
$objWriter->writeAttribute('ContentType', $contentType);
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
throw new WriterException('Invalid parameters passed.');
|
||||
}
|
||||
}
|
||||
}
|
244
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php
vendored
Normal file
244
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\DefinedName;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as ActualWorksheet;
|
||||
|
||||
class DefinedNames
|
||||
{
|
||||
/** @var XMLWriter */
|
||||
private $objWriter;
|
||||
|
||||
/** @var Spreadsheet */
|
||||
private $spreadsheet;
|
||||
|
||||
public function __construct(XMLWriter $objWriter, Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->objWriter = $objWriter;
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
}
|
||||
|
||||
public function write(): void
|
||||
{
|
||||
// Write defined names
|
||||
$this->objWriter->startElement('definedNames');
|
||||
|
||||
// Named ranges
|
||||
if (count($this->spreadsheet->getDefinedNames()) > 0) {
|
||||
// Named ranges
|
||||
$this->writeNamedRangesAndFormulae();
|
||||
}
|
||||
|
||||
// Other defined names
|
||||
$sheetCount = $this->spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
// NamedRange for autoFilter
|
||||
$this->writeNamedRangeForAutofilter($this->spreadsheet->getSheet($i), $i);
|
||||
|
||||
// NamedRange for Print_Titles
|
||||
$this->writeNamedRangeForPrintTitles($this->spreadsheet->getSheet($i), $i);
|
||||
|
||||
// NamedRange for Print_Area
|
||||
$this->writeNamedRangeForPrintArea($this->spreadsheet->getSheet($i), $i);
|
||||
}
|
||||
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write defined names.
|
||||
*/
|
||||
private function writeNamedRangesAndFormulae(): void
|
||||
{
|
||||
// Loop named ranges
|
||||
$definedNames = $this->spreadsheet->getDefinedNames();
|
||||
foreach ($definedNames as $definedName) {
|
||||
$this->writeDefinedName($definedName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Defined Name for named range.
|
||||
*/
|
||||
private function writeDefinedName(DefinedName $definedName): void
|
||||
{
|
||||
// definedName for named range
|
||||
$local = -1;
|
||||
if ($definedName->getLocalOnly() && $definedName->getScope() !== null) {
|
||||
try {
|
||||
$local = $definedName->getScope()->getParent()->getIndex($definedName->getScope());
|
||||
} catch (Exception $e) {
|
||||
// See issue 2266 - deleting sheet which contains
|
||||
// defined names will cause Exception above.
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->objWriter->startElement('definedName');
|
||||
$this->objWriter->writeAttribute('name', $definedName->getName());
|
||||
if ($local >= 0) {
|
||||
$this->objWriter->writeAttribute(
|
||||
'localSheetId',
|
||||
"$local"
|
||||
);
|
||||
}
|
||||
|
||||
$definedRange = $this->getDefinedRange($definedName);
|
||||
|
||||
$this->objWriter->writeRawData($definedRange);
|
||||
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Defined Name for autoFilter.
|
||||
*/
|
||||
private function writeNamedRangeForAutofilter(ActualWorksheet $worksheet, int $worksheetId = 0): void
|
||||
{
|
||||
// NamedRange for autoFilter
|
||||
$autoFilterRange = $worksheet->getAutoFilter()->getRange();
|
||||
if (!empty($autoFilterRange)) {
|
||||
$this->objWriter->startElement('definedName');
|
||||
$this->objWriter->writeAttribute('name', '_xlnm._FilterDatabase');
|
||||
$this->objWriter->writeAttribute('localSheetId', "$worksheetId");
|
||||
$this->objWriter->writeAttribute('hidden', '1');
|
||||
|
||||
// Create absolute coordinate and write as raw text
|
||||
$range = Coordinate::splitRange($autoFilterRange);
|
||||
$range = $range[0];
|
||||
// Strip any worksheet ref so we can make the cell ref absolute
|
||||
[, $range[0]] = ActualWorksheet::extractSheetTitle($range[0], true);
|
||||
|
||||
$range[0] = Coordinate::absoluteCoordinate($range[0]);
|
||||
if (count($range) > 1) {
|
||||
$range[1] = Coordinate::absoluteCoordinate($range[1]);
|
||||
}
|
||||
$range = implode(':', $range);
|
||||
|
||||
$this->objWriter->writeRawData('\'' . str_replace("'", "''", $worksheet->getTitle()) . '\'!' . $range);
|
||||
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Defined Name for PrintTitles.
|
||||
*/
|
||||
private function writeNamedRangeForPrintTitles(ActualWorksheet $worksheet, int $worksheetId = 0): void
|
||||
{
|
||||
// NamedRange for PrintTitles
|
||||
if ($worksheet->getPageSetup()->isColumnsToRepeatAtLeftSet() || $worksheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
|
||||
$this->objWriter->startElement('definedName');
|
||||
$this->objWriter->writeAttribute('name', '_xlnm.Print_Titles');
|
||||
$this->objWriter->writeAttribute('localSheetId', "$worksheetId");
|
||||
|
||||
// Setting string
|
||||
$settingString = '';
|
||||
|
||||
// Columns to repeat
|
||||
if ($worksheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) {
|
||||
$repeat = $worksheet->getPageSetup()->getColumnsToRepeatAtLeft();
|
||||
|
||||
$settingString .= '\'' . str_replace("'", "''", $worksheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1];
|
||||
}
|
||||
|
||||
// Rows to repeat
|
||||
if ($worksheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
|
||||
if ($worksheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) {
|
||||
$settingString .= ',';
|
||||
}
|
||||
|
||||
$repeat = $worksheet->getPageSetup()->getRowsToRepeatAtTop();
|
||||
|
||||
$settingString .= '\'' . str_replace("'", "''", $worksheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1];
|
||||
}
|
||||
|
||||
$this->objWriter->writeRawData($settingString);
|
||||
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Defined Name for PrintTitles.
|
||||
*/
|
||||
private function writeNamedRangeForPrintArea(ActualWorksheet $worksheet, int $worksheetId = 0): void
|
||||
{
|
||||
// NamedRange for PrintArea
|
||||
if ($worksheet->getPageSetup()->isPrintAreaSet()) {
|
||||
$this->objWriter->startElement('definedName');
|
||||
$this->objWriter->writeAttribute('name', '_xlnm.Print_Area');
|
||||
$this->objWriter->writeAttribute('localSheetId', "$worksheetId");
|
||||
|
||||
// Print area
|
||||
$printArea = Coordinate::splitRange($worksheet->getPageSetup()->getPrintArea());
|
||||
|
||||
$chunks = [];
|
||||
foreach ($printArea as $printAreaRect) {
|
||||
$printAreaRect[0] = Coordinate::absoluteReference($printAreaRect[0]);
|
||||
$printAreaRect[1] = Coordinate::absoluteReference($printAreaRect[1]);
|
||||
$chunks[] = '\'' . str_replace("'", "''", $worksheet->getTitle()) . '\'!' . implode(':', $printAreaRect);
|
||||
}
|
||||
|
||||
$this->objWriter->writeRawData(implode(',', $chunks));
|
||||
|
||||
$this->objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
private function getDefinedRange(DefinedName $definedName): string
|
||||
{
|
||||
$definedRange = $definedName->getValue();
|
||||
$splitCount = preg_match_all(
|
||||
'/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/mui',
|
||||
$definedRange,
|
||||
$splitRanges,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
$lengths = array_map('strlen', array_column($splitRanges[0], 0));
|
||||
$offsets = array_column($splitRanges[0], 1);
|
||||
|
||||
$worksheets = $splitRanges[2];
|
||||
$columns = $splitRanges[6];
|
||||
$rows = $splitRanges[7];
|
||||
|
||||
while ($splitCount > 0) {
|
||||
--$splitCount;
|
||||
$length = $lengths[$splitCount];
|
||||
$offset = $offsets[$splitCount];
|
||||
$worksheet = $worksheets[$splitCount][0];
|
||||
$column = $columns[$splitCount][0];
|
||||
$row = $rows[$splitCount][0];
|
||||
|
||||
$newRange = '';
|
||||
if (empty($worksheet)) {
|
||||
if (($offset === 0) || ($definedRange[$offset - 1] !== ':')) {
|
||||
// We should have a worksheet
|
||||
$ws = $definedName->getWorksheet();
|
||||
$worksheet = ($ws === null) ? null : $ws->getTitle();
|
||||
}
|
||||
} else {
|
||||
$worksheet = str_replace("''", "'", trim($worksheet, "'"));
|
||||
}
|
||||
|
||||
if (!empty($worksheet)) {
|
||||
$newRange = "'" . str_replace("'", "''", $worksheet) . "'!";
|
||||
}
|
||||
$newRange = "{$newRange}{$column}{$row}";
|
||||
|
||||
$definedRange = substr($definedRange, 0, $offset) . $newRange . substr($definedRange, $offset + $length);
|
||||
}
|
||||
|
||||
if (substr($definedRange, 0, 1) === '=') {
|
||||
$definedRange = substr($definedRange, 1);
|
||||
}
|
||||
|
||||
return $definedRange;
|
||||
}
|
||||
}
|
247
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
vendored
Normal file
247
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
class DocProps extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write docProps/app.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeDocPropsApp(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Properties
|
||||
$objWriter->startElement('Properties');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::EXTENDED_PROPERTIES);
|
||||
$objWriter->writeAttribute('xmlns:vt', Namespaces::PROPERTIES_VTYPES);
|
||||
|
||||
// Application
|
||||
$objWriter->writeElement('Application', 'Microsoft Excel');
|
||||
|
||||
// DocSecurity
|
||||
$objWriter->writeElement('DocSecurity', '0');
|
||||
|
||||
// ScaleCrop
|
||||
$objWriter->writeElement('ScaleCrop', 'false');
|
||||
|
||||
// HeadingPairs
|
||||
$objWriter->startElement('HeadingPairs');
|
||||
|
||||
// Vector
|
||||
$objWriter->startElement('vt:vector');
|
||||
$objWriter->writeAttribute('size', '2');
|
||||
$objWriter->writeAttribute('baseType', 'variant');
|
||||
|
||||
// Variant
|
||||
$objWriter->startElement('vt:variant');
|
||||
$objWriter->writeElement('vt:lpstr', 'Worksheets');
|
||||
$objWriter->endElement();
|
||||
|
||||
// Variant
|
||||
$objWriter->startElement('vt:variant');
|
||||
$objWriter->writeElement('vt:i4', (string) $spreadsheet->getSheetCount());
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// TitlesOfParts
|
||||
$objWriter->startElement('TitlesOfParts');
|
||||
|
||||
// Vector
|
||||
$objWriter->startElement('vt:vector');
|
||||
$objWriter->writeAttribute('size', (string) $spreadsheet->getSheetCount());
|
||||
$objWriter->writeAttribute('baseType', 'lpstr');
|
||||
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$objWriter->writeElement('vt:lpstr', $spreadsheet->getSheet($i)->getTitle());
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Company
|
||||
$objWriter->writeElement('Company', $spreadsheet->getProperties()->getCompany());
|
||||
|
||||
// Company
|
||||
$objWriter->writeElement('Manager', $spreadsheet->getProperties()->getManager());
|
||||
|
||||
// LinksUpToDate
|
||||
$objWriter->writeElement('LinksUpToDate', 'false');
|
||||
|
||||
// SharedDoc
|
||||
$objWriter->writeElement('SharedDoc', 'false');
|
||||
|
||||
// HyperlinksChanged
|
||||
$objWriter->writeElement('HyperlinksChanged', 'false');
|
||||
|
||||
// AppVersion
|
||||
$objWriter->writeElement('AppVersion', '12.0000');
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write docProps/core.xml to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeDocPropsCore(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// cp:coreProperties
|
||||
$objWriter->startElement('cp:coreProperties');
|
||||
$objWriter->writeAttribute('xmlns:cp', Namespaces::CORE_PROPERTIES2);
|
||||
$objWriter->writeAttribute('xmlns:dc', Namespaces::DC_ELEMENTS);
|
||||
$objWriter->writeAttribute('xmlns:dcterms', Namespaces::DC_TERMS);
|
||||
$objWriter->writeAttribute('xmlns:dcmitype', Namespaces::DC_DCMITYPE);
|
||||
$objWriter->writeAttribute('xmlns:xsi', Namespaces::SCHEMA_INSTANCE);
|
||||
|
||||
// dc:creator
|
||||
$objWriter->writeElement('dc:creator', $spreadsheet->getProperties()->getCreator());
|
||||
|
||||
// cp:lastModifiedBy
|
||||
$objWriter->writeElement('cp:lastModifiedBy', $spreadsheet->getProperties()->getLastModifiedBy());
|
||||
|
||||
// dcterms:created
|
||||
$objWriter->startElement('dcterms:created');
|
||||
$objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF');
|
||||
$created = $spreadsheet->getProperties()->getCreated();
|
||||
$date = Date::dateTimeFromTimestamp("$created");
|
||||
$objWriter->writeRawData($date->format(DATE_W3C));
|
||||
$objWriter->endElement();
|
||||
|
||||
// dcterms:modified
|
||||
$objWriter->startElement('dcterms:modified');
|
||||
$objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF');
|
||||
$created = $spreadsheet->getProperties()->getModified();
|
||||
$date = Date::dateTimeFromTimestamp("$created");
|
||||
$objWriter->writeRawData($date->format(DATE_W3C));
|
||||
$objWriter->endElement();
|
||||
|
||||
// dc:title
|
||||
$objWriter->writeElement('dc:title', $spreadsheet->getProperties()->getTitle());
|
||||
|
||||
// dc:description
|
||||
$objWriter->writeElement('dc:description', $spreadsheet->getProperties()->getDescription());
|
||||
|
||||
// dc:subject
|
||||
$objWriter->writeElement('dc:subject', $spreadsheet->getProperties()->getSubject());
|
||||
|
||||
// cp:keywords
|
||||
$objWriter->writeElement('cp:keywords', $spreadsheet->getProperties()->getKeywords());
|
||||
|
||||
// cp:category
|
||||
$objWriter->writeElement('cp:category', $spreadsheet->getProperties()->getCategory());
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write docProps/custom.xml to XML format.
|
||||
*
|
||||
* @return null|string XML Output
|
||||
*/
|
||||
public function writeDocPropsCustom(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
|
||||
if (empty($customPropertyList)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// cp:coreProperties
|
||||
$objWriter->startElement('Properties');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::CUSTOM_PROPERTIES);
|
||||
$objWriter->writeAttribute('xmlns:vt', Namespaces::PROPERTIES_VTYPES);
|
||||
|
||||
foreach ($customPropertyList as $key => $customProperty) {
|
||||
$propertyValue = $spreadsheet->getProperties()->getCustomPropertyValue($customProperty);
|
||||
$propertyType = $spreadsheet->getProperties()->getCustomPropertyType($customProperty);
|
||||
|
||||
$objWriter->startElement('property');
|
||||
$objWriter->writeAttribute('fmtid', '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}');
|
||||
$objWriter->writeAttribute('pid', (string) ($key + 2));
|
||||
$objWriter->writeAttribute('name', $customProperty);
|
||||
|
||||
switch ($propertyType) {
|
||||
case Properties::PROPERTY_TYPE_INTEGER:
|
||||
$objWriter->writeElement('vt:i4', $propertyValue);
|
||||
|
||||
break;
|
||||
case Properties::PROPERTY_TYPE_FLOAT:
|
||||
$objWriter->writeElement('vt:r8', sprintf('%F', $propertyValue));
|
||||
|
||||
break;
|
||||
case Properties::PROPERTY_TYPE_BOOLEAN:
|
||||
$objWriter->writeElement('vt:bool', ($propertyValue) ? 'true' : 'false');
|
||||
|
||||
break;
|
||||
case Properties::PROPERTY_TYPE_DATE:
|
||||
$objWriter->startElement('vt:filetime');
|
||||
$date = Date::dateTimeFromTimestamp("$propertyValue");
|
||||
$objWriter->writeRawData($date->format(DATE_W3C));
|
||||
$objWriter->endElement();
|
||||
|
||||
break;
|
||||
default:
|
||||
$objWriter->writeElement('vt:lpwstr', $propertyValue);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
}
|
571
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
vendored
Normal file
571
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
vendored
Normal file
@ -0,0 +1,571 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
class Drawing extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write drawings to XML format.
|
||||
*
|
||||
* @param bool $includeCharts Flag indicating if we should include drawing details for charts
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, $includeCharts = false)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// xdr:wsDr
|
||||
$objWriter->startElement('xdr:wsDr');
|
||||
$objWriter->writeAttribute('xmlns:xdr', Namespaces::SPREADSHEET_DRAWING);
|
||||
$objWriter->writeAttribute('xmlns:a', Namespaces::DRAWINGML);
|
||||
|
||||
// Loop through images and write drawings
|
||||
$i = 1;
|
||||
$iterator = $worksheet->getDrawingCollection()->getIterator();
|
||||
while ($iterator->valid()) {
|
||||
/** @var BaseDrawing $pDrawing */
|
||||
$pDrawing = $iterator->current();
|
||||
$pRelationId = $i;
|
||||
$hlinkClickId = $pDrawing->getHyperlink() === null ? null : ++$i;
|
||||
|
||||
$this->writeDrawing($objWriter, $pDrawing, $pRelationId, $hlinkClickId);
|
||||
|
||||
$iterator->next();
|
||||
++$i;
|
||||
}
|
||||
|
||||
if ($includeCharts) {
|
||||
$chartCount = $worksheet->getChartCount();
|
||||
// Loop through charts and write the chart position
|
||||
if ($chartCount > 0) {
|
||||
for ($c = 0; $c < $chartCount; ++$c) {
|
||||
$chart = $worksheet->getChartByIndex((string) $c);
|
||||
if ($chart !== false) {
|
||||
$this->writeChart($objWriter, $chart, $c + $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unparsed AlternateContent
|
||||
$unparsedLoadedData = $worksheet->getParent()->getUnparsedLoadedData();
|
||||
if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingAlternateContents'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingAlternateContents'] as $drawingAlternateContent) {
|
||||
$objWriter->writeRaw($drawingAlternateContent);
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write drawings to XML format.
|
||||
*
|
||||
* @param int $relationId
|
||||
*/
|
||||
public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $chart, $relationId = -1): void
|
||||
{
|
||||
$tl = $chart->getTopLeftPosition();
|
||||
$tlColRow = Coordinate::indexesFromString($tl['cell']);
|
||||
$br = $chart->getBottomRightPosition();
|
||||
|
||||
$isTwoCellAnchor = $br['cell'] !== '';
|
||||
if ($isTwoCellAnchor) {
|
||||
$brColRow = Coordinate::indexesFromString($br['cell']);
|
||||
|
||||
$objWriter->startElement('xdr:twoCellAnchor');
|
||||
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('xdr:to');
|
||||
$objWriter->writeElement('xdr:col', (string) ($brColRow[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($br['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', (string) ($brColRow[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($br['yOffset']));
|
||||
$objWriter->endElement();
|
||||
} elseif ($chart->getOneCellAnchor()) {
|
||||
$objWriter->startElement('xdr:oneCellAnchor');
|
||||
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('xdr:ext');
|
||||
$objWriter->writeAttribute('cx', self::stringEmu($br['xOffset']));
|
||||
$objWriter->writeAttribute('cy', self::stringEmu($br['yOffset']));
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
$objWriter->startElement('xdr:absoluteAnchor');
|
||||
$objWriter->startElement('xdr:pos');
|
||||
$objWriter->writeAttribute('x', '0');
|
||||
$objWriter->writeAttribute('y', '0');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('xdr:ext');
|
||||
$objWriter->writeAttribute('cx', self::stringEmu($br['xOffset']));
|
||||
$objWriter->writeAttribute('cy', self::stringEmu($br['yOffset']));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->startElement('xdr:graphicFrame');
|
||||
$objWriter->writeAttribute('macro', '');
|
||||
$objWriter->startElement('xdr:nvGraphicFramePr');
|
||||
$objWriter->startElement('xdr:cNvPr');
|
||||
$objWriter->writeAttribute('name', 'Chart ' . $relationId);
|
||||
$objWriter->writeAttribute('id', (string) (1025 * $relationId));
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('xdr:cNvGraphicFramePr');
|
||||
$objWriter->startElement('a:graphicFrameLocks');
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('xdr:xfrm');
|
||||
$objWriter->startElement('a:off');
|
||||
$objWriter->writeAttribute('x', '0');
|
||||
$objWriter->writeAttribute('y', '0');
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('a:ext');
|
||||
$objWriter->writeAttribute('cx', '0');
|
||||
$objWriter->writeAttribute('cy', '0');
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('a:graphic');
|
||||
$objWriter->startElement('a:graphicData');
|
||||
$objWriter->writeAttribute('uri', Namespaces::CHART);
|
||||
$objWriter->startElement('c:chart');
|
||||
$objWriter->writeAttribute('xmlns:c', Namespaces::CHART);
|
||||
$objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
|
||||
$objWriter->writeAttribute('r:id', 'rId' . $relationId);
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('xdr:clientData');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write drawings to XML format.
|
||||
*
|
||||
* @param int $relationId
|
||||
* @param null|int $hlinkClickId
|
||||
*/
|
||||
public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relationId = -1, $hlinkClickId = null): void
|
||||
{
|
||||
if ($relationId >= 0) {
|
||||
$isTwoCellAnchor = $drawing->getCoordinates2() !== '';
|
||||
if ($isTwoCellAnchor) {
|
||||
// xdr:twoCellAnchor
|
||||
$objWriter->startElement('xdr:twoCellAnchor');
|
||||
if ($drawing->validEditAs()) {
|
||||
$objWriter->writeAttribute('editAs', $drawing->getEditAs());
|
||||
}
|
||||
// Image location
|
||||
$aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
|
||||
$aCoordinates2 = Coordinate::indexesFromString($drawing->getCoordinates2());
|
||||
|
||||
// xdr:from
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
|
||||
$objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:to
|
||||
$objWriter->startElement('xdr:to');
|
||||
$objWriter->writeElement('xdr:col', (string) ($aCoordinates2[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX2()));
|
||||
$objWriter->writeElement('xdr:row', (string) ($aCoordinates2[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY2()));
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
// xdr:oneCellAnchor
|
||||
$objWriter->startElement('xdr:oneCellAnchor');
|
||||
// Image location
|
||||
$aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
|
||||
|
||||
// xdr:from
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
|
||||
$objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:ext
|
||||
$objWriter->startElement('xdr:ext');
|
||||
$objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
|
||||
$objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// xdr:pic
|
||||
$objWriter->startElement('xdr:pic');
|
||||
|
||||
// xdr:nvPicPr
|
||||
$objWriter->startElement('xdr:nvPicPr');
|
||||
|
||||
// xdr:cNvPr
|
||||
$objWriter->startElement('xdr:cNvPr');
|
||||
$objWriter->writeAttribute('id', (string) $relationId);
|
||||
$objWriter->writeAttribute('name', $drawing->getName());
|
||||
$objWriter->writeAttribute('descr', $drawing->getDescription());
|
||||
|
||||
//a:hlinkClick
|
||||
$this->writeHyperLinkDrawing($objWriter, $hlinkClickId);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:cNvPicPr
|
||||
$objWriter->startElement('xdr:cNvPicPr');
|
||||
|
||||
// a:picLocks
|
||||
$objWriter->startElement('a:picLocks');
|
||||
$objWriter->writeAttribute('noChangeAspect', '1');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:blipFill
|
||||
$objWriter->startElement('xdr:blipFill');
|
||||
|
||||
// a:blip
|
||||
$objWriter->startElement('a:blip');
|
||||
$objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
|
||||
$objWriter->writeAttribute('r:embed', 'rId' . $relationId);
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:stretch
|
||||
$objWriter->startElement('a:stretch');
|
||||
$objWriter->writeElement('a:fillRect', null);
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:spPr
|
||||
$objWriter->startElement('xdr:spPr');
|
||||
|
||||
// a:xfrm
|
||||
$objWriter->startElement('a:xfrm');
|
||||
$objWriter->writeAttribute('rot', (string) SharedDrawing::degreesToAngle($drawing->getRotation()));
|
||||
if ($isTwoCellAnchor) {
|
||||
$objWriter->startElement('a:ext');
|
||||
$objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
|
||||
$objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:prstGeom
|
||||
$objWriter->startElement('a:prstGeom');
|
||||
$objWriter->writeAttribute('prst', 'rect');
|
||||
|
||||
// a:avLst
|
||||
$objWriter->writeElement('a:avLst', null);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
if ($drawing->getShadow()->getVisible()) {
|
||||
// a:effectLst
|
||||
$objWriter->startElement('a:effectLst');
|
||||
|
||||
// a:outerShdw
|
||||
$objWriter->startElement('a:outerShdw');
|
||||
$objWriter->writeAttribute('blurRad', self::stringEmu($drawing->getShadow()->getBlurRadius()));
|
||||
$objWriter->writeAttribute('dist', self::stringEmu($drawing->getShadow()->getDistance()));
|
||||
$objWriter->writeAttribute('dir', (string) SharedDrawing::degreesToAngle($drawing->getShadow()->getDirection()));
|
||||
$objWriter->writeAttribute('algn', $drawing->getShadow()->getAlignment());
|
||||
$objWriter->writeAttribute('rotWithShape', '0');
|
||||
|
||||
// a:srgbClr
|
||||
$objWriter->startElement('a:srgbClr');
|
||||
$objWriter->writeAttribute('val', $drawing->getShadow()->getColor()->getRGB());
|
||||
|
||||
// a:alpha
|
||||
$objWriter->startElement('a:alpha');
|
||||
$objWriter->writeAttribute('val', (string) ($drawing->getShadow()->getAlpha() * 1000));
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:clientData
|
||||
$objWriter->writeElement('xdr:clientData', null);
|
||||
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
throw new WriterException('Invalid parameters passed.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write VML header/footer images to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Header/footer images
|
||||
$images = $worksheet->getHeaderFooter()->getImages();
|
||||
|
||||
// xml
|
||||
$objWriter->startElement('xml');
|
||||
$objWriter->writeAttribute('xmlns:v', Namespaces::URN_VML);
|
||||
$objWriter->writeAttribute('xmlns:o', Namespaces::URN_MSOFFICE);
|
||||
$objWriter->writeAttribute('xmlns:x', Namespaces::URN_EXCEL);
|
||||
|
||||
// o:shapelayout
|
||||
$objWriter->startElement('o:shapelayout');
|
||||
$objWriter->writeAttribute('v:ext', 'edit');
|
||||
|
||||
// o:idmap
|
||||
$objWriter->startElement('o:idmap');
|
||||
$objWriter->writeAttribute('v:ext', 'edit');
|
||||
$objWriter->writeAttribute('data', '1');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:shapetype
|
||||
$objWriter->startElement('v:shapetype');
|
||||
$objWriter->writeAttribute('id', '_x0000_t75');
|
||||
$objWriter->writeAttribute('coordsize', '21600,21600');
|
||||
$objWriter->writeAttribute('o:spt', '75');
|
||||
$objWriter->writeAttribute('o:preferrelative', 't');
|
||||
$objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe');
|
||||
$objWriter->writeAttribute('filled', 'f');
|
||||
$objWriter->writeAttribute('stroked', 'f');
|
||||
|
||||
// v:stroke
|
||||
$objWriter->startElement('v:stroke');
|
||||
$objWriter->writeAttribute('joinstyle', 'miter');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:formulas
|
||||
$objWriter->startElement('v:formulas');
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'sum @0 1 0');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'sum 0 0 @1');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'prod @2 1 2');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'sum @0 0 1');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'prod @6 1 2');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'sum @8 21600 0');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight');
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:f
|
||||
$objWriter->startElement('v:f');
|
||||
$objWriter->writeAttribute('eqn', 'sum @10 21600 0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// v:path
|
||||
$objWriter->startElement('v:path');
|
||||
$objWriter->writeAttribute('o:extrusionok', 'f');
|
||||
$objWriter->writeAttribute('gradientshapeok', 't');
|
||||
$objWriter->writeAttribute('o:connecttype', 'rect');
|
||||
$objWriter->endElement();
|
||||
|
||||
// o:lock
|
||||
$objWriter->startElement('o:lock');
|
||||
$objWriter->writeAttribute('v:ext', 'edit');
|
||||
$objWriter->writeAttribute('aspectratio', 't');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Loop through images
|
||||
foreach ($images as $key => $value) {
|
||||
$this->writeVMLHeaderFooterImage($objWriter, $key, $value);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write VML comment to XML format.
|
||||
*
|
||||
* @param string $reference Reference
|
||||
*/
|
||||
private function writeVMLHeaderFooterImage(XMLWriter $objWriter, $reference, HeaderFooterDrawing $image): void
|
||||
{
|
||||
// Calculate object id
|
||||
preg_match('{(\d+)}', md5($reference), $m);
|
||||
$id = 1500 + ((int) substr($m[1], 0, 2) * 1);
|
||||
|
||||
// Calculate offset
|
||||
$width = $image->getWidth();
|
||||
$height = $image->getHeight();
|
||||
$marginLeft = $image->getOffsetX();
|
||||
$marginTop = $image->getOffsetY();
|
||||
|
||||
// v:shape
|
||||
$objWriter->startElement('v:shape');
|
||||
$objWriter->writeAttribute('id', $reference);
|
||||
$objWriter->writeAttribute('o:spid', '_x0000_s' . $id);
|
||||
$objWriter->writeAttribute('type', '#_x0000_t75');
|
||||
$objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1");
|
||||
|
||||
// v:imagedata
|
||||
$objWriter->startElement('v:imagedata');
|
||||
$objWriter->writeAttribute('o:relid', 'rId' . $reference);
|
||||
$objWriter->writeAttribute('o:title', $image->getName());
|
||||
$objWriter->endElement();
|
||||
|
||||
// o:lock
|
||||
$objWriter->startElement('o:lock');
|
||||
$objWriter->writeAttribute('v:ext', 'edit');
|
||||
$objWriter->writeAttribute('textRotation', 't');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all drawings.
|
||||
*
|
||||
* @return BaseDrawing[] All drawings in PhpSpreadsheet
|
||||
*/
|
||||
public function allDrawings(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Get an array of all drawings
|
||||
$aDrawings = [];
|
||||
|
||||
// Loop through PhpSpreadsheet
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
// Loop through images and add to array
|
||||
$iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
|
||||
while ($iterator->valid()) {
|
||||
$aDrawings[] = $iterator->current();
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
}
|
||||
|
||||
return $aDrawings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|int $hlinkClickId
|
||||
*/
|
||||
private function writeHyperLinkDrawing(XMLWriter $objWriter, $hlinkClickId): void
|
||||
{
|
||||
if ($hlinkClickId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$objWriter->startElement('a:hlinkClick');
|
||||
$objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
|
||||
$objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
private static function stringEmu(int $pixelValue): string
|
||||
{
|
||||
return (string) SharedDrawing::pixelsToEMU($pixelValue);
|
||||
}
|
||||
}
|
194
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php
vendored
Normal file
194
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
class FunctionPrefix
|
||||
{
|
||||
const XLFNREGEXP = '/(?:_xlfn\.)?((?:_xlws\.)?('
|
||||
// functions added with Excel 2010
|
||||
. 'beta[.]dist'
|
||||
. '|beta[.]inv'
|
||||
. '|binom[.]dist'
|
||||
. '|binom[.]inv'
|
||||
. '|ceiling[.]precise'
|
||||
. '|chisq[.]dist'
|
||||
. '|chisq[.]dist[.]rt'
|
||||
. '|chisq[.]inv'
|
||||
. '|chisq[.]inv[.]rt'
|
||||
. '|chisq[.]test'
|
||||
. '|confidence[.]norm'
|
||||
. '|confidence[.]t'
|
||||
. '|covariance[.]p'
|
||||
. '|covariance[.]s'
|
||||
. '|erf[.]precise'
|
||||
. '|erfc[.]precise'
|
||||
. '|expon[.]dist'
|
||||
. '|f[.]dist'
|
||||
. '|f[.]dist[.]rt'
|
||||
. '|f[.]inv'
|
||||
. '|f[.]inv[.]rt'
|
||||
. '|f[.]test'
|
||||
. '|floor[.]precise'
|
||||
. '|gamma[.]dist'
|
||||
. '|gamma[.]inv'
|
||||
. '|gammaln[.]precise'
|
||||
. '|lognorm[.]dist'
|
||||
. '|lognorm[.]inv'
|
||||
. '|mode[.]mult'
|
||||
. '|mode[.]sngl'
|
||||
. '|negbinom[.]dist'
|
||||
. '|networkdays[.]intl'
|
||||
. '|norm[.]dist'
|
||||
. '|norm[.]inv'
|
||||
. '|norm[.]s[.]dist'
|
||||
. '|norm[.]s[.]inv'
|
||||
. '|percentile[.]exc'
|
||||
. '|percentile[.]inc'
|
||||
. '|percentrank[.]exc'
|
||||
. '|percentrank[.]inc'
|
||||
. '|poisson[.]dist'
|
||||
. '|quartile[.]exc'
|
||||
. '|quartile[.]inc'
|
||||
. '|rank[.]avg'
|
||||
. '|rank[.]eq'
|
||||
. '|stdev[.]p'
|
||||
. '|stdev[.]s'
|
||||
. '|t[.]dist'
|
||||
. '|t[.]dist[.]2t'
|
||||
. '|t[.]dist[.]rt'
|
||||
. '|t[.]inv'
|
||||
. '|t[.]inv[.]2t'
|
||||
. '|t[.]test'
|
||||
. '|var[.]p'
|
||||
. '|var[.]s'
|
||||
. '|weibull[.]dist'
|
||||
. '|z[.]test'
|
||||
// functions added with Excel 2013
|
||||
. '|acot'
|
||||
. '|acoth'
|
||||
. '|arabic'
|
||||
. '|averageifs'
|
||||
. '|binom[.]dist[.]range'
|
||||
. '|bitand'
|
||||
. '|bitlshift'
|
||||
. '|bitor'
|
||||
. '|bitrshift'
|
||||
. '|bitxor'
|
||||
. '|ceiling[.]math'
|
||||
. '|combina'
|
||||
. '|cot'
|
||||
. '|coth'
|
||||
. '|csc'
|
||||
. '|csch'
|
||||
. '|days'
|
||||
. '|dbcs'
|
||||
. '|decimal'
|
||||
. '|encodeurl'
|
||||
. '|filterxml'
|
||||
. '|floor[.]math'
|
||||
. '|formulatext'
|
||||
. '|gamma'
|
||||
. '|gauss'
|
||||
. '|ifna'
|
||||
. '|imcosh'
|
||||
. '|imcot'
|
||||
. '|imcsc'
|
||||
. '|imcsch'
|
||||
. '|imsec'
|
||||
. '|imsech'
|
||||
. '|imsinh'
|
||||
. '|imtan'
|
||||
. '|isformula'
|
||||
. '|iso[.]ceiling'
|
||||
. '|isoweeknum'
|
||||
. '|munit'
|
||||
. '|numbervalue'
|
||||
. '|pduration'
|
||||
. '|permutationa'
|
||||
. '|phi'
|
||||
. '|rri'
|
||||
. '|sec'
|
||||
. '|sech'
|
||||
. '|sheet'
|
||||
. '|sheets'
|
||||
. '|skew[.]p'
|
||||
. '|unichar'
|
||||
. '|unicode'
|
||||
. '|webservice'
|
||||
. '|xor'
|
||||
// functions added with Excel 2016
|
||||
. '|forecast[.]et2'
|
||||
. '|forecast[.]ets[.]confint'
|
||||
. '|forecast[.]ets[.]seasonality'
|
||||
. '|forecast[.]ets[.]stat'
|
||||
. '|forecast[.]linear'
|
||||
. '|switch'
|
||||
// functions added with Excel 2019
|
||||
. '|concat'
|
||||
. '|countifs'
|
||||
. '|ifs'
|
||||
. '|maxifs'
|
||||
. '|minifs'
|
||||
. '|sumifs'
|
||||
. '|textjoin'
|
||||
// functions added with Excel 365
|
||||
. '|filter'
|
||||
. '|randarray'
|
||||
. '|anchorarray'
|
||||
. '|sequence'
|
||||
. '|sort'
|
||||
. '|sortby'
|
||||
. '|unique'
|
||||
. '|xlookup'
|
||||
. '|xmatch'
|
||||
. '|arraytotext'
|
||||
. '|call'
|
||||
. '|let'
|
||||
. '|lambda'
|
||||
. '|single'
|
||||
. '|register[.]id'
|
||||
. '|textafter'
|
||||
. '|textbefore'
|
||||
. '|textsplit'
|
||||
. '|valuetotext'
|
||||
. '))\s*\(/Umui';
|
||||
|
||||
const XLWSREGEXP = '/(?<!_xlws\.)('
|
||||
// functions added with Excel 365
|
||||
. 'filter'
|
||||
. '|sort'
|
||||
. ')\s*\(/mui';
|
||||
|
||||
/**
|
||||
* Prefix function name in string with _xlfn. where required.
|
||||
*/
|
||||
protected static function addXlfnPrefix(string $functionString): string
|
||||
{
|
||||
return (string) preg_replace(self::XLFNREGEXP, '_xlfn.$1(', $functionString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix function name in string with _xlws. where required.
|
||||
*/
|
||||
protected static function addXlwsPrefix(string $functionString): string
|
||||
{
|
||||
return (string) preg_replace(self::XLWSREGEXP, '_xlws.$1(', $functionString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix function name in string with _xlfn. where required.
|
||||
*/
|
||||
public static function addFunctionPrefix(string $functionString): string
|
||||
{
|
||||
return self::addXlwsPrefix(self::addXlfnPrefix($functionString));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix function name in string with _xlfn. where required.
|
||||
* Leading character, expected to be equals sign, is stripped.
|
||||
*/
|
||||
public static function addFunctionPrefixStripEquals(string $functionString): string
|
||||
{
|
||||
return self::addFunctionPrefix(substr($functionString, 1));
|
||||
}
|
||||
}
|
496
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php
vendored
Normal file
496
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php
vendored
Normal file
@ -0,0 +1,496 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
class Rels extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write relationships to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeRelationships(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
|
||||
$customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
|
||||
if (!empty($customPropertyList)) {
|
||||
// Relationship docProps/app.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
4,
|
||||
Namespaces::RELATIONSHIPS_CUSTOM_PROPERTIES,
|
||||
'docProps/custom.xml'
|
||||
);
|
||||
}
|
||||
|
||||
// Relationship docProps/app.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
3,
|
||||
Namespaces::RELATIONSHIPS_EXTENDED_PROPERTIES,
|
||||
'docProps/app.xml'
|
||||
);
|
||||
|
||||
// Relationship docProps/core.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
2,
|
||||
Namespaces::CORE_PROPERTIES,
|
||||
'docProps/core.xml'
|
||||
);
|
||||
|
||||
// Relationship xl/workbook.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
1,
|
||||
Namespaces::OFFICE_DOCUMENT,
|
||||
'xl/workbook.xml'
|
||||
);
|
||||
// a custom UI in workbook ?
|
||||
$target = $spreadsheet->getRibbonXMLData('target');
|
||||
if ($spreadsheet->hasRibbon()) {
|
||||
$this->writeRelationShip(
|
||||
$objWriter,
|
||||
5,
|
||||
Namespaces::EXTENSIBILITY,
|
||||
is_string($target) ? $target : ''
|
||||
);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write workbook relationships to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeWorkbookRelationships(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
|
||||
// Relationship styles.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
1,
|
||||
Namespaces::STYLES,
|
||||
'styles.xml'
|
||||
);
|
||||
|
||||
// Relationship theme/theme1.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
2,
|
||||
Namespaces::THEME2,
|
||||
'theme/theme1.xml'
|
||||
);
|
||||
|
||||
// Relationship sharedStrings.xml
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
3,
|
||||
Namespaces::SHARED_STRINGS,
|
||||
'sharedStrings.xml'
|
||||
);
|
||||
|
||||
// Relationships with sheets
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
($i + 1 + 3),
|
||||
Namespaces::WORKSHEET,
|
||||
'worksheets/sheet' . ($i + 1) . '.xml'
|
||||
);
|
||||
}
|
||||
// Relationships for vbaProject if needed
|
||||
// id : just after the last sheet
|
||||
if ($spreadsheet->hasMacros()) {
|
||||
$this->writeRelationShip(
|
||||
$objWriter,
|
||||
($i + 1 + 3),
|
||||
Namespaces::VBA,
|
||||
'vbaProject.bin'
|
||||
);
|
||||
++$i; //increment i if needed for an another relation
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write worksheet relationships to XML format.
|
||||
*
|
||||
* Numbering is as follows:
|
||||
* rId1 - Drawings
|
||||
* rId_hyperlink_x - Hyperlinks
|
||||
*
|
||||
* @param int $worksheetId
|
||||
* @param bool $includeCharts Flag indicating if we should write charts
|
||||
* @param int $tableRef Table ID
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeWorksheetRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, $worksheetId = 1, $includeCharts = false, $tableRef = 1)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
|
||||
// Write drawing relationships?
|
||||
$drawingOriginalIds = [];
|
||||
$unparsedLoadedData = $worksheet->getParent()->getUnparsedLoadedData();
|
||||
if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingOriginalIds'])) {
|
||||
$drawingOriginalIds = $unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingOriginalIds'];
|
||||
}
|
||||
|
||||
if ($includeCharts) {
|
||||
$charts = $worksheet->getChartCollection();
|
||||
} else {
|
||||
$charts = [];
|
||||
}
|
||||
|
||||
if (($worksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
|
||||
$rId = 1;
|
||||
|
||||
// Use original $relPath to get original $rId.
|
||||
// Take first. In future can be overwritten.
|
||||
// (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::writeDrawings)
|
||||
reset($drawingOriginalIds);
|
||||
$relPath = key($drawingOriginalIds);
|
||||
if (isset($drawingOriginalIds[$relPath])) {
|
||||
$rId = (int) (substr($drawingOriginalIds[$relPath], 3));
|
||||
}
|
||||
|
||||
// Generate new $relPath to write drawing relationship
|
||||
$relPath = '../drawings/drawing' . $worksheetId . '.xml';
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$rId,
|
||||
Namespaces::RELATIONSHIPS_DRAWING,
|
||||
$relPath
|
||||
);
|
||||
}
|
||||
|
||||
// Write hyperlink relationships?
|
||||
$i = 1;
|
||||
foreach ($worksheet->getHyperlinkCollection() as $hyperlink) {
|
||||
if (!$hyperlink->isInternal()) {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
'_hyperlink_' . $i,
|
||||
Namespaces::HYPERLINK,
|
||||
$hyperlink->getUrl(),
|
||||
'External'
|
||||
);
|
||||
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
|
||||
// Write comments relationship?
|
||||
$i = 1;
|
||||
if (count($worksheet->getComments()) > 0) {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
'_comments_vml' . $i,
|
||||
Namespaces::VML,
|
||||
'../drawings/vmlDrawing' . $worksheetId . '.vml'
|
||||
);
|
||||
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
'_comments' . $i,
|
||||
Namespaces::COMMENTS,
|
||||
'../comments' . $worksheetId . '.xml'
|
||||
);
|
||||
}
|
||||
|
||||
// Write Table
|
||||
$tableCount = $worksheet->getTableCollection()->count();
|
||||
for ($i = 1; $i <= $tableCount; ++$i) {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
'_table_' . $i,
|
||||
Namespaces::RELATIONSHIPS_TABLE,
|
||||
'../tables/table' . $tableRef++ . '.xml'
|
||||
);
|
||||
}
|
||||
|
||||
// Write header/footer relationship?
|
||||
$i = 1;
|
||||
if (count($worksheet->getHeaderFooter()->getImages()) > 0) {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
'_headerfooter_vml' . $i,
|
||||
Namespaces::VML,
|
||||
'../drawings/vmlDrawingHF' . $worksheetId . '.vml'
|
||||
);
|
||||
}
|
||||
|
||||
$this->writeUnparsedRelationship($worksheet, $objWriter, 'ctrlProps', Namespaces::RELATIONSHIPS_CTRLPROP);
|
||||
$this->writeUnparsedRelationship($worksheet, $objWriter, 'vmlDrawings', Namespaces::VML);
|
||||
$this->writeUnparsedRelationship($worksheet, $objWriter, 'printerSettings', Namespaces::RELATIONSHIPS_PRINTER_SETTINGS);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
private function writeUnparsedRelationship(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, XMLWriter $objWriter, string $relationship, string $type): void
|
||||
{
|
||||
$unparsedLoadedData = $worksheet->getParent()->getUnparsedLoadedData();
|
||||
if (!isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()][$relationship])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($unparsedLoadedData['sheets'][$worksheet->getCodeName()][$relationship] as $rId => $value) {
|
||||
if (substr($rId, 0, 17) !== '_headerfooter_vml') {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$rId,
|
||||
$type,
|
||||
$value['relFilePath']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write drawing relationships to XML format.
|
||||
*
|
||||
* @param int $chartRef Chart ID
|
||||
* @param bool $includeCharts Flag indicating if we should write charts
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, &$chartRef, $includeCharts = false)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
|
||||
// Loop through images and write relationships
|
||||
$i = 1;
|
||||
$iterator = $worksheet->getDrawingCollection()->getIterator();
|
||||
while ($iterator->valid()) {
|
||||
$drawing = $iterator->current();
|
||||
if (
|
||||
$drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing
|
||||
|| $drawing instanceof MemoryDrawing
|
||||
) {
|
||||
// Write relationship for image drawing
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$i,
|
||||
Namespaces::IMAGE,
|
||||
'../media/' . $drawing->getIndexedFilename()
|
||||
);
|
||||
|
||||
$i = $this->writeDrawingHyperLink($objWriter, $drawing, $i);
|
||||
}
|
||||
|
||||
$iterator->next();
|
||||
++$i;
|
||||
}
|
||||
|
||||
if ($includeCharts) {
|
||||
// Loop through charts and write relationships
|
||||
$chartCount = $worksheet->getChartCount();
|
||||
if ($chartCount > 0) {
|
||||
for ($c = 0; $c < $chartCount; ++$c) {
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$i++,
|
||||
Namespaces::RELATIONSHIPS_CHART,
|
||||
'../charts/chart' . ++$chartRef . '.xml'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write header/footer drawing relationships to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeHeaderFooterDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
|
||||
// Loop through images and write relationships
|
||||
foreach ($worksheet->getHeaderFooter()->getImages() as $key => $value) {
|
||||
// Write relationship for image drawing
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$key,
|
||||
Namespaces::IMAGE,
|
||||
'../media/' . $value->getIndexedFilename()
|
||||
);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
public function writeVMLDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet): string
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
|
||||
// Loop through images and write relationships
|
||||
foreach ($worksheet->getComments() as $comment) {
|
||||
if (!$comment->hasBackgroundImage()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$bgImage = $comment->getBackgroundImage();
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$bgImage->getImageIndex(),
|
||||
Namespaces::IMAGE,
|
||||
'../media/' . $bgImage->getMediaFilename()
|
||||
);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Override content type.
|
||||
*
|
||||
* @param int|string $id Relationship ID. rId will be prepended!
|
||||
* @param string $type Relationship type
|
||||
* @param string $target Relationship target
|
||||
* @param string $targetMode Relationship target mode
|
||||
*/
|
||||
private function writeRelationship(XMLWriter $objWriter, $id, $type, $target, $targetMode = ''): void
|
||||
{
|
||||
if ($type != '' && $target != '') {
|
||||
// Write relationship
|
||||
$objWriter->startElement('Relationship');
|
||||
$objWriter->writeAttribute('Id', 'rId' . $id);
|
||||
$objWriter->writeAttribute('Type', $type);
|
||||
$objWriter->writeAttribute('Target', $target);
|
||||
|
||||
if ($targetMode != '') {
|
||||
$objWriter->writeAttribute('TargetMode', $targetMode);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
throw new WriterException('Invalid parameters passed.');
|
||||
}
|
||||
}
|
||||
|
||||
private function writeDrawingHyperLink(XMLWriter $objWriter, BaseDrawing $drawing, int $i): int
|
||||
{
|
||||
if ($drawing->getHyperlink() === null) {
|
||||
return $i;
|
||||
}
|
||||
|
||||
++$i;
|
||||
$this->writeRelationship(
|
||||
$objWriter,
|
||||
$i,
|
||||
Namespaces::HYPERLINK,
|
||||
$drawing->getHyperlink()->getUrl(),
|
||||
$drawing->getHyperlink()->getTypeHyperlink()
|
||||
);
|
||||
|
||||
return $i;
|
||||
}
|
||||
}
|
46
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php
vendored
Normal file
46
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
class RelsRibbon extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write relationships for additional objects of custom UI (ribbon).
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeRibbonRelationships(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
$localRels = $spreadsheet->getRibbonBinObjects('names');
|
||||
if (is_array($localRels)) {
|
||||
foreach ($localRels as $aId => $aTarget) {
|
||||
$objWriter->startElement('Relationship');
|
||||
$objWriter->writeAttribute('Id', $aId);
|
||||
$objWriter->writeAttribute('Type', Namespaces::IMAGE);
|
||||
$objWriter->writeAttribute('Target', $aTarget);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
}
|
40
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php
vendored
Normal file
40
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
|
||||
class RelsVBA extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write relationships for a signed VBA Project.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeVBARelationships()
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Relationships
|
||||
$objWriter->startElement('Relationships');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
|
||||
$objWriter->startElement('Relationship');
|
||||
$objWriter->writeAttribute('Id', 'rId1');
|
||||
$objWriter->writeAttribute('Type', Namespaces::VBA_SIGNATURE);
|
||||
$objWriter->writeAttribute('Target', 'vbaProjectSignature.bin');
|
||||
$objWriter->endElement();
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
}
|
345
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
vendored
Normal file
345
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php
vendored
Normal file
@ -0,0 +1,345 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\Run;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as ActualWorksheet;
|
||||
|
||||
class StringTable extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Create worksheet stringtable.
|
||||
*
|
||||
* @param string[] $existingTable Existing table to eventually merge with
|
||||
*
|
||||
* @return string[] String table for worksheet
|
||||
*/
|
||||
public function createStringTable(ActualWorksheet $worksheet, $existingTable = null)
|
||||
{
|
||||
// Create string lookup table
|
||||
$aStringTable = [];
|
||||
|
||||
// Is an existing table given?
|
||||
if (($existingTable !== null) && is_array($existingTable)) {
|
||||
$aStringTable = $existingTable;
|
||||
}
|
||||
|
||||
// Fill index array
|
||||
$aFlippedStringTable = $this->flipStringTable($aStringTable);
|
||||
|
||||
// Loop through cells
|
||||
foreach ($worksheet->getCellCollection()->getCoordinates() as $coordinate) {
|
||||
/** @var Cell $cell */
|
||||
$cell = $worksheet->getCellCollection()->get($coordinate);
|
||||
$cellValue = $cell->getValue();
|
||||
if (
|
||||
!is_object($cellValue) &&
|
||||
($cellValue !== null) &&
|
||||
$cellValue !== '' &&
|
||||
($cell->getDataType() == DataType::TYPE_STRING || $cell->getDataType() == DataType::TYPE_STRING2 || $cell->getDataType() == DataType::TYPE_NULL) &&
|
||||
!isset($aFlippedStringTable[$cellValue])
|
||||
) {
|
||||
$aStringTable[] = $cellValue;
|
||||
$aFlippedStringTable[$cellValue] = true;
|
||||
} elseif (
|
||||
$cellValue instanceof RichText &&
|
||||
($cellValue !== null) &&
|
||||
!isset($aFlippedStringTable[$cellValue->getHashCode()])
|
||||
) {
|
||||
$aStringTable[] = $cellValue;
|
||||
$aFlippedStringTable[$cellValue->getHashCode()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $aStringTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write string table to XML format.
|
||||
*
|
||||
* @param (string|RichText)[] $stringTable
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeStringTable(array $stringTable)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// String table
|
||||
$objWriter->startElement('sst');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
|
||||
$objWriter->writeAttribute('uniqueCount', (string) count($stringTable));
|
||||
|
||||
// Loop through string table
|
||||
foreach ($stringTable as $textElement) {
|
||||
$objWriter->startElement('si');
|
||||
|
||||
if (!($textElement instanceof RichText)) {
|
||||
$textToWrite = StringHelper::controlCharacterPHP2OOXML($textElement);
|
||||
$objWriter->startElement('t');
|
||||
if ($textToWrite !== trim($textToWrite)) {
|
||||
$objWriter->writeAttribute('xml:space', 'preserve');
|
||||
}
|
||||
$objWriter->writeRawData($textToWrite);
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
$this->writeRichText($objWriter, $textElement);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Rich Text.
|
||||
*
|
||||
* @param string $prefix Optional Namespace prefix
|
||||
*/
|
||||
public function writeRichText(XMLWriter $objWriter, RichText $richText, $prefix = null): void
|
||||
{
|
||||
if ($prefix !== null) {
|
||||
$prefix .= ':';
|
||||
}
|
||||
|
||||
// Loop through rich text elements
|
||||
$elements = $richText->getRichTextElements();
|
||||
foreach ($elements as $element) {
|
||||
// r
|
||||
$objWriter->startElement($prefix . 'r');
|
||||
|
||||
// rPr
|
||||
if ($element instanceof Run && $element->getFont() !== null) {
|
||||
// rPr
|
||||
$objWriter->startElement($prefix . 'rPr');
|
||||
|
||||
// rFont
|
||||
if ($element->getFont()->getName() !== null) {
|
||||
$objWriter->startElement($prefix . 'rFont');
|
||||
$objWriter->writeAttribute('val', $element->getFont()->getName());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Bold
|
||||
$objWriter->startElement($prefix . 'b');
|
||||
$objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false'));
|
||||
$objWriter->endElement();
|
||||
|
||||
// Italic
|
||||
$objWriter->startElement($prefix . 'i');
|
||||
$objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false'));
|
||||
$objWriter->endElement();
|
||||
|
||||
// Superscript / subscript
|
||||
if ($element->getFont()->getSuperscript() || $element->getFont()->getSubscript()) {
|
||||
$objWriter->startElement($prefix . 'vertAlign');
|
||||
if ($element->getFont()->getSuperscript()) {
|
||||
$objWriter->writeAttribute('val', 'superscript');
|
||||
} elseif ($element->getFont()->getSubscript()) {
|
||||
$objWriter->writeAttribute('val', 'subscript');
|
||||
}
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Strikethrough
|
||||
$objWriter->startElement($prefix . 'strike');
|
||||
$objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false'));
|
||||
$objWriter->endElement();
|
||||
|
||||
// Color
|
||||
if ($element->getFont()->getColor()->getARGB() !== null) {
|
||||
$objWriter->startElement($prefix . 'color');
|
||||
$objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Size
|
||||
if ($element->getFont()->getSize() !== null) {
|
||||
$objWriter->startElement($prefix . 'sz');
|
||||
$objWriter->writeAttribute('val', (string) $element->getFont()->getSize());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Underline
|
||||
if ($element->getFont()->getUnderline() !== null) {
|
||||
$objWriter->startElement($prefix . 'u');
|
||||
$objWriter->writeAttribute('val', $element->getFont()->getUnderline());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// t
|
||||
$objWriter->startElement($prefix . 't');
|
||||
$objWriter->writeAttribute('xml:space', 'preserve');
|
||||
$objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Rich Text.
|
||||
*
|
||||
* @param RichText|string $richText text string or Rich text
|
||||
* @param string $prefix Optional Namespace prefix
|
||||
*/
|
||||
public function writeRichTextForCharts(XMLWriter $objWriter, $richText = null, $prefix = ''): void
|
||||
{
|
||||
if (!($richText instanceof RichText)) {
|
||||
$textRun = $richText;
|
||||
$richText = new RichText();
|
||||
$run = $richText->createTextRun($textRun ?? '');
|
||||
$run->setFont(null);
|
||||
}
|
||||
|
||||
if ($prefix !== '') {
|
||||
$prefix .= ':';
|
||||
}
|
||||
|
||||
// Loop through rich text elements
|
||||
$elements = $richText->getRichTextElements();
|
||||
foreach ($elements as $element) {
|
||||
// r
|
||||
$objWriter->startElement($prefix . 'r');
|
||||
if ($element->getFont() !== null) {
|
||||
// rPr
|
||||
$objWriter->startElement($prefix . 'rPr');
|
||||
$size = $element->getFont()->getSize();
|
||||
if (is_numeric($size)) {
|
||||
$objWriter->writeAttribute('sz', (string) (int) ($size * 100));
|
||||
}
|
||||
|
||||
// Bold
|
||||
$objWriter->writeAttribute('b', ($element->getFont()->getBold() ? '1' : '0'));
|
||||
// Italic
|
||||
$objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? '1' : '0'));
|
||||
// Underline
|
||||
$underlineType = $element->getFont()->getUnderline();
|
||||
switch ($underlineType) {
|
||||
case 'single':
|
||||
$underlineType = 'sng';
|
||||
|
||||
break;
|
||||
case 'double':
|
||||
$underlineType = 'dbl';
|
||||
|
||||
break;
|
||||
}
|
||||
if ($underlineType !== null) {
|
||||
$objWriter->writeAttribute('u', $underlineType);
|
||||
}
|
||||
// Strikethrough
|
||||
$objWriter->writeAttribute('strike', ($element->getFont()->getStriketype() ?: 'noStrike'));
|
||||
// Superscript/subscript
|
||||
if ($element->getFont()->getBaseLine()) {
|
||||
$objWriter->writeAttribute('baseline', (string) $element->getFont()->getBaseLine());
|
||||
}
|
||||
|
||||
// Color
|
||||
$this->writeChartTextColor($objWriter, $element->getFont()->getChartColor(), $prefix);
|
||||
|
||||
// Underscore Color
|
||||
$this->writeChartTextColor($objWriter, $element->getFont()->getUnderlineColor(), $prefix, 'uFill');
|
||||
|
||||
// fontName
|
||||
if ($element->getFont()->getLatin()) {
|
||||
$objWriter->startElement($prefix . 'latin');
|
||||
$objWriter->writeAttribute('typeface', $element->getFont()->getLatin());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
if ($element->getFont()->getEastAsian()) {
|
||||
$objWriter->startElement($prefix . 'ea');
|
||||
$objWriter->writeAttribute('typeface', $element->getFont()->getEastAsian());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
if ($element->getFont()->getComplexScript()) {
|
||||
$objWriter->startElement($prefix . 'cs');
|
||||
$objWriter->writeAttribute('typeface', $element->getFont()->getComplexScript());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// t
|
||||
$objWriter->startElement($prefix . 't');
|
||||
$objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
private function writeChartTextColor(XMLWriter $objWriter, ?ChartColor $underlineColor, string $prefix, ?string $openTag = ''): void
|
||||
{
|
||||
if ($underlineColor !== null) {
|
||||
$type = $underlineColor->getType();
|
||||
$value = $underlineColor->getValue();
|
||||
if (!empty($type) && !empty($value)) {
|
||||
if ($openTag !== '') {
|
||||
$objWriter->startElement($prefix . $openTag);
|
||||
}
|
||||
$objWriter->startElement($prefix . 'solidFill');
|
||||
$objWriter->startElement($prefix . $type);
|
||||
$objWriter->writeAttribute('val', $value);
|
||||
$alpha = $underlineColor->getAlpha();
|
||||
if (is_numeric($alpha)) {
|
||||
$objWriter->startElement('a:alpha');
|
||||
$objWriter->writeAttribute('val', ChartColor::alphaToXml((int) $alpha));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$objWriter->endElement(); // srgbClr/schemeClr/prstClr
|
||||
$objWriter->endElement(); // solidFill
|
||||
if ($openTag !== '') {
|
||||
$objWriter->endElement(); // uFill
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip string table (for index searching).
|
||||
*
|
||||
* @param array $stringTable Stringtable
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function flipStringTable(array $stringTable)
|
||||
{
|
||||
// Return value
|
||||
$returnValue = [];
|
||||
|
||||
// Loop through stringtable and add flipped items to $returnValue
|
||||
foreach ($stringTable as $key => $value) {
|
||||
if (!$value instanceof RichText) {
|
||||
$returnValue[$value] = $key;
|
||||
} elseif ($value instanceof RichText) {
|
||||
$returnValue[$value->getHashCode()] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $returnValue;
|
||||
}
|
||||
}
|
688
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php
vendored
Normal file
688
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php
vendored
Normal file
@ -0,0 +1,688 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||
|
||||
class Style extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write styles to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeStyles(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// styleSheet
|
||||
$objWriter->startElement('styleSheet');
|
||||
$objWriter->writeAttribute('xml:space', 'preserve');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
|
||||
|
||||
// numFmts
|
||||
$objWriter->startElement('numFmts');
|
||||
$objWriter->writeAttribute('count', (string) $this->getParentWriter()->getNumFmtHashTable()->count());
|
||||
|
||||
// numFmt
|
||||
for ($i = 0; $i < $this->getParentWriter()->getNumFmtHashTable()->count(); ++$i) {
|
||||
$this->writeNumFmt($objWriter, $this->getParentWriter()->getNumFmtHashTable()->getByIndex($i), $i);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// fonts
|
||||
$objWriter->startElement('fonts');
|
||||
$objWriter->writeAttribute('count', (string) $this->getParentWriter()->getFontHashTable()->count());
|
||||
|
||||
// font
|
||||
for ($i = 0; $i < $this->getParentWriter()->getFontHashTable()->count(); ++$i) {
|
||||
$thisfont = $this->getParentWriter()->getFontHashTable()->getByIndex($i);
|
||||
if ($thisfont !== null) {
|
||||
$this->writeFont($objWriter, $thisfont);
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// fills
|
||||
$objWriter->startElement('fills');
|
||||
$objWriter->writeAttribute('count', (string) $this->getParentWriter()->getFillHashTable()->count());
|
||||
|
||||
// fill
|
||||
for ($i = 0; $i < $this->getParentWriter()->getFillHashTable()->count(); ++$i) {
|
||||
$thisfill = $this->getParentWriter()->getFillHashTable()->getByIndex($i);
|
||||
if ($thisfill !== null) {
|
||||
$this->writeFill($objWriter, $thisfill);
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// borders
|
||||
$objWriter->startElement('borders');
|
||||
$objWriter->writeAttribute('count', (string) $this->getParentWriter()->getBordersHashTable()->count());
|
||||
|
||||
// border
|
||||
for ($i = 0; $i < $this->getParentWriter()->getBordersHashTable()->count(); ++$i) {
|
||||
$thisborder = $this->getParentWriter()->getBordersHashTable()->getByIndex($i);
|
||||
if ($thisborder !== null) {
|
||||
$this->writeBorder($objWriter, $thisborder);
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// cellStyleXfs
|
||||
$objWriter->startElement('cellStyleXfs');
|
||||
$objWriter->writeAttribute('count', '1');
|
||||
|
||||
// xf
|
||||
$objWriter->startElement('xf');
|
||||
$objWriter->writeAttribute('numFmtId', '0');
|
||||
$objWriter->writeAttribute('fontId', '0');
|
||||
$objWriter->writeAttribute('fillId', '0');
|
||||
$objWriter->writeAttribute('borderId', '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// cellXfs
|
||||
$objWriter->startElement('cellXfs');
|
||||
$objWriter->writeAttribute('count', (string) count($spreadsheet->getCellXfCollection()));
|
||||
|
||||
// xf
|
||||
foreach ($spreadsheet->getCellXfCollection() as $cellXf) {
|
||||
$this->writeCellStyleXf($objWriter, $cellXf, $spreadsheet);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// cellStyles
|
||||
$objWriter->startElement('cellStyles');
|
||||
$objWriter->writeAttribute('count', '1');
|
||||
|
||||
// cellStyle
|
||||
$objWriter->startElement('cellStyle');
|
||||
$objWriter->writeAttribute('name', 'Normal');
|
||||
$objWriter->writeAttribute('xfId', '0');
|
||||
$objWriter->writeAttribute('builtinId', '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// dxfs
|
||||
$objWriter->startElement('dxfs');
|
||||
$objWriter->writeAttribute('count', (string) $this->getParentWriter()->getStylesConditionalHashTable()->count());
|
||||
|
||||
// dxf
|
||||
for ($i = 0; $i < $this->getParentWriter()->getStylesConditionalHashTable()->count(); ++$i) {
|
||||
$thisstyle = $this->getParentWriter()->getStylesConditionalHashTable()->getByIndex($i);
|
||||
if ($thisstyle !== null) {
|
||||
$this->writeCellStyleDxf($objWriter, $thisstyle->getStyle());
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// tableStyles
|
||||
$objWriter->startElement('tableStyles');
|
||||
$objWriter->writeAttribute('defaultTableStyle', 'TableStyleMedium9');
|
||||
$objWriter->writeAttribute('defaultPivotStyle', 'PivotTableStyle1');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Fill.
|
||||
*/
|
||||
private function writeFill(XMLWriter $objWriter, Fill $fill): void
|
||||
{
|
||||
// Check if this is a pattern type or gradient type
|
||||
if (
|
||||
$fill->getFillType() === Fill::FILL_GRADIENT_LINEAR ||
|
||||
$fill->getFillType() === Fill::FILL_GRADIENT_PATH
|
||||
) {
|
||||
// Gradient fill
|
||||
$this->writeGradientFill($objWriter, $fill);
|
||||
} elseif ($fill->getFillType() !== null) {
|
||||
// Pattern fill
|
||||
$this->writePatternFill($objWriter, $fill);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Gradient Fill.
|
||||
*/
|
||||
private function writeGradientFill(XMLWriter $objWriter, Fill $fill): void
|
||||
{
|
||||
// fill
|
||||
$objWriter->startElement('fill');
|
||||
|
||||
// gradientFill
|
||||
$objWriter->startElement('gradientFill');
|
||||
$objWriter->writeAttribute('type', (string) $fill->getFillType());
|
||||
$objWriter->writeAttribute('degree', (string) $fill->getRotation());
|
||||
|
||||
// stop
|
||||
$objWriter->startElement('stop');
|
||||
$objWriter->writeAttribute('position', '0');
|
||||
|
||||
// color
|
||||
if ($fill->getStartColor()->getARGB() !== null) {
|
||||
$objWriter->startElement('color');
|
||||
$objWriter->writeAttribute('rgb', $fill->getStartColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// stop
|
||||
$objWriter->startElement('stop');
|
||||
$objWriter->writeAttribute('position', '1');
|
||||
|
||||
// color
|
||||
if ($fill->getEndColor()->getARGB() !== null) {
|
||||
$objWriter->startElement('color');
|
||||
$objWriter->writeAttribute('rgb', $fill->getEndColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
private static function writePatternColors(Fill $fill): bool
|
||||
{
|
||||
if ($fill->getFillType() === Fill::FILL_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $fill->getFillType() === Fill::FILL_SOLID || $fill->getColorsChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Pattern Fill.
|
||||
*/
|
||||
private function writePatternFill(XMLWriter $objWriter, Fill $fill): void
|
||||
{
|
||||
// fill
|
||||
$objWriter->startElement('fill');
|
||||
|
||||
// patternFill
|
||||
$objWriter->startElement('patternFill');
|
||||
$objWriter->writeAttribute('patternType', (string) $fill->getFillType());
|
||||
|
||||
if (self::writePatternColors($fill)) {
|
||||
// fgColor
|
||||
if ($fill->getStartColor()->getARGB()) {
|
||||
$objWriter->startElement('fgColor');
|
||||
$objWriter->writeAttribute('rgb', $fill->getStartColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
// bgColor
|
||||
if ($fill->getEndColor()->getARGB()) {
|
||||
$objWriter->startElement('bgColor');
|
||||
$objWriter->writeAttribute('rgb', $fill->getEndColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Font.
|
||||
*/
|
||||
private function writeFont(XMLWriter $objWriter, Font $font): void
|
||||
{
|
||||
// font
|
||||
$objWriter->startElement('font');
|
||||
// Weird! The order of these elements actually makes a difference when opening Xlsx
|
||||
// files in Excel2003 with the compatibility pack. It's not documented behaviour,
|
||||
// and makes for a real WTF!
|
||||
|
||||
// Bold. We explicitly write this element also when false (like MS Office Excel 2007 does
|
||||
// for conditional formatting). Otherwise it will apparently not be picked up in conditional
|
||||
// formatting style dialog
|
||||
if ($font->getBold() !== null) {
|
||||
$objWriter->startElement('b');
|
||||
$objWriter->writeAttribute('val', $font->getBold() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Italic
|
||||
if ($font->getItalic() !== null) {
|
||||
$objWriter->startElement('i');
|
||||
$objWriter->writeAttribute('val', $font->getItalic() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Strikethrough
|
||||
if ($font->getStrikethrough() !== null) {
|
||||
$objWriter->startElement('strike');
|
||||
$objWriter->writeAttribute('val', $font->getStrikethrough() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Underline
|
||||
if ($font->getUnderline() !== null) {
|
||||
$objWriter->startElement('u');
|
||||
$objWriter->writeAttribute('val', $font->getUnderline());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Superscript / subscript
|
||||
if ($font->getSuperscript() === true || $font->getSubscript() === true) {
|
||||
$objWriter->startElement('vertAlign');
|
||||
if ($font->getSuperscript() === true) {
|
||||
$objWriter->writeAttribute('val', 'superscript');
|
||||
} elseif ($font->getSubscript() === true) {
|
||||
$objWriter->writeAttribute('val', 'subscript');
|
||||
}
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Size
|
||||
if ($font->getSize() !== null) {
|
||||
$objWriter->startElement('sz');
|
||||
$objWriter->writeAttribute('val', StringHelper::formatNumber($font->getSize()));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Foreground color
|
||||
if ($font->getColor()->getARGB() !== null) {
|
||||
$objWriter->startElement('color');
|
||||
$objWriter->writeAttribute('rgb', $font->getColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
// Name
|
||||
if ($font->getName() !== null) {
|
||||
$objWriter->startElement('name');
|
||||
$objWriter->writeAttribute('val', $font->getName());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Border.
|
||||
*/
|
||||
private function writeBorder(XMLWriter $objWriter, Borders $borders): void
|
||||
{
|
||||
// Write border
|
||||
$objWriter->startElement('border');
|
||||
// Diagonal?
|
||||
switch ($borders->getDiagonalDirection()) {
|
||||
case Borders::DIAGONAL_UP:
|
||||
$objWriter->writeAttribute('diagonalUp', 'true');
|
||||
$objWriter->writeAttribute('diagonalDown', 'false');
|
||||
|
||||
break;
|
||||
case Borders::DIAGONAL_DOWN:
|
||||
$objWriter->writeAttribute('diagonalUp', 'false');
|
||||
$objWriter->writeAttribute('diagonalDown', 'true');
|
||||
|
||||
break;
|
||||
case Borders::DIAGONAL_BOTH:
|
||||
$objWriter->writeAttribute('diagonalUp', 'true');
|
||||
$objWriter->writeAttribute('diagonalDown', 'true');
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// BorderPr
|
||||
$this->writeBorderPr($objWriter, 'left', $borders->getLeft());
|
||||
$this->writeBorderPr($objWriter, 'right', $borders->getRight());
|
||||
$this->writeBorderPr($objWriter, 'top', $borders->getTop());
|
||||
$this->writeBorderPr($objWriter, 'bottom', $borders->getBottom());
|
||||
$this->writeBorderPr($objWriter, 'diagonal', $borders->getDiagonal());
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/** @var mixed */
|
||||
private static $scrutinizerFalse = false;
|
||||
|
||||
/**
|
||||
* Write Cell Style Xf.
|
||||
*/
|
||||
private function writeCellStyleXf(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Style\Style $style, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
// xf
|
||||
$objWriter->startElement('xf');
|
||||
$objWriter->writeAttribute('xfId', '0');
|
||||
$objWriter->writeAttribute('fontId', (string) (int) $this->getParentWriter()->getFontHashTable()->getIndexForHashCode($style->getFont()->getHashCode()));
|
||||
if ($style->getQuotePrefix()) {
|
||||
$objWriter->writeAttribute('quotePrefix', '1');
|
||||
}
|
||||
|
||||
if ($style->getNumberFormat()->getBuiltInFormatCode() === self::$scrutinizerFalse) {
|
||||
$objWriter->writeAttribute('numFmtId', (string) (int) ($this->getParentWriter()->getNumFmtHashTable()->getIndexForHashCode($style->getNumberFormat()->getHashCode()) + 164));
|
||||
} else {
|
||||
$objWriter->writeAttribute('numFmtId', (string) (int) $style->getNumberFormat()->getBuiltInFormatCode());
|
||||
}
|
||||
|
||||
$objWriter->writeAttribute('fillId', (string) (int) $this->getParentWriter()->getFillHashTable()->getIndexForHashCode($style->getFill()->getHashCode()));
|
||||
$objWriter->writeAttribute('borderId', (string) (int) $this->getParentWriter()->getBordersHashTable()->getIndexForHashCode($style->getBorders()->getHashCode()));
|
||||
|
||||
// Apply styles?
|
||||
$objWriter->writeAttribute('applyFont', ($spreadsheet->getDefaultStyle()->getFont()->getHashCode() != $style->getFont()->getHashCode()) ? '1' : '0');
|
||||
$objWriter->writeAttribute('applyNumberFormat', ($spreadsheet->getDefaultStyle()->getNumberFormat()->getHashCode() != $style->getNumberFormat()->getHashCode()) ? '1' : '0');
|
||||
$objWriter->writeAttribute('applyFill', ($spreadsheet->getDefaultStyle()->getFill()->getHashCode() != $style->getFill()->getHashCode()) ? '1' : '0');
|
||||
$objWriter->writeAttribute('applyBorder', ($spreadsheet->getDefaultStyle()->getBorders()->getHashCode() != $style->getBorders()->getHashCode()) ? '1' : '0');
|
||||
$objWriter->writeAttribute('applyAlignment', ($spreadsheet->getDefaultStyle()->getAlignment()->getHashCode() != $style->getAlignment()->getHashCode()) ? '1' : '0');
|
||||
if ($style->getProtection()->getLocked() != Protection::PROTECTION_INHERIT || $style->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) {
|
||||
$objWriter->writeAttribute('applyProtection', 'true');
|
||||
}
|
||||
|
||||
// alignment
|
||||
$objWriter->startElement('alignment');
|
||||
$vertical = Alignment::VERTICAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getVertical()] ?? '';
|
||||
$horizontal = Alignment::HORIZONTAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getHorizontal()] ?? '';
|
||||
if ($horizontal !== '') {
|
||||
$objWriter->writeAttribute('horizontal', $horizontal);
|
||||
}
|
||||
if ($vertical !== '') {
|
||||
$objWriter->writeAttribute('vertical', $vertical);
|
||||
}
|
||||
|
||||
$textRotation = 0;
|
||||
if ($style->getAlignment()->getTextRotation() >= 0) {
|
||||
$textRotation = $style->getAlignment()->getTextRotation();
|
||||
} else {
|
||||
$textRotation = 90 - $style->getAlignment()->getTextRotation();
|
||||
}
|
||||
$objWriter->writeAttribute('textRotation', (string) $textRotation);
|
||||
|
||||
$objWriter->writeAttribute('wrapText', ($style->getAlignment()->getWrapText() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('shrinkToFit', ($style->getAlignment()->getShrinkToFit() ? 'true' : 'false'));
|
||||
|
||||
if ($style->getAlignment()->getIndent() > 0) {
|
||||
$objWriter->writeAttribute('indent', (string) $style->getAlignment()->getIndent());
|
||||
}
|
||||
if ($style->getAlignment()->getReadOrder() > 0) {
|
||||
$objWriter->writeAttribute('readingOrder', (string) $style->getAlignment()->getReadOrder());
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
// protection
|
||||
if ($style->getProtection()->getLocked() != Protection::PROTECTION_INHERIT || $style->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) {
|
||||
$objWriter->startElement('protection');
|
||||
if ($style->getProtection()->getLocked() != Protection::PROTECTION_INHERIT) {
|
||||
$objWriter->writeAttribute('locked', ($style->getProtection()->getLocked() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
|
||||
}
|
||||
if ($style->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) {
|
||||
$objWriter->writeAttribute('hidden', ($style->getProtection()->getHidden() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
|
||||
}
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write Cell Style Dxf.
|
||||
*/
|
||||
private function writeCellStyleDxf(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Style\Style $style): void
|
||||
{
|
||||
// dxf
|
||||
$objWriter->startElement('dxf');
|
||||
|
||||
// font
|
||||
$this->writeFont($objWriter, $style->getFont());
|
||||
|
||||
// numFmt
|
||||
$this->writeNumFmt($objWriter, $style->getNumberFormat());
|
||||
|
||||
// fill
|
||||
$this->writeFill($objWriter, $style->getFill());
|
||||
|
||||
// alignment
|
||||
$objWriter->startElement('alignment');
|
||||
$horizontal = Alignment::HORIZONTAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getHorizontal()] ?? '';
|
||||
if ($horizontal) {
|
||||
$objWriter->writeAttribute('horizontal', $horizontal);
|
||||
}
|
||||
$vertical = Alignment::VERTICAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getVertical()] ?? '';
|
||||
if ($vertical) {
|
||||
$objWriter->writeAttribute('vertical', $vertical);
|
||||
}
|
||||
|
||||
if ($style->getAlignment()->getTextRotation() !== null) {
|
||||
$textRotation = 0;
|
||||
if ($style->getAlignment()->getTextRotation() >= 0) {
|
||||
$textRotation = $style->getAlignment()->getTextRotation();
|
||||
} else {
|
||||
$textRotation = 90 - $style->getAlignment()->getTextRotation();
|
||||
}
|
||||
$objWriter->writeAttribute('textRotation', (string) $textRotation);
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
// border
|
||||
$this->writeBorder($objWriter, $style->getBorders());
|
||||
|
||||
// protection
|
||||
if ((!empty($style->getProtection()->getLocked())) || (!empty($style->getProtection()->getHidden()))) {
|
||||
if (
|
||||
$style->getProtection()->getLocked() !== Protection::PROTECTION_INHERIT ||
|
||||
$style->getProtection()->getHidden() !== Protection::PROTECTION_INHERIT
|
||||
) {
|
||||
$objWriter->startElement('protection');
|
||||
if (
|
||||
($style->getProtection()->getLocked() !== null) &&
|
||||
($style->getProtection()->getLocked() !== Protection::PROTECTION_INHERIT)
|
||||
) {
|
||||
$objWriter->writeAttribute('locked', ($style->getProtection()->getLocked() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
|
||||
}
|
||||
if (
|
||||
($style->getProtection()->getHidden() !== null) &&
|
||||
($style->getProtection()->getHidden() !== Protection::PROTECTION_INHERIT)
|
||||
) {
|
||||
$objWriter->writeAttribute('hidden', ($style->getProtection()->getHidden() == Protection::PROTECTION_PROTECTED ? 'true' : 'false'));
|
||||
}
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write BorderPr.
|
||||
*
|
||||
* @param string $name Element name
|
||||
*/
|
||||
private function writeBorderPr(XMLWriter $objWriter, $name, Border $border): void
|
||||
{
|
||||
// Write BorderPr
|
||||
if ($border->getBorderStyle() != Border::BORDER_NONE) {
|
||||
$objWriter->startElement($name);
|
||||
$objWriter->writeAttribute('style', $border->getBorderStyle());
|
||||
|
||||
// color
|
||||
if ($border->getColor()->getARGB() !== null) {
|
||||
$objWriter->startElement('color');
|
||||
$objWriter->writeAttribute('rgb', $border->getColor()->getARGB());
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write NumberFormat.
|
||||
*
|
||||
* @param int $id Number Format identifier
|
||||
*/
|
||||
private function writeNumFmt(XMLWriter $objWriter, ?NumberFormat $numberFormat, $id = 0): void
|
||||
{
|
||||
// Translate formatcode
|
||||
$formatCode = ($numberFormat === null) ? null : $numberFormat->getFormatCode();
|
||||
|
||||
// numFmt
|
||||
if ($formatCode !== null) {
|
||||
$objWriter->startElement('numFmt');
|
||||
$objWriter->writeAttribute('numFmtId', (string) ($id + 164));
|
||||
$objWriter->writeAttribute('formatCode', $formatCode);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all styles.
|
||||
*
|
||||
* @return \PhpOffice\PhpSpreadsheet\Style\Style[] All styles in PhpSpreadsheet
|
||||
*/
|
||||
public function allStyles(Spreadsheet $spreadsheet)
|
||||
{
|
||||
return $spreadsheet->getCellXfCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all conditional styles.
|
||||
*
|
||||
* @return Conditional[] All conditional styles in PhpSpreadsheet
|
||||
*/
|
||||
public function allConditionalStyles(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Get an array of all styles
|
||||
$aStyles = [];
|
||||
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
foreach ($spreadsheet->getSheet($i)->getConditionalStylesCollection() as $conditionalStyles) {
|
||||
foreach ($conditionalStyles as $conditionalStyle) {
|
||||
$aStyles[] = $conditionalStyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aStyles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all fills.
|
||||
*
|
||||
* @return Fill[] All fills in PhpSpreadsheet
|
||||
*/
|
||||
public function allFills(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Get an array of unique fills
|
||||
$aFills = [];
|
||||
|
||||
// Two first fills are predefined
|
||||
$fill0 = new Fill();
|
||||
$fill0->setFillType(Fill::FILL_NONE);
|
||||
$aFills[] = $fill0;
|
||||
|
||||
$fill1 = new Fill();
|
||||
$fill1->setFillType(Fill::FILL_PATTERN_GRAY125);
|
||||
$aFills[] = $fill1;
|
||||
// The remaining fills
|
||||
$aStyles = $this->allStyles($spreadsheet);
|
||||
/** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
|
||||
foreach ($aStyles as $style) {
|
||||
if (!isset($aFills[$style->getFill()->getHashCode()])) {
|
||||
$aFills[$style->getFill()->getHashCode()] = $style->getFill();
|
||||
}
|
||||
}
|
||||
|
||||
return $aFills;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all fonts.
|
||||
*
|
||||
* @return Font[] All fonts in PhpSpreadsheet
|
||||
*/
|
||||
public function allFonts(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Get an array of unique fonts
|
||||
$aFonts = [];
|
||||
$aStyles = $this->allStyles($spreadsheet);
|
||||
|
||||
/** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
|
||||
foreach ($aStyles as $style) {
|
||||
if (!isset($aFonts[$style->getFont()->getHashCode()])) {
|
||||
$aFonts[$style->getFont()->getHashCode()] = $style->getFont();
|
||||
}
|
||||
}
|
||||
|
||||
return $aFonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all borders.
|
||||
*
|
||||
* @return Borders[] All borders in PhpSpreadsheet
|
||||
*/
|
||||
public function allBorders(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Get an array of unique borders
|
||||
$aBorders = [];
|
||||
$aStyles = $this->allStyles($spreadsheet);
|
||||
|
||||
/** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
|
||||
foreach ($aStyles as $style) {
|
||||
if (!isset($aBorders[$style->getBorders()->getHashCode()])) {
|
||||
$aBorders[$style->getBorders()->getHashCode()] = $style->getBorders();
|
||||
}
|
||||
}
|
||||
|
||||
return $aBorders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all number formats.
|
||||
*
|
||||
* @return NumberFormat[] All number formats in PhpSpreadsheet
|
||||
*/
|
||||
public function allNumberFormats(Spreadsheet $spreadsheet)
|
||||
{
|
||||
// Get an array of unique number formats
|
||||
$aNumFmts = [];
|
||||
$aStyles = $this->allStyles($spreadsheet);
|
||||
|
||||
/** @var \PhpOffice\PhpSpreadsheet\Style\Style $style */
|
||||
foreach ($aStyles as $style) {
|
||||
if ($style->getNumberFormat()->getBuiltInFormatCode() === false && !isset($aNumFmts[$style->getNumberFormat()->getHashCode()])) {
|
||||
$aNumFmts[$style->getNumberFormat()->getHashCode()] = $style->getNumberFormat();
|
||||
}
|
||||
}
|
||||
|
||||
return $aNumFmts;
|
||||
}
|
||||
}
|
115
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Table.php
vendored
Normal file
115
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Table.php
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Table as WorksheetTable;
|
||||
|
||||
class Table extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write Table to XML format.
|
||||
*
|
||||
* @param int $tableRef Table ID
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeTable(WorksheetTable $table, $tableRef): string
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// Table
|
||||
$name = 'Table' . $tableRef;
|
||||
$range = $table->getRange();
|
||||
|
||||
$objWriter->startElement('table');
|
||||
$objWriter->writeAttribute('xml:space', 'preserve');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
|
||||
$objWriter->writeAttribute('id', (string) $tableRef);
|
||||
$objWriter->writeAttribute('name', $name);
|
||||
$objWriter->writeAttribute('displayName', $table->getName() ?: $name);
|
||||
$objWriter->writeAttribute('ref', $range);
|
||||
$objWriter->writeAttribute('headerRowCount', $table->getShowHeaderRow() ? '1' : '0');
|
||||
$objWriter->writeAttribute('totalsRowCount', $table->getShowTotalsRow() ? '1' : '0');
|
||||
|
||||
// Table Boundaries
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($table->getRange());
|
||||
|
||||
// Table Auto Filter
|
||||
if ($table->getShowHeaderRow() && $table->getAllowFilter() === true) {
|
||||
$objWriter->startElement('autoFilter');
|
||||
$objWriter->writeAttribute('ref', $range);
|
||||
$objWriter->endElement();
|
||||
foreach (range($rangeStart[0], $rangeEnd[0]) as $offset => $columnIndex) {
|
||||
$column = $table->getColumnByOffset($offset);
|
||||
|
||||
if (!$column->getShowFilterButton()) {
|
||||
$objWriter->startElement('filterColumn');
|
||||
$objWriter->writeAttribute('colId', (string) $offset);
|
||||
$objWriter->writeAttribute('hiddenButton', '1');
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
$column = $table->getAutoFilter()->getColumnByOffset($offset);
|
||||
AutoFilter::writeAutoFilterColumn($objWriter, $column, $offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Table Columns
|
||||
$objWriter->startElement('tableColumns');
|
||||
$objWriter->writeAttribute('count', (string) ($rangeEnd[0] - $rangeStart[0] + 1));
|
||||
foreach (range($rangeStart[0], $rangeEnd[0]) as $offset => $columnIndex) {
|
||||
$worksheet = $table->getWorksheet();
|
||||
if (!$worksheet) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$column = $table->getColumnByOffset($offset);
|
||||
$cell = $worksheet->getCell([$columnIndex, $rangeStart[1]]);
|
||||
|
||||
$objWriter->startElement('tableColumn');
|
||||
$objWriter->writeAttribute('id', (string) ($offset + 1));
|
||||
$objWriter->writeAttribute('name', $table->getShowHeaderRow() ? $cell->getValue() : 'Column' . ($offset + 1));
|
||||
|
||||
if ($table->getShowTotalsRow()) {
|
||||
if ($column->getTotalsRowLabel()) {
|
||||
$objWriter->writeAttribute('totalsRowLabel', $column->getTotalsRowLabel());
|
||||
}
|
||||
if ($column->getTotalsRowFunction()) {
|
||||
$objWriter->writeAttribute('totalsRowFunction', $column->getTotalsRowFunction());
|
||||
}
|
||||
}
|
||||
if ($column->getColumnFormula()) {
|
||||
$objWriter->writeElement('calculatedColumnFormula', $column->getColumnFormula());
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
||||
// Table Styles
|
||||
$objWriter->startElement('tableStyleInfo');
|
||||
$objWriter->writeAttribute('name', $table->getStyle()->getTheme());
|
||||
$objWriter->writeAttribute('showFirstColumn', $table->getStyle()->getShowFirstColumn() ? '1' : '0');
|
||||
$objWriter->writeAttribute('showLastColumn', $table->getStyle()->getShowLastColumn() ? '1' : '0');
|
||||
$objWriter->writeAttribute('showRowStripes', $table->getStyle()->getShowRowStripes() ? '1' : '0');
|
||||
$objWriter->writeAttribute('showColumnStripes', $table->getStyle()->getShowColumnStripes() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
}
|
829
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php
vendored
Normal file
829
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php
vendored
Normal file
@ -0,0 +1,829 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
|
||||
class Theme extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Map of Major fonts to write.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $majorFonts = [
|
||||
'Jpan' => 'MS Pゴシック',
|
||||
'Hang' => '맑은 고딕',
|
||||
'Hans' => '宋体',
|
||||
'Hant' => '新細明體',
|
||||
'Arab' => 'Times New Roman',
|
||||
'Hebr' => 'Times New Roman',
|
||||
'Thai' => 'Tahoma',
|
||||
'Ethi' => 'Nyala',
|
||||
'Beng' => 'Vrinda',
|
||||
'Gujr' => 'Shruti',
|
||||
'Khmr' => 'MoolBoran',
|
||||
'Knda' => 'Tunga',
|
||||
'Guru' => 'Raavi',
|
||||
'Cans' => 'Euphemia',
|
||||
'Cher' => 'Plantagenet Cherokee',
|
||||
'Yiii' => 'Microsoft Yi Baiti',
|
||||
'Tibt' => 'Microsoft Himalaya',
|
||||
'Thaa' => 'MV Boli',
|
||||
'Deva' => 'Mangal',
|
||||
'Telu' => 'Gautami',
|
||||
'Taml' => 'Latha',
|
||||
'Syrc' => 'Estrangelo Edessa',
|
||||
'Orya' => 'Kalinga',
|
||||
'Mlym' => 'Kartika',
|
||||
'Laoo' => 'DokChampa',
|
||||
'Sinh' => 'Iskoola Pota',
|
||||
'Mong' => 'Mongolian Baiti',
|
||||
'Viet' => 'Times New Roman',
|
||||
'Uigh' => 'Microsoft Uighur',
|
||||
'Geor' => 'Sylfaen',
|
||||
];
|
||||
|
||||
/**
|
||||
* Map of Minor fonts to write.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $minorFonts = [
|
||||
'Jpan' => 'MS Pゴシック',
|
||||
'Hang' => '맑은 고딕',
|
||||
'Hans' => '宋体',
|
||||
'Hant' => '新細明體',
|
||||
'Arab' => 'Arial',
|
||||
'Hebr' => 'Arial',
|
||||
'Thai' => 'Tahoma',
|
||||
'Ethi' => 'Nyala',
|
||||
'Beng' => 'Vrinda',
|
||||
'Gujr' => 'Shruti',
|
||||
'Khmr' => 'DaunPenh',
|
||||
'Knda' => 'Tunga',
|
||||
'Guru' => 'Raavi',
|
||||
'Cans' => 'Euphemia',
|
||||
'Cher' => 'Plantagenet Cherokee',
|
||||
'Yiii' => 'Microsoft Yi Baiti',
|
||||
'Tibt' => 'Microsoft Himalaya',
|
||||
'Thaa' => 'MV Boli',
|
||||
'Deva' => 'Mangal',
|
||||
'Telu' => 'Gautami',
|
||||
'Taml' => 'Latha',
|
||||
'Syrc' => 'Estrangelo Edessa',
|
||||
'Orya' => 'Kalinga',
|
||||
'Mlym' => 'Kartika',
|
||||
'Laoo' => 'DokChampa',
|
||||
'Sinh' => 'Iskoola Pota',
|
||||
'Mong' => 'Mongolian Baiti',
|
||||
'Viet' => 'Arial',
|
||||
'Uigh' => 'Microsoft Uighur',
|
||||
'Geor' => 'Sylfaen',
|
||||
];
|
||||
|
||||
/**
|
||||
* Map of core colours.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $colourScheme = [
|
||||
'dk2' => '1F497D',
|
||||
'lt2' => 'EEECE1',
|
||||
'accent1' => '4F81BD',
|
||||
'accent2' => 'C0504D',
|
||||
'accent3' => '9BBB59',
|
||||
'accent4' => '8064A2',
|
||||
'accent5' => '4BACC6',
|
||||
'accent6' => 'F79646',
|
||||
'hlink' => '0000FF',
|
||||
'folHlink' => '800080',
|
||||
];
|
||||
|
||||
/**
|
||||
* Write theme to XML format.
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeTheme()
|
||||
{
|
||||
// Create XML writer
|
||||
$objWriter = null;
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// a:theme
|
||||
$objWriter->startElement('a:theme');
|
||||
$objWriter->writeAttribute('xmlns:a', Namespaces::DRAWINGML);
|
||||
$objWriter->writeAttribute('name', 'Office Theme');
|
||||
|
||||
// a:themeElements
|
||||
$objWriter->startElement('a:themeElements');
|
||||
|
||||
// a:clrScheme
|
||||
$objWriter->startElement('a:clrScheme');
|
||||
$objWriter->writeAttribute('name', 'Office');
|
||||
|
||||
// a:dk1
|
||||
$objWriter->startElement('a:dk1');
|
||||
|
||||
// a:sysClr
|
||||
$objWriter->startElement('a:sysClr');
|
||||
$objWriter->writeAttribute('val', 'windowText');
|
||||
$objWriter->writeAttribute('lastClr', '000000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:lt1
|
||||
$objWriter->startElement('a:lt1');
|
||||
|
||||
// a:sysClr
|
||||
$objWriter->startElement('a:sysClr');
|
||||
$objWriter->writeAttribute('val', 'window');
|
||||
$objWriter->writeAttribute('lastClr', 'FFFFFF');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:dk2
|
||||
$this->writeColourScheme($objWriter);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:fontScheme
|
||||
$objWriter->startElement('a:fontScheme');
|
||||
$objWriter->writeAttribute('name', 'Office');
|
||||
|
||||
// a:majorFont
|
||||
$objWriter->startElement('a:majorFont');
|
||||
$this->writeFonts($objWriter, 'Cambria', self::$majorFonts);
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:minorFont
|
||||
$objWriter->startElement('a:minorFont');
|
||||
$this->writeFonts($objWriter, 'Calibri', self::$minorFonts);
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:fmtScheme
|
||||
$objWriter->startElement('a:fmtScheme');
|
||||
$objWriter->writeAttribute('name', 'Office');
|
||||
|
||||
// a:fillStyleLst
|
||||
$objWriter->startElement('a:fillStyleLst');
|
||||
|
||||
// a:solidFill
|
||||
$objWriter->startElement('a:solidFill');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gradFill
|
||||
$objWriter->startElement('a:gradFill');
|
||||
$objWriter->writeAttribute('rotWithShape', '1');
|
||||
|
||||
// a:gsLst
|
||||
$objWriter->startElement('a:gsLst');
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '0');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:tint
|
||||
$objWriter->startElement('a:tint');
|
||||
$objWriter->writeAttribute('val', '50000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '300000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '35000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:tint
|
||||
$objWriter->startElement('a:tint');
|
||||
$objWriter->writeAttribute('val', '37000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '300000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '100000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:tint
|
||||
$objWriter->startElement('a:tint');
|
||||
$objWriter->writeAttribute('val', '15000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '350000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:lin
|
||||
$objWriter->startElement('a:lin');
|
||||
$objWriter->writeAttribute('ang', '16200000');
|
||||
$objWriter->writeAttribute('scaled', '1');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gradFill
|
||||
$objWriter->startElement('a:gradFill');
|
||||
$objWriter->writeAttribute('rotWithShape', '1');
|
||||
|
||||
// a:gsLst
|
||||
$objWriter->startElement('a:gsLst');
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '0');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '51000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '130000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '80000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '93000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '130000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '100000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '94000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '135000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:lin
|
||||
$objWriter->startElement('a:lin');
|
||||
$objWriter->writeAttribute('ang', '16200000');
|
||||
$objWriter->writeAttribute('scaled', '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:lnStyleLst
|
||||
$objWriter->startElement('a:lnStyleLst');
|
||||
|
||||
// a:ln
|
||||
$objWriter->startElement('a:ln');
|
||||
$objWriter->writeAttribute('w', '9525');
|
||||
$objWriter->writeAttribute('cap', 'flat');
|
||||
$objWriter->writeAttribute('cmpd', 'sng');
|
||||
$objWriter->writeAttribute('algn', 'ctr');
|
||||
|
||||
// a:solidFill
|
||||
$objWriter->startElement('a:solidFill');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '95000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '105000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:prstDash
|
||||
$objWriter->startElement('a:prstDash');
|
||||
$objWriter->writeAttribute('val', 'solid');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:ln
|
||||
$objWriter->startElement('a:ln');
|
||||
$objWriter->writeAttribute('w', '25400');
|
||||
$objWriter->writeAttribute('cap', 'flat');
|
||||
$objWriter->writeAttribute('cmpd', 'sng');
|
||||
$objWriter->writeAttribute('algn', 'ctr');
|
||||
|
||||
// a:solidFill
|
||||
$objWriter->startElement('a:solidFill');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:prstDash
|
||||
$objWriter->startElement('a:prstDash');
|
||||
$objWriter->writeAttribute('val', 'solid');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:ln
|
||||
$objWriter->startElement('a:ln');
|
||||
$objWriter->writeAttribute('w', '38100');
|
||||
$objWriter->writeAttribute('cap', 'flat');
|
||||
$objWriter->writeAttribute('cmpd', 'sng');
|
||||
$objWriter->writeAttribute('algn', 'ctr');
|
||||
|
||||
// a:solidFill
|
||||
$objWriter->startElement('a:solidFill');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:prstDash
|
||||
$objWriter->startElement('a:prstDash');
|
||||
$objWriter->writeAttribute('val', 'solid');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:effectStyleLst
|
||||
$objWriter->startElement('a:effectStyleLst');
|
||||
|
||||
// a:effectStyle
|
||||
$objWriter->startElement('a:effectStyle');
|
||||
|
||||
// a:effectLst
|
||||
$objWriter->startElement('a:effectLst');
|
||||
|
||||
// a:outerShdw
|
||||
$objWriter->startElement('a:outerShdw');
|
||||
$objWriter->writeAttribute('blurRad', '40000');
|
||||
$objWriter->writeAttribute('dist', '20000');
|
||||
$objWriter->writeAttribute('dir', '5400000');
|
||||
$objWriter->writeAttribute('rotWithShape', '0');
|
||||
|
||||
// a:srgbClr
|
||||
$objWriter->startElement('a:srgbClr');
|
||||
$objWriter->writeAttribute('val', '000000');
|
||||
|
||||
// a:alpha
|
||||
$objWriter->startElement('a:alpha');
|
||||
$objWriter->writeAttribute('val', '38000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:effectStyle
|
||||
$objWriter->startElement('a:effectStyle');
|
||||
|
||||
// a:effectLst
|
||||
$objWriter->startElement('a:effectLst');
|
||||
|
||||
// a:outerShdw
|
||||
$objWriter->startElement('a:outerShdw');
|
||||
$objWriter->writeAttribute('blurRad', '40000');
|
||||
$objWriter->writeAttribute('dist', '23000');
|
||||
$objWriter->writeAttribute('dir', '5400000');
|
||||
$objWriter->writeAttribute('rotWithShape', '0');
|
||||
|
||||
// a:srgbClr
|
||||
$objWriter->startElement('a:srgbClr');
|
||||
$objWriter->writeAttribute('val', '000000');
|
||||
|
||||
// a:alpha
|
||||
$objWriter->startElement('a:alpha');
|
||||
$objWriter->writeAttribute('val', '35000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:effectStyle
|
||||
$objWriter->startElement('a:effectStyle');
|
||||
|
||||
// a:effectLst
|
||||
$objWriter->startElement('a:effectLst');
|
||||
|
||||
// a:outerShdw
|
||||
$objWriter->startElement('a:outerShdw');
|
||||
$objWriter->writeAttribute('blurRad', '40000');
|
||||
$objWriter->writeAttribute('dist', '23000');
|
||||
$objWriter->writeAttribute('dir', '5400000');
|
||||
$objWriter->writeAttribute('rotWithShape', '0');
|
||||
|
||||
// a:srgbClr
|
||||
$objWriter->startElement('a:srgbClr');
|
||||
$objWriter->writeAttribute('val', '000000');
|
||||
|
||||
// a:alpha
|
||||
$objWriter->startElement('a:alpha');
|
||||
$objWriter->writeAttribute('val', '35000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:scene3d
|
||||
$objWriter->startElement('a:scene3d');
|
||||
|
||||
// a:camera
|
||||
$objWriter->startElement('a:camera');
|
||||
$objWriter->writeAttribute('prst', 'orthographicFront');
|
||||
|
||||
// a:rot
|
||||
$objWriter->startElement('a:rot');
|
||||
$objWriter->writeAttribute('lat', '0');
|
||||
$objWriter->writeAttribute('lon', '0');
|
||||
$objWriter->writeAttribute('rev', '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:lightRig
|
||||
$objWriter->startElement('a:lightRig');
|
||||
$objWriter->writeAttribute('rig', 'threePt');
|
||||
$objWriter->writeAttribute('dir', 't');
|
||||
|
||||
// a:rot
|
||||
$objWriter->startElement('a:rot');
|
||||
$objWriter->writeAttribute('lat', '0');
|
||||
$objWriter->writeAttribute('lon', '0');
|
||||
$objWriter->writeAttribute('rev', '1200000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:sp3d
|
||||
$objWriter->startElement('a:sp3d');
|
||||
|
||||
// a:bevelT
|
||||
$objWriter->startElement('a:bevelT');
|
||||
$objWriter->writeAttribute('w', '63500');
|
||||
$objWriter->writeAttribute('h', '25400');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:bgFillStyleLst
|
||||
$objWriter->startElement('a:bgFillStyleLst');
|
||||
|
||||
// a:solidFill
|
||||
$objWriter->startElement('a:solidFill');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gradFill
|
||||
$objWriter->startElement('a:gradFill');
|
||||
$objWriter->writeAttribute('rotWithShape', '1');
|
||||
|
||||
// a:gsLst
|
||||
$objWriter->startElement('a:gsLst');
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '0');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:tint
|
||||
$objWriter->startElement('a:tint');
|
||||
$objWriter->writeAttribute('val', '40000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '350000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '40000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:tint
|
||||
$objWriter->startElement('a:tint');
|
||||
$objWriter->writeAttribute('val', '45000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '99000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '350000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '100000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '20000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '255000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:path
|
||||
$objWriter->startElement('a:path');
|
||||
$objWriter->writeAttribute('path', 'circle');
|
||||
|
||||
// a:fillToRect
|
||||
$objWriter->startElement('a:fillToRect');
|
||||
$objWriter->writeAttribute('l', '50000');
|
||||
$objWriter->writeAttribute('t', '-80000');
|
||||
$objWriter->writeAttribute('r', '50000');
|
||||
$objWriter->writeAttribute('b', '180000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gradFill
|
||||
$objWriter->startElement('a:gradFill');
|
||||
$objWriter->writeAttribute('rotWithShape', '1');
|
||||
|
||||
// a:gsLst
|
||||
$objWriter->startElement('a:gsLst');
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '0');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:tint
|
||||
$objWriter->startElement('a:tint');
|
||||
$objWriter->writeAttribute('val', '80000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '300000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:gs
|
||||
$objWriter->startElement('a:gs');
|
||||
$objWriter->writeAttribute('pos', '100000');
|
||||
|
||||
// a:schemeClr
|
||||
$objWriter->startElement('a:schemeClr');
|
||||
$objWriter->writeAttribute('val', 'phClr');
|
||||
|
||||
// a:shade
|
||||
$objWriter->startElement('a:shade');
|
||||
$objWriter->writeAttribute('val', '30000');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:satMod
|
||||
$objWriter->startElement('a:satMod');
|
||||
$objWriter->writeAttribute('val', '200000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:path
|
||||
$objWriter->startElement('a:path');
|
||||
$objWriter->writeAttribute('path', 'circle');
|
||||
|
||||
// a:fillToRect
|
||||
$objWriter->startElement('a:fillToRect');
|
||||
$objWriter->writeAttribute('l', '50000');
|
||||
$objWriter->writeAttribute('t', '50000');
|
||||
$objWriter->writeAttribute('r', '50000');
|
||||
$objWriter->writeAttribute('b', '50000');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:objectDefaults
|
||||
$objWriter->writeElement('a:objectDefaults', null);
|
||||
|
||||
// a:extraClrSchemeLst
|
||||
$objWriter->writeElement('a:extraClrSchemeLst', null);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write fonts to XML format.
|
||||
*
|
||||
* @param string[] $fontSet
|
||||
*/
|
||||
private function writeFonts(XMLWriter $objWriter, string $latinFont, array $fontSet): void
|
||||
{
|
||||
// a:latin
|
||||
$objWriter->startElement('a:latin');
|
||||
$objWriter->writeAttribute('typeface', $latinFont);
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:ea
|
||||
$objWriter->startElement('a:ea');
|
||||
$objWriter->writeAttribute('typeface', '');
|
||||
$objWriter->endElement();
|
||||
|
||||
// a:cs
|
||||
$objWriter->startElement('a:cs');
|
||||
$objWriter->writeAttribute('typeface', '');
|
||||
$objWriter->endElement();
|
||||
|
||||
foreach ($fontSet as $fontScript => $typeface) {
|
||||
$objWriter->startElement('a:font');
|
||||
$objWriter->writeAttribute('script', $fontScript);
|
||||
$objWriter->writeAttribute('typeface', $typeface);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write colour scheme to XML format.
|
||||
*/
|
||||
private function writeColourScheme(XMLWriter $objWriter): void
|
||||
{
|
||||
foreach (self::$colourScheme as $colourName => $colourValue) {
|
||||
$objWriter->startElement('a:' . $colourName);
|
||||
|
||||
$objWriter->startElement('a:srgbClr');
|
||||
$objWriter->writeAttribute('val', $colourValue);
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
}
|
214
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php
vendored
Normal file
214
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php
vendored
Normal file
@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\DefinedNames as DefinedNamesWriter;
|
||||
|
||||
class Workbook extends WriterPart
|
||||
{
|
||||
/**
|
||||
* Write workbook to XML format.
|
||||
*
|
||||
* @param bool $recalcRequired Indicate whether formulas should be recalculated before writing
|
||||
*
|
||||
* @return string XML Output
|
||||
*/
|
||||
public function writeWorkbook(Spreadsheet $spreadsheet, $recalcRequired = false)
|
||||
{
|
||||
// Create XML writer
|
||||
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||
} else {
|
||||
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
// XML header
|
||||
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||
|
||||
// workbook
|
||||
$objWriter->startElement('workbook');
|
||||
$objWriter->writeAttribute('xml:space', 'preserve');
|
||||
$objWriter->writeAttribute('xmlns', Namespaces::MAIN);
|
||||
$objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
|
||||
|
||||
// fileVersion
|
||||
$this->writeFileVersion($objWriter);
|
||||
|
||||
// workbookPr
|
||||
$this->writeWorkbookPr($objWriter);
|
||||
|
||||
// workbookProtection
|
||||
$this->writeWorkbookProtection($objWriter, $spreadsheet);
|
||||
|
||||
// bookViews
|
||||
if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
|
||||
$this->writeBookViews($objWriter, $spreadsheet);
|
||||
}
|
||||
|
||||
// sheets
|
||||
$this->writeSheets($objWriter, $spreadsheet);
|
||||
|
||||
// definedNames
|
||||
(new DefinedNamesWriter($objWriter, $spreadsheet))->write();
|
||||
|
||||
// calcPr
|
||||
$this->writeCalcPr($objWriter, $recalcRequired);
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
// Return
|
||||
return $objWriter->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write file version.
|
||||
*/
|
||||
private function writeFileVersion(XMLWriter $objWriter): void
|
||||
{
|
||||
$objWriter->startElement('fileVersion');
|
||||
$objWriter->writeAttribute('appName', 'xl');
|
||||
$objWriter->writeAttribute('lastEdited', '4');
|
||||
$objWriter->writeAttribute('lowestEdited', '4');
|
||||
$objWriter->writeAttribute('rupBuild', '4505');
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write WorkbookPr.
|
||||
*/
|
||||
private function writeWorkbookPr(XMLWriter $objWriter): void
|
||||
{
|
||||
$objWriter->startElement('workbookPr');
|
||||
|
||||
if (Date::getExcelCalendar() === Date::CALENDAR_MAC_1904) {
|
||||
$objWriter->writeAttribute('date1904', '1');
|
||||
}
|
||||
|
||||
$objWriter->writeAttribute('codeName', 'ThisWorkbook');
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write BookViews.
|
||||
*/
|
||||
private function writeBookViews(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
// bookViews
|
||||
$objWriter->startElement('bookViews');
|
||||
|
||||
// workbookView
|
||||
$objWriter->startElement('workbookView');
|
||||
|
||||
$objWriter->writeAttribute('activeTab', (string) $spreadsheet->getActiveSheetIndex());
|
||||
$objWriter->writeAttribute('autoFilterDateGrouping', ($spreadsheet->getAutoFilterDateGrouping() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('firstSheet', (string) $spreadsheet->getFirstSheetIndex());
|
||||
$objWriter->writeAttribute('minimized', ($spreadsheet->getMinimized() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('showHorizontalScroll', ($spreadsheet->getShowHorizontalScroll() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('showSheetTabs', ($spreadsheet->getShowSheetTabs() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('showVerticalScroll', ($spreadsheet->getShowVerticalScroll() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('tabRatio', (string) $spreadsheet->getTabRatio());
|
||||
$objWriter->writeAttribute('visibility', $spreadsheet->getVisibility());
|
||||
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write WorkbookProtection.
|
||||
*/
|
||||
private function writeWorkbookProtection(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
if ($spreadsheet->getSecurity()->isSecurityEnabled()) {
|
||||
$objWriter->startElement('workbookProtection');
|
||||
$objWriter->writeAttribute('lockRevision', ($spreadsheet->getSecurity()->getLockRevision() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('lockStructure', ($spreadsheet->getSecurity()->getLockStructure() ? 'true' : 'false'));
|
||||
$objWriter->writeAttribute('lockWindows', ($spreadsheet->getSecurity()->getLockWindows() ? 'true' : 'false'));
|
||||
|
||||
if ($spreadsheet->getSecurity()->getRevisionsPassword() != '') {
|
||||
$objWriter->writeAttribute('revisionsPassword', $spreadsheet->getSecurity()->getRevisionsPassword());
|
||||
}
|
||||
|
||||
if ($spreadsheet->getSecurity()->getWorkbookPassword() != '') {
|
||||
$objWriter->writeAttribute('workbookPassword', $spreadsheet->getSecurity()->getWorkbookPassword());
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write calcPr.
|
||||
*
|
||||
* @param bool $recalcRequired Indicate whether formulas should be recalculated before writing
|
||||
*/
|
||||
private function writeCalcPr(XMLWriter $objWriter, $recalcRequired = true): void
|
||||
{
|
||||
$objWriter->startElement('calcPr');
|
||||
|
||||
// Set the calcid to a higher value than Excel itself will use, otherwise Excel will always recalc
|
||||
// If MS Excel does do a recalc, then users opening a file in MS Excel will be prompted to save on exit
|
||||
// because the file has changed
|
||||
$objWriter->writeAttribute('calcId', '999999');
|
||||
$objWriter->writeAttribute('calcMode', 'auto');
|
||||
// fullCalcOnLoad isn't needed if we've recalculating for the save
|
||||
$objWriter->writeAttribute('calcCompleted', ($recalcRequired) ? '1' : '0');
|
||||
$objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '0' : '1');
|
||||
$objWriter->writeAttribute('forceFullCalc', ($recalcRequired) ? '0' : '1');
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write sheets.
|
||||
*/
|
||||
private function writeSheets(XMLWriter $objWriter, Spreadsheet $spreadsheet): void
|
||||
{
|
||||
// Write sheets
|
||||
$objWriter->startElement('sheets');
|
||||
$sheetCount = $spreadsheet->getSheetCount();
|
||||
for ($i = 0; $i < $sheetCount; ++$i) {
|
||||
// sheet
|
||||
$this->writeSheet(
|
||||
$objWriter,
|
||||
$spreadsheet->getSheet($i)->getTitle(),
|
||||
($i + 1),
|
||||
($i + 1 + 3),
|
||||
$spreadsheet->getSheet($i)->getSheetState()
|
||||
);
|
||||
}
|
||||
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write sheet.
|
||||
*
|
||||
* @param string $worksheetName Sheet name
|
||||
* @param int $worksheetId Sheet id
|
||||
* @param int $relId Relationship ID
|
||||
* @param string $sheetState Sheet state (visible, hidden, veryHidden)
|
||||
*/
|
||||
private function writeSheet(XMLWriter $objWriter, $worksheetName, $worksheetId = 1, $relId = 1, $sheetState = 'visible'): void
|
||||
{
|
||||
if ($worksheetName != '') {
|
||||
// Write sheet
|
||||
$objWriter->startElement('sheet');
|
||||
$objWriter->writeAttribute('name', $worksheetName);
|
||||
$objWriter->writeAttribute('sheetId', (string) $worksheetId);
|
||||
if ($sheetState !== 'visible' && $sheetState != '') {
|
||||
$objWriter->writeAttribute('state', $sheetState);
|
||||
}
|
||||
$objWriter->writeAttribute('r:id', 'rId' . $relId);
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
throw new WriterException('Invalid parameters passed.');
|
||||
}
|
||||
}
|
||||
}
|
1400
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
vendored
Normal file
1400
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
33
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php
vendored
Normal file
33
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
abstract class WriterPart
|
||||
{
|
||||
/**
|
||||
* Parent Xlsx object.
|
||||
*
|
||||
* @var Xlsx
|
||||
*/
|
||||
private $parentWriter;
|
||||
|
||||
/**
|
||||
* Get parent Xlsx object.
|
||||
*
|
||||
* @return Xlsx
|
||||
*/
|
||||
public function getParentWriter()
|
||||
{
|
||||
return $this->parentWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parent Xlsx object.
|
||||
*/
|
||||
public function __construct(Xlsx $writer)
|
||||
{
|
||||
$this->parentWriter = $writer;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user