Exemple #1
0
 /**
  * XF - Extended Format
  *
  * This record contains formatting information for cells, rows, columns or styles.
  * According to http://support.microsoft.com/kb/147732 there are always at least 15 cell style XF
  * and 1 cell XF.
  * Inspection of Excel files generated by MS Office Excel shows that XF records 0-14 are cell style XF
  * and XF record 15 is a cell XF
  * We only read the first cell style XF and skip the remaining cell style XF records
  * We read all cell XF records.
  *
  * --	"OpenOffice.org's Documentation of the Microsoft
  * 		Excel File Format"
  */
 private function _readXf()
 {
     $length = $this->_GetInt2d($this->_data, $this->_pos + 2);
     $recordData = substr($this->_data, $this->_pos + 4, $length);
     // move stream pointer to next record
     $this->_pos += 4 + $length;
     $objStyle = new Style();
     if (!$this->_readDataOnly) {
         // offset:  0; size: 2; Index to FONT record
         if ($this->_GetInt2d($recordData, 0) < 4) {
             $fontIndex = $this->_GetInt2d($recordData, 0);
         } else {
             // this has to do with that index 4 is omitted in all BIFF versions for some strange reason
             // check the OpenOffice documentation of the FONT record
             $fontIndex = $this->_GetInt2d($recordData, 0) - 1;
         }
         $objStyle->setFont($this->_objFonts[$fontIndex]);
         // offset:  2; size: 2; Index to FORMAT record
         $numberFormatIndex = $this->_GetInt2d($recordData, 2);
         if (isset($this->_formats[$numberFormatIndex])) {
             // then we have user-defined format code
             $numberformat = array('code' => $this->_formats[$numberFormatIndex]);
         } elseif (($code = Style_NumberFormat::builtInFormatCode($numberFormatIndex)) !== '') {
             // then we have built-in format code
             $numberformat = array('code' => $code);
         } else {
             // we set the general format code
             $numberformat = array('code' => 'General');
         }
         $objStyle->getNumberFormat()->setFormatCode($numberformat['code']);
         // offset:  4; size: 2; XF type, cell protection, and parent style XF
         // bit 2-0; mask 0x0007; XF_TYPE_PROT
         $xfTypeProt = $this->_GetInt2d($recordData, 4);
         // bit 0; mask 0x01; 1 = cell is locked
         $isLocked = (0x1 & $xfTypeProt) >> 0;
         $objStyle->getProtection()->setLocked($isLocked ? Style_Protection::PROTECTION_INHERIT : Style_Protection::PROTECTION_UNPROTECTED);
         // bit 1; mask 0x02; 1 = Formula is hidden
         $isHidden = (0x2 & $xfTypeProt) >> 1;
         $objStyle->getProtection()->setHidden($isHidden ? Style_Protection::PROTECTION_PROTECTED : Style_Protection::PROTECTION_UNPROTECTED);
         // bit 2; mask 0x04; 0 = Cell XF, 1 = Cell Style XF
         $isCellStyleXf = (0x4 & $xfTypeProt) >> 2;
         // offset:  6; size: 1; Alignment and text break
         // bit 2-0, mask 0x07; horizontal alignment
         $horAlign = (0x7 & ord($recordData[6])) >> 0;
         switch ($horAlign) {
             case 0:
                 $objStyle->getAlignment()->setHorizontal(Style_Alignment::HORIZONTAL_GENERAL);
                 break;
             case 1:
                 $objStyle->getAlignment()->setHorizontal(Style_Alignment::HORIZONTAL_LEFT);
                 break;
             case 2:
                 $objStyle->getAlignment()->setHorizontal(Style_Alignment::HORIZONTAL_CENTER);
                 break;
             case 3:
                 $objStyle->getAlignment()->setHorizontal(Style_Alignment::HORIZONTAL_RIGHT);
                 break;
             case 5:
                 $objStyle->getAlignment()->setHorizontal(Style_Alignment::HORIZONTAL_JUSTIFY);
                 break;
             case 6:
                 $objStyle->getAlignment()->setHorizontal(Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS);
                 break;
         }
         // bit 3, mask 0x08; wrap text
         $wrapText = (0x8 & ord($recordData[6])) >> 3;
         switch ($wrapText) {
             case 0:
                 $objStyle->getAlignment()->setWrapText(false);
                 break;
             case 1:
                 $objStyle->getAlignment()->setWrapText(true);
                 break;
         }
         // bit 6-4, mask 0x70; vertical alignment
         $vertAlign = (0x70 & ord($recordData[6])) >> 4;
         switch ($vertAlign) {
             case 0:
                 $objStyle->getAlignment()->setVertical(Style_Alignment::VERTICAL_TOP);
                 break;
             case 1:
                 $objStyle->getAlignment()->setVertical(Style_Alignment::VERTICAL_CENTER);
                 break;
             case 2:
                 $objStyle->getAlignment()->setVertical(Style_Alignment::VERTICAL_BOTTOM);
                 break;
             case 3:
                 $objStyle->getAlignment()->setVertical(Style_Alignment::VERTICAL_JUSTIFY);
                 break;
         }
         if ($this->_version == self::XLS_BIFF8) {
             // offset:  7; size: 1; XF_ROTATION: Text rotation angle
             $angle = ord($recordData[7]);
             $rotation = 0;
             if ($angle <= 90) {
                 $rotation = $angle;
             } else {
                 if ($angle <= 180) {
                     $rotation = 90 - $angle;
                 } else {
                     if ($angle == 255) {
                         $rotation = -165;
                     }
                 }
             }
             $objStyle->getAlignment()->setTextRotation($rotation);
             // offset:  8; size: 1; Indentation, shrink to cell size, and text direction
             // bit: 3-0; mask: 0x0F; indent level
             $indent = (0xf & ord($recordData[8])) >> 0;
             $objStyle->getAlignment()->setIndent($indent);
             // bit: 4; mask: 0x10; 1 = shrink content to fit into cell
             $shrinkToFit = (0x10 & ord($recordData[8])) >> 4;
             switch ($shrinkToFit) {
                 case 0:
                     $objStyle->getAlignment()->setShrinkToFit(false);
                     break;
                 case 1:
                     $objStyle->getAlignment()->setShrinkToFit(true);
                     break;
             }
             // offset:  9; size: 1; Flags used for attribute groups
             // offset: 10; size: 4; Cell border lines and background area
             // bit: 3-0; mask: 0x0000000F; left style
             if ($bordersLeftStyle = $this->_mapBorderStyle((0xf & $this->_GetInt4d($recordData, 10)) >> 0)) {
                 $objStyle->getBorders()->getLeft()->setBorderStyle($bordersLeftStyle);
             }
             // bit: 7-4; mask: 0x000000F0; right style
             if ($bordersRightStyle = $this->_mapBorderStyle((0xf0 & $this->_GetInt4d($recordData, 10)) >> 4)) {
                 $objStyle->getBorders()->getRight()->setBorderStyle($bordersRightStyle);
             }
             // bit: 11-8; mask: 0x00000F00; top style
             if ($bordersTopStyle = $this->_mapBorderStyle((0xf00 & $this->_GetInt4d($recordData, 10)) >> 8)) {
                 $objStyle->getBorders()->getTop()->setBorderStyle($bordersTopStyle);
             }
             // bit: 15-12; mask: 0x0000F000; bottom style
             if ($bordersBottomStyle = $this->_mapBorderStyle((0xf000 & $this->_GetInt4d($recordData, 10)) >> 12)) {
                 $objStyle->getBorders()->getBottom()->setBorderStyle($bordersBottomStyle);
             }
             // bit: 22-16; mask: 0x007F0000; left color
             $objStyle->getBorders()->getLeft()->colorIndex = (0x7f0000 & $this->_GetInt4d($recordData, 10)) >> 16;
             // bit: 29-23; mask: 0x3F800000; right color
             $objStyle->getBorders()->getRight()->colorIndex = (0x3f800000 & $this->_GetInt4d($recordData, 10)) >> 23;
             // bit: 30; mask: 0x40000000; 1 = diagonal line from top left to right bottom
             $diagonalDown = (0x40000000 & $this->_GetInt4d($recordData, 10)) >> 30 ? true : false;
             // bit: 31; mask: 0x80000000; 1 = diagonal line from bottom left to top right
             $diagonalUp = (0x80000000 & $this->_GetInt4d($recordData, 10)) >> 31 ? true : false;
             if ($diagonalUp == false && $diagonalDown == false) {
                 $objStyle->getBorders()->setDiagonalDirection(Style_Borders::DIAGONAL_NONE);
             } elseif ($diagonalUp == true && $diagonalDown == false) {
                 $objStyle->getBorders()->setDiagonalDirection(Style_Borders::DIAGONAL_UP);
             } elseif ($diagonalUp == false && $diagonalDown == true) {
                 $objStyle->getBorders()->setDiagonalDirection(Style_Borders::DIAGONAL_DOWN);
             } elseif ($diagonalUp == true && $diagonalDown == true) {
                 $objStyle->getBorders()->setDiagonalDirection(Style_Borders::DIAGONAL_BOTH);
             }
             // offset: 14; size: 4;
             // bit: 6-0; mask: 0x0000007F; top color
             $objStyle->getBorders()->getTop()->colorIndex = (0x7f & $this->_GetInt4d($recordData, 14)) >> 0;
             // bit: 13-7; mask: 0x00003F80; bottom color
             $objStyle->getBorders()->getBottom()->colorIndex = (0x3f80 & $this->_GetInt4d($recordData, 14)) >> 7;
             // bit: 20-14; mask: 0x001FC000; diagonal color
             $objStyle->getBorders()->getDiagonal()->colorIndex = (0x1fc000 & $this->_GetInt4d($recordData, 14)) >> 14;
             // bit: 24-21; mask: 0x01E00000; diagonal style
             if ($bordersDiagonalStyle = $this->_mapBorderStyle((0x1e00000 & $this->_GetInt4d($recordData, 14)) >> 21)) {
                 $objStyle->getBorders()->getDiagonal()->setBorderStyle($bordersDiagonalStyle);
             }
             // bit: 31-26; mask: 0xFC000000 fill pattern
             if ($fillType = $this->_mapFillPattern((0xfc000000 & $this->_GetInt4d($recordData, 14)) >> 26)) {
                 $objStyle->getFill()->setFillType($fillType);
             }
             // offset: 18; size: 2; pattern and background colour
             // bit: 6-0; mask: 0x007F; color index for pattern color
             $objStyle->getFill()->startcolorIndex = (0x7f & $this->_GetInt2d($recordData, 18)) >> 0;
             // bit: 13-7; mask: 0x3F80; color index for pattern background
             $objStyle->getFill()->endcolorIndex = (0x3f80 & $this->_GetInt2d($recordData, 18)) >> 7;
         } else {
             // BIFF5
             // offset: 7; size: 1; Text orientation and flags
             $orientationAndFlags = ord($recordData[7]);
             // bit: 1-0; mask: 0x03; XF_ORIENTATION: Text orientation
             $xfOrientation = (0x3 & $orientationAndFlags) >> 0;
             switch ($xfOrientation) {
                 case 0:
                     $objStyle->getAlignment()->setTextRotation(0);
                     break;
                 case 1:
                     $objStyle->getAlignment()->setTextRotation(-165);
                     break;
                 case 2:
                     $objStyle->getAlignment()->setTextRotation(90);
                     break;
                 case 3:
                     $objStyle->getAlignment()->setTextRotation(-90);
                     break;
             }
             // offset: 8; size: 4; cell border lines and background area
             $borderAndBackground = $this->_GetInt4d($recordData, 8);
             // bit: 6-0; mask: 0x0000007F; color index for pattern color
             $objStyle->getFill()->startcolorIndex = (0x7f & $borderAndBackground) >> 0;
             // bit: 13-7; mask: 0x00003F80; color index for pattern background
             $objStyle->getFill()->endcolorIndex = (0x3f80 & $borderAndBackground) >> 7;
             // bit: 21-16; mask: 0x003F0000; fill pattern
             $objStyle->getFill()->setFillType($this->_mapFillPattern((0x3f0000 & $borderAndBackground) >> 16));
             // bit: 24-22; mask: 0x01C00000; bottom line style
             $objStyle->getBorders()->getBottom()->setBorderStyle($this->_mapBorderStyle((0x1c00000 & $borderAndBackground) >> 22));
             // bit: 31-25; mask: 0xFE000000; bottom line color
             $objStyle->getBorders()->getBottom()->colorIndex = (0xfe000000 & $borderAndBackground) >> 25;
             // offset: 12; size: 4; cell border lines
             $borderLines = $this->_GetInt4d($recordData, 12);
             // bit: 2-0; mask: 0x00000007; top line style
             $objStyle->getBorders()->getTop()->setBorderStyle($this->_mapBorderStyle((0x7 & $borderLines) >> 0));
             // bit: 5-3; mask: 0x00000038; left line style
             $objStyle->getBorders()->getLeft()->setBorderStyle($this->_mapBorderStyle((0x38 & $borderLines) >> 3));
             // bit: 8-6; mask: 0x000001C0; right line style
             $objStyle->getBorders()->getRight()->setBorderStyle($this->_mapBorderStyle((0x1c0 & $borderLines) >> 6));
             // bit: 15-9; mask: 0x0000FE00; top line color index
             $objStyle->getBorders()->getTop()->colorIndex = (0xfe00 & $borderLines) >> 9;
             // bit: 22-16; mask: 0x007F0000; left line color index
             $objStyle->getBorders()->getLeft()->colorIndex = (0x7f0000 & $borderLines) >> 16;
             // bit: 29-23; mask: 0x3F800000; right line color index
             $objStyle->getBorders()->getRight()->colorIndex = (0x3f800000 & $borderLines) >> 23;
         }
         // add cellStyleXf or cellXf and update mapping
         if ($isCellStyleXf) {
             // we only read one style XF record which is always the first
             if ($this->_xfIndex == 0) {
                 $this->_phpExcel->addCellStyleXf($objStyle);
                 $this->_mapCellStyleXfIndex[$this->_xfIndex] = 0;
             }
         } else {
             // we read all cell XF records
             $this->_phpExcel->addCellXf($objStyle);
             $this->_mapCellXfIndex[$this->_xfIndex] = count($this->_phpExcel->getCellXfCollection()) - 1;
         }
         // update XF index for when we read next record
         ++$this->_xfIndex;
     }
 }