62 parent::__construct();
81 if ($zip->open($pFilename) ===
true) {
83 $result = !empty($workbookBasename);
102 $worksheetNames = [];
105 $zip->open($pFilename);
109 $rels = simplexml_load_string(
110 $this->securityScanner->scan($this->getFromZipArchive($zip,
'_rels/.rels'))
112 foreach ($rels->Relationship as $rel) {
113 switch ($rel[
'Type']) {
114 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
116 $xmlWorkbook = simplexml_load_string(
117 $this->securityScanner->scan($this->getFromZipArchive($zip,
"{$rel['Target']}"))
120 if ($xmlWorkbook->sheets) {
121 foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
123 $worksheetNames[] = (string) $eleSheet[
'name'];
131 return $worksheetNames;
141 public function listWorksheetInfo($pFilename)
148 $zip->open($pFilename);
151 $rels = simplexml_load_string(
152 $this->securityScanner->scan($this->getFromZipArchive($zip,
'_rels/.rels')),
156 foreach ($rels->Relationship as $rel) {
157 if ($rel[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument') {
158 $dir = dirname($rel[
'Target']);
161 $relsWorkbook = simplexml_load_string(
162 $this->securityScanner->scan(
163 $this->getFromZipArchive($zip,
"$dir/_rels/" . basename($rel[
'Target']) .
'.rels')
168 $relsWorkbook->registerXPathNamespace(
'rel',
'http://schemas.openxmlformats.org/package/2006/relationships');
171 foreach ($relsWorkbook->Relationship as $ele) {
172 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') {
173 $worksheets[(string) $ele[
'Id']] = $ele[
'Target'];
178 $xmlWorkbook = simplexml_load_string(
179 $this->securityScanner->scan(
180 $this->getFromZipArchive($zip,
"{$rel['Target']}")
185 if ($xmlWorkbook->sheets) {
186 $dir = dirname($rel[
'Target']);
188 foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
190 'worksheetName' => (string) $eleSheet[
'name'],
191 'lastColumnLetter' =>
'A',
192 'lastColumnIndex' => 0,
197 $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
'id')];
198 $fileWorksheetPath = strpos($fileWorksheet,
'/') === 0 ? substr($fileWorksheet, 1) :
"$dir/$fileWorksheet";
202 $this->securityScanner->scanFile(
208 $xml->setParserProperty(2,
true);
211 while (
$xml->read()) {
212 if (
$xml->name ==
'row' &&
$xml->nodeType == XMLReader::ELEMENT) {
214 $tmpInfo[
'totalRows'] =
$row;
215 $tmpInfo[
'totalColumns'] = max($tmpInfo[
'totalColumns'], $currCells);
217 } elseif (
$xml->name ==
'c' &&
$xml->nodeType == XMLReader::ELEMENT) {
221 $tmpInfo[
'totalColumns'] = max($tmpInfo[
'totalColumns'], $currCells);
224 $tmpInfo[
'lastColumnIndex'] = $tmpInfo[
'totalColumns'] - 1;
227 $worksheetInfo[] = $tmpInfo;
235 return $worksheetInfo;
240 $value = isset(
$c->v) ? (string)
$c->v : null;
243 } elseif ($value ==
'1') {
252 return isset(
$c->v) ? (string)
$c->v : null;
257 return isset(
$c->v) ? (string)
$c->v : null;
260 private function castToFormula(
$c,
$r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType): void
264 $calculatedValue = self::$castBaseType(
$c);
267 if (isset(
$c->f[
't']) && strtolower((
string)
$c->f[
't']) ==
'shared') {
268 $instance = (string)
$c->f[
'si'];
270 if (!isset($sharedFormulas[(
string)
$c->f[
'si']])) {
271 $sharedFormulas[$instance] = [
'master' =>
$r,
'formula' => $value];
276 $difference = [0, 0];
277 $difference[0] =
$current[0] - $master[0];
278 $difference[1] =
$current[1] - $master[1];
280 $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance][
'formula'],
'A1', $difference[0], $difference[1]);
293 if (strpos($fileName,
'//') !==
false) {
294 $fileName = substr($fileName, strpos($fileName,
'//') + 1);
302 $contents = $archive->getFromName($fileName, 0, ZipArchive::FL_NOCASE);
303 if ($contents ===
false) {
304 $contents = $archive->getFromName(substr($fileName, 1), 0, ZipArchive::FL_NOCASE);
317 public function load($pFilename)
323 $excel->removeSheetByIndex(0);
324 if (!$this->readDataOnly) {
325 $excel->removeCellStyleXfByIndex(0);
326 $excel->removeCellXfByIndex(0);
328 $unparsedLoadedData = [];
331 $zip->open($pFilename);
336 $wbRels = simplexml_load_string(
337 $this->securityScanner->scan($this->getFromZipArchive($zip,
"xl/_rels/${workbookBasename}.rels")),
341 foreach ($wbRels->Relationship as $rel) {
342 switch ($rel[
'Type']) {
343 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme':
344 $themeOrderArray = [
'lt1',
'dk1',
'lt2',
'dk2'];
345 $themeOrderAdditional = count($themeOrderArray);
347 $xmlTheme = simplexml_load_string(
348 $this->securityScanner->scan($this->getFromZipArchive($zip,
"xl/{$rel['Target']}")),
352 if (is_object($xmlTheme)) {
353 $xmlThemeName = $xmlTheme->attributes();
354 $xmlTheme = $xmlTheme->children(
'http://schemas.openxmlformats.org/drawingml/2006/main');
355 $themeName = (string) $xmlThemeName[
'name'];
357 $colourScheme = $xmlTheme->themeElements->clrScheme->attributes();
358 $colourSchemeName = (string) $colourScheme[
'name'];
359 $colourScheme = $xmlTheme->themeElements->clrScheme->children(
'http://schemas.openxmlformats.org/drawingml/2006/main');
362 foreach ($colourScheme as $k => $xmlColour) {
363 $themePos = array_search($k, $themeOrderArray);
364 if ($themePos ===
false) {
365 $themePos = $themeOrderAdditional++;
367 if (isset($xmlColour->sysClr)) {
368 $xmlColourData = $xmlColour->sysClr->attributes();
369 $themeColours[$themePos] = $xmlColourData[
'lastClr'];
370 } elseif (isset($xmlColour->srgbClr)) {
371 $xmlColourData = $xmlColour->srgbClr->attributes();
372 $themeColours[$themePos] = $xmlColourData[
'val'];
375 self::$theme =
new Xlsx\Theme($themeName, $colourSchemeName, $themeColours);
383 $rels = simplexml_load_string(
384 $this->securityScanner->scan($this->getFromZipArchive($zip,
'_rels/.rels')),
389 $propertyReader =
new PropertyReader($this->securityScanner, $excel->getProperties());
390 foreach ($rels->Relationship as $rel) {
391 switch ($rel[
'Type']) {
392 case 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties':
393 $propertyReader->readCoreProperties($this->
getFromZipArchive($zip,
"{$rel['Target']}"));
396 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties':
397 $propertyReader->readExtendedProperties($this->
getFromZipArchive($zip,
"{$rel['Target']}"));
400 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties':
401 $propertyReader->readCustomProperties($this->
getFromZipArchive($zip,
"{$rel['Target']}"));
405 case 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility':
406 $customUI = $rel[
'Target'];
407 if ($customUI !== null) {
412 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
413 $dir = dirname($rel[
'Target']);
415 $relsWorkbook = simplexml_load_string(
416 $this->securityScanner->scan($this->getFromZipArchive($zip,
"$dir/_rels/" . basename($rel[
'Target']) .
'.rels')),
420 $relsWorkbook->registerXPathNamespace(
'rel',
'http://schemas.openxmlformats.org/package/2006/relationships');
423 $xpath = self::getArrayItem($relsWorkbook->xpath(
"rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
426 $xmlStrings = simplexml_load_string(
427 $this->securityScanner->scan($this->getFromZipArchive($zip,
"$dir/$xpath[Target]")),
431 if (isset($xmlStrings->si)) {
432 foreach ($xmlStrings->si as $val) {
433 if (isset($val->t)) {
435 } elseif (isset($val->r)) {
436 $sharedStrings[] = $this->parseRichText($val);
443 $macros = $customUI = null;
444 foreach ($relsWorkbook->Relationship as $ele) {
445 switch ($ele[
'Type']) {
446 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet':
447 $worksheets[(string) $ele[
'Id']] = $ele[
'Target'];
451 case 'http://schemas.microsoft.com/office/2006/relationships/vbaProject':
452 $macros = $ele[
'Target'];
458 if ($macros !== null) {
460 if ($macrosCode !==
false) {
461 $excel->setMacrosCode($macrosCode);
462 $excel->setHasMacros(
true);
465 if ($Certificate !==
false) {
466 $excel->setMacrosCertificate($Certificate);
471 $xpath = self::getArrayItem($relsWorkbook->xpath(
"rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
473 $xmlStyles = simplexml_load_string(
474 $this->securityScanner->scan($this->getFromZipArchive($zip,
"$dir/$xpath[Target]")),
482 if ($xmlStyles && $xmlStyles->numFmts[0]) {
483 $numFmts = $xmlStyles->numFmts[0];
485 if (isset($numFmts) && ($numFmts !== null)) {
486 $numFmts->registerXPathNamespace(
'sml',
'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
488 if (!$this->readDataOnly && $xmlStyles) {
489 foreach ($xmlStyles->cellXfs->xf as $xf) {
492 if ($xf[
'numFmtId']) {
493 if (isset($numFmts)) {
494 $tmpNumFmt = self::getArrayItem($numFmts->xpath(
"sml:numFmt[@numFmtId=$xf[numFmtId]]"));
496 if (isset($tmpNumFmt[
'formatCode'])) {
497 $numFmt = (string) $tmpNumFmt[
'formatCode'];
506 (
int) $xf[
'numFmtId'] < 164 &&
512 $quotePrefix = (bool) ($xf[
'quotePrefix'] ??
false);
516 'font' => $xmlStyles->fonts->font[(
int) ($xf[
'fontId'])],
517 'fill' => $xmlStyles->fills->fill[(
int) ($xf[
'fillId'])],
518 'border' => $xmlStyles->borders->border[(
int) ($xf[
'borderId'])],
519 'alignment' => $xf->alignment,
520 'protection' => $xf->protection,
521 'quotePrefix' => $quotePrefix,
526 $objStyle =
new Style();
527 self::readStyle($objStyle,
$style);
528 $excel->addCellXf($objStyle);
531 foreach ($xmlStyles->cellStyleXfs->xf ?? [] as $xf) {
533 if ($numFmts && $xf[
'numFmtId']) {
534 $tmpNumFmt = self::getArrayItem($numFmts->xpath(
"sml:numFmt[@numFmtId=$xf[numFmtId]]"));
535 if (isset($tmpNumFmt[
'formatCode'])) {
536 $numFmt = (string) $tmpNumFmt[
'formatCode'];
537 } elseif ((
int) $xf[
'numFmtId'] < 165) {
542 $quotePrefix = (bool) ($xf[
'quotePrefix'] ??
false);
544 $cellStyle = (object) [
546 'font' => $xmlStyles->fonts->font[(
int) ($xf[
'fontId'])],
547 'fill' => $xmlStyles->fills->fill[(
int) ($xf[
'fillId'])],
548 'border' => $xmlStyles->borders->border[(
int) ($xf[
'borderId'])],
549 'alignment' => $xf->alignment,
550 'protection' => $xf->protection,
551 'quotePrefix' => $quotePrefix,
553 $cellStyles[] = $cellStyle;
556 $objStyle =
new Style();
557 self::readStyle($objStyle, $cellStyle);
558 $excel->addCellStyleXf($objStyle);
562 $styleReader =
new Styles($xmlStyles);
563 $styleReader->setStyleBaseData(self::$theme, $styles, $cellStyles);
564 $dxfs = $styleReader->dxfs($this->readDataOnly);
565 $styles = $styleReader->styles();
568 $xmlWorkbook = simplexml_load_string(
569 $this->securityScanner->scan($this->getFromZipArchive($zip,
"{$rel['Target']}")),
575 if ($xmlWorkbook->workbookPr) {
577 if (isset($xmlWorkbook->workbookPr[
'date1904'])) {
578 if (self::boolean((
string) $xmlWorkbook->workbookPr[
'date1904'])) {
589 $countSkippedSheets = 0;
592 $charts = $chartDetails = [];
594 if ($xmlWorkbook->sheets) {
596 foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
600 if (isset($this->loadSheetsOnly) && !in_array((
string) $eleSheet[
'name'], $this->loadSheetsOnly)) {
601 ++$countSkippedSheets;
602 $mapSheetId[$oldSheetId] = null;
609 $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets;
612 $docSheet = $excel->createSheet();
617 $docSheet->setTitle((
string) $eleSheet[
'name'],
false,
false);
618 $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
'id')];
620 $xmlSheet = simplexml_load_string(
621 $this->securityScanner->scan($this->getFromZipArchive($zip,
"$dir/$fileWorksheet")),
626 $sharedFormulas = [];
628 if (isset($eleSheet[
'state']) && (string) $eleSheet[
'state'] !=
'') {
629 $docSheet->setSheetState((
string) $eleSheet[
'state']);
635 if (!$this->readDataOnly && $xmlSheet->conditionalFormatting) {
639 if (isset($xmlSheet->sheetViews, $xmlSheet->sheetViews->sheetView)) {
640 $sheetViews =
new SheetViews($xmlSheet->sheetViews->sheetView, $docSheet);
651 if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
653 foreach ($xmlSheet->sheetData->row as
$row) {
655 foreach ($row->c as
$c) {
656 $r = (string) $c[
'r'];
660 $cellDataType = (string) $c[
't'];
662 $calculatedValue = null;
668 if (!$this->
getReadFilter()->readCell($coordinates[0], (
int) $coordinates[1], $docSheet->getTitle())) {
670 $this->
castToFormula($c,
$r, $cellDataType, $value, $calculatedValue, $sharedFormulas,
'castToError');
679 switch ($cellDataType) {
681 if ((
string) $c->v !=
'') {
682 $value = $sharedStrings[(int) ($c->v)];
685 $value = clone $value;
694 $value = self::castToBoolean($c);
697 $this->
castToFormula($c,
$r, $cellDataType, $value, $calculatedValue, $sharedFormulas,
'castToBoolean');
698 if (isset($c->f[
't'])) {
700 $docSheet->getCell(
$r)->setFormulaAttributes($att);
707 $this->
castToFormula($c,
$r, $cellDataType, $value, $calculatedValue, $sharedFormulas,
'castToError');
709 $value = $this->parseRichText($c->is);
715 $value = self::castToError($c);
718 $this->
castToFormula($c,
$r, $cellDataType, $value, $calculatedValue, $sharedFormulas,
'castToError');
724 $value = self::castToString($c);
727 $this->
castToFormula($c,
$r, $cellDataType, $value, $calculatedValue, $sharedFormulas,
'castToString');
728 if (isset($c->f[
't'])) {
730 $docSheet->getCell(
$r)->setFormulaAttributes([
't' => (
string)
$attributes]);
738 if ($this->readEmptyCells || ($value !== null && $value !==
'')) {
740 if ($value instanceof
RichText && $this->readDataOnly) {
741 $value = $value->getPlainText();
744 $cell = $docSheet->getCell(
$r);
746 if ($cellDataType !=
'') {
751 $cell->setValueExplicit($value, $cellDataType);
753 $cell->setValue($value);
755 if ($calculatedValue !== null) {
756 $cell->setCalculatedValue($calculatedValue);
760 if ($c[
's'] && !$this->readDataOnly) {
762 $cell->setXfIndex(isset($styles[(
int) ($c[
's'])]) ?
763 (
int) ($c[
's']) : 0);
772 $aKeys = [
'sheet',
'objects',
'scenarios',
'formatCells',
'formatColumns',
'formatRows',
'insertColumns',
'insertRows',
'insertHyperlinks',
'deleteColumns',
'deleteRows',
'selectLockedCells',
'sort',
'autoFilter',
'pivotTables',
'selectUnlockedCells'];
773 if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
774 foreach ($aKeys as
$key) {
775 $method =
'set' . ucfirst($key);
776 $docSheet->getProtection()->$method(self::boolean((
string) $xmlSheet->sheetProtection[$key]));
784 if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
788 if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
789 foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
790 $mergeRef = (string) $mergeCell[
'ref'];
791 if (strpos($mergeRef,
':') !==
false) {
792 $docSheet->mergeCells((
string) $mergeCell[
'ref']);
797 if ($xmlSheet && !$this->readDataOnly) {
798 $unparsedLoadedData = (
new PageSetup($docSheet, $xmlSheet))->
load($unparsedLoadedData);
801 if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
806 if ($xmlSheet && !$this->readDataOnly) {
807 $mc = $xmlSheet->children(
'http://schemas.openxmlformats.org/markup-compatibility/2006');
808 if ($mc->AlternateContent) {
809 foreach ($mc->AlternateContent as $alternateContent) {
810 $unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'AlternateContents'][] = $alternateContent->asXML();
816 if (!$this->readDataOnly) {
819 $relationsFileName = dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels';
820 if ($zip->locateName($relationsFileName)) {
822 $relsWorksheet = simplexml_load_string(
823 $this->securityScanner->scan(
824 $this->getFromZipArchive($zip, $relationsFileName)
829 $hyperlinkReader->readHyperlinks($relsWorksheet);
833 if ($xmlSheet && $xmlSheet->hyperlinks) {
834 $hyperlinkReader->setHyperlinks($xmlSheet->hyperlinks);
841 if (!$this->readDataOnly) {
843 if ($zip->locateName(dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')) {
845 $relsWorksheet = simplexml_load_string(
846 $this->securityScanner->scan(
847 $this->getFromZipArchive($zip, dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')
852 foreach ($relsWorksheet->Relationship as $ele) {
853 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments') {
854 $comments[(string) $ele[
'Id']] = (
string) $ele[
'Target'];
856 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing') {
857 $vmlComments[(string) $ele[
'Id']] = (
string) $ele[
'Target'];
863 foreach ($comments as $relName => $relPath) {
865 $relPath =
File::realpath(dirname(
"$dir/$fileWorksheet") .
'/' . $relPath);
866 $commentsFile = simplexml_load_string(
867 $this->securityScanner->scan($this->getFromZipArchive($zip, $relPath)),
876 foreach ($commentsFile->authors->author as $author) {
877 $authors[] = (string) $author;
881 foreach ($commentsFile->commentList->comment as
$comment) {
882 $commentModel = $docSheet->getComment((
string) $comment[
'ref']);
883 if (!empty($comment[
'authorId'])) {
884 $commentModel->setAuthor($authors[$comment[
'authorId']]);
886 $commentModel->setText($this->parseRichText($comment->text));
891 $unparsedVmlDrawings = $vmlComments;
894 foreach ($vmlComments as $relName => $relPath) {
896 $relPath =
File::realpath(dirname(
"$dir/$fileWorksheet") .
'/' . $relPath);
899 $vmlCommentsFile = simplexml_load_string(
900 $this->securityScanner->scan($this->getFromZipArchive($zip, $relPath)),
904 $vmlCommentsFile->registerXPathNamespace(
'v',
'urn:schemas-microsoft-com:vml');
910 $shapes = $vmlCommentsFile->xpath(
'//v:shape');
911 foreach ($shapes as $shape) {
912 $shape->registerXPathNamespace(
'v',
'urn:schemas-microsoft-com:vml');
914 if (isset($shape[
'style'])) {
915 $style = (string) $shape[
'style'];
916 $fillColor = strtoupper(substr((
string) $shape[
'fillcolor'], 1));
920 $clientData = $shape->xpath(
'.//x:ClientData');
921 if (is_array($clientData) && !empty($clientData)) {
922 $clientData = $clientData[0];
924 if (isset($clientData[
'ObjectType']) && (
string) $clientData[
'ObjectType'] ==
'Note') {
925 $temp = $clientData->xpath(
'.//x:Row');
926 if (is_array($temp)) {
930 $temp = $clientData->xpath(
'.//x:Column');
931 if (is_array($temp)) {
937 if (($column !== null) && (
$row !== null)) {
939 $comment = $docSheet->getCommentByColumnAndRow($column + 1,
$row + 1);
940 $comment->getFillColor()->setRGB($fillColor);
943 $styleArray = explode(
';', str_replace(
' ',
'',
$style));
944 foreach ($styleArray as $stylePair) {
945 $stylePair = explode(
':', $stylePair);
947 if ($stylePair[0] ==
'margin-left') {
948 $comment->setMarginLeft($stylePair[1]);
950 if ($stylePair[0] ==
'margin-top') {
951 $comment->setMarginTop($stylePair[1]);
953 if ($stylePair[0] ==
'width') {
956 if ($stylePair[0] ==
'height') {
959 if ($stylePair[0] ==
'visibility') {
960 $comment->setVisible($stylePair[1] ==
'visible');
964 unset($unparsedVmlDrawings[$relName]);
971 if ($unparsedVmlDrawings) {
972 foreach ($unparsedVmlDrawings as $rId => $relPath) {
973 $rId = substr($rId, 3);
974 $unparsedVmlDrawing = &$unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'vmlDrawings'];
975 $unparsedVmlDrawing[$rId] = [];
976 $unparsedVmlDrawing[$rId][
'filePath'] = self::dirAdd(
"$dir/$fileWorksheet", $relPath);
977 $unparsedVmlDrawing[$rId][
'relFilePath'] = $relPath;
978 $unparsedVmlDrawing[$rId][
'content'] = $this->securityScanner->scan($this->
getFromZipArchive($zip, $unparsedVmlDrawing[$rId][
'filePath']));
979 unset($unparsedVmlDrawing);
984 if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->readDataOnly) {
985 if ($zip->locateName(dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')) {
987 $relsWorksheet = simplexml_load_string(
988 $this->securityScanner->scan(
989 $this->getFromZipArchive($zip, dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')
994 $vmlRelationship =
'';
996 foreach ($relsWorksheet->Relationship as $ele) {
997 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing') {
998 $vmlRelationship = self::dirAdd(
"$dir/$fileWorksheet", $ele[
'Target']);
1002 if ($vmlRelationship !=
'') {
1005 $relsVML = simplexml_load_string(
1006 $this->securityScanner->scan(
1007 $this->getFromZipArchive($zip, dirname($vmlRelationship) .
'/_rels/' . basename($vmlRelationship) .
'.rels')
1013 if (isset($relsVML->Relationship)) {
1014 foreach ($relsVML->Relationship as $ele) {
1015 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1016 $drawings[(string) $ele[
'Id']] = self::dirAdd($vmlRelationship, $ele[
'Target']);
1021 $vmlDrawing = simplexml_load_string(
1022 $this->securityScanner->scan($this->getFromZipArchive($zip, $vmlRelationship)),
1026 $vmlDrawing->registerXPathNamespace(
'v',
'urn:schemas-microsoft-com:vml');
1030 $shapes = $vmlDrawing->xpath(
'//v:shape');
1031 foreach ($shapes as $idx => $shape) {
1032 $shape->registerXPathNamespace(
'v',
'urn:schemas-microsoft-com:vml');
1033 $imageData = $shape->xpath(
'//v:imagedata');
1039 $imageData = $imageData[$idx];
1041 $imageData = $imageData->attributes(
'urn:schemas-microsoft-com:office:office');
1042 $style = self::toCSSArray((
string) $shape[
'style']);
1045 if (isset($imageData[
'title'])) {
1046 $hfImages[(string) $shape[
'id']]->setName((
string) $imageData[
'title']);
1049 $hfImages[(string) $shape[
'id']]->setPath(
'zip://' .
File::realpath($pFilename) .
'#' . $drawings[(string) $imageData[
'relid']],
false);
1050 $hfImages[(string) $shape[
'id']]->setResizeProportional(
false);
1051 $hfImages[(string) $shape[
'id']]->setWidth(
$style[
'width']);
1052 $hfImages[(string) $shape[
'id']]->setHeight(
$style[
'height']);
1053 if (isset(
$style[
'margin-left'])) {
1054 $hfImages[(string) $shape[
'id']]->setOffsetX(
$style[
'margin-left']);
1056 $hfImages[(string) $shape[
'id']]->setOffsetY(
$style[
'margin-top']);
1057 $hfImages[(string) $shape[
'id']]->setResizeProportional(
true);
1060 $docSheet->getHeaderFooter()->setImages($hfImages);
1067 if ($zip->locateName(dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')) {
1069 $relsWorksheet = simplexml_load_string(
1070 $this->securityScanner->scan(
1071 $this->getFromZipArchive($zip, dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')
1077 foreach ($relsWorksheet->Relationship as $ele) {
1078 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing') {
1079 $drawings[(string) $ele[
'Id']] = self::dirAdd(
"$dir/$fileWorksheet", $ele[
'Target']);
1082 if ($xmlSheet->drawing && !$this->readDataOnly) {
1083 $unparsedDrawings = [];
1084 $fileDrawing = null;
1085 foreach ($xmlSheet->drawing as $drawing) {
1086 $drawingRelId = (string) self::getArrayItem($drawing->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
'id');
1087 $fileDrawing = $drawings[$drawingRelId];
1089 $relsDrawing = simplexml_load_string(
1090 $this->securityScanner->scan(
1091 $this->getFromZipArchive($zip, dirname($fileDrawing) .
'/_rels/' . basename($fileDrawing) .
'.rels')
1098 if ($relsDrawing && $relsDrawing->Relationship) {
1099 foreach ($relsDrawing->Relationship as $ele) {
1100 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
1101 $hyperlinks[(string) $ele[
'Id']] = (
string) $ele[
'Target'];
1103 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1104 $images[(string) $ele[
'Id']] = self::dirAdd($fileDrawing, $ele[
'Target']);
1105 } elseif ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart') {
1106 if ($this->includeCharts) {
1107 $charts[self::dirAdd($fileDrawing, $ele[
'Target'])] = [
1108 'id' => (string) $ele[
'Id'],
1109 'sheet' => $docSheet->getTitle(),
1115 $xmlDrawing = simplexml_load_string(
1116 $this->securityScanner->scan($this->getFromZipArchive($zip, $fileDrawing)),
1120 $xmlDrawingChildren = $xmlDrawing->children(
'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
1122 if ($xmlDrawingChildren->oneCellAnchor) {
1123 foreach ($xmlDrawingChildren->oneCellAnchor as $oneCellAnchor) {
1124 if ($oneCellAnchor->pic->blipFill) {
1126 $blip = $oneCellAnchor->pic->blipFill->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->blip;
1128 $xfrm = $oneCellAnchor->pic->spPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->xfrm;
1130 $outerShdw = $oneCellAnchor->pic->spPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->effectLst->outerShdw;
1132 $hlinkClick = $oneCellAnchor->pic->nvPicPr->cNvPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->hlinkClick;
1134 $objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
1135 $objDrawing->setName((
string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(),
'name'));
1136 $objDrawing->setDescription((
string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(),
'descr'));
1137 $imageKey = (string) self::getArrayItem(
1138 $blip->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
1142 if (isset($images[$imageKey])) {
1143 $objDrawing->setPath(
1153 $objDrawing->setResizeProportional(
false);
1154 $objDrawing->setWidth(
Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(),
'cx')));
1155 $objDrawing->setHeight(
Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(),
'cy')));
1160 $shadow = $objDrawing->getShadow();
1161 $shadow->setVisible(
true);
1162 $shadow->setBlurRadius(
Drawing::EMUToPixels(self::getArrayItem($outerShdw->attributes(),
'blurRad')));
1163 $shadow->setDistance(
Drawing::EMUToPixels(self::getArrayItem($outerShdw->attributes(),
'dist')));
1165 $shadow->setAlignment((
string) self::getArrayItem($outerShdw->attributes(),
'algn'));
1166 $clr = $outerShdw->srgbClr ?? $outerShdw->prstClr;
1167 $shadow->getColor()->setRGB(self::getArrayItem($clr->attributes(),
'val'));
1168 $shadow->setAlpha(self::getArrayItem($clr->alpha->attributes(),
'val') / 1000);
1173 $objDrawing->setWorksheet($docSheet);
1174 } elseif ($this->includeCharts && $oneCellAnchor->graphicFrame) {
1182 $graphic = $oneCellAnchor->graphicFrame->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->graphic;
1184 $chartRef = $graphic->graphicData->children(
'http://schemas.openxmlformats.org/drawingml/2006/chart')->chart;
1185 $thisChart = (string) $chartRef->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1187 $chartDetails[$docSheet->getTitle() .
'!' . $thisChart] = [
1188 'fromCoordinate' => $coordinates,
1189 'fromOffsetX' => $offsetX,
1190 'fromOffsetY' => $offsetY,
1192 'height' => $height,
1193 'worksheetTitle' => $docSheet->getTitle(),
1198 if ($xmlDrawingChildren->twoCellAnchor) {
1199 foreach ($xmlDrawingChildren->twoCellAnchor as $twoCellAnchor) {
1200 if ($twoCellAnchor->pic->blipFill) {
1201 $blip = $twoCellAnchor->pic->blipFill->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->blip;
1202 $xfrm = $twoCellAnchor->pic->spPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->xfrm;
1203 $outerShdw = $twoCellAnchor->pic->spPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->effectLst->outerShdw;
1204 $hlinkClick = $twoCellAnchor->pic->nvPicPr->cNvPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->hlinkClick;
1205 $objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
1206 $objDrawing->setName((
string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(),
'name'));
1207 $objDrawing->setDescription((
string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(),
'descr'));
1208 $imageKey = (string) self::getArrayItem(
1209 $blip->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
1212 if (isset($images[$imageKey])) {
1213 $objDrawing->setPath(
1223 $objDrawing->setResizeProportional(
false);
1226 $objDrawing->setWidth(
Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(),
'cx')));
1227 $objDrawing->setHeight(
Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(),
'cy')));
1231 $shadow = $objDrawing->getShadow();
1232 $shadow->setVisible(
true);
1233 $shadow->setBlurRadius(
Drawing::EMUToPixels(self::getArrayItem($outerShdw->attributes(),
'blurRad')));
1234 $shadow->setDistance(
Drawing::EMUToPixels(self::getArrayItem($outerShdw->attributes(),
'dist')));
1236 $shadow->setAlignment((
string) self::getArrayItem($outerShdw->attributes(),
'algn'));
1237 $clr = $outerShdw->srgbClr ?? $outerShdw->prstClr;
1238 $shadow->getColor()->setRGB(self::getArrayItem($clr->attributes(),
'val'));
1239 $shadow->setAlpha(self::getArrayItem($clr->alpha->attributes(),
'val') / 1000);
1244 $objDrawing->setWorksheet($docSheet);
1245 } elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) {
1252 $graphic = $twoCellAnchor->graphicFrame->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->graphic;
1254 $chartRef = $graphic->graphicData->children(
'http://schemas.openxmlformats.org/drawingml/2006/chart')->chart;
1255 $thisChart = (string) $chartRef->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1257 $chartDetails[$docSheet->getTitle() .
'!' . $thisChart] = [
1258 'fromCoordinate' => $fromCoordinate,
1259 'fromOffsetX' => $fromOffsetX,
1260 'fromOffsetY' => $fromOffsetY,
1261 'toCoordinate' => $toCoordinate,
1262 'toOffsetX' => $toOffsetX,
1263 'toOffsetY' => $toOffsetY,
1264 'worksheetTitle' => $docSheet->getTitle(),
1269 if ($relsDrawing ===
false && $xmlDrawing->count() == 0) {
1271 $unparsedDrawings[$drawingRelId] = $xmlDrawing->asXML();
1276 $unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'drawingOriginalIds'] = [];
1277 foreach ($relsWorksheet->Relationship as $ele) {
1278 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing') {
1279 $drawingRelId = (string) $ele[
'Id'];
1280 $unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'drawingOriginalIds'][(string) $ele[
'Target']] = $drawingRelId;
1281 if (isset($unparsedDrawings[$drawingRelId])) {
1282 $unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'Drawings'][$drawingRelId] = $unparsedDrawings[$drawingRelId];
1288 $xmlAltDrawing = simplexml_load_string(
1289 $this->securityScanner->scan($this->getFromZipArchive($zip, $fileDrawing)),
1292 )->children(
'http://schemas.openxmlformats.org/markup-compatibility/2006');
1294 if ($xmlAltDrawing->AlternateContent) {
1295 foreach ($xmlAltDrawing->AlternateContent as $alternateContent) {
1296 $unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'drawingAlternateContents'][] = $alternateContent->asXML();
1303 $this->
readPrinterSettings($excel, $zip, $dir, $fileWorksheet, $docSheet, $unparsedLoadedData);
1306 if ($xmlWorkbook->definedNames) {
1307 foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1309 $extractedRange = (string) $definedName;
1310 if (($spos = strpos($extractedRange,
'!')) !==
false) {
1311 $extractedRange = substr($extractedRange, 0, $spos) . str_replace(
'$',
'', substr($extractedRange, $spos));
1313 $extractedRange = str_replace(
'$',
'', $extractedRange);
1317 if ($extractedRange ==
'') {
1322 if ((
string) $definedName[
'localSheetId'] !=
'' && (
string) $definedName[
'localSheetId'] == $oldSheetId) {
1324 switch ((
string) $definedName[
'name']) {
1325 case '_xlnm._FilterDatabase':
1326 if ((
string) $definedName[
'hidden'] !==
'1') {
1327 $extractedRange = explode(
',', $extractedRange);
1328 foreach ($extractedRange as $range) {
1329 $autoFilterRange = $range;
1330 if (strpos($autoFilterRange,
':') !==
false) {
1331 $docSheet->getAutoFilter()->setRange($autoFilterRange);
1337 case '_xlnm.Print_Titles':
1339 $extractedRange = explode(
',', $extractedRange);
1342 foreach ($extractedRange as $range) {
1344 $range = str_replace(
'$',
'', $range);
1347 if (preg_match(
'/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) {
1348 $docSheet->getPageSetup()->setColumnsToRepeatAtLeft([$matches[1], $matches[2]]);
1349 } elseif (preg_match(
'/!?(\d+)\:(\d+)$/', $range, $matches)) {
1351 $docSheet->getPageSetup()->setRowsToRepeatAtTop([$matches[1], $matches[2]]);
1356 case '_xlnm.Print_Area':
1357 $rangeSets = preg_split(
"/('?(?:.*?)'?(?:![A-Z0-9]+:[A-Z0-9]+)),?/", $extractedRange, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
1359 foreach ($rangeSets as $rangeSet) {
1361 if (strpos($rangeSet,
':') ===
false) {
1362 $rangeSet = $rangeSet .
':' . $rangeSet;
1364 $newRangeSets[] = str_replace(
'$',
'', $rangeSet);
1366 $docSheet->getPageSetup()->setPrintArea(implode(
',', $newRangeSets));
1381 if ($xmlWorkbook->definedNames) {
1382 foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1384 $extractedRange = (string) $definedName;
1387 if ($extractedRange ==
'') {
1392 if ((
string) $definedName[
'localSheetId'] !=
'') {
1395 switch ((
string) $definedName[
'name']) {
1396 case '_xlnm._FilterDatabase':
1397 case '_xlnm.Print_Titles':
1398 case '_xlnm.Print_Area':
1401 if ($mapSheetId[(
int) $definedName[
'localSheetId']] !== null) {
1403 $scope = $excel->getSheet($mapSheetId[(
int) $definedName[
'localSheetId']]);
1404 if (strpos((
string) $definedName,
'!') !==
false) {
1405 $range[0] = str_replace(
"''",
"'", $range[0]);
1406 $range[0] = str_replace(
"'",
'', $range[0]);
1407 if ($worksheet = $excel->getSheetByName($range[0])) {
1419 } elseif (!isset($definedName[
'localSheetId'])) {
1420 $definedRange = (string) $definedName;
1422 $locatedSheet = null;
1423 if (strpos((
string) $definedName,
'!') !==
false) {
1426 $definedNameValueParts = preg_split(
"/[ ,](?=([^']*'[^']*')*[^']*$)/miuU", $definedRange);
1429 $extractedSheetName = trim($extractedSheetName,
"'");
1432 $locatedSheet = $excel->getSheetByName($extractedSheetName);
1436 $definedRange =
'#REF!';
1444 if ((!$this->readDataOnly || !empty($this->loadSheetsOnly)) && isset($xmlWorkbook->bookViews->workbookView)) {
1445 $workbookView = $xmlWorkbook->bookViews->workbookView;
1448 $activeTab = (int) ($workbookView[
'activeTab']);
1451 if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
1452 $excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1454 if ($excel->getSheetCount() == 0) {
1455 $excel->createSheet();
1457 $excel->setActiveSheetIndex(0);
1460 if (isset($workbookView[
'showHorizontalScroll'])) {
1461 $showHorizontalScroll = (string) $workbookView[
'showHorizontalScroll'];
1465 if (isset($workbookView[
'showVerticalScroll'])) {
1466 $showVerticalScroll = (string) $workbookView[
'showVerticalScroll'];
1470 if (isset($workbookView[
'showSheetTabs'])) {
1471 $showSheetTabs = (string) $workbookView[
'showSheetTabs'];
1475 if (isset($workbookView[
'minimized'])) {
1476 $minimized = (string) $workbookView[
'minimized'];
1480 if (isset($workbookView[
'autoFilterDateGrouping'])) {
1481 $autoFilterDateGrouping = (string) $workbookView[
'autoFilterDateGrouping'];
1485 if (isset($workbookView[
'firstSheet'])) {
1486 $firstSheet = (string) $workbookView[
'firstSheet'];
1487 $excel->setFirstSheetIndex((
int) $firstSheet);
1490 if (isset($workbookView[
'visibility'])) {
1491 $visibility = (string) $workbookView[
'visibility'];
1492 $excel->setVisibility($visibility);
1495 if (isset($workbookView[
'tabRatio'])) {
1496 $tabRatio = (string) $workbookView[
'tabRatio'];
1497 $excel->setTabRatio((
int) $tabRatio);
1505 if (!$this->readDataOnly) {
1506 $contentTypes = simplexml_load_string(
1507 $this->securityScanner->scan(
1508 $this->getFromZipArchive($zip,
'[Content_Types].xml')
1516 switch ($contentType[
'ContentType']) {
1517 case 'application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings':
1518 $unparsedLoadedData[
'default_content_types'][(string) $contentType[
'Extension']] = (
string) $contentType[
'ContentType'];
1525 foreach ($contentTypes->Override as $contentType) {
1526 switch ($contentType[
'ContentType']) {
1527 case 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml':
1528 if ($this->includeCharts) {
1529 $chartEntryRef = ltrim($contentType[
'PartName'],
'/');
1530 $chartElements = simplexml_load_string(
1531 $this->securityScanner->scan(
1532 $this->getFromZipArchive($zip, $chartEntryRef)
1537 $objChart =
Chart::readChart($chartElements, basename($chartEntryRef,
'.xml'));
1539 if (isset($charts[$chartEntryRef])) {
1540 $chartPositionRef = $charts[$chartEntryRef][
'sheet'] .
'!' . $charts[$chartEntryRef][
'id'];
1541 if (isset($chartDetails[$chartPositionRef])) {
1542 $excel->getSheetByName($charts[$chartEntryRef][
'sheet'])->addChart($objChart);
1543 $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef][
'sheet']));
1544 $objChart->setTopLeftPosition($chartDetails[$chartPositionRef][
'fromCoordinate'], $chartDetails[$chartPositionRef][
'fromOffsetX'], $chartDetails[$chartPositionRef][
'fromOffsetY']);
1545 if (array_key_exists(
'toCoordinate', $chartDetails[$chartPositionRef])) {
1547 $objChart->setBottomRightPosition($chartDetails[$chartPositionRef][
'toCoordinate'], $chartDetails[$chartPositionRef][
'toOffsetX'], $chartDetails[$chartPositionRef][
'toOffsetY']);
1556 case 'application/vnd.ms-excel.controlproperties+xml':
1557 $unparsedLoadedData[
'override_content_types'][(string) $contentType[
'PartName']] = (
string) $contentType[
'ContentType'];
1564 $excel->setUnparsedLoadedData($unparsedLoadedData);
1576 $docStyle->getNumberFormat()->setFormatCode(
$style->numFmt);
1579 if (isset(
$style->font)) {
1584 if (isset(
$style->fill)) {
1585 Styles::readFillStyle($docStyle->getFill(),
$style->fill);
1589 if (isset(
$style->border)) {
1594 if (isset(
$style->alignment)) {
1599 if (isset(
$style->protection)) {
1605 if (isset(
$style->quotePrefix)) {
1606 $docStyle->setQuotePrefix((
bool)
$style->quotePrefix);
1619 if (isset($is->t)) {
1622 if (is_object($is->r)) {
1625 foreach ($is->r as $run) {
1626 if (!isset($run->rPr)) {
1631 if (isset($run->rPr->rFont[
'val'])) {
1632 $objText->getFont()->setName((
string) $run->rPr->rFont[
'val']);
1634 if (isset($run->rPr->sz[
'val'])) {
1635 $objText->getFont()->setSize((
float) $run->rPr->sz[
'val']);
1637 if (isset($run->rPr->color)) {
1641 (isset($run->rPr->b[
'val']) && self::boolean((
string) $run->rPr->b[
'val'])) ||
1642 (isset($run->rPr->b) && !isset($run->rPr->b[
'val']))
1644 $objText->getFont()->setBold(
true);
1647 (isset($run->rPr->i[
'val']) && self::boolean((
string) $run->rPr->i[
'val'])) ||
1648 (isset($run->rPr->i) && !isset($run->rPr->i[
'val']))
1650 $objText->getFont()->setItalic(
true);
1652 if (isset($run->rPr->vertAlign, $run->rPr->vertAlign[
'val'])) {
1653 $vertAlign = strtolower((
string) $run->rPr->vertAlign[
'val']);
1654 if ($vertAlign ==
'superscript') {
1655 $objText->getFont()->setSuperscript(
true);
1657 if ($vertAlign ==
'subscript') {
1658 $objText->getFont()->setSubscript(
true);
1661 if (isset($run->rPr->u) && !isset($run->rPr->u[
'val'])) {
1662 $objText->getFont()->setUnderline(\
PhpOffice\PhpSpreadsheet\
Style\Font::UNDERLINE_SINGLE);
1663 } elseif (isset($run->rPr->u, $run->rPr->u[
'val'])) {
1664 $objText->getFont()->setUnderline((
string) $run->rPr->u[
'val']);
1667 (isset($run->rPr->strike[
'val']) && self::boolean((
string) $run->rPr->strike[
'val'])) ||
1668 (isset($run->rPr->strike) && !isset($run->rPr->strike[
'val']))
1670 $objText->getFont()->setStrikethrough(
true);
1686 $baseDir = dirname($customUITarget);
1687 $nameCustomUI = basename($customUITarget);
1690 $customUIImagesNames = [];
1691 $customUIImagesBinaries = [];
1693 $pathRels =
$baseDir .
'/_rels/' . $nameCustomUI .
'.rels';
1697 $UIRels = simplexml_load_string(
1698 $this->securityScanner->scan($dataRels),
1702 if (
false !== $UIRels) {
1704 foreach ($UIRels->Relationship as $ele) {
1705 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1707 $customUIImagesNames[(string) $ele[
'Id']] = (
string) $ele[
'Target'];
1708 $customUIImagesBinaries[(string) $ele[
'Target']] = $this->
getFromZipArchive($zip,
$baseDir .
'/' . (
string) $ele[
'Target']);
1715 if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) {
1728 return $array[
$key] ?? null;
1733 return preg_replace(
'~[^/]+/\.\./~',
'', dirname(
$base) .
"/$add");
1740 $temp = explode(
';',
$style);
1742 foreach ($temp as $item) {
1743 $item = explode(
':', $item);
1745 if (strpos($item[1],
'px') !==
false) {
1746 $item[1] = str_replace(
'px',
'', $item[1]);
1748 if (strpos($item[1],
'pt') !==
false) {
1749 $item[1] = str_replace(
'pt',
'', $item[1]);
1752 if (strpos($item[1],
'in') !==
false) {
1753 $item[1] = str_replace(
'in',
'', $item[1]);
1756 if (strpos($item[1],
'cm') !==
false) {
1757 $item[1] = str_replace(
'cm',
'', $item[1]);
1761 $style[$item[0]] = $item[1];
1769 return trim(str_replace([
"\r",
"\n",
' '],
'', $string),
';');
1774 if (is_object($value)) {
1775 $value = (string) $value;
1777 if (is_numeric($value)) {
1778 return (
bool) $value;
1781 return $value ===
'true' || $value ===
'TRUE';
1791 $hlinkClick = $cellAnchor->pic->nvPicPr->cNvPr->children(
'http://schemas.openxmlformats.org/drawingml/2006/main')->hlinkClick;
1793 if ($hlinkClick->count() === 0) {
1797 $hlinkId = (string) $hlinkClick->attributes(
'http://schemas.openxmlformats.org/officeDocument/2006/relationships')[
'id'];
1799 $hyperlinks[$hlinkId],
1800 (
string) self::getArrayItem($cellAnchor->pic->nvPicPr->cNvPr->attributes(),
'name')
1802 $objDrawing->setHyperlink($hyperlink);
1807 if (!$xmlWorkbook->workbookProtection) {
1811 $excel->
getSecurity()->setLockRevision(self::getLockValue($xmlWorkbook->workbookProtection,
'lockRevision'));
1812 $excel->
getSecurity()->setLockStructure(self::getLockValue($xmlWorkbook->workbookProtection,
'lockStructure'));
1813 $excel->
getSecurity()->setLockWindows(self::getLockValue($xmlWorkbook->workbookProtection,
'lockWindows'));
1815 if ($xmlWorkbook->workbookProtection[
'revisionsPassword']) {
1817 (
string) $xmlWorkbook->workbookProtection[
'revisionsPassword'],
1822 if ($xmlWorkbook->workbookProtection[
'workbookPassword']) {
1824 (
string) $xmlWorkbook->workbookProtection[
'workbookPassword'],
1832 $returnValue = null;
1833 $protectKey = $protection[
$key];
1834 if (!empty($protectKey)) {
1835 $protectKey = (string) $protectKey;
1836 $returnValue = $protectKey !==
'false' && (bool) $protectKey;
1839 return $returnValue;
1844 if (!$zip->locateName(dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')) {
1849 $relsWorksheet = simplexml_load_string(
1850 $this->securityScanner->scan(
1851 $this->getFromZipArchive($zip, dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')
1857 foreach ($relsWorksheet->Relationship as $ele) {
1858 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp') {
1859 $ctrlProps[(string) $ele[
'Id']] = $ele;
1863 $unparsedCtrlProps = &$unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'ctrlProps'];
1864 foreach ($ctrlProps as $rId => $ctrlProp) {
1865 $rId = substr($rId, 3);
1866 $unparsedCtrlProps[$rId] = [];
1867 $unparsedCtrlProps[$rId][
'filePath'] = self::dirAdd(
"$dir/$fileWorksheet", $ctrlProp[
'Target']);
1868 $unparsedCtrlProps[$rId][
'relFilePath'] = (string) $ctrlProp[
'Target'];
1869 $unparsedCtrlProps[$rId][
'content'] = $this->securityScanner->scan($this->
getFromZipArchive($zip, $unparsedCtrlProps[$rId][
'filePath']));
1871 unset($unparsedCtrlProps);
1876 if (!$zip->locateName(dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')) {
1881 $relsWorksheet = simplexml_load_string(
1882 $this->securityScanner->scan(
1883 $this->getFromZipArchive($zip, dirname(
"$dir/$fileWorksheet") .
'/_rels/' . basename($fileWorksheet) .
'.rels')
1888 $sheetPrinterSettings = [];
1889 foreach ($relsWorksheet->Relationship as $ele) {
1890 if ($ele[
'Type'] ==
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings') {
1891 $sheetPrinterSettings[(string) $ele[
'Id']] = $ele;
1895 $unparsedPrinterSettings = &$unparsedLoadedData[
'sheets'][$docSheet->getCodeName()][
'printerSettings'];
1896 foreach ($sheetPrinterSettings as $rId => $printerSettings) {
1897 $rId = substr($rId, 3) .
'ps';
1898 $unparsedPrinterSettings[$rId] = [];
1899 $unparsedPrinterSettings[$rId][
'filePath'] = self::dirAdd(
"$dir/$fileWorksheet", $printerSettings[
'Target']);
1900 $unparsedPrinterSettings[$rId][
'relFilePath'] = (string) $printerSettings[
'Target'];
1901 $unparsedPrinterSettings[$rId][
'content'] = $this->securityScanner->scan($this->
getFromZipArchive($zip, $unparsedPrinterSettings[$rId][
'filePath']));
1903 unset($unparsedPrinterSettings);
1922 if ($xsdBoolean ===
'false') {
1926 return (
bool) $xsdBoolean;
1936 $workbookBasename =
'';
1939 $rels = simplexml_load_string(
1940 $this->securityScanner->scan(
1941 $this->getFromZipArchive($zip,
'_rels/.rels')
1946 if ($rels !==
false) {
1947 foreach ($rels->Relationship as $rel) {
1948 switch ($rel[
'Type']) {
1949 case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
1950 $basename = basename($rel[
'Target']);
1951 if (preg_match(
'/workbook.*\.xml/', $basename)) {
1952 $workbookBasename = $basename;
1960 return $workbookBasename;
1965 if ($this->readDataOnly || !$xmlSheet->sheetProtection) {
1969 $algorithmName = (string) $xmlSheet->sheetProtection[
'algorithmName'];
1971 $protection->setAlgorithm($algorithmName);
1973 if ($algorithmName) {
1974 $protection->setPassword((
string) $xmlSheet->sheetProtection[
'hashValue'],
true);
1975 $protection->setSalt((
string) $xmlSheet->sheetProtection[
'saltValue']);
1976 $protection->setSpinCount((
int) $xmlSheet->sheetProtection[
'spinCount']);
1978 $protection->setPassword((
string) $xmlSheet->sheetProtection[
'password'],
true);
1981 if ($xmlSheet->protectedRanges->protectedRange) {
1982 foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
1983 $docSheet->
protectCells((
string) $protectedRange[
'sqref'], (
string) $protectedRange[
'password'],
true);
setRibbonXMLData($target, $xmlData)
set ribbon XML data.
static controlCharacterOOXML2PHP($value)
Convert from OpenXML escaped control character to PHP control character.
canRead($pFilename)
Can the current IReader read the file?
getFromZipArchive(ZipArchive $archive, $fileName='')
static createInstance(string $name, ?Worksheet $worksheet=null, ?string $value=null, bool $localOnly=false, ?Worksheet $scope=null)
Create a new defined name, either a range or a formula.
static dirAdd($base, $add)
static readProtectionHidden(Style $docStyle, $style)
__construct()
Create a new Xlsx Reader instance.
readHyperLinkDrawing($objDrawing, $cellAnchor, $hyperlinks)
static extractSheetTitle($pRange, $returnRange=false)
Extract worksheet title from range.
static testIfFormula(string $value)
getReadDataOnly()
Read data only? If this is true, then the Reader will only read data values for cells, it will not read any formatting information.
static angleToDegrees($pValue)
Convert angle to degrees.
static readFontStyle(Font $fontStyle, SimpleXMLElement $fontStyleXml)
static readBorderStyle(Borders $borderStyle, SimpleXMLElement $borderStyleXml)
readFormControlProperties(Spreadsheet $excel, ZipArchive $zip, $dir, $fileWorksheet, $docSheet, array &$unparsedLoadedData)
static centimeterSizeToPixels($sizeInCm)
Calculate an (approximate) pixel size, based on centimeter size.
static readChart(SimpleXMLElement $chartElements, $chartName)
readRibbon(Spreadsheet $excel, $customUITarget, $zip)
static realpath($pFilename)
Returns canonicalized absolute pathname, also for ZIP archives.
static readStyle(Style $docStyle, $style)
protectCells($pRange, $pPassword, $pAlreadyHashed=false)
Set protection on a cell range.
static inchSizeToPixels($sizeInInch)
Calculate an (approximate) pixel size, based on inch size.
getReadFilter()
Read filter.
if(!file_exists(getcwd() . '/ilias.ini.php'))
registration confirmation script for ilias
static readProtectionLocked(Style $docStyle, $style)
getSecurity()
Get security.
static readColor($color, $background=false)
readProtection(Spreadsheet $excel, SimpleXMLElement $xmlWorkbook)
static getInstance(Reader\IReader $reader)
static fontSizeToPixels($fontSizeInPoints)
Calculate an (approximate) pixel size, based on a font points size.
const CALENDAR_WINDOWS_1900
constants
listWorksheetNames($pFilename)
Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object...
readPrinterSettings(Spreadsheet $excel, ZipArchive $zip, $dir, $fileWorksheet, $docSheet, array &$unparsedLoadedData)
static getInstance()
Get an instance of this class.
if(array_key_exists('yes', $_REQUEST)) $attributes
static indexesFromString(string $coordinates)
Get indexes from a string coordinates.
static getArrayItem($array, $key=0)
static toCSSArray($style)
static EMUToPixels($pValue)
Convert EMU to pixels.
load($pFilename)
Loads PhpSpreadsheet from file.
getProtection()
Get Protection.
setRibbonBinObjects($BinObjectsNames, $BinObjectsData)
store binaries ribbon objects (pictures).
static coordinateFromString($pCoordinateString)
Coordinate from string.
static setExcelCalendar($baseDate)
Set the Excel calendar (Windows 1900 or Mac 1904).
static getLibXmlLoaderOptions()
Get default options for libxml loader.
castXsdBooleanToBool($xsdBoolean)
Convert an 'xsd:boolean' XML value to a PHP boolean value.
static readAlignmentStyle(Alignment $alignment, SimpleXMLElement $alignmentXml)
if($path[strlen($path) - 1]==='/') if(is_dir($path)) if(!file_exists($path)) if(preg_match('#\.php$#D', mb_strtolower($path, 'UTF-8'))) $contentType
static assertFile($filename)
Assert that given path is an existing file and is readable, otherwise throw exception.
castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType)
static stringFromColumnIndex($columnIndex)
String from column index.
readSheetProtection(Worksheet $docSheet, SimpleXMLElement $xmlSheet)
getWorkbookBaseName(ZipArchive $zip)
static getLockValue(SimpleXmlElement $protection, string $key)
static stripWhiteSpaceFromStyleString($string)