You are here

private function PHPExcel_Reader_Excel5::_readSst in Loft Data Grids 7.2

Same name and namespace in other branches
  1. 6.2 vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel5.php \PHPExcel_Reader_Excel5::_readSst()

* SST - Shared String Table * * This record contains a list of all strings used anywhere * in the workbook. Each string occurs only once. The * workbook uses indexes into the list to reference the * strings. * * -- "OpenOffice.org's Documentation of the Microsoft * Excel File Format" *

1 call to PHPExcel_Reader_Excel5::_readSst()
PHPExcel_Reader_Excel5::load in vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel5.php
* Loads PHPExcel from file * *

File

vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel5.php, line 2803

Class

PHPExcel_Reader_Excel5
PHPExcel_Reader_Excel5

Code

private function _readSst() {

  // offset within (spliced) record data
  $pos = 0;

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

  // offset: 0; size: 4; total number of strings in the workbook
  $pos += 4;

  // offset: 4; size: 4; number of following strings ($nm)
  $nm = self::_GetInt4d($recordData, 4);
  $pos += 4;

  // loop through the Unicode strings (16-bit length)
  for ($i = 0; $i < $nm; ++$i) {

    // number of characters in the Unicode string
    $numChars = self::_GetInt2d($recordData, $pos);
    $pos += 2;

    // option flags
    $optionFlags = ord($recordData[$pos]);
    ++$pos;

    // bit: 0; mask: 0x01; 0 = compressed; 1 = uncompressed
    $isCompressed = ($optionFlags & 0x1) == 0;

    // bit: 2; mask: 0x02; 0 = ordinary; 1 = Asian phonetic
    $hasAsian = ($optionFlags & 0x4) != 0;

    // bit: 3; mask: 0x03; 0 = ordinary; 1 = Rich-Text
    $hasRichText = ($optionFlags & 0x8) != 0;
    if ($hasRichText) {

      // number of Rich-Text formatting runs
      $formattingRuns = self::_GetInt2d($recordData, $pos);
      $pos += 2;
    }
    if ($hasAsian) {

      // size of Asian phonetic setting
      $extendedRunLength = self::_GetInt4d($recordData, $pos);
      $pos += 4;
    }

    // expected byte length of character array if not split
    $len = $isCompressed ? $numChars : $numChars * 2;

    // look up limit position
    foreach ($spliceOffsets as $spliceOffset) {

      // it can happen that the string is empty, therefore we need
      // <= and not just <
      if ($pos <= $spliceOffset) {
        $limitpos = $spliceOffset;
        break;
      }
    }
    if ($pos + $len <= $limitpos) {

      // character array is not split between records
      $retstr = substr($recordData, $pos, $len);
      $pos += $len;
    }
    else {

      // character array is split between records
      // first part of character array
      $retstr = substr($recordData, $pos, $limitpos - $pos);
      $bytesRead = $limitpos - $pos;

      // remaining characters in Unicode string
      $charsLeft = $numChars - ($isCompressed ? $bytesRead : $bytesRead / 2);
      $pos = $limitpos;

      // keep reading the characters
      while ($charsLeft > 0) {

        // look up next limit position, in case the string span more than one continue record
        foreach ($spliceOffsets as $spliceOffset) {
          if ($pos < $spliceOffset) {
            $limitpos = $spliceOffset;
            break;
          }
        }

        // repeated option flags
        // OpenOffice.org documentation 5.21
        $option = ord($recordData[$pos]);
        ++$pos;
        if ($isCompressed && $option == 0) {

          // 1st fragment compressed
          // this fragment compressed
          $len = min($charsLeft, $limitpos - $pos);
          $retstr .= substr($recordData, $pos, $len);
          $charsLeft -= $len;
          $isCompressed = true;
        }
        elseif (!$isCompressed && $option != 0) {

          // 1st fragment uncompressed
          // this fragment uncompressed
          $len = min($charsLeft * 2, $limitpos - $pos);
          $retstr .= substr($recordData, $pos, $len);
          $charsLeft -= $len / 2;
          $isCompressed = false;
        }
        elseif (!$isCompressed && $option == 0) {

          // 1st fragment uncompressed
          // this fragment compressed
          $len = min($charsLeft, $limitpos - $pos);
          for ($j = 0; $j < $len; ++$j) {
            $retstr .= $recordData[$pos + $j] . chr(0);
          }
          $charsLeft -= $len;
          $isCompressed = false;
        }
        else {

          // 1st fragment compressed
          // this fragment uncompressed
          $newstr = '';
          for ($j = 0; $j < strlen($retstr); ++$j) {
            $newstr .= $retstr[$j] . chr(0);
          }
          $retstr = $newstr;
          $len = min($charsLeft * 2, $limitpos - $pos);
          $retstr .= substr($recordData, $pos, $len);
          $charsLeft -= $len / 2;
          $isCompressed = false;
        }
        $pos += $len;
      }
    }

    // convert to UTF-8
    $retstr = self::_encodeUTF16($retstr, $isCompressed);

    // read additional Rich-Text information, if any
    $fmtRuns = array();
    if ($hasRichText) {

      // list of formatting runs
      for ($j = 0; $j < $formattingRuns; ++$j) {

        // first formatted character; zero-based
        $charPos = self::_GetInt2d($recordData, $pos + $j * 4);

        // index to font record
        $fontIndex = self::_GetInt2d($recordData, $pos + 2 + $j * 4);
        $fmtRuns[] = array(
          'charPos' => $charPos,
          'fontIndex' => $fontIndex,
        );
      }
      $pos += 4 * $formattingRuns;
    }

    // read additional Asian phonetics information, if any
    if ($hasAsian) {

      // For Asian phonetic settings, we skip the extended string data
      $pos += $extendedRunLength;
    }

    // store the shared sting
    $this->_sst[] = array(
      'value' => $retstr,
      'fmtRuns' => $fmtRuns,
    );
  }

  // _getSplicedRecordData() takes care of moving current position in data stream
}