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