61 if (!defined(
'PHPEXCEL_ROOT')) {
65 define(
'PHPEXCEL_ROOT', dirname(__FILE__) .
'/../../');
69 require_once PHPEXCEL_ROOT .
'PHPExcel.php';
72 require_once PHPEXCEL_ROOT .
'PHPExcel/Reader/IReader.php';
75 require_once PHPEXCEL_ROOT .
'PHPExcel/Reader/Excel5/Escher.php';
78 require_once PHPEXCEL_ROOT .
'PHPExcel/Shared/Date.php';
81 require_once PHPEXCEL_ROOT .
'PHPExcel/Shared/Excel5.php';
84 require_once PHPEXCEL_ROOT .
'PHPExcel/Shared/Escher.php';
87 require_once PHPEXCEL_ROOT .
'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php';
90 require_once PHPEXCEL_ROOT .
'PHPExcel/Shared/OLERead.php';
93 require_once PHPEXCEL_ROOT .
'PHPExcel/Shared/String.php';
96 require_once PHPEXCEL_ROOT .
'PHPExcel/Cell.php';
99 require_once PHPEXCEL_ROOT .
'PHPExcel/NamedRange.php';
102 require_once PHPEXCEL_ROOT .
'PHPExcel/Reader/IReadFilter.php';
105 require_once PHPEXCEL_ROOT .
'PHPExcel/Reader/DefaultReadFilter.php';
108 require_once PHPEXCEL_ROOT .
'PHPExcel/Worksheet/MemoryDrawing.php';
417 $this->_readDataOnly = $pValue;
439 $this->_loadSheetsOnly = is_array($value) ?
440 $value : array($value);
451 $this->_loadSheetsOnly = null;
471 $this->_readFilter = $pValue;
491 if (!file_exists($pFilename)) {
492 throw new Exception(
"Could not open " . $pFilename .
" for reading! File does not exist.");
500 $res = $this->_ole->read($pFilename);
514 public function load($pFilename)
519 if (!$this->_readDataOnly) {
520 $this->_phpExcel->removeCellStyleXfByIndex(0);
521 $this->_phpExcel->removeCellXfByIndex(0);
528 $res = $this->_ole->read($pFilename);
529 $this->_data = $this->_ole->getWorkBook();
532 $this->_dataSize = strlen($this->_data);
536 $this->_codepage =
'CP1252';
537 $this->_formats = array();
538 $this->_objFonts = array();
539 $this->_palette = array();
540 $this->_sheets = array();
541 $this->_externalBooks = array();
542 $this->_ref = array();
543 $this->_definedname = array();
544 $this->_sst = array();
545 $this->_drawingGroupData =
'';
546 $this->_xfIndex =
'';
547 $this->_mapCellXfIndex = array();
548 $this->_mapCellStyleXfIndex = array();
551 while ($this->_pos < $this->_dataSize) {
552 $code = $this->
_GetInt2d($this->_data, $this->_pos);
555 case self::XLS_Type_BOF:
557 $length = $this->
_GetInt2d($this->_data, $pos + 2);
558 $recordData = substr($this->_data, $pos + 4, $length);
561 $this->_version = $this->
_GetInt2d($this->_data, $pos + 4);
563 if (($this->_version != self::XLS_BIFF8) && ($this->_version != self::XLS_BIFF7)) {
568 $substreamType = $this->
_GetInt2d($this->_data, $pos + 6);
569 if ($substreamType != self::XLS_WorkbookGlobals) {
572 $this->_pos += 4 + $length;
578 case self::XLS_Type_FONT: $this->
_readFont();
break;
579 case self::XLS_Type_FORMAT: $this->
_readFormat();
break;
580 case self::XLS_Type_XF: $this->
_readXf();
break;
581 case self::XLS_Type_STYLE: $this->
_readStyle();
break;
582 case self::XLS_Type_PALETTE: $this->
_readPalette();
break;
583 case self::XLS_Type_SHEET: $this->
_readSheet();
break;
588 case self::XLS_Type_SST: $this->
_readSst();
break;
589 case self::XLS_Type_EOF: $this->
_readDefault();
break 2;
596 if (!$this->_readDataOnly) {
597 foreach ($this->_objFonts as $objFont) {
598 $color = $this->
_readColor($objFont->colorIndex);
599 $objFont->getColor()->setRGB($color[
'rgb']);
602 foreach ($this->_phpExcel->getCellXfCollection() as $objStyle) {
604 $startColor = $this->
_readColor($objStyle->getFill()->startcolorIndex);
605 $objStyle->getFill()->getStartColor()->setRGB($startColor[
'rgb']);
607 $endColor = $this->
_readColor($objStyle->getFill()->endcolorIndex);
608 $objStyle->getFill()->getEndColor()->setRGB($endColor[
'rgb']);
611 $borderTopColor = $this->
_readColor($objStyle->getBorders()->getTop()->colorIndex);
612 $objStyle->getBorders()->getTop()->getColor()->setRGB($borderTopColor[
'rgb']);
614 $borderRightColor = $this->
_readColor($objStyle->getBorders()->getRight()->colorIndex);
615 $objStyle->getBorders()->getRight()->getColor()->setRGB($borderRightColor[
'rgb']);
617 $borderBottomColor = $this->
_readColor($objStyle->getBorders()->getBottom()->colorIndex);
618 $objStyle->getBorders()->getBottom()->getColor()->setRGB($borderBottomColor[
'rgb']);
620 $borderLeftColor = $this->
_readColor($objStyle->getBorders()->getLeft()->colorIndex);
621 $objStyle->getBorders()->getLeft()->getColor()->setRGB($borderLeftColor[
'rgb']);
626 if (!$this->_readDataOnly && $this->_drawingGroupData) {
629 $escherWorkbook =
$reader->load($this->_drawingGroupData);
637 foreach ($this->_sheets as $sheet) {
640 if (isset($this->_loadSheetsOnly) && !in_array($sheet[
'name'], $this->_loadSheetsOnly)) {
645 $this->_phpSheet = $this->_phpExcel->createSheet();
646 $this->_phpSheet->setTitle($sheet[
'name']);
648 $this->_pos = $sheet[
'offset'];
651 $this->_isFitToPages =
false;
654 $this->_drawingData =
'';
657 $this->_objs = array();
660 $this->_sharedFormulaParts = array();
663 $this->_sharedFormulas = array();
665 while ($this->_pos < $this->_dataSize) {
666 $code = $this->
_GetInt2d($this->_data, $this->_pos);
669 case self::XLS_Type_BOF:
670 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
671 $recordData = substr($this->_data, $this->_pos + 4, $length);
674 $this->_pos += 4 + $length;
680 $substreamType = $this->
_GetInt2d($recordData, 2);
681 if ($substreamType != self::XLS_Worksheet) {
688 case self::XLS_Type_SHEETPR: $this->
_readSheetPr();
break;
691 case self::XLS_Type_HEADER: $this->
_readHeader();
break;
692 case self::XLS_Type_FOOTER: $this->
_readFooter();
break;
693 case self::XLS_Type_HCENTER: $this->
_readHcenter();
break;
694 case self::XLS_Type_VCENTER: $this->
_readVcenter();
break;
700 case self::XLS_Type_PROTECT: $this->
_readProtect();
break;
703 case self::XLS_Type_COLINFO: $this->
_readColInfo();
break;
704 case self::XLS_Type_DIMENSION: $this->
_readDefault();
break;
705 case self::XLS_Type_ROW: $this->
_readRow();
break;
706 case self::XLS_Type_DBCELL: $this->
_readDefault();
break;
707 case self::XLS_Type_RK: $this->
_readRk();
break;
709 case self::XLS_Type_MULRK: $this->
_readMulRk();
break;
710 case self::XLS_Type_NUMBER: $this->
_readNumber();
break;
711 case self::XLS_Type_FORMULA: $this->
_readFormula();
break;
713 case self::XLS_Type_BOOLERR: $this->
_readBoolErr();
break;
715 case self::XLS_Type_LABEL: $this->
_readLabel();
break;
716 case self::XLS_Type_BLANK: $this->
_readBlank();
break;
718 case self::XLS_Type_OBJ: $this->
_readObj();
break;
719 case self::XLS_Type_WINDOW2: $this->
_readWindow2();
break;
720 case self::XLS_Type_SCL: $this->
_readScl();
break;
721 case self::XLS_Type_PANE: $this->
_readPane();
break;
727 case self::XLS_Type_EOF: $this->
_readDefault();
break 2;
734 if (!$this->_readDataOnly && $this->_drawingData) {
737 $escherWorksheet =
$reader->load($this->_drawingData);
744 $allSpContainers = $escherWorksheet->getDgContainer()->getSpgrContainer()->getAllSpContainers();
748 foreach ($this->_objs as
$n => $obj) {
751 $spContainer = $allSpContainers[
$n + 1];
754 if ($spContainer->getNestingLevel() > 1) {
762 $startOffsetX = $spContainer->getStartOffsetX();
763 $startOffsetY = $spContainer->getStartOffsetY();
764 $endOffsetX = $spContainer->getEndOffsetX();
765 $endOffsetY = $spContainer->getEndOffsetY();
774 switch ($obj[
'type']) {
780 $BSEindex = $spContainer->getOPT(0x0104);
781 $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection();
782 $BSE = $BSECollection[$BSEindex - 1];
783 $blipType = $BSE->getBlipType();
786 if ($blip = $BSE->getBlip()) {
787 $ih = imagecreatefromstring($blip->getData());
789 $drawing->setImageResource($ih);
792 $drawing->setResizeProportional(
false);
793 $drawing->setWidth($width);
794 $drawing->setHeight($height);
795 $drawing->setOffsetX($offsetX);
796 $drawing->setOffsetY($offsetY);
811 $drawing->setWorksheet($this->_phpSheet);
812 $drawing->setCoordinates($spContainer->getStartCoordinates());
825 if ($this->_version == self::XLS_BIFF8) {
826 foreach ($this->_sharedFormulaParts as $cell => $baseCell) {
834 foreach ($this->_definedname as $definedName) {
835 if ($definedName[
'isBuiltInName']) {
836 switch ($definedName[
'name']) {
838 case pack(
'C', 0x06):
842 $ranges = explode(
',', $definedName[
'formula']);
844 foreach ($ranges as $range) {
849 $explodes = explode(
'!', $range);
851 if (count($explodes) == 2) {
852 if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) {
853 $extractedRange = $explodes[1];
854 $extractedRange = str_replace(
'$',
'', $extractedRange);
855 $docSheet->getPageSetup()->setPrintArea($extractedRange);
861 case pack(
'C', 0x07):
873 $ranges = explode(
',', $definedName[
'formula']);
875 foreach ($ranges as $range) {
880 $explodes = explode(
'!', $range);
882 if (count($explodes) == 2) {
883 if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) {
885 $extractedRange = $explodes[1];
886 $extractedRange = str_replace(
'$',
'', $extractedRange);
888 $coordinateStrings = explode(
':', $extractedRange);
889 if (count($coordinateStrings) == 2) {
893 if ($firstColumn ==
'A' and $lastColumn ==
'IV') {
895 $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($firstRow, $lastRow));
896 }
elseif ($firstRow == 1 and $lastRow == 65536) {
898 $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($firstColumn, $lastColumn));
909 $explodes = explode(
'!', $definedName[
'formula']);
911 if (count($explodes) == 2) {
912 if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) {
913 $extractedRange = $explodes[1];
914 $extractedRange = str_replace(
'$',
'', $extractedRange);
916 $this->_phpExcel->addNamedRange(
new PHPExcel_NamedRange((
string)$definedName[
'name'], $docSheet, $extractedRange,
false) );
930 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
931 $recordData = substr($this->_data, $this->_pos + 4, $length);
934 $this->_pos += 4 + $length;
950 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
951 $recordData = substr($this->_data, $this->_pos + 4, $length);
954 $this->_pos += 4 + $length;
956 throw new Exception(
'Cannot read encrypted file');
970 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
971 $recordData = substr($this->_data, $this->_pos + 4, $length);
974 $this->_pos += 4 + $length;
977 $codepage = $this->
_GetInt2d($recordData, 0);
982 $this->_codepage =
"ASCII";
986 $this->_codepage =
"CP437";
991 $this->_codepage =
"";
995 $this->_codepage =
"CP737";
999 $this->_codepage =
"CP775";
1003 $this->_codepage =
"CP850";
1007 $this->_codepage =
"CP852";
1011 $this->_codepage =
"CP855";
1015 $this->_codepage =
"CP857";
1019 $this->_codepage =
"CP858";
1023 $this->_codepage =
"CP860";
1027 $this->_codepage =
"CP861";
1031 $this->_codepage =
"CP862";
1035 $this->_codepage =
"CP863";
1039 $this->_codepage =
"CP864";
1043 $this->_codepage =
"CP865";
1047 $this->_codepage =
"CP866";
1051 $this->_codepage =
"CP869";
1055 $this->_codepage =
"CP874";
1059 $this->_codepage =
"CP932";
1063 $this->_codepage =
"CP936";
1067 $this->_codepage =
"CP949";
1071 $this->_codepage =
"CP950";
1075 $this->_codepage =
"UTF-16LE";
1079 $this->_codepage =
"CP1250";
1083 $this->_codepage =
"CP1251";
1087 $this->_codepage =
"CP1252";
1091 $this->_codepage =
"CP1253";
1095 $this->_codepage =
"CP1254";
1099 $this->_codepage =
"CP1255";
1103 $this->_codepage =
"CP1256";
1107 $this->_codepage =
"CP1257";
1111 $this->_codepage =
"CP1258";
1115 $this->_codepage =
"CP1361";
1119 $this->_codepage =
'MAC';
1123 $this->_codepage =
'MAC';
1128 $this->_codepage =
"";
1148 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1149 $recordData = substr($this->_data, $this->_pos + 4, $length);
1152 $this->_pos += 4 + $length;
1156 if (ord($recordData{0}) == 1) {
1166 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1167 $recordData = substr($this->_data, $this->_pos + 4, $length);
1170 $this->_pos += 4 + $length;
1172 if (!$this->_readDataOnly) {
1177 $objFont->setSize(
$size / 20);
1182 $isItalic = (0x0002 & $this->
_GetInt2d($recordData, 2)) >> 1;
1183 if ($isItalic) $objFont->setItalic(
true);
1187 $isStrike = (0x0008 & $this->
_GetInt2d($recordData, 2)) >> 3;
1188 if ($isStrike) $objFont->setStriketrough(
true);
1191 $colorIndex = $this->
_GetInt2d($recordData, 4);
1192 $objFont->colorIndex = $colorIndex;
1195 $weight = $this->
_GetInt2d($recordData, 6);
1198 $objFont->setBold(
true);
1203 $escapement = $this->
_GetInt2d($recordData, 8);
1204 switch ($escapement) {
1206 $objFont->setSuperScript(
true);
1209 $objFont->setSubScript(
true);
1214 $underlineType = ord($recordData{10});
1215 switch ($underlineType) {
1236 if ($this->_version == self::XLS_BIFF8) {
1241 $objFont->setName($string[
'value']);
1243 $this->_objFonts[] = $objFont;
1263 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1264 $recordData = substr($this->_data, $this->_pos + 4, $length);
1267 $this->_pos += 4 + $length;
1269 if (!$this->_readDataOnly) {
1270 $indexCode = $this->
_GetInt2d($recordData, 0);
1272 if ($this->_version == self::XLS_BIFF8) {
1279 $formatString = $string[
'value'];
1280 $this->_formats[$indexCode] = $formatString;
1300 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1301 $recordData = substr($this->_data, $this->_pos + 4, $length);
1304 $this->_pos += 4 + $length;
1308 if (!$this->_readDataOnly) {
1310 if ($this->
_GetInt2d($recordData, 0) < 4) {
1311 $fontIndex = $this->
_GetInt2d($recordData, 0);
1315 $fontIndex = $this->
_GetInt2d($recordData, 0) - 1;
1317 $objStyle->setFont($this->_objFonts[$fontIndex]);
1320 $numberFormatIndex = $this->
_GetInt2d($recordData, 2);
1321 if (isset($this->_formats[$numberFormatIndex])) {
1323 $numberformat = array(
'code' => $this->_formats[$numberFormatIndex]);
1326 $numberformat = array(
'code' => $code);
1329 $numberformat = array(
'code' =>
'General');
1331 $objStyle->getNumberFormat()->setFormatCode($numberformat[
'code']);
1335 $xfTypeProt = $this->
_GetInt2d($recordData, 4);
1337 $isLocked = (0x01 & $xfTypeProt) >> 0;
1338 $objStyle->getProtection()->setLocked($isLocked ?
1342 $isHidden = (0x02 & $xfTypeProt) >> 1;
1343 $objStyle->getProtection()->setHidden($isHidden ?
1347 $isCellStyleXf = (0x04 & $xfTypeProt) >> 2;
1351 $horAlign = (0x07 & ord($recordData{6})) >> 0;
1352 switch ($horAlign) {
1373 $wrapText = (0x08 & ord($recordData{6})) >> 3;
1374 switch ($wrapText) {
1376 $objStyle->getAlignment()->setWrapText(
false);
1379 $objStyle->getAlignment()->setWrapText(
true);
1383 $vertAlign = (0x70 & ord($recordData{6})) >> 4;
1384 switch ($vertAlign) {
1399 if ($this->_version == self::XLS_BIFF8) {
1401 $angle = ord($recordData{7});
1405 }
else if ($angle <= 180) {
1406 $rotation = 90 - $angle;
1407 }
else if ($angle == 255) {
1410 $objStyle->getAlignment()->setTextRotation($rotation);
1414 $indent = (0x0F & ord($recordData{8})) >> 0;
1415 $objStyle->getAlignment()->setIndent($indent);
1418 $shrinkToFit = (0x10 & ord($recordData{8})) >> 4;
1419 switch ($shrinkToFit) {
1421 $objStyle->getAlignment()->setShrinkToFit(
false);
1424 $objStyle->getAlignment()->setShrinkToFit(
true);
1433 $objStyle->getBorders()->getLeft()->setBorderStyle($bordersLeftStyle);
1437 $objStyle->getBorders()->getRight()->setBorderStyle($bordersRightStyle);
1441 $objStyle->getBorders()->getTop()->setBorderStyle($bordersTopStyle);
1445 $objStyle->getBorders()->getBottom()->setBorderStyle($bordersBottomStyle);
1448 $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & $this->
_GetInt4d($recordData, 10)) >> 16;
1451 $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $this->
_GetInt4d($recordData, 10)) >> 23;
1455 $objStyle->getBorders()->getTop()->colorIndex = (0x0000007F & $this->
_GetInt4d($recordData, 14)) >> 0;
1458 $objStyle->getBorders()->getBottom()->colorIndex = (0x00003F80 & $this->
_GetInt4d($recordData, 14)) >> 7;
1462 $objStyle->getFill()->setFillType($fillType);
1466 $objStyle->getFill()->startcolorIndex = (0x007F & $this->
_GetInt2d($recordData, 18)) >> 0;
1469 $objStyle->getFill()->endcolorIndex = (0x3F80 & $this->
_GetInt2d($recordData, 18)) >> 7;
1474 $orientationAndFlags = ord($recordData{7});
1477 $xfOrientation = (0x03 & $orientationAndFlags) >> 0;
1478 switch ($xfOrientation) {
1480 $objStyle->getAlignment()->setTextRotation(0);
1483 $objStyle->getAlignment()->setTextRotation(-165);
1486 $objStyle->getAlignment()->setTextRotation(90);
1489 $objStyle->getAlignment()->setTextRotation(-90);
1494 $borderAndBackground = $this->
_GetInt4d($recordData, 8);
1497 $objStyle->getFill()->startcolorIndex = (0x0000007F & $borderAndBackground) >> 0;
1500 $objStyle->getFill()->endcolorIndex = (0x00003F80 & $borderAndBackground) >> 7;
1503 $objStyle->getFill()->setFillType($this->
_mapFillPattern((0x003F0000 & $borderAndBackground) >> 16));
1506 $objStyle->getBorders()->getBottom()->setBorderStyle($this->
_mapBorderStyle((0x01C00000 & $borderAndBackground) >> 22));
1509 $objStyle->getBorders()->getBottom()->colorIndex = (0xFE000000 & $borderAndBackground) >> 25;
1512 $borderLines = $this->
_GetInt4d($recordData, 12);
1515 $objStyle->getBorders()->getTop()->setBorderStyle($this->
_mapBorderStyle((0x00000007 & $borderLines) >> 0));
1518 $objStyle->getBorders()->getLeft()->setBorderStyle($this->
_mapBorderStyle((0x00000038 & $borderLines) >> 3));
1521 $objStyle->getBorders()->getRight()->setBorderStyle($this->
_mapBorderStyle((0x000001C0 & $borderLines) >> 6));
1524 $objStyle->getBorders()->getTop()->colorIndex = (0x0000FE00 & $borderLines) >> 9;
1527 $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & $borderLines) >> 16;
1530 $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $borderLines) >> 23;
1534 if ($isCellStyleXf) {
1536 if ($this->_xfIndex == 0) {
1537 $this->_phpExcel->addCellStyleXf($objStyle);
1542 $this->_phpExcel->addCellXf($objStyle);
1543 $this->_mapCellXfIndex[
$this->_xfIndex] = count($this->_phpExcel->getCellXfCollection()) - 1;
1556 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1557 $recordData = substr($this->_data, $this->_pos + 4, $length);
1560 $this->_pos += 4 + $length;
1562 if (!$this->_readDataOnly) {
1564 $ixfe = $this->
_GetInt2d($recordData, 0);
1567 $xfIndex = (0x0FFF & $ixfe) >> 0;
1570 $isBuiltIn = (bool) ((0x8000 & $ixfe) >> 15);
1574 $builtInId = ord($recordData{2});
1576 switch ($builtInId) {
1596 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1597 $recordData = substr($this->_data, $this->_pos + 4, $length);
1600 $this->_pos += 4 + $length;
1602 if (!$this->_readDataOnly) {
1607 for ($i = 0; $i < $nm; ++$i) {
1608 $rgb = substr($recordData, 2 + 4 * $i, 4);
1609 $this->_palette[] = $this->
_readRGB($rgb);
1628 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1629 $recordData = substr($this->_data, $this->_pos + 4, $length);
1632 $this->_pos += 4 + $length;
1635 $rec_offset = $this->
_GetInt4d($recordData, 0);
1638 $rec_typeFlag = ord($recordData{4});
1641 $rec_visibilityFlag = ord($recordData{5});
1644 if ($this->_version == self::XLS_BIFF8) {
1646 $rec_name = $string[
'value'];
1647 }
elseif ($this->_version == self::XLS_BIFF7) {
1649 $rec_name = $string[
'value'];
1651 $this->_sheets[] = array(
1652 'name' => $rec_name,
1653 'offset' => $rec_offset
1662 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1663 $recordData = substr($this->_data, $this->_pos + 4, $length);
1666 $this->_pos += 4 + $length;
1672 if (strlen($recordData) > 4) {
1680 $offset += $encodedUrlString[
'size'];
1683 $externalSheetNames = array();
1684 for ($i = 0; $i < $nm; ++$i) {
1686 $externalSheetNames[] = $externalSheetNameString[
'value'];
1687 $offset += $externalSheetNameString[
'size'];
1691 $this->_externalBooks[] = array(
1692 'type' =>
'external',
1693 'encodedUrl' => $encodedUrlString[
'value'],
1694 'externalSheetNames' => $externalSheetNames,
1697 }
elseif (substr($recordData, 2, 2) == pack(
'CC', 0x01, 0x04)) {
1701 $this->_externalBooks[] = array(
1702 'type' =>
'internal',
1704 }
elseif (substr($recordData, 0, 4) == pack(
'VCC', 0x0001, 0x01, 0x3A)) {
1707 $this->_externalBooks[] = array(
1708 'type' =>
'addInFunction',
1710 }
elseif (substr($recordData, 0, 2) == pack(
'V', 0x0000)) {
1714 $this->_externalBooks[] = array(
1715 'type' =>
'DDEorOLE',
1725 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1726 $recordData = substr($this->_data, $this->_pos + 4, $length);
1729 $this->_pos += 4 + $length;
1732 if ($this->_version == self::XLS_BIFF8) {
1735 for ($i = 0; $i < $nm; ++$i) {
1736 $this->_ref[] = array(
1738 'externalBookIndex' => $this->
_GetInt2d($recordData, 2 + 6 * $i),
1740 'firstSheetIndex' => $this->
_GetInt2d($recordData, 4 + 6 * $i),
1742 'lastSheetIndex' => $this->
_GetInt2d($recordData, 6 + 6 * $i),
1761 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1762 $recordData = substr($this->_data, $this->_pos + 4, $length);
1765 $this->_pos += 4 + $length;
1767 if ($this->_version == self::XLS_BIFF8) {
1771 $opts = $this->
_GetInt2d($recordData, 0);
1774 $isBuiltInName = (0x0020 & $opts) >> 5;
1779 $nlen = ord($recordData{3});
1782 $flen = $this->
_GetInt2d($recordData, 4);
1788 $offset = 14 + $string[
'size'];
1789 $formulaStructure = pack(
'v', $flen) . substr($recordData, $offset, $flen);
1797 $this->_definedname[] = array(
1798 'isBuiltInName' => $isBuiltInName,
1799 'name' => $string[
'value'],
1800 'formula' => $formula,
1810 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
1814 $recordData = $splicedRecordData[
'recordData'];
1816 $this->_drawingGroupData .= $recordData;
1838 $recordData = $splicedRecordData[
'recordData'];
1839 $spliceOffsets = $splicedRecordData[
'spliceOffsets'];
1849 for ($i = 0; $i < $nm; ++$i) {
1852 $numChars = $this->
_GetInt2d($recordData, $pos);
1856 $optionFlags = ord($recordData{$pos});
1860 $isCompressed = (($optionFlags & 0x01) == 0) ;
1863 $hasAsian = (($optionFlags & 0x04) != 0);
1866 $hasRichText = (($optionFlags & 0x08) != 0);
1870 $formattingRuns = $this->
_GetInt2d($recordData, $pos);
1876 $extendedRunLength = $this->
_GetInt4d($recordData, $pos);
1881 $len = ($isCompressed) ? $numChars : $numChars * 2;
1884 foreach ($spliceOffsets as $spliceOffset) {
1885 if ($pos < $spliceOffset) {
1886 $limitpos = $spliceOffset;
1891 if ($pos + $len <= $limitpos) {
1894 $retstr = substr($recordData, $pos, $len);
1901 $retstr = substr($recordData, $pos, $limitpos - $pos);
1903 $bytesRead = $limitpos - $pos;
1906 $charsLeft = $numChars - (($isCompressed) ? $bytesRead : ($bytesRead / 2));
1911 while ($charsLeft > 0) {
1914 foreach ($spliceOffsets as $spliceOffset) {
1915 if ($pos < $spliceOffset) {
1916 $limitpos = $spliceOffset;
1923 $option = ord($recordData{$pos});
1926 if ($isCompressed && ($option == 0)) {
1929 $len = min($charsLeft, $limitpos - $pos);
1930 $retstr .= substr($recordData, $pos, $len);
1932 $isCompressed =
true;
1934 }
elseif (!$isCompressed && ($option != 0)) {
1937 $len = min($charsLeft * 2, $limitpos - $pos);
1938 $retstr .= substr($recordData, $pos, $len);
1939 $charsLeft -= $len / 2;
1940 $isCompressed =
false;
1942 }
elseif (!$isCompressed && ($option == 0)) {
1945 $len = min($charsLeft, $limitpos - $pos);
1946 for ($j = 0; $j < $len; ++$j) {
1947 $retstr .= $recordData{$pos + $j} . chr(0);
1950 $isCompressed =
false;
1956 for ($j = 0; $j < strlen($retstr); ++$j) {
1957 $newstr .= $retstr[$j] . chr(0);
1960 $len = min($charsLeft * 2, $limitpos - $pos);
1961 $retstr .= substr($recordData, $pos, $len);
1962 $charsLeft -= $len / 2;
1963 $isCompressed =
false;
1977 for ($j = 0; $j < $formattingRuns; ++$j) {
1979 $charPos = $this->
_GetInt2d($recordData, $pos + $j * 4);
1982 $fontIndex = $this->
_GetInt2d($recordData, $pos + 2 + $j * 4);
1985 'charPos' => $charPos,
1986 'fontIndex' => $fontIndex,
1989 $pos += 4 * $formattingRuns;
1995 $pos += $extendedRunLength;
1999 $this->_sst[] = array(
2001 'fmtRuns' => $fmtRuns,
2013 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2014 $recordData = substr($this->_data, $this->_pos + 4, $length);
2017 $this->_pos += 4 + $length;
2019 if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) {
2021 $printGridlines = (bool) $this->
_GetInt2d($recordData, 0);
2022 $this->_phpSheet->setPrintGridlines($printGridlines);
2031 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2032 $recordData = substr($this->_data, $this->_pos + 4, $length);
2035 $this->_pos += 4 + $length;
2039 $height = $this->
_GetInt2d($recordData, 2);
2040 $this->_phpSheet->getDefaultRowDimension()->setRowHeight($height / 20);
2048 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2049 $recordData = substr($this->_data, $this->_pos + 4, $length);
2052 $this->_pos += 4 + $length;
2057 $isSummaryBelow = (0x0040 & $this->
_GetInt2d($recordData, 0)) >> 6;
2058 $this->_phpSheet->setShowSummaryBelow($isSummaryBelow);
2061 $isSummaryRight = (0x0080 & $this->
_GetInt2d($recordData, 0)) >> 7;
2062 $this->_phpSheet->setShowSummaryRight($isSummaryRight);
2066 $this->_isFitToPages = (bool) ((0x0100 & $this->
_GetInt2d($recordData, 0)) >> 8);
2074 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2075 $recordData = substr($this->_data, $this->_pos + 4, $length);
2078 $this->_pos += 4 + $length;
2080 if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) {
2086 for ($i = 0; $i < $nm; ++$i) {
2087 $r = $this->
_GetInt2d($recordData, 2 + 6 * $i);
2088 $cf = $this->
_GetInt2d($recordData, 2 + 6 * $i + 2);
2089 $cl = $this->
_GetInt2d($recordData, 2 + 6 * $i + 4);
2102 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2103 $recordData = substr($this->_data, $this->_pos + 4, $length);
2106 $this->_pos += 4 + $length;
2108 if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) {
2113 for ($i = 0; $i < $nm; ++$i) {
2114 $c = $this->
_GetInt2d($recordData, 2 + 6 * $i);
2115 $rf = $this->
_GetInt2d($recordData, 2 + 6 * $i + 2);
2116 $rl = $this->
_GetInt2d($recordData, 2 + 6 * $i + 4);
2129 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2130 $recordData = substr($this->_data, $this->_pos + 4, $length);
2133 $this->_pos += 4 + $length;
2135 if (!$this->_readDataOnly) {
2139 if ($this->_version == self::XLS_BIFF8) {
2145 $this->_phpSheet->getHeaderFooter()->setOddHeader($string[
'value']);
2146 $this->_phpSheet->getHeaderFooter()->setEvenHeader($string[
'value']);
2156 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2157 $recordData = substr($this->_data, $this->_pos + 4, $length);
2160 $this->_pos += 4 + $length;
2162 if (!$this->_readDataOnly) {
2166 if ($this->_version == self::XLS_BIFF8) {
2171 $this->_phpSheet->getHeaderFooter()->setOddFooter($string[
'value']);
2172 $this->_phpSheet->getHeaderFooter()->setEvenFooter($string[
'value']);
2182 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2183 $recordData = substr($this->_data, $this->_pos + 4, $length);
2186 $this->_pos += 4 + $length;
2188 if (!$this->_readDataOnly) {
2190 $isHorizontalCentered = (bool) $this->
_GetInt2d($recordData, 0);
2192 $this->_phpSheet->getPageSetup()->setHorizontalCentered($isHorizontalCentered);
2201 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2202 $recordData = substr($this->_data, $this->_pos + 4, $length);
2205 $this->_pos += 4 + $length;
2207 if (!$this->_readDataOnly) {
2209 $isVerticalCentered = (bool) $this->
_GetInt2d($recordData, 0);
2211 $this->_phpSheet->getPageSetup()->setVerticalCentered($isVerticalCentered);
2220 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2221 $recordData = substr($this->_data, $this->_pos + 4, $length);
2224 $this->_pos += 4 + $length;
2226 if (!$this->_readDataOnly) {
2228 $this->_phpSheet->getPageMargins()->setLeft($this->
_extractNumber($recordData));
2237 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2238 $recordData = substr($this->_data, $this->_pos + 4, $length);
2241 $this->_pos += 4 + $length;
2243 if (!$this->_readDataOnly) {
2245 $this->_phpSheet->getPageMargins()->setRight($this->
_extractNumber($recordData));
2254 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2255 $recordData = substr($this->_data, $this->_pos + 4, $length);
2258 $this->_pos += 4 + $length;
2260 if (!$this->_readDataOnly) {
2262 $this->_phpSheet->getPageMargins()->setTop($this->
_extractNumber($recordData));
2271 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2272 $recordData = substr($this->_data, $this->_pos + 4, $length);
2275 $this->_pos += 4 + $length;
2277 if (!$this->_readDataOnly) {
2279 $this->_phpSheet->getPageMargins()->setBottom($this->
_extractNumber($recordData));
2288 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2289 $recordData = substr($this->_data, $this->_pos + 4, $length);
2292 $this->_pos += 4 + $length;
2294 if (!$this->_readDataOnly) {
2296 $paperSize = $this->
_GetInt2d($recordData, 0);
2299 $scale = $this->
_GetInt2d($recordData, 2);
2302 $fitToWidth = $this->
_GetInt2d($recordData, 6);
2305 $fitToHeight = $this->
_GetInt2d($recordData, 8);
2310 $isPortrait = (0x0002 & $this->
_GetInt2d($recordData, 10)) >> 1;
2314 $isNotInit = (0x0004 & $this->
_GetInt2d($recordData, 10)) >> 2;
2317 $this->_phpSheet->getPageSetup()->setPaperSize($paperSize);
2318 switch ($isPortrait) {
2323 if (!$this->_isFitToPages) {
2324 $this->_phpSheet->getPageSetup()->setScale($scale);
2326 $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth);
2327 $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight);
2332 $marginHeader = $this->
_extractNumber(substr($recordData, 16, 8));
2333 $this->_phpSheet->getPageMargins()->setHeader($marginHeader);
2336 $marginFooter = $this->
_extractNumber(substr($recordData, 24, 8));
2337 $this->_phpSheet->getPageMargins()->setFooter($marginFooter);
2347 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2348 $recordData = substr($this->_data, $this->_pos + 4, $length);
2351 $this->_pos += 4 + $length;
2353 if (!$this->_readDataOnly) {
2357 $isSheetProtected = (0x01 & $this->
_GetInt2d($recordData, 0)) >> 0;
2358 switch ($isSheetProtected) {
2360 case 1: $this->_phpSheet->getProtection()->setSheet(
true);
break;
2370 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2371 $recordData = substr($this->_data, $this->_pos + 4, $length);
2374 $this->_pos += 4 + $length;
2376 if (!$this->_readDataOnly) {
2379 $this->_phpSheet->getProtection()->setPassword(
$password,
true);
2388 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2389 $recordData = substr($this->_data, $this->_pos + 4, $length);
2392 $this->_pos += 4 + $length;
2395 $width = $this->
_GetInt2d($recordData, 0);
2397 $this->_phpSheet->getDefaultColumnDimension()->setWidth($width);
2406 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2407 $recordData = substr($this->_data, $this->_pos + 4, $length);
2410 $this->_pos += 4 + $length;
2412 if (!$this->_readDataOnly) {
2420 $width = $this->
_GetInt2d($recordData, 4);
2423 $xfIndex = $this->
_GetInt2d($recordData, 6);
2428 $isHidden = (0x0001 & $this->
_GetInt2d($recordData, 8)) >> 0;
2431 $level = (0x0700 & $this->
_GetInt2d($recordData, 8)) >> 8;
2434 $isCollapsed = (0x1000 & $this->
_GetInt2d($recordData, 8)) >> 12;
2438 for ($i = $fc; $i <= $lc; ++$i) {
2439 if ($lc == 255 || $lc == 256) {
2440 $this->_phpSheet->getDefaultColumnDimension()->setWidth($width / 256);
2443 $this->_phpSheet->getColumnDimensionByColumn($i)->setWidth($width / 256);
2444 $this->_phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden);
2445 $this->_phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level);
2446 $this->_phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed);
2463 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2464 $recordData = substr($this->_data, $this->_pos + 4, $length);
2467 $this->_pos += 4 + $length;
2469 if (!$this->_readDataOnly) {
2480 $height = (0x7FF & $this->
_GetInt2d($recordData, 6)) >> 0;
2483 $useDefaultHeight = (0x8000 & $this->
_GetInt2d($recordData, 6)) >> 15;
2485 if (!$useDefaultHeight) {
2486 $this->_phpSheet->getRowDimension($r + 1)->setRowHeight($height / 20);
2496 $level = (0x00000007 & $this->
_GetInt4d($recordData, 12)) >> 0;
2497 $this->_phpSheet->getRowDimension($r + 1)->setOutlineLevel($level);
2500 $isCollapsed = (0x00000010 & $this->
_GetInt4d($recordData, 12)) >> 4;
2501 $this->_phpSheet->getRowDimension($r + 1)->setCollapsed($isCollapsed);
2504 $isHidden = (0x00000020 & $this->
_GetInt4d($recordData, 12)) >> 5;
2505 $this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden);
2508 $hasDefaultFormat = (0x00000080 & $this->
_GetInt4d($recordData, 12)) >> 7;
2511 $xfIndex = (0x0FFF0000 & $this->
_GetInt4d($recordData, 12)) >> 16;
2528 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2529 $recordData = substr($this->_data, $this->_pos + 4, $length);
2532 $this->_pos += 4 + $length;
2538 $column = $this->
_GetInt2d($recordData, 2);
2544 $xfindex = $this->
_GetInt2d($recordData, 4);
2547 $rknum = $this->
_GetInt4d($recordData, 6);
2551 if (!$this->_readDataOnly) {
2552 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
2571 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2572 $recordData = substr($this->_data, $this->_pos + 4, $length);
2575 $this->_pos += 4 + $length;
2581 $column = $this->
_GetInt2d($recordData, 2);
2587 $xfindex = $this->
_GetInt2d($recordData, 4);
2590 $index = $this->
_GetInt4d($recordData, 6);
2593 if (($fmtRuns = $this->_sst[$index][
'fmtRuns']) && !$this->_readDataOnly) {
2597 for ($i = 0; $i <= count($this->_sst[$index][
'fmtRuns']); ++$i) {
2598 if (isset($fmtRuns[$i])) {
2599 $text = mb_substr($this->_sst[$index][
'value'], $charPos, $fmtRuns[$i][
'charPos'] - $charPos,
'UTF-8');
2600 $charPos = $fmtRuns[$i][
'charPos'];
2602 $text = mb_substr($this->_sst[$index][
'value'], $charPos, mb_strlen($this->_sst[$index][
'value']),
'UTF-8');
2605 if (mb_strlen($text) > 0) {
2607 $richText->createText($text);
2609 $textRun = $richText->createTextRun($text);
2610 if (isset($fmtRuns[$i - 1])) {
2611 if ($fmtRuns[$i - 1][
'fontIndex'] < 4) {
2612 $fontIndex = $fmtRuns[$i - 1][
'fontIndex'];
2616 $fontIndex = $fmtRuns[$i - 1][
'fontIndex'] - 1;
2618 $textRun->setFont(clone $this->_objFonts[$fontIndex]);
2628 if (!$this->_readDataOnly) {
2629 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
2644 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2645 $recordData = substr($this->_data, $this->_pos + 4, $length);
2648 $this->_pos += 4 + $length;
2654 $colFirst = $this->
_GetInt2d($recordData, 2);
2657 $colLast = $this->
_GetInt2d($recordData, $length - 2);
2658 $columns = $colLast - $colFirst + 1;
2663 for ($i = 0; $i <
$columns; ++$i) {
2670 $xfindex = $this->
_GetInt2d($recordData, $offset);
2674 if (!$this->_readDataOnly) {
2676 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
2697 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2698 $recordData = substr($this->_data, $this->_pos + 4, $length);
2701 $this->_pos += 4 + $length;
2707 $column = $this->
_GetInt2d($recordData, 2);
2713 $xfindex = $this->
_GetInt2d($recordData, 4);
2718 if (!$this->_readDataOnly) {
2719 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
2737 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2738 $recordData = substr($this->_data, $this->_pos + 4, $length);
2741 $this->_pos += 4 + $length;
2747 $column = $this->
_GetInt2d($recordData, 2);
2754 $formulaStructure = substr($recordData, 20);
2757 $options = $this->
_GetInt2d($recordData, 14);
2762 $isPartOfSharedFormula = (bool) (0x0008 & $options);
2763 if ($isPartOfSharedFormula) {
2766 $baseRow = $this->
_GetInt2d($formulaStructure, 3);
2767 $baseCol = $this->
_GetInt2d($formulaStructure, 5);
2771 $this->_sharedFormulaParts[$columnString . (
$row + 1)] = $this->_baseCell;
2777 $xfindex = $this->
_GetInt2d($recordData, 4);
2780 if ( (ord($recordData{6}) == 0)
2781 && (ord($recordData{12}) == 255)
2782 && (ord($recordData{13}) == 255) ) {
2788 $code = $this->
_GetInt2d($this->_data, $this->_pos);
2789 if ($code == self::XLS_Type_SHAREDFMLA) {
2796 }
elseif ((ord($recordData{6}) == 1)
2797 && (ord($recordData{12}) == 255)
2798 && (ord($recordData{13}) == 255)) {
2802 $value = (bool) ord($recordData{8});
2804 }
elseif ((ord($recordData{6}) == 2)
2805 && (ord($recordData{12}) == 255)
2806 && (ord($recordData{13}) == 255)) {
2812 }
elseif ((ord($recordData{6}) == 3)
2813 && (ord($recordData{12}) == 255)
2814 && (ord($recordData{13}) == 255)) {
2829 if (!$this->_readDataOnly) {
2830 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
2834 if (!$isPartOfSharedFormula) {
2838 if ($this->_version != self::XLS_BIFF8) {
2839 throw new Exception(
'Not BIFF8. Can only read BIFF8 formulas');
2845 $this->_phpSheet->setCellValueExplicit($columnString . (
$row + 1), $value, $dataType);
2848 if ($this->_version == self::XLS_BIFF8) {
2851 $this->_phpSheet->setCellValueExplicit($columnString . (
$row + 1), $value, $dataType);
2856 $this->_phpSheet->getCell($columnString . (
$row + 1))->setCalculatedValue($value);
2867 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2868 $recordData = substr($this->_data, $this->_pos + 4, $length);
2871 $this->_pos += 4 + $length;
2874 $cellRange = substr($recordData, 0, 6);
2880 $no = ord($recordData{7});
2883 $formula = substr($recordData, 8);
2886 $this->_sharedFormulas[$this->_baseCell] = $formula;
2899 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2900 $recordData = substr($this->_data, $this->_pos + 4, $length);
2903 $this->_pos += 4 + $length;
2905 if ($this->_version == self::XLS_BIFF8) {
2907 $value = $string[
'value'];
2910 $value = $string[
'value'];
2926 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2927 $recordData = substr($this->_data, $this->_pos + 4, $length);
2930 $this->_pos += 4 + $length;
2936 $column = $this->
_GetInt2d($recordData, 2);
2942 $xfindex = $this->
_GetInt2d($recordData, 4);
2945 $boolErr = ord($recordData{6});
2948 $isError = ord($recordData{7});
2952 $value = (bool) $boolErr;
2967 if (!$this->_readDataOnly) {
2968 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
2983 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
2984 $recordData = substr($this->_data, $this->_pos + 4, $length);
2987 $this->_pos += 4 + $length;
2997 if (!$this->_readDataOnly) {
2998 for ($i = 0; $i < $length / 2 - 3; ++$i) {
3003 $xfindex = $this->
_GetInt2d($recordData, 4 + 2 * $i);
3004 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
3024 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3025 $recordData = substr($this->_data, $this->_pos + 4, $length);
3028 $this->_pos += 4 + $length;
3034 $column = $this->
_GetInt2d($recordData, 2);
3040 $xfindex = $this->
_GetInt2d($recordData, 4);
3044 if ($this->_version == self::XLS_BIFF8) {
3046 $value = $string[
'value'];
3049 $value = $string[
'value'];
3054 if (!$this->_readDataOnly) {
3055 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
3065 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3066 $recordData = substr($this->_data, $this->_pos + 4, $length);
3069 $this->_pos += 4 + $length;
3075 $col = $this->
_GetInt2d($recordData, 2);
3081 $xfindex = $this->
_GetInt2d($recordData, 4);
3084 if (!$this->_readDataOnly) {
3085 $this->_phpSheet->getCell($columnString . (
$row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]);
3096 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3097 $recordData = substr($this->_data, $this->_pos + 4, $length);
3100 $this->_pos += 4 + $length;
3102 $this->_drawingData .= $recordData;
3110 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3111 $recordData = substr($this->_data, $this->_pos + 4, $length);
3114 $this->_pos += 4 + $length;
3116 if ($this->_readDataOnly || $this->_version != self::XLS_BIFF8) {
3128 $this->_objs[] = array(
3138 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3139 $recordData = substr($this->_data, $this->_pos + 4, $length);
3142 $this->_pos += 4 + $length;
3145 $options = $this->
_GetInt2d($recordData, 0);
3148 $showGridlines = (bool) ((0x0002 & $options) >> 1);
3149 $this->_phpSheet->setShowGridlines($showGridlines);
3152 $this->_frozen = (bool) ((0x0008 & $options) >> 3);
3155 $this->_phpSheet->setRightToLeft((
bool)((0x0040 & $options) >> 6));
3158 $isActive = (bool) ((0x0400 & $options) >> 10);
3160 $this->_phpExcel->setActiveSheetIndex($this->_phpExcel->getIndex($this->_phpSheet));
3169 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3170 $recordData = substr($this->_data, $this->_pos + 4, $length);
3173 $this->_pos += 4 + $length;
3176 $numerator = $this->
_GetInt2d($recordData, 0);
3179 $denumerator = $this->
_GetInt2d($recordData, 2);
3182 $this->_phpSheet->getSheetView()->setZoomScale($numerator * 100 / $denumerator);
3190 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3191 $recordData = substr($this->_data, $this->_pos + 4, $length);
3194 $this->_pos += 4 + $length;
3196 if (!$this->_readDataOnly) {
3203 if ($this->_frozen) {
3223 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3224 $recordData = substr($this->_data, $this->_pos + 4, $length);
3227 $this->_pos += 4 + $length;
3229 if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) {
3231 foreach ($cellRangeAddressList[
'cellRangeAddresses'] as $cellRangeAddress) {
3232 $this->_phpSheet->mergeCells($cellRangeAddress);
3242 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3243 $recordData = substr($this->_data, $this->_pos + 4, $length);
3246 $this->_pos += 4 + $length;
3248 if (!$this->_readDataOnly) {
3263 $isFileLinkOrUrl = (0x00000001 & $this->
_GetInt2d($recordData, 28)) >> 0;
3266 $isAbsPathOrUrl = (0x00000001 & $this->
_GetInt2d($recordData, 28)) >> 1;
3269 $hasDesc = (0x00000014 & $this->
_GetInt2d($recordData, 28)) >> 2;
3272 $hasText = (0x00000008 & $this->
_GetInt2d($recordData, 28)) >> 3;
3275 $hasFrame = (0x00000080 & $this->
_GetInt2d($recordData, 28)) >> 7;
3278 $isUNC = (0x00000100 & $this->
_GetInt2d($recordData, 28)) >> 8;
3285 $dl = $this->
_GetInt4d($recordData, 32);
3288 $offset += 4 + 2 * $dl;
3291 $fl = $this->
_GetInt4d($recordData, $offset);
3292 $offset += 4 + 2 * $fl;
3296 $hyperlinkType = null;
3299 $hyperlinkType =
'UNC';
3300 }
else if (!$isFileLinkOrUrl) {
3301 $hyperlinkType =
'workbook';
3302 }
else if (ord($recordData{$offset}) == 0x03) {
3303 $hyperlinkType =
'local';
3304 }
else if (ord($recordData{$offset}) == 0xE0) {
3305 $hyperlinkType =
'URL';
3308 switch ($hyperlinkType) {
3313 $us = $this->
_GetInt4d($recordData, $offset);
3316 $url = $this->
_encodeUTF16(substr($recordData, $offset, $us - 2),
false);
3317 $url .= $hasText ?
'#' :
'';
3343 $tl = $this->
_GetInt4d($recordData, $offset);
3346 $text = $this->
_encodeUTF16(substr($recordData, $offset, 2 * ($tl - 1)),
false);
3352 $this->_phpSheet->getCell($coordinate)->getHyperLink()->setUrl($url);
3364 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3365 $recordData = substr($this->_data, $this->_pos + 4, $length);
3368 $this->_pos += 4 + $length;
3373 if (!$this->_readDataOnly) {
3377 $isf = $this->
_GetInt2d($recordData, 12);
3387 $cref = $this->
_GetInt2d($recordData, 19);
3393 $cellRanges = array();
3394 for ($i = 0; $i < $cref; ++$i) {
3400 $cellRanges[] = $cellRange;
3405 $rgbFeat = substr($recordData, $offset);
3409 $wPassword = $this->
_GetInt4d($recordData, $offset);
3414 $this->_phpSheet->protectCells(implode(
' ', $cellRanges), strtoupper(dechex($wPassword)),
true);
3424 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3428 $recordData = $splicedRecordData[
'recordData'];
3436 $env = $this->
_GetInt2d($recordData, 2);
3439 $lcb = $this->
_GetInt4d($recordData, 4);
3442 $iData = substr($recordData, 8);
3457 $bcHeight = $this->
_GetInt2d($iData, 6);
3458 var_dump($bcHeight);
3459 $ih = imagecreatetruecolor($bcWidth, $bcHeight);
3464 $bcBitCount = $this->
_GetInt2d($iData, 10);
3465 var_dump($bcBitCount);
3467 $rgbString = substr($iData, 12);
3468 $rgbTriples = array();
3469 while (strlen($rgbString) > 0) {
3470 $rgbTriples[] = unpack(
'Cb/Cg/Cr', $rgbString);
3471 $rgbString = substr($rgbString, 3);
3475 foreach ($rgbTriples as $i => $rgbTriple) {
3476 $color = imagecolorallocate($ih, $rgbTriple[
'r'], $rgbTriple[
'g'], $rgbTriple[
'b']);
3477 imagesetpixel($ih,
$x, $bcHeight - 1 -
$y, $color);
3478 $x = (
$x + 1) % $bcWidth;
3479 $y =
$y + floor((
$x + 1) / $bcWidth);
3485 $drawing->setWorksheet($this->_phpSheet);
3506 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3507 $recordData = substr($this->_data, $this->_pos + 4, $length);
3510 $this->_pos += 4 + $length;
3514 if ($this->_drawingData ==
'') {
3519 if (strlen($recordData) < 4) {
3528 $validSplitPoints = array(0xF004, 0xF00D);
3530 $splitPoint = $this->
_GetInt2d($recordData, 2);
3531 if (in_array($splitPoint, $validSplitPoints)) {
3532 $this->_drawingData .= $recordData;
3548 $spliceOffsets = array();
3551 $spliceOffsets[0] = 0;
3557 $identifier = $this->
_GetInt2d($this->_data, $this->_pos);
3559 $length = $this->
_GetInt2d($this->_data, $this->_pos + 2);
3560 $data .= substr($this->_data, $this->_pos + 4, $length);
3562 $spliceOffsets[$i] = $spliceOffsets[$i - 1] + $length;
3564 $this->_pos += 4 + $length;
3565 $nextIdentifier = $this->
_GetInt2d($this->_data, $this->_pos);
3567 while ($nextIdentifier == self::XLS_Type_CONTINUE);
3569 $splicedData = array(
3570 'recordData' =>
$data,
3571 'spliceOffsets' => $spliceOffsets,
3574 return $splicedData;
3588 $sz = $this->
_GetInt2d($formulaStructure, 0);
3591 $formulaData = substr($formulaStructure, 2, $sz);
3601 if (strlen($formulaStructure) > 2 + $sz) {
3602 $additionalData = substr($formulaStructure, 2 + $sz);
3610 $additionalData =
'';
3629 while (strlen($formulaData) > 0 and $token = $this->
_getNextToken($formulaData, $baseCell)) {
3631 $formulaData = substr($formulaData, $token[
'size']);
3639 return $formulaString;
3653 if (count($tokens) == 0) {
3657 $formulaStrings = array();
3658 foreach ($tokens as $token) {
3660 $space0 = isset($space0) ? $space0 :
'';
3661 $space1 = isset($space1) ? $space1 :
'';
3662 $space2 = isset($space2) ? $space2 :
'';
3663 $space3 = isset($space3) ? $space3 :
'';
3664 $space4 = isset($space4) ? $space4 :
'';
3665 $space5 = isset($space5) ? $space5 :
'';
3667 switch ($token[
'name']) {
3683 $op2 = array_pop($formulaStrings);
3684 $op1 = array_pop($formulaStrings);
3685 $formulaStrings[] =
"$op1$space1$space0{$token['data']}$op2";
3686 unset($space0, $space1);
3690 $op = array_pop($formulaStrings);
3691 $formulaStrings[] =
"$space1$space0{$token['data']}$op";
3692 unset($space0, $space1);
3695 $op = array_pop($formulaStrings);
3696 $formulaStrings[] =
"$op$space1$space0{$token['data']}";
3697 unset($space0, $space1);
3699 case 'tAttrVolatile':
3708 switch ($token[
'data'][
'spacetype']) {
3710 $space0 = str_repeat(
' ', $token[
'data'][
'spacecount']);
3713 $space1 = str_repeat(
"\n", $token[
'data'][
'spacecount']);
3716 $space2 = str_repeat(
' ', $token[
'data'][
'spacecount']);
3719 $space3 = str_repeat(
"\n", $token[
'data'][
'spacecount']);
3722 $space4 = str_repeat(
' ', $token[
'data'][
'spacecount']);
3725 $space5 = str_repeat(
"\n", $token[
'data'][
'spacecount']);
3730 $op = array_pop($formulaStrings);
3731 $formulaStrings[] =
"{$space1}{$space0}SUM($op)";
3732 unset($space0, $space1);
3737 for ($i = 0; $i < $token[
'data'][
'args']; ++$i) {
3738 $ops[] = array_pop($formulaStrings);
3740 $ops = array_reverse($ops);
3741 $formulaStrings[] =
"$space1$space0{$token['data']['function']}(" . implode(
',', $ops) .
")";
3742 unset($space0, $space1);
3745 $expression = array_pop($formulaStrings);
3746 $formulaStrings[] =
"$space3$space2($expression$space5$space4)";
3747 unset($space2, $space3, $space4, $space5);
3751 $formulaStrings[] = $space1 . $space0 . $constantArray[
'value'];
3752 $additionalData = substr($additionalData, $constantArray[
'size']);
3753 unset($space0, $space1);
3758 $additionalData = substr($additionalData, $cellRangeAddressList[
'size']);
3759 $formulaStrings[] =
"$space1$space0{$token['data']}";
3760 unset($space0, $space1);
3776 $formulaStrings[] =
"$space1$space0{$token['data']}";
3777 unset($space0, $space1);
3781 $formulaString = $formulaStrings[0];
3787 return $formulaString;
3801 $id = ord($formulaData[0]);
3837 $size = 1 + $string[
'size'];
3842 switch (ord($formulaData[1])) {
3844 $name =
'tAttrVolatile';
3854 $name =
'tAttrChoose';
3856 $nc = $this->
_GetInt2d($formulaData, 2);
3859 $size = 2 * $nc + 6;
3863 $name =
'tAttrSkip';
3874 $name =
'tAttrSpace';
3877 switch (ord($formulaData[2])) {
3879 $spacetype =
'type0';
3882 $spacetype =
'type1';
3885 $spacetype =
'type2';
3888 $spacetype =
'type3';
3891 $spacetype =
'type4';
3894 $spacetype =
'type5';
3897 throw new Exception(
'Unrecognized space type in tAttrSpace token');
3901 $spacecount = ord($formulaData[3]);
3903 $data = array(
'spacetype' => $spacetype,
'spacecount' => $spacecount);
3906 throw new Exception(
'Unrecognized attribute flag in tAttr token');
3920 $data = ord($formulaData[1]) ?
'TRUE' :
'FALSE';
3933 $data = str_replace(
',',
'.', (
string)
$data);
3946 switch ($this->
_GetInt2d($formulaData, 1)) {
3947 case 2: $function =
'ISNA'; $args = 1;
break;
3948 case 3: $function =
'ISERROR'; $args = 1;
break;
3949 case 10: $function =
'NA'; $args = 0;
break;
3950 case 15: $function =
'SIN'; $args = 1;
break;
3951 case 16: $function =
'COS'; $args = 1;
break;
3952 case 17: $function =
'TAN'; $args = 1;
break;
3953 case 18: $function =
'ATAN'; $args = 1;
break;
3954 case 19: $function =
'PI'; $args = 0;
break;
3955 case 20: $function =
'SQRT'; $args = 1;
break;
3956 case 21: $function =
'EXP'; $args = 1;
break;
3957 case 22: $function =
'LN'; $args = 1;
break;
3958 case 23: $function =
'LOG10'; $args = 1;
break;
3959 case 24: $function =
'ABS'; $args = 1;
break;
3960 case 25: $function =
'INT'; $args = 1;
break;
3961 case 26: $function =
'SIGN'; $args = 1;
break;
3962 case 27: $function =
'ROUND'; $args = 2;
break;
3963 case 30: $function =
'REPT'; $args = 2;
break;
3964 case 31: $function =
'MID'; $args = 3;
break;
3965 case 32: $function =
'LEN'; $args = 1;
break;
3966 case 33: $function =
'VALUE'; $args = 1;
break;
3967 case 34: $function =
'TRUE'; $args = 0;
break;
3968 case 35: $function =
'FALSE'; $args = 0;
break;
3969 case 38: $function =
'NOT'; $args = 1;
break;
3970 case 39: $function =
'MOD'; $args = 2;
break;
3971 case 40: $function =
'DCOUNT'; $args = 3;
break;
3972 case 41: $function =
'DSUM'; $args = 3;
break;
3973 case 42: $function =
'DAVERAGE'; $args = 3;
break;
3974 case 43: $function =
'DMIN'; $args = 3;
break;
3975 case 44: $function =
'DMAX'; $args = 3;
break;
3976 case 45: $function =
'DSTDEV'; $args = 3;
break;
3977 case 48: $function =
'TEXT'; $args = 2;
break;
3978 case 61: $function =
'MIRR'; $args = 3;
break;
3979 case 63: $function =
'RAND'; $args = 0;
break;
3980 case 65: $function =
'DATE'; $args = 3;
break;
3981 case 66: $function =
'TIME'; $args = 3;
break;
3982 case 67: $function =
'DAY'; $args = 1;
break;
3983 case 68: $function =
'MONTH'; $args = 1;
break;
3984 case 69: $function =
'YEAR'; $args = 1;
break;
3985 case 71: $function =
'HOUR'; $args = 1;
break;
3986 case 72: $function =
'MINUTE'; $args = 1;
break;
3987 case 73: $function =
'SECOND'; $args = 1;
break;
3988 case 74: $function =
'NOW'; $args = 0;
break;
3989 case 75: $function =
'AREAS'; $args = 1;
break;
3990 case 76: $function =
'ROWS'; $args = 1;
break;
3991 case 77: $function =
'COLUMNS'; $args = 1;
break;
3992 case 83: $function =
'TRANSPOSE'; $args = 1;
break;
3993 case 86: $function =
'TYPE'; $args = 1;
break;
3994 case 97: $function =
'ATAN2'; $args = 2;
break;
3995 case 98: $function =
'ASIN'; $args = 1;
break;
3996 case 99: $function =
'ACOS'; $args = 1;
break;
3997 case 105: $function =
'ISREF'; $args = 1;
break;
3998 case 111: $function =
'CHAR'; $args = 1;
break;
3999 case 112: $function =
'LOWER'; $args = 1;
break;
4000 case 113: $function =
'UPPER'; $args = 1;
break;
4001 case 114: $function =
'PROPER'; $args = 1;
break;
4002 case 117: $function =
'EXACT'; $args = 2;
break;
4003 case 118: $function =
'TRIM'; $args = 1;
break;
4004 case 119: $function =
'REPLACE'; $args = 4;
break;
4005 case 121: $function =
'CODE'; $args = 1;
break;
4006 case 126: $function =
'ISERR'; $args = 1;
break;
4007 case 127: $function =
'ISTEXT'; $args = 1;
break;
4008 case 128: $function =
'ISNUMBER'; $args = 1;
break;
4009 case 129: $function =
'ISBLANK'; $args = 1;
break;
4010 case 130: $function =
'T'; $args = 1;
break;
4011 case 131: $function =
'N'; $args = 1;
break;
4012 case 140: $function =
'DATEVALUE'; $args = 1;
break;
4013 case 141: $function =
'TIMEVALUE'; $args = 1;
break;
4014 case 142: $function =
'SLN'; $args = 3;
break;
4015 case 143: $function =
'SYD'; $args = 4;
break;
4016 case 162: $function =
'CLEAN'; $args = 1;
break;
4017 case 163: $function =
'MDETERM'; $args = 1;
break;
4018 case 164: $function =
'MINVERSE'; $args = 1;
break;
4019 case 165: $function =
'MMULT'; $args = 2;
break;
4020 case 184: $function =
'FACT'; $args = 1;
break;
4021 case 189: $function =
'DPRODUCT'; $args = 3;
break;
4022 case 190: $function =
'ISNONTEXT'; $args = 1;
break;
4023 case 195: $function =
'DSTDEVP'; $args = 3;
break;
4024 case 196: $function =
'DVARP'; $args = 3;
break;
4025 case 198: $function =
'ISLOGICAL'; $args = 1;
break;
4026 case 199: $function =
'DCOUNTA'; $args = 3;
break;
4027 case 207: $function =
'REPLACEB'; $args = 4;
break;
4028 case 210: $function =
'MIDB'; $args = 3;
break;
4029 case 211: $function =
'LENB'; $args = 1;
break;
4030 case 212: $function =
'ROUNDUP'; $args = 2;
break;
4031 case 213: $function =
'ROUNDDOWN'; $args = 2;
break;
4032 case 214: $function =
'ASC'; $args = 1;
break;
4033 case 215: $function =
'DBCS'; $args = 1;
break;
4034 case 221: $function =
'TODAY'; $args = 0;
break;
4035 case 229: $function =
'SINH'; $args = 1;
break;
4036 case 230: $function =
'COSH'; $args = 1;
break;
4037 case 231: $function =
'TANH'; $args = 1;
break;
4038 case 232: $function =
'ASINH'; $args = 1;
break;
4039 case 233: $function =
'ACOSH'; $args = 1;
break;
4040 case 234: $function =
'ATANH'; $args = 1;
break;
4041 case 235: $function =
'DGET'; $args = 3;
break;
4042 case 244: $function =
'INFO'; $args = 1;
break;
4043 case 252: $function =
'FREQUENCY'; $args = 2;
break;
4044 case 261: $function =
'ERROR.TYPE'; $args = 1;
break;
4045 case 271: $function =
'GAMMALN'; $args = 1;
break;
4046 case 273: $function =
'BINOMDIST'; $args = 4;
break;
4047 case 274: $function =
'CHIDIST'; $args = 2;
break;
4048 case 275: $function =
'CHIINV'; $args = 2;
break;
4049 case 276: $function =
'COMBIN'; $args = 2;
break;
4050 case 277: $function =
'CONFIDENCE'; $args = 3;
break;
4051 case 278: $function =
'CRITBINOM'; $args = 3;
break;
4052 case 279: $function =
'EVEN'; $args = 1;
break;
4053 case 280: $function =
'EXPONDIST'; $args = 3;
break;
4054 case 281: $function =
'FDIST'; $args = 3;
break;
4055 case 282: $function =
'FINV'; $args = 3;
break;
4056 case 283: $function =
'FISHER'; $args = 1;
break;
4057 case 284: $function =
'FISHERINV'; $args = 1;
break;
4058 case 285: $function =
'FLOOR'; $args = 2;
break;
4059 case 286: $function =
'GAMMADIST'; $args = 4;
break;
4060 case 287: $function =
'GAMMAINV'; $args = 3;
break;
4061 case 288: $function =
'CEILING'; $args = 2;
break;
4062 case 289: $function =
'HYPGEOMDIST'; $args = 4;
break;
4063 case 290: $function =
'LOGNORMDIST'; $args = 3;
break;
4064 case 291: $function =
'LOGINV'; $args = 3;
break;
4065 case 292: $function =
'NEGBINOMDIST'; $args = 3;
break;
4066 case 293: $function =
'NORMDIST'; $args = 4;
break;
4067 case 294: $function =
'NORMSDIST'; $args = 1;
break;
4068 case 295: $function =
'NORMINV'; $args = 3;
break;
4069 case 296: $function =
'NORMSINV'; $args = 1;
break;
4070 case 297: $function =
'STANDARDIZE'; $args = 3;
break;
4071 case 298: $function =
'ODD'; $args = 1;
break;
4072 case 299: $function =
'PERMUT'; $args = 2;
break;
4073 case 300: $function =
'POISSON'; $args = 3;
break;
4074 case 301: $function =
'TDIST'; $args = 3;
break;
4075 case 302: $function =
'WEIBULL'; $args = 4;
break;
4076 case 303: $function =
'SUMXMY2'; $args = 2;
break;
4077 case 304: $function =
'SUMX2MY2'; $args = 2;
break;
4078 case 305: $function =
'SUMX2PY2'; $args = 2;
break;
4079 case 306: $function =
'CHITEST'; $args = 2;
break;
4080 case 307: $function =
'CORREL'; $args = 2;
break;
4081 case 308: $function =
'COVAR'; $args = 2;
break;
4082 case 309: $function =
'FORECAST'; $args = 3;
break;
4083 case 310: $function =
'FTEST'; $args = 2;
break;
4084 case 311: $function =
'INTERCEPT'; $args = 2;
break;
4085 case 312: $function =
'PEARSON'; $args = 2;
break;
4086 case 313: $function =
'RSQ'; $args = 2;
break;
4087 case 314: $function =
'STEYX'; $args = 2;
break;
4088 case 315: $function =
'SLOPE'; $args = 2;
break;
4089 case 316: $function =
'TTEST'; $args = 4;
break;
4090 case 325: $function =
'LARGE'; $args = 2;
break;
4091 case 326: $function =
'SMALL'; $args = 2;
break;
4092 case 327: $function =
'QUARTILE'; $args = 2;
break;
4093 case 328: $function =
'PERCENTILE'; $args = 2;
break;
4094 case 331: $function =
'TRIMMEAN'; $args = 2;
break;
4095 case 332: $function =
'TINV'; $args = 2;
break;
4096 case 337: $function =
'POWER'; $args = 2;
break;
4097 case 342: $function =
'RADIANS'; $args = 1;
break;
4098 case 343: $function =
'DEGREES'; $args = 1;
break;
4099 case 346: $function =
'COUNTIF'; $args = 2;
break;
4100 case 347: $function =
'COUNTBLANK'; $args = 1;
break;
4101 case 350: $function =
'ISPMT'; $args = 4;
break;
4102 case 351: $function =
'DATEDIF'; $args = 3;
break;
4103 case 352: $function =
'DATESTRING'; $args = 1;
break;
4104 case 353: $function =
'NUMBERSTRING'; $args = 2;
break;
4105 case 360: $function =
'PHONETIC'; $args = 1;
break;
4107 throw new Exception(
'Unrecognized function in formula');
4110 $data = array(
'function' => $function,
'args' => $args);
4118 $args = ord($formulaData[1]);
4120 switch ($this->
_GetInt2d($formulaData, 2)) {
4121 case 0: $function =
'COUNT';
break;
4122 case 1: $function =
'IF';
break;
4123 case 4: $function =
'SUM';
break;
4124 case 5: $function =
'AVERAGE';
break;
4125 case 6: $function =
'MIN';
break;
4126 case 7: $function =
'MAX';
break;
4127 case 8: $function =
'ROW';
break;
4128 case 9: $function =
'COLUMN';
break;
4129 case 11: $function =
'NPV';
break;
4130 case 12: $function =
'STDEV';
break;
4131 case 13: $function =
'DOLLAR';
break;
4132 case 14: $function =
'FIXED';
break;
4133 case 28: $function =
'LOOKUP';
break;
4134 case 29: $function =
'INDEX';
break;
4135 case 36: $function =
'AND';
break;
4136 case 37: $function =
'OR';
break;
4137 case 46: $function =
'VAR';
break;
4138 case 49: $function =
'LINEST';
break;
4139 case 50: $function =
'TREND';
break;
4140 case 51: $function =
'LOGEST';
break;
4141 case 52: $function =
'GROWTH';
break;
4142 case 56: $function =
'PV';
break;
4143 case 57: $function =
'FV';
break;
4144 case 58: $function =
'NPER';
break;
4145 case 59: $function =
'PMT';
break;
4146 case 60: $function =
'RATE';
break;
4147 case 62: $function =
'IRR';
break;
4148 case 64: $function =
'MATCH';
break;
4149 case 70: $function =
'WEEKDAY';
break;
4150 case 78: $function =
'OFFSET';
break;
4151 case 82: $function =
'SEARCH';
break;
4152 case 100: $function =
'CHOOSE';
break;
4153 case 101: $function =
'HLOOKUP';
break;
4154 case 102: $function =
'VLOOKUP';
break;
4155 case 109: $function =
'LOG';
break;
4156 case 115: $function =
'LEFT';
break;
4157 case 116: $function =
'RIGHT';
break;
4158 case 120: $function =
'SUBSTITUTE';
break;
4159 case 124: $function =
'FIND';
break;
4160 case 125: $function =
'CELL';
break;
4161 case 144: $function =
'DDB';
break;
4162 case 148: $function =
'INDIRECT';
break;
4163 case 167: $function =
'IPMT';
break;
4164 case 168: $function =
'PPMT';
break;
4165 case 169: $function =
'COUNTA';
break;
4166 case 183: $function =
'PRODUCT';
break;
4167 case 193: $function =
'STDEVP';
break;
4168 case 194: $function =
'VARP';
break;
4169 case 197: $function =
'TRUNC';
break;
4170 case 204: $function =
'USDOLLAR';
break;
4171 case 205: $function =
'FINDB';
break;
4172 case 206: $function =
'SEARCHB';
break;
4173 case 208: $function =
'LEFTB';
break;
4174 case 209: $function =
'RIGHTB';
break;
4175 case 216: $function =
'RANK';
break;
4176 case 219: $function =
'ADDRESS';
break;
4177 case 220: $function =
'DAYS360';
break;
4178 case 222: $function =
'VDB';
break;
4179 case 227: $function =
'MEDIAN';
break;
4180 case 228: $function =
'SUMPRODUCT';
break;
4181 case 247: $function =
'DB';
break;
4182 case 269: $function =
'AVEDEV';
break;
4183 case 270: $function =
'BETADIST';
break;
4184 case 272: $function =
'BETAINV';
break;
4185 case 317: $function =
'PROB';
break;
4186 case 318: $function =
'DEVSQ';
break;
4187 case 319: $function =
'GEOMEAN';
break;
4188 case 320: $function =
'HARMEAN';
break;
4189 case 321: $function =
'SUMSQ';
break;
4190 case 322: $function =
'KURT';
break;
4191 case 323: $function =
'SKEW';
break;
4192 case 324: $function =
'ZTEST';
break;
4193 case 329: $function =
'PERCENTRANK';
break;
4194 case 330: $function =
'MODE';
break;
4195 case 336: $function =
'CONCATENATE';
break;
4196 case 344: $function =
'SUBTOTAL';
break;
4197 case 345: $function =
'SUMIF';
break;
4198 case 354: $function =
'ROMAN';
break;
4199 case 358: $function =
'GETPIVOTDATA';
break;
4200 case 359: $function =
'HYPERLINK';
break;
4201 case 361: $function =
'AVERAGEA';
break;
4202 case 362: $function =
'MAXA';
break;
4203 case 363: $function =
'MINA';
break;
4204 case 364: $function =
'STDEVPA';
break;
4205 case 365: $function =
'VARPA';
break;
4206 case 366: $function =
'STDEVA';
break;
4207 case 367: $function =
'VARA';
break;
4209 throw new Exception(
'Unrecognized function in formula');
4212 $data = array(
'function' => $function,
'args' => $args);
4219 $definedNameIndex = $this->
_GetInt2d($formulaData, 1) - 1;
4221 $data = $this->_definedname[$definedNameIndex][
'name'];
4242 $subSize = $this->
_GetInt2d($formulaData, 5);
4243 $size = 7 + $subSize;
4250 $subSize = $this->
_GetInt2d($formulaData, 5);
4251 $size = 7 + $subSize;
4258 $subSize = $this->
_GetInt2d($formulaData, 1);
4259 $size = 3 + $subSize;
4278 $data =
"$sheetRange!$cellAddress";
4290 $data =
"$sheetRange!$cellRangeAddress";
4295 throw new Exception(
'Unrecognized token ' . sprintf(
'%02X', $id) .
' in formula');
4325 if (!(0x4000 & $this->
_GetInt2d($cellAddressStructure, 2))) {
4326 $column =
'$' . $column;
4329 if (!(0x8000 & $this->
_GetInt2d($cellAddressStructure, 2))) {
4333 return $column .
$row;
4351 $rowIndex = $this->
_GetInt2d($cellAddressStructure, 0);
4357 $colIndex = 0x00FF & $this->
_GetInt2d($cellAddressStructure, 2);
4360 if (!(0x4000 & $this->
_GetInt2d($cellAddressStructure, 2))) {
4362 $column =
'$' . $column;
4364 $colIndex = ($colIndex <= 127) ? $colIndex : $colIndex - 256;
4369 if (!(0x8000 & $this->
_GetInt2d($cellAddressStructure, 2))) {
4372 $rowIndex = ($rowIndex <= 32767) ? $rowIndex : $rowIndex - 65536;
4373 $row = $baseRow + $rowIndex;
4376 return $column .
$row;
4391 $fr = $this->
_GetInt2d($subData, 0) + 1;
4397 $fc = ord($subData{4});
4400 $lc = ord($subData{5});
4403 if ($fr >
$lr || $fc > $lc) {
4404 throw new Exception(
'Not a cell range address');
4411 if ($fr ==
$lr and $fc == $lc) {
4414 return "$fc$fr:$lc$lr";
4429 $fr = $this->
_GetInt2d($subData, 0) + 1;
4441 if ($fr >
$lr || $fc > $lc) {
4442 throw new Exception(
'Not a cell range address');
4449 if ($fr ==
$lr and $fc == $lc) {
4452 return "$fc$fr:$lc$lr";
4469 $fr = $this->
_GetInt2d($subData, 0) + 1;
4480 if (!(0x4000 & $this->
_GetInt2d($subData, 4))) {
4485 if (!(0x8000 & $this->
_GetInt2d($subData, 4))) {
4495 if (!(0x4000 & $this->
_GetInt2d($subData, 6))) {
4500 if (!(0x8000 & $this->
_GetInt2d($subData, 6))) {
4504 return "$fc$fr:$lc$lr";
4516 $cellRangeAddresses = array();
4523 for ($i = 0; $i < $nm; ++$i) {
4529 'size' => 2 + 8 * $nm,
4530 'cellRangeAddresses' => $cellRangeAddresses,
4546 if (isset($this->_ref[$index])) {
4548 $type = $this->_externalBooks[$this->_ref[$index][
'externalBookIndex']][
'type'];
4553 if ($this->_ref[$index][
'firstSheetIndex'] == 0xFFFF or $this->_ref[$index][
'lastSheetIndex'] == 0xFFFF) {
4554 throw new Exception(
'Deleted sheet reference');
4558 $firstSheetName = $this->_sheets[$this->_ref[$index][
'firstSheetIndex']][
'name'];
4559 $lastSheetName = $this->_sheets[$this->_ref[$index][
'lastSheetIndex']][
'name'];
4561 if ($firstSheetName == $lastSheetName) {
4563 $sheetRange = $firstSheetName;
4565 $sheetRange =
"$firstSheetName:$lastSheetName";
4569 $sheetRange = str_replace(
"'",
"''", $sheetRange);
4575 if (preg_match(
"/[ !\"@#£$%&{()}<>=+'|^,;-]/", $sheetRange)) {
4576 $sheetRange =
"'$sheetRange'";
4584 throw new Exception(
'Excel5 reader only supports internal sheets in fomulas');
4602 $nc = ord($arrayData[0]);
4607 $arrayData = substr($arrayData, 3);
4610 $matrixChunks = array();
4611 for ($r = 1; $r <= $nr + 1; ++$r) {
4613 for ($c = 1; $c <= $nc + 1; ++$c) {
4615 $items[] = $constant[
'value'];
4616 $arrayData = substr($arrayData, $constant[
'size']);
4617 $size += $constant[
'size'];
4619 $matrixChunks[] = implode(
',', $items);
4621 $matrix =
'{' . implode(
';', $matrixChunks) .
'}';
4640 $identifier = ord($valueData[0]);
4642 switch ($identifier) {
4655 $value =
'"' . $string[
'value'] .
'"';
4656 $size = 1 + $string[
'size'];
4660 if (ord($valueData[1])) {
4698 $rgb = sprintf(
'%02X', $r) . sprintf(
'%02X', $g) . sprintf(
'%02X', $b);
4700 return array(
'rgb' => $rgb);
4713 $ln = ord($subData[0]);
4759 $characterCount = ord($subData[0]);
4764 $string[
'size'] += 1;
4782 $characterCount = $this->
_GetInt2d($subData, 0);
4787 $string[
'size'] += 2;
4808 $isCompressed = !((0x01 & ord($subData[0])) >> 0);
4811 $hasAsian = (0x04) & ord($subData[0]) >> 2;
4814 $hasRichText = (0x08) & ord($subData[0]) >> 3;
4819 $value = $this->
_encodeUTF16(substr($subData, 1, $isCompressed ? $characterCount : 2 * $characterCount), $isCompressed);
4823 'size' => $isCompressed ? 1 + $characterCount : 1 + 2 * $characterCount,
4836 return '"' . str_replace(
'"',
'""', $value) .
'"';
4849 $sign = ($rknumhigh & 0x80000000) >> 31;
4850 $exp = ($rknumhigh & 0x7ff00000) >> 20;
4851 $mantissa = (0x100000 | ($rknumhigh & 0x000fffff));
4852 $mantissalow1 = ($rknumlow & 0x80000000) >> 31;
4853 $mantissalow2 = ($rknumlow & 0x7fffffff);
4854 $value = $mantissa / pow( 2 , (20 - ($exp - 1023)));
4856 if ($mantissalow1 != 0) {
4857 $value += 1 / pow (2 , (21 - ($exp - 1023)));
4860 $value += $mantissalow2 / pow (2 , (52 - ($exp - 1023)));
4862 $value = -1 * $value;
4870 if (($rknum & 0x02) != 0) {
4871 $value = $rknum >> 2;
4879 $sign = ($rknum & 0x80000000) >> 31;
4880 $exp = ($rknum & 0x7ff00000) >> 20;
4881 $mantissa = (0x100000 | ($rknum & 0x000ffffc));
4882 $value = $mantissa / pow( 2 , (20- ($exp - 1023)));
4884 $value = -1 * $value;
4888 if (($rknum & 0x01) != 0) {
4920 $uncompressedString =
'';
4921 for ($i = 0; $i < strlen($string); ++$i) {
4922 $uncompressedString .= $string[$i] .
"\0";
4925 return $uncompressedString;
4949 return ord(
$data[$pos]) | (ord(
$data[$pos + 1]) << 8);
4966 $_or_24 = ord(
$data[$pos + 3]);
4967 if ($_or_24 >= 128) {
4969 $_ord_24 = -abs((256 - $_or_24) << 24);
4971 $_ord_24 = ($_or_24 & 127) << 24;
4973 return ord(
$data[$pos]) | (ord(
$data[$pos + 1]) << 8) | (ord(
$data[$pos + 2]) << 16) | $_ord_24;
4984 if ($color <= 0x07 || $color >= 0x40) {
4987 }
else if (isset($this->_palette) && isset($this->_palette[$color - 8])) {
4989 $color = $this->_palette[$color - 8];
4992 if ($this->_version == self::XLS_BIFF8) {
5074 case 0x00:
return '#NULL!';
break;
5075 case 0x07:
return '#DIV/0!';
break;
5076 case 0x0F:
return '#VALUE!';
break;
5077 case 0x17:
return '#REF!';
break;
5078 case 0x1D:
return '#NAME?';
break;
5079 case 0x24:
return '#NUM!';
break;
5080 case 0x2A:
return '#N/A';
break;
5081 default:
return false;
5094 case 0x00:
return array(
'rgb' =>
'000000');
5095 case 0x01:
return array(
'rgb' =>
'FFFFFF');
5096 case 0x02:
return array(
'rgb' =>
'FF0000');
5097 case 0x03:
return array(
'rgb' =>
'00FF00');
5098 case 0x04:
return array(
'rgb' =>
'0000FF');
5099 case 0x05:
return array(
'rgb' =>
'FFFF00');
5100 case 0x06:
return array(
'rgb' =>
'FF00FF');
5101 case 0x07:
return array(
'rgb' =>
'00FFFF');
5102 case 0x40:
return array(
'rgb' =>
'000000');
5103 case 0x41:
return array(
'rgb' =>
'FFFFFF');
5104 default:
return array(
'rgb' =>
'000000');
5117 case 0x08:
return array(
'rgb' =>
'000000');
5118 case 0x09:
return array(
'rgb' =>
'FFFFFF');
5119 case 0x0A:
return array(
'rgb' =>
'FF0000');
5120 case 0x0B:
return array(
'rgb' =>
'00FF00');
5121 case 0x0C:
return array(
'rgb' =>
'0000FF');
5122 case 0x0D:
return array(
'rgb' =>
'FFFF00');
5123 case 0x0E:
return array(
'rgb' =>
'FF00FF');
5124 case 0x0F:
return array(
'rgb' =>
'00FFFF');
5125 case 0x10:
return array(
'rgb' =>
'800000');
5126 case 0x11:
return array(
'rgb' =>
'008000');
5127 case 0x12:
return array(
'rgb' =>
'000080');
5128 case 0x13:
return array(
'rgb' =>
'808000');
5129 case 0x14:
return array(
'rgb' =>
'800080');
5130 case 0x15:
return array(
'rgb' =>
'008080');
5131 case 0x16:
return array(
'rgb' =>
'C0C0C0');
5132 case 0x17:
return array(
'rgb' =>
'808080');
5133 case 0x18:
return array(
'rgb' =>
'8080FF');
5134 case 0x19:
return array(
'rgb' =>
'802060');
5135 case 0x1A:
return array(
'rgb' =>
'FFFFC0');
5136 case 0x1B:
return array(
'rgb' =>
'A0E0F0');
5137 case 0x1C:
return array(
'rgb' =>
'600080');
5138 case 0x1D:
return array(
'rgb' =>
'FF8080');
5139 case 0x1E:
return array(
'rgb' =>
'0080C0');
5140 case 0x1F:
return array(
'rgb' =>
'C0C0FF');
5141 case 0x20:
return array(
'rgb' =>
'000080');
5142 case 0x21:
return array(
'rgb' =>
'FF00FF');
5143 case 0x22:
return array(
'rgb' =>
'FFFF00');
5144 case 0x23:
return array(
'rgb' =>
'00FFFF');
5145 case 0x24:
return array(
'rgb' =>
'800080');
5146 case 0x25:
return array(
'rgb' =>
'800000');
5147 case 0x26:
return array(
'rgb' =>
'008080');
5148 case 0x27:
return array(
'rgb' =>
'0000FF');
5149 case 0x28:
return array(
'rgb' =>
'00CFFF');
5150 case 0x29:
return array(
'rgb' =>
'69FFFF');
5151 case 0x2A:
return array(
'rgb' =>
'E0FFE0');
5152 case 0x2B:
return array(
'rgb' =>
'FFFF80');
5153 case 0x2C:
return array(
'rgb' =>
'A6CAF0');
5154 case 0x2D:
return array(
'rgb' =>
'DD9CB3');
5155 case 0x2E:
return array(
'rgb' =>
'B38FEE');
5156 case 0x2F:
return array(
'rgb' =>
'E3E3E3');
5157 case 0x30:
return array(
'rgb' =>
'2A6FF9');
5158 case 0x31:
return array(
'rgb' =>
'3FB8CD');
5159 case 0x32:
return array(
'rgb' =>
'488436');
5160 case 0x33:
return array(
'rgb' =>
'958C41');
5161 case 0x34:
return array(
'rgb' =>
'8E5E42');
5162 case 0x35:
return array(
'rgb' =>
'A0627A');
5163 case 0x36:
return array(
'rgb' =>
'624FAC');
5164 case 0x37:
return array(
'rgb' =>
'969696');
5165 case 0x38:
return array(
'rgb' =>
'1D2FBE');
5166 case 0x39:
return array(
'rgb' =>
'286676');
5167 case 0x3A:
return array(
'rgb' =>
'004500');
5168 case 0x3B:
return array(
'rgb' =>
'453E01');
5169 case 0x3C:
return array(
'rgb' =>
'6A2813');
5170 case 0x3D:
return array(
'rgb' =>
'85396A');
5171 case 0x3E:
return array(
'rgb' =>
'4A3285');
5172 case 0x3F:
return array(
'rgb' =>
'424242');
5173 default:
return array(
'rgb' =>
'000000');
5186 case 0x08:
return array(
'rgb' =>
'000000');
5187 case 0x09:
return array(
'rgb' =>
'FFFFFF');
5188 case 0x0A:
return array(
'rgb' =>
'FF0000');
5189 case 0x0B:
return array(
'rgb' =>
'00FF00');
5190 case 0x0C:
return array(
'rgb' =>
'0000FF');
5191 case 0x0D:
return array(
'rgb' =>
'FFFF00');
5192 case 0x0E:
return array(
'rgb' =>
'FF00FF');
5193 case 0x0F:
return array(
'rgb' =>
'00FFFF');
5194 case 0x10:
return array(
'rgb' =>
'800000');
5195 case 0x11:
return array(
'rgb' =>
'008000');
5196 case 0x12:
return array(
'rgb' =>
'000080');
5197 case 0x13:
return array(
'rgb' =>
'808000');
5198 case 0x14:
return array(
'rgb' =>
'800080');
5199 case 0x15:
return array(
'rgb' =>
'008080');
5200 case 0x16:
return array(
'rgb' =>
'C0C0C0');
5201 case 0x17:
return array(
'rgb' =>
'808080');
5202 case 0x18:
return array(
'rgb' =>
'9999FF');
5203 case 0x19:
return array(
'rgb' =>
'993366');
5204 case 0x1A:
return array(
'rgb' =>
'FFFFCC');
5205 case 0x1B:
return array(
'rgb' =>
'CCFFFF');
5206 case 0x1C:
return array(
'rgb' =>
'660066');
5207 case 0x1D:
return array(
'rgb' =>
'FF8080');
5208 case 0x1E:
return array(
'rgb' =>
'0066CC');
5209 case 0x1F:
return array(
'rgb' =>
'CCCCFF');
5210 case 0x20:
return array(
'rgb' =>
'000080');
5211 case 0x21:
return array(
'rgb' =>
'FF00FF');
5212 case 0x22:
return array(
'rgb' =>
'FFFF00');
5213 case 0x23:
return array(
'rgb' =>
'00FFFF');
5214 case 0x24:
return array(
'rgb' =>
'800080');
5215 case 0x25:
return array(
'rgb' =>
'800000');
5216 case 0x26:
return array(
'rgb' =>
'008080');
5217 case 0x27:
return array(
'rgb' =>
'0000FF');
5218 case 0x28:
return array(
'rgb' =>
'00CCFF');
5219 case 0x29:
return array(
'rgb' =>
'CCFFFF');
5220 case 0x2A:
return array(
'rgb' =>
'CCFFCC');
5221 case 0x2B:
return array(
'rgb' =>
'FFFF99');
5222 case 0x2C:
return array(
'rgb' =>
'99CCFF');
5223 case 0x2D:
return array(
'rgb' =>
'FF99CC');
5224 case 0x2E:
return array(
'rgb' =>
'CC99FF');
5225 case 0x2F:
return array(
'rgb' =>
'FFCC99');
5226 case 0x30:
return array(
'rgb' =>
'3366FF');
5227 case 0x31:
return array(
'rgb' =>
'33CCCC');
5228 case 0x32:
return array(
'rgb' =>
'99CC00');
5229 case 0x33:
return array(
'rgb' =>
'FFCC00');
5230 case 0x34:
return array(
'rgb' =>
'FF9900');
5231 case 0x35:
return array(
'rgb' =>
'FF6600');
5232 case 0x36:
return array(
'rgb' =>
'666699');
5233 case 0x37:
return array(
'rgb' =>
'969696');
5234 case 0x38:
return array(
'rgb' =>
'003366');
5235 case 0x39:
return array(
'rgb' =>
'339966');
5236 case 0x3A:
return array(
'rgb' =>
'003300');
5237 case 0x3B:
return array(
'rgb' =>
'333300');
5238 case 0x3C:
return array(
'rgb' =>
'993300');
5239 case 0x3D:
return array(
'rgb' =>
'993366');
5240 case 0x3E:
return array(
'rgb' =>
'333399');
5241 case 0x3F:
return array(
'rgb' =>
'333333');
5242 default:
return array(
'rgb' =>
'000000');