62        parent::__construct();
 
   79        $zip = 
new ZipArchive();
 
   81        if ($zip->open($pFilename) === 
true) {
 
   83            $result = !empty($workbookBasename);
 
  102        $worksheetNames = [];
 
  104        $zip = 
new ZipArchive();
 
  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)
 
  147        $zip = 
new ZipArchive();
 
  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";
 
  200                        $xml = 
new XMLReader();
 
  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 = [];
 
  330        $zip = 
new ZipArchive();
 
  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();
 
  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();
 
  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) {
 
  636                                    (
new ConditionalStyles($docSheet, $xmlSheet, $dxfs))->
load();
 
  639                                if (isset($xmlSheet->sheetViews, $xmlSheet->sheetViews->sheetView)) {
 
  640                                    $sheetViews = 
new SheetViews($xmlSheet->sheetViews->sheetView, $docSheet);
 
  644                                $sheetViewOptions = 
new SheetViewOptions($docSheet, $xmlSheet);
 
  647                                (
new ColumnAndRowAttributes($docSheet, $xmlSheet))
 
  651                            if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
 
  653                                foreach ($xmlSheet->sheetData->row as 
$row) {
 
  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)];
 
  684                                                    if ($value instanceof RichText) {
 
  685                                                        $value = clone $value;
 
  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);
 
  718                                                    $this->
castToFormula($c, 
$r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 
'castToError');
 
  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) {
 
  785                                (
new AutoFilter($docSheet, $xmlSheet))->
load();
 
  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) {
 
  802                                (
new DataValidations($docSheet, $xmlSheet))->
load();
 
  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) {
 
  817                                $hyperlinkReader = 
new Hyperlinks($docSheet);
 
  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']);
 
  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');
 
  905                                    } 
catch (Throwable $ex) {
 
  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');
 
 1044                                                $hfImages[(string) $shape[
'id']] = 
new HeaderFooterDrawing();
 
 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) {
 
 1360                                                    [$sheetName, $rangeSet] = Worksheet::extractSheetTitle($rangeSet, 
true);
 
 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) {
 
 1402                                                $range = Worksheet::extractSheetTitle((
string) $definedName, 
true);
 
 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);
 
 1428                                        [$extractedSheetName] = Worksheet::extractSheetTitle((
string) $definedNameValueParts[0], 
true);
 
 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')
 
 1517                    case 'application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings':
 
 1518                        $unparsedLoadedData[
'default_content_types'][(string) 
$contentType[
'Extension']] = (
string) 
$contentType[
'ContentType'];
 
 1527                    case 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml':
 
 1528                        if ($this->includeCharts) {
 
 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);
 
 1615    private function parseRichText(?SimpleXMLElement $is)
 
 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'])) {
 
 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]);
 
 1750                $item[1] = Font::fontSizeToPixels($item[1]);
 
 1752            if (strpos($item[1], 
'in') !== 
false) {
 
 1753                $item[1] = str_replace(
'in', 
'', $item[1]);
 
 1754                $item[1] = Font::inchSizeToPixels($item[1]);
 
 1756            if (strpos($item[1], 
'cm') !== 
false) {
 
 1757                $item[1] = str_replace(
'cm', 
'', $item[1]);
 
 1758                $item[1] = Font::centimeterSizeToPixels($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'];
 
 1970        $protection = $docSheet->getProtection();
 
 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);
 
An exception for terminatinating execution or to throw for unit testing.
Helper class to manipulate cell coordinates.
static coordinateFromString($pCoordinateString)
Coordinate from string.
static indexesFromString(string $coordinates)
Get indexes from a string coordinates.
static stringFromColumnIndex($columnIndex)
String from column index.
static testIfFormula(string $value)
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.
getReadFilter()
Read filter.
getReadDataOnly()
Read data only? If this is true, then the Reader will only read data values for cells,...
static getInstance(Reader\IReader $reader)
static readChart(SimpleXMLElement $chartElements, $chartName)
static readProtectionHidden(Style $docStyle, $style)
static readBorderStyle(Borders $borderStyle, SimpleXMLElement $borderStyleXml)
static readFontStyle(Font $fontStyle, SimpleXMLElement $fontStyleXml)
static readProtectionLocked(Style $docStyle, $style)
static readAlignmentStyle(Alignment $alignment, SimpleXMLElement $alignmentXml)
static readColor($color, $background=false)
static getLockValue(SimpleXmlElement $protection, string $key)
readSheetProtection(Worksheet $docSheet, SimpleXMLElement $xmlSheet)
listWorksheetNames($pFilename)
Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object.
readProtection(Spreadsheet $excel, SimpleXMLElement $xmlWorkbook)
readPrinterSettings(Spreadsheet $excel, ZipArchive $zip, $dir, $fileWorksheet, $docSheet, array &$unparsedLoadedData)
static readStyle(Style $docStyle, $style)
canRead($pFilename)
Can the current IReader read the file?
castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType)
readHyperLinkDrawing($objDrawing, $cellAnchor, $hyperlinks)
static getArrayItem($array, $key=0)
readFormControlProperties(Spreadsheet $excel, ZipArchive $zip, $dir, $fileWorksheet, $docSheet, array &$unparsedLoadedData)
static dirAdd($base, $add)
readRibbon(Spreadsheet $excel, $customUITarget, $zip)
static stripWhiteSpaceFromStyleString($string)
getFromZipArchive(ZipArchive $archive, $fileName='')
__construct()
Create a new Xlsx Reader instance.
getWorkbookBaseName(ZipArchive $zip)
castXsdBooleanToBool($xsdBoolean)
Convert an 'xsd:boolean' XML value to a PHP boolean value.
static toCSSArray($style)
static getInstance()
Get an instance of this class.
static getLibXmlLoaderOptions()
Get default options for libxml loader.
static setExcelCalendar($baseDate)
Set the Excel calendar (Windows 1900 or Mac 1904).
const CALENDAR_WINDOWS_1900
constants
static angleToDegrees($pValue)
Convert angle to degrees.
static EMUToPixels($pValue)
Convert EMU to pixels.
static realpath($pFilename)
Returns canonicalized absolute pathname, also for ZIP archives.
static assertFile($filename)
Assert that given path is an existing file and is readable, otherwise throw exception.
static controlCharacterOOXML2PHP($value)
Convert from OpenXML escaped control character to PHP control character.
setRibbonXMLData($target, $xmlData)
set ribbon XML data.
setRibbonBinObjects($BinObjectsNames, $BinObjectsData)
store binaries ribbon objects (pictures).
getSecurity()
Get security.
if(!file_exists(getcwd() . '/ilias.ini.php'))
registration confirmation script for ilias
if(array_key_exists('yes', $_REQUEST)) $attributes
load($pFilename)
Loads PhpSpreadsheet from file.
if( $path[strlen( $path) - 1]==='/') if(is_dir($path)) if(!file_exists( $path)) if(preg_match('#\.php$#D', mb_strtolower($path, 'UTF-8'))) $contentType
echo;exit;}function LogoutNotification($SessionID){ global $ilDB;$q="SELECT session_id, data FROM usr_session WHERE expires > (\w+)\|/" PREG_SPLIT_NO_EMPTY PREG_SPLIT_DELIM_CAPTURE