/** * 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; } }
/** * Write Cell Style Dxf * * @param Shared_XMLWriter $objWriter XML Writer * @param Style $pStyle Style * @throws Exception */ private function _writeCellStyleDxf(Shared_XMLWriter $objWriter = null, Style $pStyle = null) { // dxf $objWriter->startElement('dxf'); // font $this->_writeFont($objWriter, $pStyle->getFont()); // numFmt $this->_writeNumFmt($objWriter, $pStyle->getNumberFormat()); // fill $this->_writeFill($objWriter, $pStyle->getFill()); // alignment $objWriter->startElement('alignment'); $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); $textRotation = 0; if ($pStyle->getAlignment()->getTextRotation() >= 0) { $textRotation = $pStyle->getAlignment()->getTextRotation(); } else { if ($pStyle->getAlignment()->getTextRotation() < 0) { $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); } } $objWriter->writeAttribute('textRotation', $textRotation); $objWriter->endElement(); // border $this->_writeBorder($objWriter, $pStyle->getBorders()); // protection if ($pStyle->getProtection()->getLocked() != Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != Style_Protection::PROTECTION_INHERIT) { $objWriter->startElement('protection'); if ($pStyle->getProtection()->getLocked() != Style_Protection::PROTECTION_INHERIT) { $objWriter->writeAttribute('locked', $pStyle->getProtection()->getLocked() == Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false'); } if ($pStyle->getProtection()->getHidden() != Style_Protection::PROTECTION_INHERIT) { $objWriter->writeAttribute('hidden', $pStyle->getProtection()->getHidden() == Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false'); } $objWriter->endElement(); } $objWriter->endElement(); }