PHPExcel_Writer_Excel5
[ class tree: PHPExcel_Writer_Excel5 ] [ index: PHPExcel_Writer_Excel5 ] [ all elements ]

Source for file Excel5.php

Documentation is available at Excel5.php

  1. <?php
  2. /**
  3.  * PHPExcel
  4.  *
  5.  * Copyright (c) 2006 - 2011 PHPExcel
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  20.  *
  21.  * @category   PHPExcel
  22.  * @package    PHPExcel_Writer_Excel5
  23.  * @copyright  Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  24.  * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  25.  * @version    1.7.6, 2011-02-27
  26.  */
  27.  
  28.  
  29. /**
  30.  * PHPExcel_Writer_Excel5
  31.  *
  32.  * @category   PHPExcel
  33.  * @package    PHPExcel_Writer_Excel5
  34.  * @copyright  Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  35.  */
  36. class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
  37. {
  38.     /**
  39.      * Pre-calculate formulas
  40.      *
  41.      * @var boolean 
  42.      */
  43.     private $_preCalculateFormulas    = true;
  44.  
  45.     /**
  46.      * PHPExcel object
  47.      *
  48.      * @var PHPExcel 
  49.      */
  50.     private $_phpExcel;
  51.  
  52.     /**
  53.      * The BIFF version of the written Excel file, BIFF5 = 0x0500, BIFF8 = 0x0600
  54.      *
  55.      * @var integer 
  56.      */
  57.     private $_BIFF_version    = 0x0600;
  58.  
  59.     /**
  60.      * Total number of shared strings in workbook
  61.      *
  62.      * @var int 
  63.      */
  64.     private $_str_total        = 0;
  65.  
  66.     /**
  67.      * Number of unique shared strings in workbook
  68.      *
  69.      * @var int 
  70.      */
  71.     private $_str_unique    = 0;
  72.  
  73.     /**
  74.      * Array of unique shared strings in workbook
  75.      *
  76.      * @var array 
  77.      */
  78.     private $_str_table        = array();
  79.  
  80.     /**
  81.      * Color cache. Mapping between RGB value and color index.
  82.      *
  83.      * @var array 
  84.      */
  85.     private $_colors;
  86.  
  87.     /**
  88.      * Formula parser
  89.      *
  90.      * @var PHPExcel_Writer_Excel5_Parser 
  91.      */
  92.     private $_parser;
  93.  
  94.     /**
  95.      * Identifier clusters for drawings. Used in MSODRAWINGGROUP record.
  96.      *
  97.      * @var array 
  98.      */
  99.     private $_IDCLs;
  100.  
  101.  
  102.     /**
  103.      * Create a new PHPExcel_Writer_Excel5
  104.      *
  105.      * @param    PHPExcel    $phpExcel    PHPExcel object
  106.      */
  107.     public function __construct(PHPExcel $phpExcel) {
  108.         $this->_phpExcel        = $phpExcel;
  109.  
  110.         $this->_parser            = new PHPExcel_Writer_Excel5_Parser($this->_BIFF_version);
  111.     }
  112.  
  113.     /**
  114.      * Save PHPExcel to file
  115.      *
  116.      * @param    string        $pFileName 
  117.      * @throws    Exception
  118.      */
  119.     public function save($pFilename = null) {
  120.  
  121.         // garbage collect
  122.         $this->_phpExcel->garbageCollect();
  123.  
  124.         $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
  125.         PHPExcel_Calculation::getInstance()->writeDebugLog = false;
  126.         $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType();
  127.  
  128.         // initialize colors array
  129.         $this->_colors          = array();
  130.  
  131.         // Initialise workbook writer
  132.         $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, $this->_BIFF_version,
  133.                     $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser);
  134.  
  135.         // Initialise worksheet writers
  136.         $countSheets = $this->_phpExcel->getSheetCount();
  137.         for ($i = 0; $i < $countSheets; ++$i) {
  138.             $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_BIFF_version,
  139.                                        $this->_str_total, $this->_str_unique,
  140.                                        $this->_str_table, $this->_colors,
  141.                                        $this->_parser,
  142.                                        $this->_preCalculateFormulas,
  143.                                        $this->_phpExcel->getSheet($i));
  144.         }
  145.  
  146.         // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
  147.         $this->_buildWorksheetEschers();
  148.         $this->_buildWorkbookEscher();
  149.  
  150.         // add 15 identical cell style Xfs
  151.         // for now, we use the first cellXf instead of cellStyleXf
  152.         $cellXfCollection = $this->_phpExcel->getCellXfCollection();
  153.         for ($i = 0; $i < 15; ++$i) {
  154.             $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true);
  155.         }
  156.  
  157.         // add all the cell Xfs
  158.         foreach ($this->_phpExcel->getCellXfCollection() as $style) {
  159.             $this->_writerWorkbook->addXfWriter($style, false);
  160.         }
  161.  
  162.         // initialize OLE file
  163.         $workbookStreamName = ($this->_BIFF_version == 0x0600) ? 'Workbook' : 'Book';
  164.         $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName));
  165.  
  166.         // Write the worksheet streams before the global workbook stream,
  167.         // because the byte sizes of these are needed in the global workbook stream
  168.         $worksheetSizes = array();
  169.         for ($i = 0; $i < $countSheets; ++$i) {
  170.             $this->_writerWorksheets[$i]->close();
  171.             $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize;
  172.         }
  173.  
  174.         // add binary data for global workbook stream
  175.         $OLE->append( $this->_writerWorkbook->writeWorkbook($worksheetSizes) );
  176.  
  177.         // add binary data for sheet streams
  178.         for ($i = 0; $i < $countSheets; ++$i) {
  179.             $OLE->append($this->_writerWorksheets[$i]->getData());
  180.         }
  181.  
  182.         $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), array($OLE));
  183.         // save the OLE file
  184.         $res = $root->save($pFilename);
  185.  
  186.         PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType);
  187.         PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
  188.     }
  189.  
  190.     /**
  191.      * Set temporary storage directory
  192.      *
  193.      * @deprecated
  194.      * @param    string    $pValue        Temporary storage directory
  195.      * @throws    Exception    Exception when directory does not exist
  196.      * @return PHPExcel_Writer_Excel5 
  197.      */
  198.     public function setTempDir($pValue = '') {
  199.         return $this;
  200.     }
  201.  
  202.     /**
  203.      * Get Pre-Calculate Formulas
  204.      *
  205.      * @return boolean 
  206.      */
  207.     public function getPreCalculateFormulas() {
  208.         return $this->_preCalculateFormulas;
  209.     }
  210.  
  211.     /**
  212.      * Set Pre-Calculate Formulas
  213.      *
  214.      * @param boolean $pValue    Pre-Calculate Formulas?
  215.      */
  216.     public function setPreCalculateFormulas($pValue = true) {
  217.         $this->_preCalculateFormulas = $pValue;
  218.     }
  219.  
  220.     private function _buildWorksheetEschers()
  221.     {
  222.         // 1-based index to BstoreContainer
  223.         $blipIndex = 0;
  224.  
  225.         foreach ($this->_phpExcel->getAllsheets() as $sheet) {
  226.             // sheet index
  227.             $sheetIndex = $sheet->getParent()->getIndex($sheet);
  228.  
  229.             $escher = null;
  230.  
  231.             // check if there are any shapes for this sheet
  232.             if (count($sheet->getDrawingCollection()) == 0) {
  233.                 continue;
  234.             }
  235.  
  236.             // create intermediate Escher object
  237.             $escher = new PHPExcel_Shared_Escher();
  238.  
  239.             // dgContainer
  240.             $dgContainer = new PHPExcel_Shared_Escher_DgContainer();
  241.  
  242.             // set the drawing index (we use sheet index + 1)
  243.             $dgId = $sheet->getParent()->getIndex($sheet) + 1;
  244.             $dgContainer->setDgId($dgId);
  245.             $escher->setDgContainer($dgContainer);
  246.  
  247.             // spgrContainer
  248.             $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer();
  249.             $dgContainer->setSpgrContainer($spgrContainer);
  250.  
  251.             // add one shape which is the group shape
  252.             $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
  253.             $spContainer->setSpgr(true);
  254.             $spContainer->setSpType(0);
  255.             $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
  256.             $spgrContainer->addChild($spContainer);
  257.  
  258.             // add the shapes
  259.  
  260.             $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet
  261.  
  262.             foreach ($sheet->getDrawingCollection() as $drawing) {
  263.                 ++$blipIndex;
  264.  
  265.                 ++$countShapes[$sheetIndex];
  266.  
  267.                 // add the shape
  268.                 $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
  269.  
  270.                 // set the shape type
  271.                 $spContainer->setSpType(0x004B);
  272.  
  273.                 // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
  274.                 $reducedSpId = $countShapes[$sheetIndex];
  275.                 $spId = $reducedSpId
  276.                     | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
  277.                 $spContainer->setSpId($spId);
  278.  
  279.                 // keep track of last reducedSpId
  280.                 $lastReducedSpId = $reducedSpId;
  281.  
  282.                 // keep track of last spId
  283.                 $lastSpId = $spId;
  284.  
  285.                 // set the BLIP index
  286.                 $spContainer->setOPT(0x4104, $blipIndex);
  287.  
  288.                 // set coordinates and offsets, client anchor
  289.                 $coordinates = $drawing->getCoordinates();
  290.                 $offsetX = $drawing->getOffsetX();
  291.                 $offsetY = $drawing->getOffsetY();
  292.                 $width = $drawing->getWidth();
  293.                 $height = $drawing->getHeight();
  294.  
  295.                 $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
  296.  
  297.                 $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
  298.                 $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
  299.                 $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
  300.                 $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
  301.                 $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
  302.                 $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
  303.  
  304.                 $spgrContainer->addChild($spContainer);
  305.             }
  306.  
  307.             // identifier clusters, used for workbook Escher object
  308.             $this->_IDCLs[$dgId] = $lastReducedSpId;
  309.  
  310.             // set last shape index
  311.             $dgContainer->setLastSpId($lastSpId);
  312.  
  313.             // set the Escher object
  314.             $this->_writerWorksheets[$sheetIndex]->setEscher($escher);
  315.         }
  316.     }
  317.  
  318.     /**
  319.      * Build the Escher object corresponding to the MSODRAWINGGROUP record
  320.      */
  321.     private function _buildWorkbookEscher()
  322.     {
  323.         $escher = null;
  324.  
  325.         // any drawings in this workbook?
  326.         $found = false;
  327.         foreach ($this->_phpExcel->getAllSheets() as $sheet) {
  328.             if (count($sheet->getDrawingCollection()) > 0) {
  329.                 $found = true;
  330.             }
  331.         }
  332.  
  333.         // nothing to do if there are no drawings
  334.         if (!$found) {
  335.             return;
  336.         }
  337.  
  338.         // if we reach here, then there are drawings in the workbook
  339.         $escher = new PHPExcel_Shared_Escher();
  340.  
  341.         // dggContainer
  342.         $dggContainer = new PHPExcel_Shared_Escher_DggContainer();
  343.         $escher->setDggContainer($dggContainer);
  344.  
  345.         // set IDCLs (identifier clusters)
  346.         $dggContainer->setIDCLs($this->_IDCLs);
  347.  
  348.         // this loop is for determining maximum shape identifier of all drawing
  349.         $spIdMax = 0;
  350.         $totalCountShapes = 0;
  351.         $countDrawings = 0;
  352.  
  353.         foreach ($this->_phpExcel->getAllsheets() as $sheet) {
  354.             $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
  355.  
  356.             if (count($sheet->getDrawingCollection()) > 0) {
  357.                 ++$countDrawings;
  358.  
  359.                 foreach ($sheet->getDrawingCollection() as $drawing) {
  360.                     ++$sheetCountShapes;
  361.                     ++$totalCountShapes;
  362.  
  363.                     $spId = $sheetCountShapes
  364.                         | ($this->_phpExcel->getIndex($sheet) + 1) << 10;
  365.                     $spIdMax = max($spId, $spIdMax);
  366.                 }
  367.             }
  368.         }
  369.  
  370.         $dggContainer->setSpIdMax($spIdMax + 1);
  371.         $dggContainer->setCDgSaved($countDrawings);
  372.         $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
  373.  
  374.         // bstoreContainer
  375.         $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer();
  376.         $dggContainer->setBstoreContainer($bstoreContainer);
  377.  
  378.         // the BSE's (all the images)
  379.         foreach ($this->_phpExcel->getAllsheets() as $sheet) {
  380.             foreach ($sheet->getDrawingCollection() as $drawing) {
  381.                 if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
  382.  
  383.                     $filename = $drawing->getPath();
  384.  
  385.                     list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);
  386.  
  387.                     switch ($imageFormat) {
  388.  
  389.                     case 1: // GIF, not supported by BIFF8, we convert to PNG
  390.                         $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
  391.                         ob_start();
  392.                         imagepng(imagecreatefromgif($filename));
  393.                         $blipData = ob_get_contents();
  394.                         ob_end_clean();
  395.                         break;
  396.  
  397.                     case 2: // JPEG
  398.                         $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG;
  399.                         $blipData = file_get_contents($filename);
  400.                         break;
  401.  
  402.                     case 3: // PNG
  403.                         $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
  404.                         $blipData = file_get_contents($filename);
  405.                         break;
  406.  
  407.                     case 6: // Windows DIB (BMP), we convert to PNG
  408.                         $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
  409.                         ob_start();
  410.                         imagepng(PHPExcel_Shared_Drawing::imagecreatefrombmp($filename));
  411.                         $blipData = ob_get_contents();
  412.                         ob_end_clean();
  413.                         break;
  414.  
  415.                     default: continue 2;
  416.  
  417.                     }
  418.  
  419.                     $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip();
  420.                     $blip->setData($blipData);
  421.  
  422.                     $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE();
  423.                     $BSE->setBlipType($blipType);
  424.                     $BSE->setBlip($blip);
  425.  
  426.                     $bstoreContainer->addBSE($BSE);
  427.  
  428.                 } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {
  429.  
  430.                     switch ($drawing->getRenderingFunction()) {
  431.  
  432.                     case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG:
  433.                         $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG;
  434.                         $renderingFunction = 'imagejpeg';
  435.                         break;
  436.  
  437.                     case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF:
  438.                     case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG:
  439.                     case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT:
  440.                         $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG;
  441.                         $renderingFunction = 'imagepng';
  442.                         break;
  443.  
  444.                     }
  445.  
  446.                     ob_start();
  447.                     call_user_func($renderingFunction, $drawing->getImageResource());
  448.                     $blipData = ob_get_contents();
  449.                     ob_end_clean();
  450.  
  451.                     $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip();
  452.                     $blip->setData($blipData);
  453.  
  454.                     $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE();
  455.                     $BSE->setBlipType($blipType);
  456.                     $BSE->setBlip($blip);
  457.  
  458.                     $bstoreContainer->addBSE($BSE);
  459.                 }
  460.             }
  461.         }
  462.  
  463.         // Set the Escher object
  464.         $this->_writerWorkbook->setEscher($escher);
  465.     }
  466.  
  467. }

Documentation generated on Sun, 27 Feb 2011 16:31:13 -0800 by phpDocumentor 1.4.3