See Release Notes
Long Term Support Release
<?php namespace PhpOffice\PhpSpreadsheet\Writer;< use PhpOffice\PhpSpreadsheet\Shared\File;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 ZipArchive;> use ZipStream\Exception\OverflowException; > use ZipStream\Option\Archive; > use ZipStream\ZipStream;class Ods extends BaseWriter { /**< * Private writer parts. < * < * @var Ods\WriterPart[] < */ < private $writerParts = []; < < /*** Private PhpSpreadsheet. * * @var Spreadsheet */ private $spreadSheet; /**> * @var Content * Create a new Ods. > */ * > private $writerPartContent; * @param Spreadsheet $spreadsheet > */ > /** public function __construct(Spreadsheet $spreadsheet) > * @var Meta { > */ $this->setSpreadsheet($spreadsheet); > private $writerPartMeta; > $writerPartsArray = [ > /** 'content' => Content::class, > * @var MetaInf 'meta' => Meta::class, > */ 'meta_inf' => MetaInf::class, > private $writerPartMetaInf; 'mimetype' => Mimetype::class, > 'settings' => Settings::class, > /** 'styles' => Styles::class, > * @var Mimetype 'thumbnails' => Thumbnails::class, > */ ]; > private $writerPartMimetype; > foreach ($writerPartsArray as $writer => $class) { > /** $this->writerParts[$writer] = new $class($this); > * @var Settings } > */ } > private $writerPartSettings; > /** > /** * Get writer part. > * @var Styles * > */ * @param string $pPartName Writer part name > private $writerPartStyles; * > * @return null|Ods\WriterPart > /** */ > * @var Thumbnails public function getWriterPart($pPartName) > */ { > private $writerPartThumbnails; if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) { > return $this->writerParts[strtolower($pPartName)]; > /**< * < * @param Spreadsheet $spreadsheet< $writerPartsArray = [ < 'content' => Content::class, < 'meta' => Meta::class, < 'meta_inf' => MetaInf::class, < 'mimetype' => Mimetype::class, < 'settings' => Settings::class, < 'styles' => Styles::class, < 'thumbnails' => Thumbnails::class, < ];> $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; > }< foreach ($writerPartsArray as $writer => $class) { < $this->writerParts[$writer] = new $class($this);> public function getWriterPartMetaInf(): MetaInf > { > return $this->writerPartMetaInf;{> if (!$this->spreadSheet) { > public function getWriterPartMimetype(): Mimetype throw new WriterException('PhpSpreadsheet object unassigned.'); > { } > return $this->writerPartMimetype;< /** < * Get writer part. < * < * @param string $pPartName Writer part name < * < * @return null|Ods\WriterPart < */ < public function getWriterPart($pPartName)> public function getWriterPartSettings(): Settings< if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) { < return $this->writerParts[strtolower($pPartName)];> return $this->writerPartSettings;< return null;> public function getWriterPartStyles(): Styles > { > return $this->writerPartStyles; > } > > public function getWriterPartThumbnails(): Thumbnails > { > return $this->writerPartThumbnails;< * @param string $pFilename < * < * @throws WriterException> * @param resource|string $filename< public function save($pFilename)> public function save($filename, int $flags = 0): void$zip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());> $this->processFlags($flags); $zip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail()); >< // If $pFilename is php://output or php://stdout, make it a temporary file... < $originalFilename = $pFilename; < if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { < $pFilename = @tempnam(File::sysGetTempDir(), 'phpxltmp'); < if ($pFilename == '') { < $pFilename = $originalFilename; < } < }> $this->openFileHandle($filename);< $zip = $this->createZip($pFilename); < < $zip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest()); < $zip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail()); < $zip->addFromString('content.xml', $this->getWriterPart('content')->write()); < $zip->addFromString('meta.xml', $this->getWriterPart('meta')->write()); < $zip->addFromString('mimetype', $this->getWriterPart('mimetype')->write()); < $zip->addFromString('settings.xml', $this->getWriterPart('settings')->write()); < $zip->addFromString('styles.xml', $this->getWriterPart('styles')->write());> $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());< if ($zip->close() === false) { < throw new WriterException("Could not close zip file $pFilename.");> try { > $zip->finish(); > } catch (OverflowException $e) { > throw new WriterException('Could not close resource.');< // If a temporary file was used, copy it to the correct file stream < if ($originalFilename != $pFilename) { < if (copy($pFilename, $originalFilename) === false) { < throw new WriterException("Could not copy temporary zip file $pFilename to $originalFilename."); < } < @unlink($pFilename); < }> $this->maybeCloseFileHandle();< * @param string $pFilename < * < * @throws WriterException < * < * @return ZipArchive> * @return ZipStream< private function createZip($pFilename)> private function createZip()< // Create new ZIP file and open it for writing < $zip = new ZipArchive(); < < if (file_exists($pFilename)) { < unlink($pFilename); < }< if ($zip->open($pFilename, ZipArchive::OVERWRITE) !== true) { < if ($zip->open($pFilename, ZipArchive::CREATE) !== true) { < throw new WriterException("Could not open $pFilename for writing."); < }> if (!is_resource($this->fileHandle)) { > throw new WriterException('Could not open resource for writing.');}< return $zip;> // Create new ZIP stream > $options = new Archive(); > $options->setEnableZip64(false); > $options->setOutputStream($this->fileHandle); > > return new ZipStream(null, $options);} /** * Get Spreadsheet object. *< * @throws WriterException < ** @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 self> * @return $this*/ public function setSpreadsheet(Spreadsheet $spreadsheet) { $this->spreadSheet = $spreadsheet; return $this; } }