Read NUMBER record
This record represents a cell that contains a
floating-point value.

--	"OpenOffice.org's Documentation of the Microsoft
Excel File Format"
181327
private function _readNumber()
	{
		$length = self::_GetInt2d($this->_data, $this->_pos + 2);
		$recordData = substr($this->_data, $this->_pos + 4, $length);

		// move stream pointer to next record
		$this->_pos += 4 + $length;

		// offset: 0; size: 2; index to row
		$row = self::_GetInt2d($recordData, 0);

		// offset: 2; size 2; index to column
		$column = self::_GetInt2d($recordData, 2);
		$columnString = PHPExcel_Cell::stringFromColumnIndex($column);

		// Read cell?
		if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) {
			// offset 4; size: 2; index to XF record
			$xfIndex = self::_GetInt2d($recordData, 4);

			$numValue = self::_extractNumber(substr($recordData, 6, 8));

			$cell = $this->_phpSheet->getCell($columnString . ($row + 1));
			if (!$this->_readDataOnly) {
				// add cell style
				$cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]);
			}

			// add cell value
			$cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC);
		}
	}
31230
public int readBit( int row , int col ) {
		// todo use adjustments from near by alignment patterns

		float center = 0.5f;

//		if( pixel.x < -0.5 || pixel.y < -0.5 || pixel.x > imageWidth || pixel.y > imageHeight )
//			return -1;

		transformGrid.gridToImage(row+center-0.2f, col+center, pixel);
		float pixel01 = interpolate.get(pixel.x,pixel.y);
		transformGrid.gridToImage(row+center+0.2f, col+center, pixel);
		float pixel21 = interpolate.get(pixel.x,pixel.y);
		transformGrid.gridToImage(row+center, col+center-0.2f, pixel);
		float pixel10 = interpolate.get(pixel.x,pixel.y);
		transformGrid.gridToImage(row+center, col+center+0.2f, pixel);
		float pixel12 = interpolate.get(pixel.x,pixel.y);
		transformGrid.gridToImage(row+center, col+center, pixel);
		float pixel00 = interpolate.get(pixel.x,pixel.y);

//		float threshold = this.threshold*1.25f;

		int total = 0;
		if( pixel01 < threshold ) total++;
		if( pixel21 < threshold ) total++;
		if( pixel10 < threshold ) total++;
		if( pixel12 < threshold ) total++;
		if( pixel00 < threshold ) total++;

		if( total >= 3 )
			return 1;
		else
			return 0;

//		float value = (pixel01+pixel21+pixel10+pixel12)*0.25f;
//		value = value*0.5f + pixel00*0.5f;

		// in at least one situation this was found to improve the reading
//		float threshold;
//		if( qr  != null ) {
//			int N = qr.getNumberOfModules();
//			if( row > N/2 ) {
//				if( col < N/2 )
//					threshold = (float)qr.threshDown;
//				else {
//					threshold = (float)(qr.threshDown+qr.threshRight)/2f;
//				}
//			} else if( col < N/2 ) {
//				threshold = (float)qr.threshCorner;
//			} else {
//				threshold = (float)qr.threshRight;
//			}
//		} else {
//			threshold = this.threshold;
//		}

//		if( pixel00 < threshold )
//			return 1;
//		else
//			return 0;
	}
493822
private void scanNumber(int pos, int radix) {
        // for octal, allow base-10 digit in case it's a float literal
        this.radix = radix;
        int digitRadix = (radix == 8 ? 10 : radix);
        boolean seendigit = false;
        if (reader.digit(pos, digitRadix) >= 0) {
            seendigit = true;
            scanDigits(pos, digitRadix);
        }
        if (radix == 16 && reader.ch == '.') {
            scanHexFractionAndSuffix(pos, seendigit);
        } else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) {
            scanHexExponentAndSuffix(pos);
        } else if (digitRadix == 10 && reader.ch == '.') {
            reader.putChar(true);
            scanFractionAndSuffix(pos);
        } else if (digitRadix == 10 &&
                   (reader.ch == 'e' || reader.ch == 'E' ||
                    reader.ch == 'f' || reader.ch == 'F' ||
                    reader.ch == 'd' || reader.ch == 'D')) {
            scanFractionAndSuffix(pos);
        } else {
            if (reader.ch == 'l' || reader.ch == 'L') {
                reader.scanChar();
                tk = TokenKind.LONGLITERAL;
            } else {
                tk = TokenKind.INTLITERAL;
            }
        }
    }
1340732
@Override
    public Number readNumber() {
        if (buf.hasRemaining()) {
            int remaining = buf.remaining();
            if (log.isTraceEnabled()) {
                log.trace("Remaining bytes for Number: {}", remaining);
            }
            Number v;
            if (currentDataType == AMF3.TYPE_NUMBER) {
                // prevent buffer underrun if we dont have 8 bytes for the expected double
                if (remaining >= 8) {
                    v = buf.getDouble();
                } else {
                    v = buf.getInt();
                }
            } else {
                // we are decoding an int
                v = readInteger();
            }
            if (log.isTraceEnabled()) {
                log.trace("readNumber - value: {}", v);
            }
            return v;
        } else {
            log.warn("No remaining bytes for buffer readNumber");
        }
        return null;
    }
571245
def read_number(source, start, first_code):
    # type: (Source, int, Optional[int]) -> Token
    """
    code = first_code
    body = source.body
    position = start
    is_float = False

    if code == 45:  # -
        position += 1
        code = char_code_at(body, position)

    if code == 48:  # 0
        position += 1
        code = char_code_at(body, position)

        if code is not None and 48 <= code <= 57:
            raise GraphQLSyntaxError(
                source,
                position,
                u"Invalid number, unexpected digit after 0: {}.".format(
                    print_char_code(code)
                ),
            )
    else:
        position = read_digits(source, position, code)
        code = char_code_at(body, position)

    if code == 46:  # .
        is_float = True

        position += 1
        code = char_code_at(body, position)
        position = read_digits(source, position, code)
        code = char_code_at(body, position)

    if code in (69, 101):  # E e
        is_float = True
        position += 1
        code = char_code_at(body, position)
        if code in (43, 45):  # + -
            position += 1
            code = char_code_at(body, position)

        position = read_digits(source, position, code)

    return Token(
        TokenKind.FLOAT if is_float else TokenKind.INT,
        start,
        position,
        body[start:position],
    )
293644
private function readExternName()
    {
        $length = self::getInt2d($this->data, $this->pos + 2);
        $recordData = $this->readRecordData($this->data, $this->pos + 4, $length);

        // move stream pointer to next record
        $this->pos += 4 + $length;

        // external sheet references provided for named cells
        if ($this->version == self::XLS_BIFF8) {
            // offset: 0; size: 2; options
            $options = self::getInt2d($recordData, 0);

            // offset: 2; size: 2;

            // offset: 4; size: 2; not used

            // offset: 6; size: var
            $nameString = self::readUnicodeStringShort(substr($recordData, 6));

            // offset: var; size: var; formula data
            $offset = 6 + $nameString['size'];
            $formula = $this->getFormulaFromStructure(substr($recordData, $offset));

            $this->externalNames[] = array(
                'name' => $nameString['value'],
                'formula' => $formula,
            );
        }
    }
1060140
private function readImData()
    {
        $length = self::getInt2d($this->data, $this->pos + 2);

        // get spliced record data
        $splicedRecordData = $this->getSplicedRecordData();
        $recordData = $splicedRecordData['recordData'];

        // UNDER CONSTRUCTION

        // offset: 0; size: 2; image format
        $cf = self::getInt2d($recordData, 0);

        // offset: 2; size: 2; environment from which the file was written
        $env = self::getInt2d($recordData, 2);

        // offset: 4; size: 4; length of the image data
        $lcb = self::getInt4d($recordData, 4);

        // offset: 8; size: var; image data
        $iData = substr($recordData, 8);

        switch ($cf) {
            case 0x09: // Windows bitmap format
                // BITMAPCOREINFO
                // 1. BITMAPCOREHEADER
                // offset: 0; size: 4; bcSize, Specifies the number of bytes required by the structure
                $bcSize = self::getInt4d($iData, 0);
    //            var_dump($bcSize);

                // offset: 4; size: 2; bcWidth, specifies the width of the bitmap, in pixels
                $bcWidth = self::getInt2d($iData, 4);
    //            var_dump($bcWidth);

                // offset: 6; size: 2; bcHeight, specifies the height of the bitmap, in pixels.
                $bcHeight = self::getInt2d($iData, 6);
    //            var_dump($bcHeight);
                $ih = imagecreatetruecolor($bcWidth, $bcHeight);

                // offset: 8; size: 2; bcPlanes, specifies the number of planes for the target device. This value must be 1

                // offset: 10; size: 2; bcBitCount specifies the number of bits-per-pixel. This value must be 1, 4, 8, or 24
                $bcBitCount = self::getInt2d($iData, 10);
    //            var_dump($bcBitCount);

                $rgbString = substr($iData, 12);
                $rgbTriples = array();
                while (strlen($rgbString) > 0) {
                    $rgbTriples[] = unpack('Cb/Cg/Cr', $rgbString);
                    $rgbString = substr($rgbString, 3);
                }
                $x = 0;
                $y = 0;
                foreach ($rgbTriples as $i => $rgbTriple) {
                    $color = imagecolorallocate($ih, $rgbTriple['r'], $rgbTriple['g'], $rgbTriple['b']);
                    imagesetpixel($ih, $x, $bcHeight - 1 - $y, $color);
                    $x = ($x + 1) % $bcWidth;
                    $y = $y + floor(($x + 1) / $bcWidth);
                }
                //imagepng($ih, 'image.png');

                $drawing = new PHPExcel_Worksheet_Drawing();
                $drawing->setPath($filename);
                $drawing->setWorksheet($this->phpSheet);
                break;
            case 0x02: // Windows metafile or Macintosh PICT format
            case 0x0e: // native format
            default:
                break;
        }

        // getSplicedRecordData() takes care of moving current position in data stream
    }
1259077
private function _readNote()
	{
//		echo '<b>Read Cell Annotation</b><br />';
		$length = self::_GetInt2d($this->_data, $this->_pos + 2);
		$recordData = substr($this->_data, $this->_pos + 4, $length);

		// move stream pointer to next record
		$this->_pos += 4 + $length;

		if ($this->_readDataOnly) {
			return;
		}

		$cellAddress = $this->_readBIFF8CellAddress(substr($recordData, 0, 4));
		if ($this->_version == self::XLS_BIFF8) {
			$noteObjID = self::_GetInt2d($recordData, 6);
			$noteAuthor = self::_readUnicodeStringLong(substr($recordData, 8));
			$noteAuthor = $noteAuthor['value'];
//			echo 'Note Address=',$cellAddress,'<br />';
//			echo 'Note Object ID=',$noteObjID,'<br />';
//			echo 'Note Author=',$noteAuthor,'<hr />';
//
			$this->_cellNotes[$noteObjID] = array('cellRef'		=> $cellAddress,
												  'objectID'	=> $noteObjID,
												  'author'		=> $noteAuthor
												 );
		} else {
			$extension = false;
			if ($cellAddress == '$B$65536') {
				//	If the address row is -1 and the column is 0, (which translates as $B$65536) then this is a continuation
				//		note from the previous cell annotation. We're not yet handling this, so annotations longer than the
				//		max 2048 bytes will probably throw a wobbly.
				$row = self::_GetInt2d($recordData, 0);
				$extension = true;
				$cellAddress = array_pop(array_keys($this->_phpSheet->getComments()));
			}
//			echo 'Note Address=',$cellAddress,'<br />';

			$cellAddress = str_replace('$','',$cellAddress);
			$noteLength = self::_GetInt2d($recordData, 4);
			$noteText = trim(substr($recordData, 6));
//			echo 'Note Length=',$noteLength,'<br />';
//			echo 'Note Text=',$noteText,'<br />';

			if ($extension) {
				//	Concatenate this extension with the currently set comment for the cell
				$comment = $this->_phpSheet->getComment( $cellAddress );
				$commentText = $comment->getText()->getPlainText();
				$comment->setText($this->_parseRichText($commentText.$noteText) );
			} else {
				//	Set comment for the cell
				$this->_phpSheet->getComment( $cellAddress )
//													->setAuthor( $author )
													->setText($this->_parseRichText($noteText) );
			}
		}

	}
1080501
function _storeAllNumFormats()
    {
        // Leaning num_format syndrome
        $hash_num_formats = array();
        $num_formats      = array();
        $index = 164;

        // Iterate through the XF objects and write a FORMAT record if it isn't a
        // built-in format type and if the FORMAT string hasn't already been used.
        $total_formats = count($this->_formats);
        for ($i = 0; $i < $total_formats; $i++) {
            $num_format = $this->_formats[$i]->_num_format;

            // Check if $num_format is an index to a built-in format.
            // Also check for a string of zeros, which is a valid format string
            // but would evaluate to zero.
            //
            if (!preg_match("/^0+\d/", $num_format)) {
                if (preg_match("/^\d+$/", $num_format)) { // built-in format
                    continue;
                }
            }

            if (isset($hash_num_formats[$num_format])) {
                // FORMAT has already been used
                $this->_formats[$i]->_num_format = $hash_num_formats[$num_format];
            } else{
                // Add a new FORMAT
                $hash_num_formats[$num_format]  = $index;
                $this->_formats[$i]->_num_format = $index;
                array_push($num_formats,$num_format);
                $index++;
            }
        }

        // Write the new FORMAT records starting from 0xA4
        $index = 164;
        foreach ($num_formats as $num_format) {
            $this->_storeNumFormat($num_format,$index);
            $index++;
        }
    }
1365602
private Token scanNumber(int c) throws IOException {
        int startLine = mSource.getLineNumber();
        int startPos = mSource.getStartPosition();
        mWord.setLength(0);
        
        int errorPos = -1;

        // 0 is decimal int, 
        // 1 is hex int, 
        // 2 is decimal long, 
        // 3 is hex long, 
        // 4 is float, 
        // 5 is double,
        // 6 is auto-double by decimal
        // 7 is auto-double by exponent ('e' or 'E')
        int type = 0; 

        if (c == '0') {
            if (mSource.peek() == 'x' || mSource.peek() == 'X') {
                type = 1;
                mSource.read(); // absorb the 'x'
                c = mSource.read(); // get the first digit after the 'x'
            }
        }

        for (; c != -1; c = mSource.read()) {
            if (c == '.') {
                int peek = mSource.peek();
                if (peek == '.') {
                    mSource.unread();
                    break;
                }
                else {
                    if (peek < '0' || peek > '9') {
                        error("number.decimal.end");
                    }

                    mWord.append((char)c);

                    if (type == 0) {
                        type = 6;
                    }
                    else if (errorPos < 0) {
                        errorPos = mSource.getStartPosition();
                    }

                    continue;
                }
            }

            if (c >= '0' && c <= '9') {
                mWord.append((char)c);

                if (type == 2 || type == 3 || type == 4 || type == 5) {
                    if (errorPos < 0) {
                        errorPos = mSource.getStartPosition();
                    }
                }

                continue;
            }

            if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
                if (type == 1) {
                    mWord.append((char)c);
                    continue;
                }

                if (c == 'f' || c == 'F') {
                    if (type == 0 || type == 6 || type == 7) {
                        type = 4;
                        continue;
                    }
                }
                else if (c == 'd' || c == 'D') {
                    if (type == 0 || type == 6 || type == 7) {
                        type = 5;
                        continue;
                    }
                }
                else if (c == 'e' || c == 'E') {
                    if (type == 0 || type == 6) {
                        mWord.append((char)c);
                        type = 7;
                        int peek = mSource.peek();
                        if (peek == '+' || peek == '-') {
                            mWord.append((char)mSource.read());
                        }
                        continue;
                    }
                }

                mWord.append((char)c);

                if (errorPos < 0) {
                    errorPos = mSource.getStartPosition();
                }

                continue;
            }

            if (c == 'l' || c == 'L') {
                if (type == 0) {
                    type = 2;
                }
                else if (type == 1) {
                    type = 3;
                }
                else {
                    mWord.append((char)c);
                    if (errorPos < 0) {
                        errorPos = mSource.getStartPosition();
                    }
                }

                continue;
            }

            if (Character.isLetterOrDigit((char)c)) {
                mWord.append((char)c);

                if (errorPos < 0) {
                    errorPos = mSource.getStartPosition();
                }
            }
            else {
                mSource.unread();
                break;
            }
        }
        
        String str = mWord.toString();
        int endPos = mSource.getEndPosition();
        Token token;

        if (errorPos >= 0) {
            token = new StringToken
                (startLine, startPos, endPos, errorPos, Token.NUMBER, str);
        }
        else {
            try {
                switch (type) {
                case 0:
                default:
                    try {
                        token = new IntToken
                            (startLine, startPos, endPos,
                             Integer.parseInt(str));
                    }
                    catch (NumberFormatException e) {
                        token = new LongToken
                            (startLine, startPos, endPos, Long.parseLong(str));
                    }
                    break;
                case 1:
                    try {
                        token = new IntToken
                            (startLine, startPos, endPos, parseHexInt(str));
                    }
                    catch (NumberFormatException e) {
                        token = new LongToken
                            (startLine, startPos, endPos, parseHexLong(str));
                    }
                    break;
                case 2:
                    token = new LongToken
                        (startLine, startPos, endPos, Long.parseLong(str));
                    break;
                case 3:
                    token = new LongToken
                        (startLine, startPos, endPos, parseHexLong(str));
                    break;
                case 4:
                    token = new FloatToken
                        (startLine, startPos, endPos, Float.parseFloat(str));
                    break;
                case 5:
                case 6:
                case 7:
                    token = new DoubleToken
                        (startLine, startPos, endPos, Double.parseDouble(str));
                    break;
                }
            }
            catch (NumberFormatException e) {
                token = new IntToken(startLine, startPos, endPos, 0);
                error("number.range", token.getSourceInfo());
            }
        }

        return token;
    }
1059015
def store_dataformat(series_index, series_number, point_number)   # :nodoc:
    record        = 0x1006     # Record identifier.
    length        = 0x0008     # Number of bytes to follow.
    # series_index             # Series index.
    # series_number            # Series number. (Same as index).
    # point_number             # Point number.
    grbit         = 0x0000     # Format flags.

    store_simple(record, length, point_number, series_index, series_number, grbit)
  end
609284
private function _readRow()
	{
		$length = self::_GetInt2d($this->_data, $this->_pos + 2);
		$recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length);

		// move stream pointer to next record
		$this->_pos += 4 + $length;

		if (!$this->_readDataOnly) {
			// offset: 0; size: 2; index of this row
			$r = self::_GetInt2d($recordData, 0);

			// offset: 2; size: 2; index to column of the first cell which is described by a cell record

			// offset: 4; size: 2; index to column of the last cell which is described by a cell record, increased by 1

			// offset: 6; size: 2;

			// bit: 14-0; mask: 0x7FFF; height of the row, in twips = 1/20 of a point
			$height = (0x7FFF & self::_GetInt2d($recordData, 6)) >> 0;

			// bit: 15: mask: 0x8000; 0 = row has custom height; 1= row has default height
			$useDefaultHeight = (0x8000 & self::_GetInt2d($recordData, 6)) >> 15;

			if (!$useDefaultHeight) {
				$this->_phpSheet->getRowDimension($r + 1)->setRowHeight($height / 20);
			}

			// offset: 8; size: 2; not used

			// offset: 10; size: 2; not used in BIFF5-BIFF8

			// offset: 12; size: 4; option flags and default row formatting

			// bit: 2-0: mask: 0x00000007; outline level of the row
			$level = (0x00000007 & self::_GetInt4d($recordData, 12)) >> 0;
			$this->_phpSheet->getRowDimension($r + 1)->setOutlineLevel($level);

			// bit: 4; mask: 0x00000010; 1 = outline group start or ends here... and is collapsed
			$isCollapsed = (0x00000010 & self::_GetInt4d($recordData, 12)) >> 4;
			$this->_phpSheet->getRowDimension($r + 1)->setCollapsed($isCollapsed);

			// bit: 5; mask: 0x00000020; 1 = row is hidden
			$isHidden = (0x00000020 & self::_GetInt4d($recordData, 12)) >> 5;
			$this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden);

			// bit: 7; mask: 0x00000080; 1 = row has explicit format
			$hasExplicitFormat = (0x00000080 & self::_GetInt4d($recordData, 12)) >> 7;

			// bit: 27-16; mask: 0x0FFF0000; only applies when hasExplicitFormat = 1; index to XF record
			$xfIndex = (0x0FFF0000 & self::_GetInt4d($recordData, 12)) >> 16;

			if ($hasExplicitFormat) {
				$this->_phpSheet->getRowDimension($r + 1)->setXfIndex($this->_mapCellXfIndex[$xfIndex]);
			}
		}
	}
389013
def store_valuerange   # :nodoc:
    record   = 0x101F         # Record identifier.
    length   = 0x002A         # Number of bytes to follow.
    numMin   = 0x00000000     # Minimum value on axis.
    numMax   = 0x00000000     # Maximum value on axis.
    numMajor = 0x00000000     # Value of major increment.
    numMinor = 0x00000000     # Value of minor increment.
    numCross = 0x00000000     # Value where category axis crosses.
    grbit    = 0x011F         # Format flags.

    # TODO. Reverse doubles when they are handled.

    header = [record, length].pack('vv')
    data  = [numMin].pack('d')
    data += [numMax].pack('d')
    data += [numMajor].pack('d')
    data += [numMinor].pack('d')
    data += [numCross].pack('d')
    data += [grbit].pack('v')

    append(header, data)
  end
928992
def parse_cell(self, cell, coords, cell_mode=CellMode.cooked):
    
    try:
      return int(cell)
    except ValueError:
      pass
    try:
      return float(cell)
    except ValueError:
      pass
    # TODO Check for dates?
    return cell
1001908
def _cast_number(value): # source: https://bitbucket.org/openpyxl/openpyxl/src/93604327bce7aac5e8270674579af76d390e09c0/openpyxl/cell/read_only.py?at=default&fileviewer=file-view-default
    ""
    m = FLOAT_REGEX.search(value)
    if m is not None:
        return float(value)
    return int(value)
1228318
private function _readExternSheet()
	{
		$length = self::_GetInt2d($this->_data, $this->_pos + 2);
		$recordData = substr($this->_data, $this->_pos + 4, $length);

		// move stream pointer to next record
		$this->_pos += 4 + $length;

		// external sheet references provided for named cells
		if ($this->_version == self::XLS_BIFF8) {
			// offset: 0; size: 2; number of following ref structures
			$nm = self::_GetInt2d($recordData, 0);
			for ($i = 0; $i < $nm; ++$i) {
				$this->_ref[] = array(
					// offset: 2 + 6 * $i; index to EXTERNALBOOK record
					'externalBookIndex' => self::_GetInt2d($recordData, 2 + 6 * $i),
					// offset: 4 + 6 * $i; index to first sheet in EXTERNALBOOK record
					'firstSheetIndex' => self::_GetInt2d($recordData, 4 + 6 * $i),
					// offset: 6 + 6 * $i; index to last sheet in EXTERNALBOOK record
					'lastSheetIndex' => self::_GetInt2d($recordData, 6 + 6 * $i),
				);
			}
		}
	}
1236874
private function _readFormula()
	{
		$length = self::_GetInt2d($this->_data, $this->_pos + 2);
		$recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length);

		// move stream pointer to next record
		$this->_pos += 4 + $length;

		// offset: 0; size: 2; row index
		$row = self::_GetInt2d($recordData, 0);

		// offset: 2; size: 2; col index
		$column = self::_GetInt2d($recordData, 2);
		$columnString = PHPExcel_Cell::stringFromColumnIndex($column);

		// offset: 20: size: variable; formula structure
		$formulaStructure = substr($recordData, 20);

		// offset: 14: size: 2; option flags, recalculate always, recalculate on open etc.
		$options = self::_GetInt2d($recordData, 14);

		// bit: 0; mask: 0x0001; 1 = recalculate always
		// bit: 1; mask: 0x0002; 1 = calculate on open
		// bit: 2; mask: 0x0008; 1 = part of a shared formula
		$isPartOfSharedFormula = (bool) (0x0008 & $options);

		// WARNING:
		// We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true
		// the formula data may be ordinary formula data, therefore we need to check
		// explicitly for the tExp token (0x01)
		$isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01;

		if ($isPartOfSharedFormula) {
			// part of shared formula which means there will be a formula with a tExp token and nothing else
			// get the base cell, grab tExp token
			$baseRow = self::_GetInt2d($formulaStructure, 3);
			$baseCol = self::_GetInt2d($formulaStructure, 5);
			$this->_baseCell = PHPExcel_Cell::stringFromColumnIndex($baseCol). ($baseRow + 1);
		}

		// Read cell?
		if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) {

			if ($isPartOfSharedFormula) {
				// formula is added to this cell after the sheet has been read
				$this->_sharedFormulaParts[$columnString . ($row + 1)] = $this->_baseCell;
			}

			// offset: 16: size: 4; not used

			// offset: 4; size: 2; XF index
			$xfIndex = self::_GetInt2d($recordData, 4);

			// offset: 6; size: 8; result of the formula
			if ( (ord($recordData{6}) == 0)
				&& (ord($recordData{12}) == 255)
				&& (ord($recordData{13}) == 255) ) {

				// String formula. Result follows in appended STRING record
				$dataType = PHPExcel_Cell_DataType::TYPE_STRING;

				// read possible SHAREDFMLA record
				$code = self::_GetInt2d($this->_data, $this->_pos);
				if ($code == self::XLS_Type_SHAREDFMLA) {
					$this->_readSharedFmla();
				}

				// read STRING record
				$value = $this->_readString();

			} elseif ((ord($recordData{6}) == 1)
				&& (ord($recordData{12}) == 255)
				&& (ord($recordData{13}) == 255)) {

				// Boolean formula. Result is in +2; 0=false, 1=true
				$dataType = PHPExcel_Cell_DataType::TYPE_BOOL;
				$value = (bool) ord($recordData{8});

			} elseif ((ord($recordData{6}) == 2)
				&& (ord($recordData{12}) == 255)
				&& (ord($recordData{13}) == 255)) {

				// Error formula. Error code is in +2
				$dataType = PHPExcel_Cell_DataType::TYPE_ERROR;
				$value = self::_mapErrorCode(ord($recordData{8}));

			} elseif ((ord($recordData{6}) == 3)
				&& (ord($recordData{12}) == 255)
				&& (ord($recordData{13}) == 255)) {

				// Formula result is a null string
				$dataType = PHPExcel_Cell_DataType::TYPE_NULL;
				$value = '';

			} else {

				// forumla result is a number, first 14 bytes like _NUMBER record
				$dataType = PHPExcel_Cell_DataType::TYPE_NUMERIC;
				$value = self::_extractNumber(substr($recordData, 6, 8));

			}

			$cell = $this->_phpSheet->getCell($columnString . ($row + 1));
			if (!$this->_readDataOnly) {
				// add cell style
				$cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]);
			}

			// store the formula
			if (!$isPartOfSharedFormula) {
				// not part of shared formula
				// add cell value. If we can read formula, populate with formula, otherwise just used cached value
				try {
					if ($this->_version != self::XLS_BIFF8) {
						throw new PHPExcel_Reader_Exception('Not BIFF8. Can only read BIFF8 formulas');
					}
					$formula = $this->_getFormulaFromStructure($formulaStructure); // get formula in human language
					$cell->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA);

				} catch (PHPExcel_Exception $e) {
					$cell->setValueExplicit($value, $dataType);
				}
			} else {
				if ($this->_version == self::XLS_BIFF8) {
					// do nothing at this point, formula id added later in the code
				} else {
					$cell->setValueExplicit($value, $dataType);
				}
			}

			// store the cached calculated value
			$cell->setCalculatedValue($value);
		}
	}