You are here

private function PHPExcel_Writer_Excel5_Workbook::_writeSharedStringsTable in Loft Data Grids 7.2

Same name and namespace in other branches
  1. 6.2 vendor/phpoffice/phpexcel/Classes/PHPExcel/Writer/Excel5/Workbook.php \PHPExcel_Writer_Excel5_Workbook::_writeSharedStringsTable()

* Handling of the SST continue blocks is complicated by the need to include an * additional continuation byte depending on whether the string is split between * blocks or whether it starts at the beginning of the block. (There are also * additional complications that will arise later when/if Rich Strings are * supported). * * The Excel documentation says that the SST record should be followed by an * EXTSST record. The EXTSST record is a hash table that is used to optimise * access to SST. However, despite the documentation it doesn't seem to be * required so we will ignore it. * *

Return value

string Binary data

1 call to PHPExcel_Writer_Excel5_Workbook::_writeSharedStringsTable()
PHPExcel_Writer_Excel5_Workbook::writeWorkbook in vendor/phpoffice/phpexcel/Classes/PHPExcel/Writer/Excel5/Workbook.php
* Assemble worksheets into a workbook and send the BIFF data to an OLE * storage. * *

File

vendor/phpoffice/phpexcel/Classes/PHPExcel/Writer/Excel5/Workbook.php, line 1297

Class

PHPExcel_Writer_Excel5_Workbook
PHPExcel_Writer_Excel5_Workbook

Code

private function _writeSharedStringsTable() {

  // maximum size of record data (excluding record header)
  $continue_limit = 8224;

  // initialize array of record data blocks
  $recordDatas = array();

  // start SST record data block with total number of strings, total number of unique strings
  $recordData = pack("VV", $this->_str_total, $this->_str_unique);

  // loop through all (unique) strings in shared strings table
  foreach (array_keys($this->_str_table) as $string) {

    // here $string is a BIFF8 encoded string
    // length = character count
    $headerinfo = unpack("vlength/Cencoding", $string);

    // currently, this is always 1 = uncompressed
    $encoding = $headerinfo["encoding"];

    // initialize finished writing current $string
    $finished = false;
    while ($finished === false) {

      // normally, there will be only one cycle, but if string cannot immediately be written as is
      // there will be need for more than one cylcle, if string longer than one record data block, there
      // may be need for even more cycles
      if (strlen($recordData) + strlen($string) <= $continue_limit) {

        // then we can write the string (or remainder of string) without any problems
        $recordData .= $string;
        if (strlen($recordData) + strlen($string) == $continue_limit) {

          // we close the record data block, and initialize a new one
          $recordDatas[] = $recordData;
          $recordData = '';
        }

        // we are finished writing this string
        $finished = true;
      }
      else {

        // special treatment writing the string (or remainder of the string)
        // If the string is very long it may need to be written in more than one CONTINUE record.
        // check how many bytes more there is room for in the current record
        $space_remaining = $continue_limit - strlen($recordData);

        // minimum space needed
        // uncompressed: 2 byte string length length field + 1 byte option flags + 2 byte character
        // compressed:   2 byte string length length field + 1 byte option flags + 1 byte character
        $min_space_needed = $encoding == 1 ? 5 : 4;

        // We have two cases
        // 1. space remaining is less than minimum space needed
        //		here we must waste the space remaining and move to next record data block
        // 2. space remaining is greater than or equal to minimum space needed
        //		here we write as much as we can in the current block, then move to next record data block
        // 1. space remaining is less than minimum space needed
        if ($space_remaining < $min_space_needed) {

          // we close the block, store the block data
          $recordDatas[] = $recordData;

          // and start new record data block where we start writing the string
          $recordData = '';

          // 2. space remaining is greater than or equal to minimum space needed
        }
        else {

          // initialize effective remaining space, for Unicode strings this may need to be reduced by 1, see below
          $effective_space_remaining = $space_remaining;

          // for uncompressed strings, sometimes effective space remaining is reduced by 1
          if ($encoding == 1 && (strlen($string) - $space_remaining) % 2 == 1) {
            --$effective_space_remaining;
          }

          // one block fininshed, store the block data
          $recordData .= substr($string, 0, $effective_space_remaining);
          $string = substr($string, $effective_space_remaining);

          // for next cycle in while loop
          $recordDatas[] = $recordData;

          // start new record data block with the repeated option flags
          $recordData = pack('C', $encoding);
        }
      }
    }
  }

  // Store the last record data block unless it is empty
  // if there was no need for any continue records, this will be the for SST record data block itself
  if (strlen($recordData) > 0) {
    $recordDatas[] = $recordData;
  }

  // combine into one chunk with all the blocks SST, CONTINUE,...
  $chunk = '';
  foreach ($recordDatas as $i => $recordData) {

    // first block should have the SST record header, remaing should have CONTINUE header
    $record = $i == 0 ? 0xfc : 0x3c;
    $header = pack("vv", $record, strlen($recordData));
    $data = $header . $recordData;
    $chunk .= $this
      ->writeData($data);
  }
  return $chunk;
}