See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Writer; 4 5 use PhpOffice\PhpSpreadsheet\Calculation\Calculation; 6 use PhpOffice\PhpSpreadsheet\Calculation\Functions; 7 use PhpOffice\PhpSpreadsheet\HashTable; 8 use PhpOffice\PhpSpreadsheet\Spreadsheet; 9 use PhpOffice\PhpSpreadsheet\Style\Borders; 10 use PhpOffice\PhpSpreadsheet\Style\Conditional; 11 use PhpOffice\PhpSpreadsheet\Style\Fill; 12 use PhpOffice\PhpSpreadsheet\Style\Font; 13 use PhpOffice\PhpSpreadsheet\Style\NumberFormat; 14 use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing; 15 use PhpOffice\PhpSpreadsheet\Worksheet\Drawing as WorksheetDrawing; 16 use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing; 17 use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException; 18 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Chart; 19 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Comments; 20 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\ContentTypes; 21 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\DocProps; 22 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Drawing; 23 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels; 24 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsRibbon; 25 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsVBA; 26 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable; 27 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Style; 28 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Table; 29 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Theme; 30 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Workbook; 31 use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet; 32 use ZipArchive; 33 use ZipStream\Exception\OverflowException; 34 use ZipStream\Option\Archive; 35 use ZipStream\ZipStream; 36 37 class Xlsx extends BaseWriter 38 { 39 /** 40 * Office2003 compatibility. 41 * 42 * @var bool 43 */ 44 private $office2003compatibility = false; 45 46 /** 47 * Private Spreadsheet. 48 * 49 * @var Spreadsheet 50 */ 51 private $spreadSheet; 52 53 /** 54 * Private string table. 55 * 56 * @var string[] 57 */ 58 private $stringTable = []; 59 60 /** 61 * Private unique Conditional HashTable. 62 * 63 * @var HashTable<Conditional> 64 */ 65 private $stylesConditionalHashTable; 66 67 /** 68 * Private unique Style HashTable. 69 * 70 * @var HashTable<\PhpOffice\PhpSpreadsheet\Style\Style> 71 */ 72 private $styleHashTable; 73 74 /** 75 * Private unique Fill HashTable. 76 * 77 * @var HashTable<Fill> 78 */ 79 private $fillHashTable; 80 81 /** 82 * Private unique \PhpOffice\PhpSpreadsheet\Style\Font HashTable. 83 * 84 * @var HashTable<Font> 85 */ 86 private $fontHashTable; 87 88 /** 89 * Private unique Borders HashTable. 90 * 91 * @var HashTable<Borders> 92 */ 93 private $bordersHashTable; 94 95 /** 96 * Private unique NumberFormat HashTable. 97 * 98 * @var HashTable<NumberFormat> 99 */ 100 private $numFmtHashTable; 101 102 /** 103 * Private unique \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable. 104 * 105 * @var HashTable<BaseDrawing> 106 */ 107 private $drawingHashTable; 108 109 /** 110 * Private handle for zip stream. 111 * 112 * @var ZipStream 113 */ 114 private $zip; 115 116 /** 117 * @var Chart 118 */ 119 private $writerPartChart; 120 121 /** 122 * @var Comments 123 */ 124 private $writerPartComments; 125 126 /** 127 * @var ContentTypes 128 */ 129 private $writerPartContentTypes; 130 131 /** 132 * @var DocProps 133 */ 134 private $writerPartDocProps; 135 136 /** 137 * @var Drawing 138 */ 139 private $writerPartDrawing; 140 141 /** 142 * @var Rels 143 */ 144 private $writerPartRels; 145 146 /** 147 * @var RelsRibbon 148 */ 149 private $writerPartRelsRibbon; 150 151 /** 152 * @var RelsVBA 153 */ 154 private $writerPartRelsVBA; 155 156 /** 157 * @var StringTable 158 */ 159 private $writerPartStringTable; 160 161 /** 162 * @var Style 163 */ 164 private $writerPartStyle; 165 166 /** 167 * @var Theme 168 */ 169 private $writerPartTheme; 170 171 /** 172 * @var Table 173 */ 174 private $writerPartTable; 175 176 /** 177 * @var Workbook 178 */ 179 private $writerPartWorkbook; 180 181 /** 182 * @var Worksheet 183 */ 184 private $writerPartWorksheet; 185 186 /** 187 * Create a new Xlsx Writer. 188 */ 189 public function __construct(Spreadsheet $spreadsheet) 190 { 191 // Assign PhpSpreadsheet 192 $this->setSpreadsheet($spreadsheet); 193 194 $this->writerPartChart = new Chart($this); 195 $this->writerPartComments = new Comments($this); 196 $this->writerPartContentTypes = new ContentTypes($this); 197 $this->writerPartDocProps = new DocProps($this); 198 $this->writerPartDrawing = new Drawing($this); 199 $this->writerPartRels = new Rels($this); 200 $this->writerPartRelsRibbon = new RelsRibbon($this); 201 $this->writerPartRelsVBA = new RelsVBA($this); 202 $this->writerPartStringTable = new StringTable($this); 203 $this->writerPartStyle = new Style($this); 204 $this->writerPartTheme = new Theme($this); 205 $this->writerPartTable = new Table($this); 206 $this->writerPartWorkbook = new Workbook($this); 207 $this->writerPartWorksheet = new Worksheet($this); 208 209 // Set HashTable variables 210 // @phpstan-ignore-next-line 211 $this->bordersHashTable = new HashTable(); 212 // @phpstan-ignore-next-line 213 $this->drawingHashTable = new HashTable(); 214 // @phpstan-ignore-next-line 215 $this->fillHashTable = new HashTable(); 216 // @phpstan-ignore-next-line 217 $this->fontHashTable = new HashTable(); 218 // @phpstan-ignore-next-line 219 $this->numFmtHashTable = new HashTable(); 220 // @phpstan-ignore-next-line 221 $this->styleHashTable = new HashTable(); 222 // @phpstan-ignore-next-line 223 $this->stylesConditionalHashTable = new HashTable(); 224 } 225 226 public function getWriterPartChart(): Chart 227 { 228 return $this->writerPartChart; 229 } 230 231 public function getWriterPartComments(): Comments 232 { 233 return $this->writerPartComments; 234 } 235 236 public function getWriterPartContentTypes(): ContentTypes 237 { 238 return $this->writerPartContentTypes; 239 } 240 241 public function getWriterPartDocProps(): DocProps 242 { 243 return $this->writerPartDocProps; 244 } 245 246 public function getWriterPartDrawing(): Drawing 247 { 248 return $this->writerPartDrawing; 249 } 250 251 public function getWriterPartRels(): Rels 252 { 253 return $this->writerPartRels; 254 } 255 256 public function getWriterPartRelsRibbon(): RelsRibbon 257 { 258 return $this->writerPartRelsRibbon; 259 } 260 261 public function getWriterPartRelsVBA(): RelsVBA 262 { 263 return $this->writerPartRelsVBA; 264 } 265 266 public function getWriterPartStringTable(): StringTable 267 { 268 return $this->writerPartStringTable; 269 } 270 271 public function getWriterPartStyle(): Style 272 { 273 return $this->writerPartStyle; 274 } 275 276 public function getWriterPartTheme(): Theme 277 { 278 return $this->writerPartTheme; 279 } 280 281 public function getWriterPartTable(): Table 282 { 283 return $this->writerPartTable; 284 } 285 286 public function getWriterPartWorkbook(): Workbook 287 { 288 return $this->writerPartWorkbook; 289 } 290 291 public function getWriterPartWorksheet(): Worksheet 292 { 293 return $this->writerPartWorksheet; 294 } 295 296 /** 297 * Save PhpSpreadsheet to file. 298 * 299 * @param resource|string $filename 300 */ 301 public function save($filename, int $flags = 0): void 302 { 303 $this->processFlags($flags); 304 305 // garbage collect 306 $this->pathNames = []; 307 $this->spreadSheet->garbageCollect(); 308 309 $saveDebugLog = Calculation::getInstance($this->spreadSheet)->getDebugLog()->getWriteDebugLog(); 310 Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog(false); 311 $saveDateReturnType = Functions::getReturnDateType(); 312 Functions::setReturnDateType(Functions::RETURNDATE_EXCEL); 313 314 // Create string lookup table 315 $this->stringTable = []; 316 for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) { 317 $this->stringTable = $this->getWriterPartStringTable()->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable); 318 } 319 320 // Create styles dictionaries 321 $this->styleHashTable->addFromSource($this->getWriterPartStyle()->allStyles($this->spreadSheet)); 322 $this->stylesConditionalHashTable->addFromSource($this->getWriterPartStyle()->allConditionalStyles($this->spreadSheet)); 323 $this->fillHashTable->addFromSource($this->getWriterPartStyle()->allFills($this->spreadSheet)); 324 $this->fontHashTable->addFromSource($this->getWriterPartStyle()->allFonts($this->spreadSheet)); 325 $this->bordersHashTable->addFromSource($this->getWriterPartStyle()->allBorders($this->spreadSheet)); 326 $this->numFmtHashTable->addFromSource($this->getWriterPartStyle()->allNumberFormats($this->spreadSheet)); 327 328 // Create drawing dictionary 329 $this->drawingHashTable->addFromSource($this->getWriterPartDrawing()->allDrawings($this->spreadSheet)); 330 331 $zipContent = []; 332 // Add [Content_Types].xml to ZIP file 333 $zipContent['[Content_Types].xml'] = $this->getWriterPartContentTypes()->writeContentTypes($this->spreadSheet, $this->includeCharts); 334 335 //if hasMacros, add the vbaProject.bin file, Certificate file(if exists) 336 if ($this->spreadSheet->hasMacros()) { 337 $macrosCode = $this->spreadSheet->getMacrosCode(); 338 if ($macrosCode !== null) { 339 // we have the code ? 340 $zipContent['xl/vbaProject.bin'] = $macrosCode; //allways in 'xl', allways named vbaProject.bin 341 if ($this->spreadSheet->hasMacrosCertificate()) { 342 //signed macros ? 343 // Yes : add the certificate file and the related rels file 344 $zipContent['xl/vbaProjectSignature.bin'] = $this->spreadSheet->getMacrosCertificate(); 345 $zipContent['xl/_rels/vbaProject.bin.rels'] = $this->getWriterPartRelsVBA()->writeVBARelationships($this->spreadSheet); 346 } 347 } 348 } 349 //a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels) 350 if ($this->spreadSheet->hasRibbon()) { 351 $tmpRibbonTarget = $this->spreadSheet->getRibbonXMLData('target'); 352 $tmpRibbonTarget = is_string($tmpRibbonTarget) ? $tmpRibbonTarget : ''; 353 $zipContent[$tmpRibbonTarget] = $this->spreadSheet->getRibbonXMLData('data'); 354 if ($this->spreadSheet->hasRibbonBinObjects()) { 355 $tmpRootPath = dirname($tmpRibbonTarget) . '/'; 356 $ribbonBinObjects = $this->spreadSheet->getRibbonBinObjects('data'); //the files to write 357 if (is_array($ribbonBinObjects)) { 358 foreach ($ribbonBinObjects as $aPath => $aContent) { 359 $zipContent[$tmpRootPath . $aPath] = $aContent; 360 } 361 } 362 //the rels for files 363 $zipContent[$tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels'] = $this->getWriterPartRelsRibbon()->writeRibbonRelationships($this->spreadSheet); 364 } 365 } 366 367 // Add relationships to ZIP file 368 $zipContent['_rels/.rels'] = $this->getWriterPartRels()->writeRelationships($this->spreadSheet); 369 $zipContent['xl/_rels/workbook.xml.rels'] = $this->getWriterPartRels()->writeWorkbookRelationships($this->spreadSheet); 370 371 // Add document properties to ZIP file 372 $zipContent['docProps/app.xml'] = $this->getWriterPartDocProps()->writeDocPropsApp($this->spreadSheet); 373 $zipContent['docProps/core.xml'] = $this->getWriterPartDocProps()->writeDocPropsCore($this->spreadSheet); 374 $customPropertiesPart = $this->getWriterPartDocProps()->writeDocPropsCustom($this->spreadSheet); 375 if ($customPropertiesPart !== null) { 376 $zipContent['docProps/custom.xml'] = $customPropertiesPart; 377 } 378 379 // Add theme to ZIP file 380 $zipContent['xl/theme/theme1.xml'] = $this->getWriterPartTheme()->writeTheme($this->spreadSheet); 381 382 // Add string table to ZIP file 383 $zipContent['xl/sharedStrings.xml'] = $this->getWriterPartStringTable()->writeStringTable($this->stringTable); 384 385 // Add styles to ZIP file 386 $zipContent['xl/styles.xml'] = $this->getWriterPartStyle()->writeStyles($this->spreadSheet); 387 388 // Add workbook to ZIP file 389 $zipContent['xl/workbook.xml'] = $this->getWriterPartWorkbook()->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas); 390 391 $chartCount = 0; 392 // Add worksheets 393 for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) { 394 $zipContent['xl/worksheets/sheet' . ($i + 1) . '.xml'] = $this->getWriterPartWorksheet()->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts); 395 if ($this->includeCharts) { 396 $charts = $this->spreadSheet->getSheet($i)->getChartCollection(); 397 if (count($charts) > 0) { 398 foreach ($charts as $chart) { 399 $zipContent['xl/charts/chart' . ($chartCount + 1) . '.xml'] = $this->getWriterPartChart()->writeChart($chart, $this->preCalculateFormulas); 400 ++$chartCount; 401 } 402 } 403 } 404 } 405 406 $chartRef1 = 0; 407 $tableRef1 = 1; 408 // Add worksheet relationships (drawings, ...) 409 for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) { 410 // Add relationships 411 $zipContent['xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels'] = $this->getWriterPartRels()->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts, $tableRef1); 412 413 // Add unparsedLoadedData 414 $sheetCodeName = $this->spreadSheet->getSheet($i)->getCodeName(); 415 $unparsedLoadedData = $this->spreadSheet->getUnparsedLoadedData(); 416 if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'])) { 417 foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'] as $ctrlProp) { 418 $zipContent[$ctrlProp['filePath']] = $ctrlProp['content']; 419 } 420 } 421 if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'])) { 422 foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'] as $ctrlProp) { 423 $zipContent[$ctrlProp['filePath']] = $ctrlProp['content']; 424 } 425 } 426 427 $drawings = $this->spreadSheet->getSheet($i)->getDrawingCollection(); 428 $drawingCount = count($drawings); 429 if ($this->includeCharts) { 430 $chartCount = $this->spreadSheet->getSheet($i)->getChartCount(); 431 } 432 433 // Add drawing and image relationship parts 434 if (($drawingCount > 0) || ($chartCount > 0)) { 435 // Drawing relationships 436 $zipContent['xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels'] = $this->getWriterPartRels()->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts); 437 438 // Drawings 439 $zipContent['xl/drawings/drawing' . ($i + 1) . '.xml'] = $this->getWriterPartDrawing()->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts); 440 } elseif (isset($unparsedLoadedData['sheets'][$sheetCodeName]['drawingAlternateContents'])) { 441 // Drawings 442 $zipContent['xl/drawings/drawing' . ($i + 1) . '.xml'] = $this->getWriterPartDrawing()->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts); 443 } 444 445 // Add unparsed drawings 446 if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['Drawings'])) { 447 foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['Drawings'] as $relId => $drawingXml) { 448 $drawingFile = array_search($relId, $unparsedLoadedData['sheets'][$sheetCodeName]['drawingOriginalIds']); 449 if ($drawingFile !== false) { 450 //$drawingFile = ltrim($drawingFile, '.'); 451 //$zipContent['xl' . $drawingFile] = $drawingXml; 452 $zipContent['xl/drawings/drawing' . ($i + 1) . '.xml'] = $drawingXml; 453 } 454 } 455 } 456 457 // Add comment relationship parts 458 if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) { 459 // VML Comments relationships 460 $zipContent['xl/drawings/_rels/vmlDrawing' . ($i + 1) . '.vml.rels'] = $this->getWriterPartRels()->writeVMLDrawingRelationships($this->spreadSheet->getSheet($i)); 461 462 // VML Comments 463 $zipContent['xl/drawings/vmlDrawing' . ($i + 1) . '.vml'] = $this->getWriterPartComments()->writeVMLComments($this->spreadSheet->getSheet($i)); 464 465 // Comments 466 $zipContent['xl/comments' . ($i + 1) . '.xml'] = $this->getWriterPartComments()->writeComments($this->spreadSheet->getSheet($i)); 467 468 // Media 469 foreach ($this->spreadSheet->getSheet($i)->getComments() as $comment) { 470 if ($comment->hasBackgroundImage()) { 471 $image = $comment->getBackgroundImage(); 472 $zipContent['xl/media/' . $image->getMediaFilename()] = $this->processDrawing($image); 473 } 474 } 475 } 476 477 // Add unparsed relationship parts 478 if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'])) { 479 foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'] as $vmlDrawing) { 480 $zipContent[$vmlDrawing['filePath']] = $vmlDrawing['content']; 481 } 482 } 483 484 // Add header/footer relationship parts 485 if (count($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) { 486 // VML Drawings 487 $zipContent['xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml'] = $this->getWriterPartDrawing()->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i)); 488 489 // VML Drawing relationships 490 $zipContent['xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels'] = $this->getWriterPartRels()->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i)); 491 492 // Media 493 foreach ($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) { 494 $zipContent['xl/media/' . $image->getIndexedFilename()] = file_get_contents($image->getPath()); 495 } 496 } 497 498 // Add Table parts 499 $tables = $this->spreadSheet->getSheet($i)->getTableCollection(); 500 foreach ($tables as $table) { 501 $zipContent['xl/tables/table' . $tableRef1 . '.xml'] = $this->getWriterPartTable()->writeTable($table, $tableRef1++); 502 } 503 } 504 505 // Add media 506 for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { 507 if ($this->getDrawingHashTable()->getByIndex($i) instanceof WorksheetDrawing) { 508 $imageContents = null; 509 $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); 510 if (strpos($imagePath, 'zip://') !== false) { 511 $imagePath = substr($imagePath, 6); 512 $imagePathSplitted = explode('#', $imagePath); 513 514 $imageZip = new ZipArchive(); 515 $imageZip->open($imagePathSplitted[0]); 516 $imageContents = $imageZip->getFromName($imagePathSplitted[1]); 517 $imageZip->close(); 518 unset($imageZip); 519 } else { 520 $imageContents = file_get_contents($imagePath); 521 } 522 523 $zipContent['xl/media/' . $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()] = $imageContents; 524 } elseif ($this->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) { 525 ob_start(); 526 /** @var callable */ 527 $callable = $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(); 528 call_user_func( 529 $callable, 530 $this->getDrawingHashTable()->getByIndex($i)->getImageResource() 531 ); 532 $imageContents = ob_get_contents(); 533 ob_end_clean(); 534 535 $zipContent['xl/media/' . $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()] = $imageContents; 536 } 537 } 538 539 Functions::setReturnDateType($saveDateReturnType); 540 Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); 541 542 $this->openFileHandle($filename); 543 544 $options = new Archive(); 545 $options->setEnableZip64(false); 546 $options->setOutputStream($this->fileHandle); 547 548 $this->zip = new ZipStream(null, $options); 549 550 $this->addZipFiles($zipContent); 551 552 // Close file 553 try { 554 $this->zip->finish(); 555 } catch (OverflowException $e) { 556 throw new WriterException('Could not close resource.'); 557 } 558 559 $this->maybeCloseFileHandle(); 560 } 561 562 /** 563 * Get Spreadsheet object. 564 * 565 * @return Spreadsheet 566 */ 567 public function getSpreadsheet() 568 { 569 return $this->spreadSheet; 570 } 571 572 /** 573 * Set Spreadsheet object. 574 * 575 * @param Spreadsheet $spreadsheet PhpSpreadsheet object 576 * 577 * @return $this 578 */ 579 public function setSpreadsheet(Spreadsheet $spreadsheet) 580 { 581 $this->spreadSheet = $spreadsheet; 582 583 return $this; 584 } 585 586 /** 587 * Get string table. 588 * 589 * @return string[] 590 */ 591 public function getStringTable() 592 { 593 return $this->stringTable; 594 } 595 596 /** 597 * Get Style HashTable. 598 * 599 * @return HashTable<\PhpOffice\PhpSpreadsheet\Style\Style> 600 */ 601 public function getStyleHashTable() 602 { 603 return $this->styleHashTable; 604 } 605 606 /** 607 * Get Conditional HashTable. 608 * 609 * @return HashTable<Conditional> 610 */ 611 public function getStylesConditionalHashTable() 612 { 613 return $this->stylesConditionalHashTable; 614 } 615 616 /** 617 * Get Fill HashTable. 618 * 619 * @return HashTable<Fill> 620 */ 621 public function getFillHashTable() 622 { 623 return $this->fillHashTable; 624 } 625 626 /** 627 * Get \PhpOffice\PhpSpreadsheet\Style\Font HashTable. 628 * 629 * @return HashTable<Font> 630 */ 631 public function getFontHashTable() 632 { 633 return $this->fontHashTable; 634 } 635 636 /** 637 * Get Borders HashTable. 638 * 639 * @return HashTable<Borders> 640 */ 641 public function getBordersHashTable() 642 { 643 return $this->bordersHashTable; 644 } 645 646 /** 647 * Get NumberFormat HashTable. 648 * 649 * @return HashTable<NumberFormat> 650 */ 651 public function getNumFmtHashTable() 652 { 653 return $this->numFmtHashTable; 654 } 655 656 /** 657 * Get \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable. 658 * 659 * @return HashTable<BaseDrawing> 660 */ 661 public function getDrawingHashTable() 662 { 663 return $this->drawingHashTable; 664 } 665 666 /** 667 * Get Office2003 compatibility. 668 * 669 * @return bool 670 */ 671 public function getOffice2003Compatibility() 672 { 673 return $this->office2003compatibility; 674 } 675 676 /** 677 * Set Office2003 compatibility. 678 * 679 * @param bool $office2003compatibility Office2003 compatibility? 680 * 681 * @return $this 682 */ 683 public function setOffice2003Compatibility($office2003compatibility) 684 { 685 $this->office2003compatibility = $office2003compatibility; 686 687 return $this; 688 } 689 690 /** @var array */ 691 private $pathNames = []; 692 693 private function addZipFile(string $path, string $content): void 694 { 695 if (!in_array($path, $this->pathNames)) { 696 $this->pathNames[] = $path; 697 $this->zip->addFile($path, $content); 698 } 699 } 700 701 private function addZipFiles(array $zipContent): void 702 { 703 foreach ($zipContent as $path => $content) { 704 $this->addZipFile($path, $content); 705 } 706 } 707 708 /** 709 * @return mixed 710 */ 711 private function processDrawing(WorksheetDrawing $drawing) 712 { 713 $data = null; 714 $filename = $drawing->getPath(); 715 $imageData = getimagesize($filename); 716 717 if (is_array($imageData)) { 718 switch ($imageData[2]) { 719 case 1: // GIF, not supported by BIFF8, we convert to PNG 720 $image = imagecreatefromgif($filename); 721 if ($image !== false) { 722 ob_start(); 723 imagepng($image); 724 $data = ob_get_contents(); 725 ob_end_clean(); 726 } 727 728 break; 729 730 case 2: // JPEG 731 $data = file_get_contents($filename); 732 733 break; 734 735 case 3: // PNG 736 $data = file_get_contents($filename); 737 738 break; 739 740 case 6: // Windows DIB (BMP), we convert to PNG 741 $image = imagecreatefrombmp($filename); 742 if ($image !== false) { 743 ob_start(); 744 imagepng($image); 745 $data = ob_get_contents(); 746 ob_end_clean(); 747 } 748 749 break; 750 } 751 } 752 753 return $data; 754 } 755 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body