You are here

Excel5.php in Loft Data Grids 7.2

File

vendor/phpoffice/phpexcel/Classes/PHPExcel/Writer/Excel5.php
View source
<?php

/**
 * PHPExcel
 *
 * Copyright (c) 2006 - 2014 PHPExcel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   PHPExcel
 * @package    PHPExcel_Writer_Excel5
 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
 * @license	http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
 * @version	##VERSION##, ##DATE##
 */

/**
 * PHPExcel_Writer_Excel5
 *
 * @category   PHPExcel
 * @package    PHPExcel_Writer_Excel5
 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
 */
class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter {

  /**
   * PHPExcel object
   *
   * @var PHPExcel
   */
  private $_phpExcel;

  /**
   * Total number of shared strings in workbook
   *
   * @var int
   */
  private $_str_total = 0;

  /**
   * Number of unique shared strings in workbook
   *
   * @var int
   */
  private $_str_unique = 0;

  /**
   * Array of unique shared strings in workbook
   *
   * @var array
   */
  private $_str_table = array();

  /**
   * Color cache. Mapping between RGB value and color index.
   *
   * @var array
   */
  private $_colors;

  /**
   * Formula parser
   *
   * @var PHPExcel_Writer_Excel5_Parser
   */
  private $_parser;

  /**
   * Identifier clusters for drawings. Used in MSODRAWINGGROUP record.
   *
   * @var array
   */
  private $_IDCLs;

  /**
   * Basic OLE object summary information
   *
   * @var array
   */
  private $_summaryInformation;

  /**
   * Extended OLE object document summary information
   *
   * @var array
   */
  private $_documentSummaryInformation;

  /**
   * Create a new PHPExcel_Writer_Excel5
   *
   * @param	PHPExcel	$phpExcel	PHPExcel object
   */
  public function __construct(PHPExcel $phpExcel) {
    $this->_phpExcel = $phpExcel;
    $this->_parser = new PHPExcel_Writer_Excel5_Parser();
  }

  /**
   * Save PHPExcel to file
   *
   * @param	string		$pFilename
   * @throws	PHPExcel_Writer_Exception
   */
  public function save($pFilename = null) {

    // garbage collect
    $this->_phpExcel
      ->garbageCollect();
    $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)
      ->getDebugLog()
      ->getWriteDebugLog();
    PHPExcel_Calculation::getInstance($this->_phpExcel)
      ->getDebugLog()
      ->setWriteDebugLog(FALSE);
    $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType();
    PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL);

    // initialize colors array
    $this->_colors = array();

    // Initialise workbook writer
    $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser);

    // Initialise worksheet writers
    $countSheets = $this->_phpExcel
      ->getSheetCount();
    for ($i = 0; $i < $countSheets; ++$i) {
      $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser, $this->_preCalculateFormulas, $this->_phpExcel
        ->getSheet($i));
    }

    // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
    $this
      ->_buildWorksheetEschers();
    $this
      ->_buildWorkbookEscher();

    // add 15 identical cell style Xfs
    // for now, we use the first cellXf instead of cellStyleXf
    $cellXfCollection = $this->_phpExcel
      ->getCellXfCollection();
    for ($i = 0; $i < 15; ++$i) {
      $this->_writerWorkbook
        ->addXfWriter($cellXfCollection[0], true);
    }

    // add all the cell Xfs
    foreach ($this->_phpExcel
      ->getCellXfCollection() as $style) {
      $this->_writerWorkbook
        ->addXfWriter($style, false);
    }

    // add fonts from rich text eleemnts
    for ($i = 0; $i < $countSheets; ++$i) {
      foreach ($this->_writerWorksheets[$i]->_phpSheet
        ->getCellCollection() as $cellID) {
        $cell = $this->_writerWorksheets[$i]->_phpSheet
          ->getCell($cellID);
        $cVal = $cell
          ->getValue();
        if ($cVal instanceof PHPExcel_RichText) {
          $elements = $cVal
            ->getRichTextElements();
          foreach ($elements as $element) {
            if ($element instanceof PHPExcel_RichText_Run) {
              $font = $element
                ->getFont();
              $this->_writerWorksheets[$i]->_fntHashIndex[$font
                ->getHashCode()] = $this->_writerWorkbook
                ->_addFont($font);
            }
          }
        }
      }
    }

    // initialize OLE file
    $workbookStreamName = 'Workbook';
    $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName));

    // Write the worksheet streams before the global workbook stream,
    // because the byte sizes of these are needed in the global workbook stream
    $worksheetSizes = array();
    for ($i = 0; $i < $countSheets; ++$i) {
      $this->_writerWorksheets[$i]
        ->close();
      $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize;
    }

    // add binary data for global workbook stream
    $OLE
      ->append($this->_writerWorkbook
      ->writeWorkbook($worksheetSizes));

    // add binary data for sheet streams
    for ($i = 0; $i < $countSheets; ++$i) {
      $OLE
        ->append($this->_writerWorksheets[$i]
        ->getData());
    }
    $this->_documentSummaryInformation = $this
      ->_writeDocumentSummaryInformation();

    // initialize OLE Document Summary Information
    if (isset($this->_documentSummaryInformation) && !empty($this->_documentSummaryInformation)) {
      $OLE_DocumentSummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'DocumentSummaryInformation'));
      $OLE_DocumentSummaryInformation
        ->append($this->_documentSummaryInformation);
    }
    $this->_summaryInformation = $this
      ->_writeSummaryInformation();

    // initialize OLE Summary Information
    if (isset($this->_summaryInformation) && !empty($this->_summaryInformation)) {
      $OLE_SummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'SummaryInformation'));
      $OLE_SummaryInformation
        ->append($this->_summaryInformation);
    }

    // define OLE Parts
    $arrRootData = array(
      $OLE,
    );

    // initialize OLE Properties file
    if (isset($OLE_SummaryInformation)) {
      $arrRootData[] = $OLE_SummaryInformation;
    }

    // initialize OLE Extended Properties file
    if (isset($OLE_DocumentSummaryInformation)) {
      $arrRootData[] = $OLE_DocumentSummaryInformation;
    }
    $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), $arrRootData);

    // save the OLE file
    $res = $root
      ->save($pFilename);
    PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType);
    PHPExcel_Calculation::getInstance($this->_phpExcel)
      ->getDebugLog()
      ->setWriteDebugLog($saveDebugLog);
  }

  /**
   * Set temporary storage directory
   *
   * @deprecated
   * @param	string	$pValue		Temporary storage directory
   * @throws	PHPExcel_Writer_Exception	when directory does not exist
   * @return PHPExcel_Writer_Excel5
   */
  public function setTempDir($pValue = '') {
    return $this;
  }

  /**
   * Build the Worksheet Escher objects
   *
   */
  private function _buildWorksheetEschers() {

    // 1-based index to BstoreContainer
    $blipIndex = 0;
    $lastReducedSpId = 0;
    $lastSpId = 0;
    foreach ($this->_phpExcel
      ->getAllsheets() as $sheet) {

      // sheet index
      $sheetIndex = $sheet
        ->getParent()
        ->getIndex($sheet);
      $escher = null;

      // check if there are any shapes for this sheet
      $filterRange = $sheet
        ->getAutoFilter()
        ->getRange();
      if (count($sheet
        ->getDrawingCollection()) == 0 && empty($filterRange)) {
        continue;
      }

      // create intermediate Escher object
      $escher = new PHPExcel_Shared_Escher();

      // dgContainer
      $dgContainer = new PHPExcel_Shared_Escher_DgContainer();

      // set the drawing index (we use sheet index + 1)
      $dgId = $sheet
        ->getParent()
        ->getIndex($sheet) + 1;
      $dgContainer
        ->setDgId($dgId);
      $escher
        ->setDgContainer($dgContainer);

      // spgrContainer
      $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer();
      $dgContainer
        ->setSpgrContainer($spgrContainer);

      // add one shape which is the group shape
      $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
      $spContainer
        ->setSpgr(true);
      $spContainer
        ->setSpType(0);
      $spContainer
        ->setSpId($sheet
        ->getParent()
        ->getIndex($sheet) + 1 << 10);
      $spgrContainer
        ->addChild($spContainer);

      // add the shapes
      $countShapes[$sheetIndex] = 0;

      // count number of shapes (minus group shape), in sheet
      foreach ($sheet
        ->getDrawingCollection() as $drawing) {
        ++$blipIndex;
        ++$countShapes[$sheetIndex];

        // add the shape
        $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();

        // set the shape type
        $spContainer
          ->setSpType(0x4b);

        // set the shape flag
        $spContainer
          ->setSpFlag(0x2);

        // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
        $reducedSpId = $countShapes[$sheetIndex];
        $spId = $reducedSpId | $sheet
          ->getParent()
          ->getIndex($sheet) + 1 << 10;
        $spContainer
          ->setSpId($spId);

        // keep track of last reducedSpId
        $lastReducedSpId = $reducedSpId;

        // keep track of last spId
        $lastSpId = $spId;

        // set the BLIP index
        $spContainer
          ->setOPT(0x4104, $blipIndex);

        // set coordinates and offsets, client anchor
        $coordinates = $drawing
          ->getCoordinates();
        $offsetX = $drawing
          ->getOffsetX();
        $offsetY = $drawing
          ->getOffsetY();
        $width = $drawing
          ->getWidth();
        $height = $drawing
          ->getHeight();
        $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
        $spContainer
          ->setStartCoordinates($twoAnchor['startCoordinates']);
        $spContainer
          ->setStartOffsetX($twoAnchor['startOffsetX']);
        $spContainer
          ->setStartOffsetY($twoAnchor['startOffsetY']);
        $spContainer
          ->setEndCoordinates($twoAnchor['endCoordinates']);
        $spContainer
          ->setEndOffsetX($twoAnchor['endOffsetX']);
        $spContainer
          ->setEndOffsetY($twoAnchor['endOffsetY']);
        $spgrContainer
          ->addChild($spContainer);
      }

      // AutoFilters
      if (!empty($filterRange)) {
        $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange);
        $iNumColStart = $rangeBounds[0][0];
        $iNumColEnd = $rangeBounds[1][0];
        $iInc = $iNumColStart;
        while ($iInc <= $iNumColEnd) {
          ++$countShapes[$sheetIndex];

          // create an Drawing Object for the dropdown
          $oDrawing = new PHPExcel_Worksheet_BaseDrawing();

          // get the coordinates of drawing
          $cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1];
          $oDrawing
            ->setCoordinates($cDrawing);
          $oDrawing
            ->setWorksheet($sheet);

          // add the shape
          $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();

          // set the shape type
          $spContainer
            ->setSpType(0xc9);

          // set the shape flag
          $spContainer
            ->setSpFlag(0x1);

          // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
          $reducedSpId = $countShapes[$sheetIndex];
          $spId = $reducedSpId | $sheet
            ->getParent()
            ->getIndex($sheet) + 1 << 10;
          $spContainer
            ->setSpId($spId);

          // keep track of last reducedSpId
          $lastReducedSpId = $reducedSpId;

          // keep track of last spId
          $lastSpId = $spId;
          $spContainer
            ->setOPT(0x7f, 0x1040104);

          // Protection -> fLockAgainstGrouping
          $spContainer
            ->setOPT(0xbf, 0x80008);

          // Text -> fFitTextToShape
          $spContainer
            ->setOPT(0x1bf, 0x10000);

          // Fill Style -> fNoFillHitTest
          $spContainer
            ->setOPT(0x1ff, 0x80000);

          // Line Style -> fNoLineDrawDash
          $spContainer
            ->setOPT(0x3bf, 0xa0000);

          // Group Shape -> fPrint
          // set coordinates and offsets, client anchor
          $endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1));
          $endCoordinates .= $rangeBounds[0][1] + 1;
          $spContainer
            ->setStartCoordinates($cDrawing);
          $spContainer
            ->setStartOffsetX(0);
          $spContainer
            ->setStartOffsetY(0);
          $spContainer
            ->setEndCoordinates($endCoordinates);
          $spContainer
            ->setEndOffsetX(0);
          $spContainer
            ->setEndOffsetY(0);
          $spgrContainer
            ->addChild($spContainer);
          $iInc++;
        }
      }

      // identifier clusters, used for workbook Escher object
      $this->_IDCLs[$dgId] = $lastReducedSpId;

      // set last shape index
      $dgContainer
        ->setLastSpId($lastSpId);

      // set the Escher object
      $this->_writerWorksheets[$sheetIndex]
        ->setEscher($escher);
    }
  }

  /**
   * Build the Escher object corresponding to the MSODRAWINGGROUP record
   */
  private function _buildWorkbookEscher() {
    $escher = null;

    // any drawings in this workbook?
    $found = false;
    foreach ($this->_phpExcel
      ->getAllSheets() as $sheet) {
      if (count($sheet
        ->getDrawingCollection()) > 0) {
        $found = true;
        break;
      }
    }

    // nothing to do if there are no drawings
    if (!$found) {
      return;
    }

    // if we reach here, then there are drawings in the workbook
    $escher = new PHPExcel_Shared_Escher();

    // dggContainer
    $dggContainer = new PHPExcel_Shared_Escher_DggContainer();
    $escher
      ->setDggContainer($dggContainer);

    // set IDCLs (identifier clusters)
    $dggContainer
      ->setIDCLs($this->_IDCLs);

    // this loop is for determining maximum shape identifier of all drawing
    $spIdMax = 0;
    $totalCountShapes = 0;
    $countDrawings = 0;
    foreach ($this->_phpExcel
      ->getAllsheets() as $sheet) {
      $sheetCountShapes = 0;

      // count number of shapes (minus group shape), in sheet
      if (count($sheet
        ->getDrawingCollection()) > 0) {
        ++$countDrawings;
        foreach ($sheet
          ->getDrawingCollection() as $drawing) {
          ++$sheetCountShapes;
          ++$totalCountShapes;
          $spId = $sheetCountShapes | $this->_phpExcel
            ->getIndex($sheet) + 1 << 10;
          $spIdMax = max($spId, $spIdMax);
        }
      }
    }
    $dggContainer
      ->setSpIdMax($spIdMax + 1);
    $dggContainer
      ->setCDgSaved($countDrawings);
    $dggContainer
      ->setCSpSaved($totalCountShapes + $countDrawings);

    // total number of shapes incl. one group shapes per drawing
    // bstoreContainer
    $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer();
    $dggContainer
      ->setBstoreContainer($bstoreContainer);

    // the BSE's (all the images)
    foreach ($this->_phpExcel
      ->getAllsheets() as $sheet) {
      foreach ($sheet
        ->getDrawingCollection() as $drawing) {
        if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
          $filename = $drawing
            ->getPath();
          list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);
          switch ($imageFormat) {
            case 1:

              // GIF, not supported by BIFF8, we convert to PNG
              $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
              ob_start();
              imagepng(imagecreatefromgif($filename));
              $blipData = ob_get_contents();
              ob_end_clean();
              break;
            case 2:

              // JPEG
              $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG;
              $blipData = file_get_contents($filename);
              break;
            case 3:

              // PNG
              $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
              $blipData = file_get_contents($filename);
              break;
            case 6:

              // Windows DIB (BMP), we convert to PNG
              $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
              ob_start();
              imagepng(PHPExcel_Shared_Drawing::imagecreatefrombmp($filename));
              $blipData = ob_get_contents();
              ob_end_clean();
              break;
            default:
              continue 2;
          }
          $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip();
          $blip
            ->setData($blipData);
          $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE();
          $BSE
            ->setBlipType($blipType);
          $BSE
            ->setBlip($blip);
          $bstoreContainer
            ->addBSE($BSE);
        }
        else {
          if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {
            switch ($drawing
              ->getRenderingFunction()) {
              case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG:
                $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG;
                $renderingFunction = 'imagejpeg';
                break;
              case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF:
              case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG:
              case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT:
                $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
                $renderingFunction = 'imagepng';
                break;
            }
            ob_start();
            call_user_func($renderingFunction, $drawing
              ->getImageResource());
            $blipData = ob_get_contents();
            ob_end_clean();
            $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip();
            $blip
              ->setData($blipData);
            $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE();
            $BSE
              ->setBlipType($blipType);
            $BSE
              ->setBlip($blip);
            $bstoreContainer
              ->addBSE($BSE);
          }
        }
      }
    }

    // Set the Escher object
    $this->_writerWorkbook
      ->setEscher($escher);
  }

  /**
   * Build the OLE Part for DocumentSummary Information
   * @return string
   */
  private function _writeDocumentSummaryInformation() {

    // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
    $data = pack('v', 0xfffe);

    // offset: 2; size: 2;
    $data .= pack('v', 0x0);

    // offset: 4; size: 2; OS version
    $data .= pack('v', 0x106);

    // offset: 6; size: 2; OS indicator
    $data .= pack('v', 0x2);

    // offset: 8; size: 16
    $data .= pack('VVVV', 0x0, 0x0, 0x0, 0x0);

    // offset: 24; size: 4; section count
    $data .= pack('V', 0x1);

    // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae
    $data .= pack('vvvvvvvv', 0xd502, 0xd5cd, 0x2e9c, 0x101b, 0x9793, 0x8, 0x2c2b, 0xaef9);

    // offset: 44; size: 4; offset of the start
    $data .= pack('V', 0x30);

    // SECTION
    $dataSection = array();
    $dataSection_NumProps = 0;
    $dataSection_Summary = '';
    $dataSection_Content = '';

    // GKPIDDSI_CODEPAGE: CodePage
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x1,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0x2,
      ),
      // 2 byte signed integer
      'data' => array(
        'data' => 1252,
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_CATEGORY : Category
    if ($this->_phpExcel
      ->getProperties()
      ->getCategory()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getCategory();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x2,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    // GKPIDDSI_VERSION :Version of the application that wrote the property storage
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x17,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0x3,
      ),
      'data' => array(
        'pack' => 'V',
        'data' => 0xc0000,
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_SCALE : FALSE
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0xb,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0xb,
      ),
      'data' => array(
        'data' => false,
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x10,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0xb,
      ),
      'data' => array(
        'data' => false,
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_SHAREDOC : FALSE
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x13,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0xb,
      ),
      'data' => array(
        'data' => false,
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x16,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0xb,
      ),
      'data' => array(
        'data' => false,
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_DOCSPARTS
    // MS-OSHARED p75 (2.3.3.2.2.1)
    // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9)
    // cElements
    $dataProp = pack('v', 0x1);
    $dataProp .= pack('v', 0x0);

    // array of UnalignedLpstr
    // cch
    $dataProp .= pack('v', 0xa);
    $dataProp .= pack('v', 0x0);

    // value
    $dataProp .= 'Worksheet' . chr(0);
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0xd,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0x101e,
      ),
      'data' => array(
        'data' => $dataProp,
        'length' => strlen($dataProp),
      ),
    );
    $dataSection_NumProps++;

    // GKPIDDSI_HEADINGPAIR
    // VtVecHeadingPairValue
    // cElements
    $dataProp = pack('v', 0x2);
    $dataProp .= pack('v', 0x0);

    // Array of vtHeadingPair
    // vtUnalignedString - headingString
    // stringType
    $dataProp .= pack('v', 0x1e);

    // padding
    $dataProp .= pack('v', 0x0);

    // UnalignedLpstr
    // cch
    $dataProp .= pack('v', 0x13);
    $dataProp .= pack('v', 0x0);

    // value
    $dataProp .= 'Feuilles de calcul';

    // vtUnalignedString - headingParts
    // wType : 0x0003 = 32 bit signed integer
    $dataProp .= pack('v', 0x300);

    // padding
    $dataProp .= pack('v', 0x0);

    // value
    $dataProp .= pack('v', 0x100);
    $dataProp .= pack('v', 0x0);
    $dataProp .= pack('v', 0x0);
    $dataProp .= pack('v', 0x0);
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0xc,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0x100c,
      ),
      'data' => array(
        'data' => $dataProp,
        'length' => strlen($dataProp),
      ),
    );
    $dataSection_NumProps++;

    // 		4 	Section Length
    //		4 	Property count
    //		8 * $dataSection_NumProps (8 =  ID (4) + OffSet(4))
    $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
    foreach ($dataSection as $dataProp) {

      // Summary
      $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);

      // Offset
      $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);

      // DataType
      $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);

      // Data
      if ($dataProp['type']['data'] == 0x2) {

        // 2 byte signed integer
        $dataSection_Content .= pack('V', $dataProp['data']['data']);
        $dataSection_Content_Offset += 4 + 4;
      }
      elseif ($dataProp['type']['data'] == 0x3) {

        // 4 byte signed integer
        $dataSection_Content .= pack('V', $dataProp['data']['data']);
        $dataSection_Content_Offset += 4 + 4;
      }
      elseif ($dataProp['type']['data'] == 0xb) {

        // Boolean
        if ($dataProp['data']['data'] == false) {
          $dataSection_Content .= pack('V', 0x0);
        }
        else {
          $dataSection_Content .= pack('V', 0x1);
        }
        $dataSection_Content_Offset += 4 + 4;
      }
      elseif ($dataProp['type']['data'] == 0x1e) {

        // null-terminated string prepended by dword string length
        // Null-terminated string
        $dataProp['data']['data'] .= chr(0);
        $dataProp['data']['length'] += 1;

        // Complete the string with null string for being a %4
        $dataProp['data']['length'] = $dataProp['data']['length'] + (4 - $dataProp['data']['length'] % 4 == 4 ? 0 : 4 - $dataProp['data']['length'] % 4);
        $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
        $dataSection_Content .= pack('V', $dataProp['data']['length']);
        $dataSection_Content .= $dataProp['data']['data'];
        $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
      }
      elseif ($dataProp['type']['data'] == 0x40) {

        // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
        $dataSection_Content .= $dataProp['data']['data'];
        $dataSection_Content_Offset += 4 + 8;
      }
      else {

        // Data Type Not Used at the moment
        $dataSection_Content .= $dataProp['data']['data'];
        $dataSection_Content_Offset += 4 + $dataProp['data']['length'];
      }
    }

    // Now $dataSection_Content_Offset contains the size of the content
    // section header
    // offset: $secOffset; size: 4; section length
    // 		+ x  Size of the content (summary + content)
    $data .= pack('V', $dataSection_Content_Offset);

    // offset: $secOffset+4; size: 4; property count
    $data .= pack('V', $dataSection_NumProps);

    // Section Summary
    $data .= $dataSection_Summary;

    // Section Content
    $data .= $dataSection_Content;
    return $data;
  }

  /**
   * Build the OLE Part for Summary Information
   * @return string
   */
  private function _writeSummaryInformation() {

    // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
    $data = pack('v', 0xfffe);

    // offset: 2; size: 2;
    $data .= pack('v', 0x0);

    // offset: 4; size: 2; OS version
    $data .= pack('v', 0x106);

    // offset: 6; size: 2; OS indicator
    $data .= pack('v', 0x2);

    // offset: 8; size: 16
    $data .= pack('VVVV', 0x0, 0x0, 0x0, 0x0);

    // offset: 24; size: 4; section count
    $data .= pack('V', 0x1);

    // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9
    $data .= pack('vvvvvvvv', 0x85e0, 0xf29f, 0x4ff9, 0x1068, 0x91ab, 0x8, 0x272b, 0xd9b3);

    // offset: 44; size: 4; offset of the start
    $data .= pack('V', 0x30);

    // SECTION
    $dataSection = array();
    $dataSection_NumProps = 0;
    $dataSection_Summary = '';
    $dataSection_Content = '';

    // CodePage : CP-1252
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x1,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0x2,
      ),
      // 2 byte signed integer
      'data' => array(
        'data' => 1252,
      ),
    );
    $dataSection_NumProps++;

    //	Title
    if ($this->_phpExcel
      ->getProperties()
      ->getTitle()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getTitle();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x2,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        // null-terminated string prepended by dword string length
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Subject
    if ($this->_phpExcel
      ->getProperties()
      ->getSubject()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getSubject();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x3,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        // null-terminated string prepended by dword string length
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Author (Creator)
    if ($this->_phpExcel
      ->getProperties()
      ->getCreator()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getCreator();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x4,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        // null-terminated string prepended by dword string length
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Keywords
    if ($this->_phpExcel
      ->getProperties()
      ->getKeywords()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getKeywords();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x5,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        // null-terminated string prepended by dword string length
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Comments (Description)
    if ($this->_phpExcel
      ->getProperties()
      ->getDescription()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getDescription();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x6,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        // null-terminated string prepended by dword string length
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Last Saved By (LastModifiedBy)
    if ($this->_phpExcel
      ->getProperties()
      ->getLastModifiedBy()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getLastModifiedBy();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0x8,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x1e,
        ),
        // null-terminated string prepended by dword string length
        'data' => array(
          'data' => $dataProp,
          'length' => strlen($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Created Date/Time
    if ($this->_phpExcel
      ->getProperties()
      ->getCreated()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getCreated();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0xc,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x40,
        ),
        // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
        'data' => array(
          'data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Modified Date/Time
    if ($this->_phpExcel
      ->getProperties()
      ->getModified()) {
      $dataProp = $this->_phpExcel
        ->getProperties()
        ->getModified();
      $dataSection[] = array(
        'summary' => array(
          'pack' => 'V',
          'data' => 0xd,
        ),
        'offset' => array(
          'pack' => 'V',
        ),
        'type' => array(
          'pack' => 'V',
          'data' => 0x40,
        ),
        // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
        'data' => array(
          'data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp),
        ),
      );
      $dataSection_NumProps++;
    }

    //	Security
    $dataSection[] = array(
      'summary' => array(
        'pack' => 'V',
        'data' => 0x13,
      ),
      'offset' => array(
        'pack' => 'V',
      ),
      'type' => array(
        'pack' => 'V',
        'data' => 0x3,
      ),
      // 4 byte signed integer
      'data' => array(
        'data' => 0x0,
      ),
    );
    $dataSection_NumProps++;

    // 		4 	Section Length
    //		4 	Property count
    //		8 * $dataSection_NumProps (8 =  ID (4) + OffSet(4))
    $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
    foreach ($dataSection as $dataProp) {

      // Summary
      $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);

      // Offset
      $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);

      // DataType
      $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);

      // Data
      if ($dataProp['type']['data'] == 0x2) {

        // 2 byte signed integer
        $dataSection_Content .= pack('V', $dataProp['data']['data']);
        $dataSection_Content_Offset += 4 + 4;
      }
      elseif ($dataProp['type']['data'] == 0x3) {

        // 4 byte signed integer
        $dataSection_Content .= pack('V', $dataProp['data']['data']);
        $dataSection_Content_Offset += 4 + 4;
      }
      elseif ($dataProp['type']['data'] == 0x1e) {

        // null-terminated string prepended by dword string length
        // Null-terminated string
        $dataProp['data']['data'] .= chr(0);
        $dataProp['data']['length'] += 1;

        // Complete the string with null string for being a %4
        $dataProp['data']['length'] = $dataProp['data']['length'] + (4 - $dataProp['data']['length'] % 4 == 4 ? 0 : 4 - $dataProp['data']['length'] % 4);
        $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
        $dataSection_Content .= pack('V', $dataProp['data']['length']);
        $dataSection_Content .= $dataProp['data']['data'];
        $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
      }
      elseif ($dataProp['type']['data'] == 0x40) {

        // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
        $dataSection_Content .= $dataProp['data']['data'];
        $dataSection_Content_Offset += 4 + 8;
      }
      else {

        // Data Type Not Used at the moment
      }
    }

    // Now $dataSection_Content_Offset contains the size of the content
    // section header
    // offset: $secOffset; size: 4; section length
    // 		+ x  Size of the content (summary + content)
    $data .= pack('V', $dataSection_Content_Offset);

    // offset: $secOffset+4; size: 4; property count
    $data .= pack('V', $dataSection_NumProps);

    // Section Summary
    $data .= $dataSection_Summary;

    // Section Content
    $data .= $dataSection_Content;
    return $data;
  }

}

Classes

Namesort descending Description
PHPExcel_Writer_Excel5 PHPExcel_Writer_Excel5