[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/phpexcel/PHPExcel/Writer/ -> HTML.php (source)

   1  <?php
   2  /**
   3   * PHPExcel
   4   *
   5   * Copyright (c) 2006 - 2014 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_HTML
  23   * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
  24   * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  25   * @version    ##VERSION##, ##DATE##
  26   */
  27  
  28  
  29  /**
  30   * PHPExcel_Writer_HTML
  31   *
  32   * @category   PHPExcel
  33   * @package    PHPExcel_Writer_HTML
  34   * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
  35   */
  36  class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter {
  37      /**
  38       * PHPExcel object
  39       *
  40       * @var PHPExcel
  41       */
  42      protected $_phpExcel;
  43  
  44      /**
  45       * Sheet index to write
  46       *
  47       * @var int
  48       */
  49      private $_sheetIndex    = 0;
  50  
  51      /**
  52       * Images root
  53       *
  54       * @var string
  55       */
  56      private $_imagesRoot    = '.';
  57  
  58      /**
  59       * embed images, or link to images
  60       *
  61       * @var boolean
  62       */
  63      private $_embedImages    = FALSE;
  64  
  65      /**
  66       * Use inline CSS?
  67       *
  68       * @var boolean
  69       */
  70      private $_useInlineCss = false;
  71  
  72      /**
  73       * Array of CSS styles
  74       *
  75       * @var array
  76       */
  77      private $_cssStyles = null;
  78  
  79      /**
  80       * Array of column widths in points
  81       *
  82       * @var array
  83       */
  84      private $_columnWidths = null;
  85  
  86      /**
  87       * Default font
  88       *
  89       * @var PHPExcel_Style_Font
  90       */
  91      private $_defaultFont;
  92  
  93      /**
  94       * Flag whether spans have been calculated
  95       *
  96       * @var boolean
  97       */
  98      private $_spansAreCalculated    = false;
  99  
 100      /**
 101       * Excel cells that should not be written as HTML cells
 102       *
 103       * @var array
 104       */
 105      private $_isSpannedCell    = array();
 106  
 107      /**
 108       * Excel cells that are upper-left corner in a cell merge
 109       *
 110       * @var array
 111       */
 112      private $_isBaseCell    = array();
 113  
 114      /**
 115       * Excel rows that should not be written as HTML rows
 116       *
 117       * @var array
 118       */
 119      private $_isSpannedRow    = array();
 120  
 121      /**
 122       * Is the current writer creating PDF?
 123       *
 124       * @var boolean
 125       */
 126      protected $_isPdf = false;
 127  
 128      /**
 129       * Generate the Navigation block
 130       *
 131       * @var boolean
 132       */
 133      private $_generateSheetNavigationBlock = true;
 134  
 135      /**
 136       * Create a new PHPExcel_Writer_HTML
 137       *
 138       * @param    PHPExcel    $phpExcel    PHPExcel object
 139       */
 140  	public function __construct(PHPExcel $phpExcel) {
 141          $this->_phpExcel = $phpExcel;
 142          $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont();
 143      }
 144  
 145      /**
 146       * Save PHPExcel to file
 147       *
 148       * @param    string        $pFilename
 149       * @throws    PHPExcel_Writer_Exception
 150       */
 151  	public function save($pFilename = null) {
 152          // garbage collect
 153          $this->_phpExcel->garbageCollect();
 154  
 155          $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog();
 156          PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE);
 157          $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType();
 158          PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE);
 159  
 160          // Build CSS
 161          $this->buildCSS(!$this->_useInlineCss);
 162  
 163          // Open file
 164          $fileHandle = fopen($pFilename, 'wb+');
 165          if ($fileHandle === false) {
 166              throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing.");
 167          }
 168  
 169          // Write headers
 170          fwrite($fileHandle, $this->generateHTMLHeader(!$this->_useInlineCss));
 171  
 172          // Write navigation (tabs)
 173          if ((!$this->_isPdf) && ($this->_generateSheetNavigationBlock)) {
 174              fwrite($fileHandle, $this->generateNavigation());
 175          }
 176  
 177          // Write data
 178          fwrite($fileHandle, $this->generateSheetData());
 179  
 180          // Write footer
 181          fwrite($fileHandle, $this->generateHTMLFooter());
 182  
 183          // Close file
 184          fclose($fileHandle);
 185  
 186          PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType);
 187          PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog);
 188      }
 189  
 190      /**
 191       * Map VAlign
 192       *
 193       * @param    string        $vAlign        Vertical alignment
 194       * @return string
 195       */
 196  	private function _mapVAlign($vAlign) {
 197          switch ($vAlign) {
 198              case PHPExcel_Style_Alignment::VERTICAL_BOTTOM:        return 'bottom';
 199              case PHPExcel_Style_Alignment::VERTICAL_TOP:        return 'top';
 200              case PHPExcel_Style_Alignment::VERTICAL_CENTER:
 201              case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY:    return 'middle';
 202              default: return 'baseline';
 203          }
 204      }
 205  
 206      /**
 207       * Map HAlign
 208       *
 209       * @param    string        $hAlign        Horizontal alignment
 210       * @return string|false
 211       */
 212  	private function _mapHAlign($hAlign) {
 213          switch ($hAlign) {
 214              case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL:                return false;
 215              case PHPExcel_Style_Alignment::HORIZONTAL_LEFT:                    return 'left';
 216              case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT:                return 'right';
 217              case PHPExcel_Style_Alignment::HORIZONTAL_CENTER:
 218              case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS:    return 'center';
 219              case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY:                return 'justify';
 220              default: return false;
 221          }
 222      }
 223  
 224      /**
 225       * Map border style
 226       *
 227       * @param    int        $borderStyle        Sheet index
 228       * @return    string
 229       */
 230  	private function _mapBorderStyle($borderStyle) {
 231          switch ($borderStyle) {
 232              case PHPExcel_Style_Border::BORDER_NONE:                return 'none';
 233              case PHPExcel_Style_Border::BORDER_DASHDOT:                return '1px dashed';
 234              case PHPExcel_Style_Border::BORDER_DASHDOTDOT:            return '1px dotted';
 235              case PHPExcel_Style_Border::BORDER_DASHED:                return '1px dashed';
 236              case PHPExcel_Style_Border::BORDER_DOTTED:                return '1px dotted';
 237              case PHPExcel_Style_Border::BORDER_DOUBLE:                return '3px double';
 238              case PHPExcel_Style_Border::BORDER_HAIR:                return '1px solid';
 239              case PHPExcel_Style_Border::BORDER_MEDIUM:                return '2px solid';
 240              case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT:        return '2px dashed';
 241              case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT:    return '2px dotted';
 242              case PHPExcel_Style_Border::BORDER_MEDIUMDASHED:        return '2px dashed';
 243              case PHPExcel_Style_Border::BORDER_SLANTDASHDOT:        return '2px dashed';
 244              case PHPExcel_Style_Border::BORDER_THICK:                return '3px solid';
 245              case PHPExcel_Style_Border::BORDER_THIN:                return '1px solid';
 246              default: return '1px solid'; // map others to thin
 247          }
 248      }
 249  
 250      /**
 251       * Get sheet index
 252       *
 253       * @return int
 254       */
 255  	public function getSheetIndex() {
 256          return $this->_sheetIndex;
 257      }
 258  
 259      /**
 260       * Set sheet index
 261       *
 262       * @param    int        $pValue        Sheet index
 263       * @return PHPExcel_Writer_HTML
 264       */
 265  	public function setSheetIndex($pValue = 0) {
 266          $this->_sheetIndex = $pValue;
 267          return $this;
 268      }
 269  
 270      /**
 271       * Get sheet index
 272       *
 273       * @return boolean
 274       */
 275  	public function getGenerateSheetNavigationBlock() {
 276          return $this->_generateSheetNavigationBlock;
 277      }
 278  
 279      /**
 280       * Set sheet index
 281       *
 282       * @param    boolean        $pValue        Flag indicating whether the sheet navigation block should be generated or not
 283       * @return PHPExcel_Writer_HTML
 284       */
 285  	public function setGenerateSheetNavigationBlock($pValue = true) {
 286          $this->_generateSheetNavigationBlock = (bool) $pValue;
 287          return $this;
 288      }
 289  
 290      /**
 291       * Write all sheets (resets sheetIndex to NULL)
 292       */
 293  	public function writeAllSheets() {
 294          $this->_sheetIndex = null;
 295          return $this;
 296      }
 297  
 298      /**
 299       * Generate HTML header
 300       *
 301       * @param    boolean        $pIncludeStyles        Include styles?
 302       * @return    string
 303       * @throws PHPExcel_Writer_Exception
 304       */
 305  	public function generateHTMLHeader($pIncludeStyles = false) {
 306          // PHPExcel object known?
 307          if (is_null($this->_phpExcel)) {
 308              throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
 309          }
 310  
 311          // Construct HTML
 312          $properties = $this->_phpExcel->getProperties();
 313          $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' . PHP_EOL;
 314          $html .= '<!-- Generated by PHPExcel - http://www.phpexcel.net -->' . PHP_EOL;
 315          $html .= '<html>' . PHP_EOL;
 316          $html .= '  <head>' . PHP_EOL;
 317          $html .= '      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . PHP_EOL;
 318          if ($properties->getTitle() > '')
 319              $html .= '      <title>' . htmlspecialchars($properties->getTitle()) . '</title>' . PHP_EOL;
 320  
 321          if ($properties->getCreator() > '')
 322              $html .= '      <meta name="author" content="' . htmlspecialchars($properties->getCreator()) . '" />' . PHP_EOL;
 323          if ($properties->getTitle() > '')
 324              $html .= '      <meta name="title" content="' . htmlspecialchars($properties->getTitle()) . '" />' . PHP_EOL;
 325          if ($properties->getDescription() > '')
 326              $html .= '      <meta name="description" content="' . htmlspecialchars($properties->getDescription()) . '" />' . PHP_EOL;
 327          if ($properties->getSubject() > '')
 328              $html .= '      <meta name="subject" content="' . htmlspecialchars($properties->getSubject()) . '" />' . PHP_EOL;
 329          if ($properties->getKeywords() > '')
 330              $html .= '      <meta name="keywords" content="' . htmlspecialchars($properties->getKeywords()) . '" />' . PHP_EOL;
 331          if ($properties->getCategory() > '')
 332              $html .= '      <meta name="category" content="' . htmlspecialchars($properties->getCategory()) . '" />' . PHP_EOL;
 333          if ($properties->getCompany() > '')
 334              $html .= '      <meta name="company" content="' . htmlspecialchars($properties->getCompany()) . '" />' . PHP_EOL;
 335          if ($properties->getManager() > '')
 336              $html .= '      <meta name="manager" content="' . htmlspecialchars($properties->getManager()) . '" />' . PHP_EOL;
 337  
 338          if ($pIncludeStyles) {
 339              $html .= $this->generateStyles(true);
 340          }
 341  
 342          $html .= '  </head>' . PHP_EOL;
 343          $html .= '' . PHP_EOL;
 344          $html .= '  <body>' . PHP_EOL;
 345  
 346          // Return
 347          return $html;
 348      }
 349  
 350      /**
 351       * Generate sheet data
 352       *
 353       * @return    string
 354       * @throws PHPExcel_Writer_Exception
 355       */
 356  	public function generateSheetData() {
 357          // PHPExcel object known?
 358          if (is_null($this->_phpExcel)) {
 359              throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
 360          }
 361  
 362          // Ensure that Spans have been calculated?
 363          if (!$this->_spansAreCalculated) {
 364              $this->_calculateSpans();
 365          }
 366  
 367          // Fetch sheets
 368          $sheets = array();
 369          if (is_null($this->_sheetIndex)) {
 370              $sheets = $this->_phpExcel->getAllSheets();
 371          } else {
 372              $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
 373          }
 374  
 375          // Construct HTML
 376          $html = '';
 377  
 378          // Loop all sheets
 379          $sheetId = 0;
 380          foreach ($sheets as $sheet) {
 381              // Write table header
 382              $html .= $this->_generateTableHeader($sheet);
 383  
 384              // Get worksheet dimension
 385              $dimension = explode(':', $sheet->calculateWorksheetDimension());
 386              $dimension[0] = PHPExcel_Cell::coordinateFromString($dimension[0]);
 387              $dimension[0][0] = PHPExcel_Cell::columnIndexFromString($dimension[0][0]) - 1;
 388              $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]);
 389              $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1;
 390  
 391              // row min,max
 392              $rowMin = $dimension[0][1];
 393              $rowMax = $dimension[1][1];
 394  
 395              // calculate start of <tbody>, <thead>
 396              $tbodyStart = $rowMin;
 397              $theadStart = $theadEnd   = 0; // default: no <thead>    no </thead>
 398              if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
 399                  $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop();
 400  
 401                  // we can only support repeating rows that start at top row
 402                  if ($rowsToRepeatAtTop[0] == 1) {
 403                      $theadStart = $rowsToRepeatAtTop[0];
 404                      $theadEnd   = $rowsToRepeatAtTop[1];
 405                      $tbodyStart = $rowsToRepeatAtTop[1] + 1;
 406                  }
 407              }
 408  
 409              // Loop through cells
 410              $row = $rowMin-1;
 411              while($row++ < $rowMax) {
 412                  // <thead> ?
 413                  if ($row == $theadStart) {
 414                      $html .= '        <thead>' . PHP_EOL;
 415                  }
 416  
 417                  // <tbody> ?
 418                  if ($row == $tbodyStart) {
 419                      $html .= '        <tbody>' . PHP_EOL;
 420                  }
 421  
 422                  // Write row if there are HTML table cells in it
 423                  if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) {
 424                      // Start a new rowData
 425                      $rowData = array();
 426                      // Loop through columns
 427                      $column = $dimension[0][0] - 1;
 428                      while($column++ < $dimension[1][0]) {
 429                          // Cell exists?
 430                          if ($sheet->cellExistsByColumnAndRow($column, $row)) {
 431                              $rowData[$column] = PHPExcel_Cell::stringFromColumnIndex($column) . $row;
 432                          } else {
 433                              $rowData[$column] = '';
 434                          }
 435                      }
 436                      $html .= $this->_generateRow($sheet, $rowData, $row - 1);
 437                  }
 438  
 439                  // </thead> ?
 440                  if ($row == $theadEnd) {
 441                      $html .= '        </thead>' . PHP_EOL;
 442                  }
 443              }
 444              $html .= $this->_extendRowsForChartsAndImages($sheet, $row);
 445  
 446              // Close table body.
 447              $html .= '        </tbody>' . PHP_EOL;
 448  
 449              // Write table footer
 450              $html .= $this->_generateTableFooter();
 451  
 452              // Writing PDF?
 453              if ($this->_isPdf) {
 454                  if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) {
 455                      $html .= '<div style="page-break-before:always" />';
 456                  }
 457              }
 458  
 459              // Next sheet
 460              ++$sheetId;
 461          }
 462  
 463          // Return
 464          return $html;
 465      }
 466  
 467      /**
 468       * Generate sheet tabs
 469       *
 470       * @return    string
 471       * @throws PHPExcel_Writer_Exception
 472       */
 473  	public function generateNavigation()
 474      {
 475          // PHPExcel object known?
 476          if (is_null($this->_phpExcel)) {
 477              throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
 478          }
 479  
 480          // Fetch sheets
 481          $sheets = array();
 482          if (is_null($this->_sheetIndex)) {
 483              $sheets = $this->_phpExcel->getAllSheets();
 484          } else {
 485              $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
 486          }
 487  
 488          // Construct HTML
 489          $html = '';
 490  
 491          // Only if there are more than 1 sheets
 492          if (count($sheets) > 1) {
 493              // Loop all sheets
 494              $sheetId = 0;
 495  
 496              $html .= '<ul class="navigation">' . PHP_EOL;
 497  
 498              foreach ($sheets as $sheet) {
 499                  $html .= '  <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL;
 500                  ++$sheetId;
 501              }
 502  
 503              $html .= '</ul>' . PHP_EOL;
 504          }
 505  
 506          return $html;
 507      }
 508  
 509  	private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) {
 510          $rowMax = $row;
 511          $colMax = 'A';
 512          if ($this->_includeCharts) {
 513              foreach ($pSheet->getChartCollection() as $chart) {
 514                  if ($chart instanceof PHPExcel_Chart) {
 515                      $chartCoordinates = $chart->getTopLeftPosition();
 516                      $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']);
 517                      $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]);
 518                      if ($chartTL[1] > $rowMax) {
 519                          $rowMax = $chartTL[1];
 520                          if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) {
 521                              $colMax = $chartTL[0];
 522                          }
 523                      }
 524                  }
 525              }
 526          }
 527  
 528          foreach ($pSheet->getDrawingCollection() as $drawing) {
 529              if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
 530                  $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates());
 531                  $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]);
 532                  if ($imageTL[1] > $rowMax) {
 533                      $rowMax = $imageTL[1];
 534                      if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) {
 535                          $colMax = $imageTL[0];
 536                      }
 537                  }
 538              }
 539          }
 540          $html = '';
 541          $colMax++;
 542          while ($row < $rowMax) {
 543              $html .= '<tr>';
 544              for ($col = 'A'; $col != $colMax; ++$col) {
 545                  $html .= '<td>';
 546                  $html .= $this->_writeImageInCell($pSheet, $col.$row);
 547                  if ($this->_includeCharts) {
 548                      $html .= $this->_writeChartInCell($pSheet, $col.$row);
 549                  }
 550                  $html .= '</td>';
 551              }
 552              ++$row;
 553              $html .= '</tr>';
 554          }
 555          return $html;
 556      }
 557  
 558  
 559      /**
 560       * Generate image tag in cell
 561       *
 562       * @param    PHPExcel_Worksheet    $pSheet            PHPExcel_Worksheet
 563       * @param    string                $coordinates    Cell coordinates
 564       * @return    string
 565       * @throws    PHPExcel_Writer_Exception
 566       */
 567  	private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) {
 568          // Construct HTML
 569          $html = '';
 570  
 571          // Write images
 572          foreach ($pSheet->getDrawingCollection() as $drawing) {
 573              if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
 574                  if ($drawing->getCoordinates() == $coordinates) {
 575                      $filename = $drawing->getPath();
 576  
 577                      // Strip off eventual '.'
 578                      if (substr($filename, 0, 1) == '.') {
 579                          $filename = substr($filename, 1);
 580                      }
 581  
 582                      // Prepend images root
 583                      $filename = $this->getImagesRoot() . $filename;
 584  
 585                      // Strip off eventual '.'
 586                      if (substr($filename, 0, 1) == '.' && substr($filename, 0, 2) != './') {
 587                          $filename = substr($filename, 1);
 588                      }
 589  
 590                      // Convert UTF8 data to PCDATA
 591                      $filename = htmlspecialchars($filename);
 592  
 593                      $html .= PHP_EOL;
 594                      if ((!$this->_embedImages) || ($this->_isPdf)) {
 595                          $imageData = $filename;
 596                      } else {
 597                          $imageDetails = getimagesize($filename);
 598                          if ($fp = fopen($filename,"rb", 0)) {
 599                              $picture = fread($fp,filesize($filename));
 600                              fclose($fp);
 601                              // base64 encode the binary data, then break it
 602                              // into chunks according to RFC 2045 semantics
 603                              $base64 = chunk_split(base64_encode($picture));
 604                              $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64;
 605                          } else {
 606                              $imageData = $filename;
 607                          }
 608                      }
 609  
 610                      $html .= '<div style="position: relative;">';
 611                      $html .= '<img style="position: absolute; z-index: 1; left: ' . 
 612                          $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' . 
 613                          $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' . 
 614                          $imageData . '" border="0" />';
 615                      $html .= '</div>';
 616                  }
 617              }
 618          }
 619  
 620          // Return
 621          return $html;
 622      }
 623  
 624      /**
 625       * Generate chart tag in cell
 626       *
 627       * @param    PHPExcel_Worksheet    $pSheet            PHPExcel_Worksheet
 628       * @param    string                $coordinates    Cell coordinates
 629       * @return    string
 630       * @throws    PHPExcel_Writer_Exception
 631       */
 632  	private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) {
 633          // Construct HTML
 634          $html = '';
 635  
 636          // Write charts
 637          foreach ($pSheet->getChartCollection() as $chart) {
 638              if ($chart instanceof PHPExcel_Chart) {
 639                  $chartCoordinates = $chart->getTopLeftPosition();
 640                  if ($chartCoordinates['cell'] == $coordinates) {
 641                      $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png';
 642                      if (!$chart->render($chartFileName)) {
 643                          return;
 644                      }
 645  
 646                      $html .= PHP_EOL;
 647                      $imageDetails = getimagesize($chartFileName);
 648                      if ($fp = fopen($chartFileName,"rb", 0)) {
 649                          $picture = fread($fp,filesize($chartFileName));
 650                          fclose($fp);
 651                          // base64 encode the binary data, then break it
 652                          // into chunks according to RFC 2045 semantics
 653                          $base64 = chunk_split(base64_encode($picture));
 654                          $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64;
 655  
 656                          $html .= '<div style="position: relative;">';
 657                          $html .= '<img style="position: absolute; z-index: 1; left: ' . $chartCoordinates['xOffset'] . 'px; top: ' . $chartCoordinates['yOffset'] . 'px; width: ' . $imageDetails[0] . 'px; height: ' . $imageDetails[1] . 'px;" src="' . $imageData . '" border="0" />' . PHP_EOL;
 658                          $html .= '</div>';
 659  
 660                          unlink($chartFileName);
 661                      }
 662                  }
 663              }
 664          }
 665  
 666          // Return
 667          return $html;
 668      }
 669  
 670      /**
 671       * Generate CSS styles
 672       *
 673       * @param    boolean    $generateSurroundingHTML    Generate surrounding HTML tags? (<style> and </style>)
 674       * @return    string
 675       * @throws    PHPExcel_Writer_Exception
 676       */
 677  	public function generateStyles($generateSurroundingHTML = true) {
 678          // PHPExcel object known?
 679          if (is_null($this->_phpExcel)) {
 680              throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
 681          }
 682  
 683          // Build CSS
 684          $css = $this->buildCSS($generateSurroundingHTML);
 685  
 686          // Construct HTML
 687          $html = '';
 688  
 689          // Start styles
 690          if ($generateSurroundingHTML) {
 691              $html .= '    <style type="text/css">' . PHP_EOL;
 692              $html .= '      html { ' . $this->_assembleCSS($css['html']) . ' }' . PHP_EOL;
 693          }
 694  
 695          // Write all other styles
 696          foreach ($css as $styleName => $styleDefinition) {
 697              if ($styleName != 'html') {
 698                  $html .= '      ' . $styleName . ' { ' . $this->_assembleCSS($styleDefinition) . ' }' . PHP_EOL;
 699              }
 700          }
 701  
 702          // End styles
 703          if ($generateSurroundingHTML) {
 704              $html .= '    </style>' . PHP_EOL;
 705          }
 706  
 707          // Return
 708          return $html;
 709      }
 710  
 711      /**
 712       * Build CSS styles
 713       *
 714       * @param    boolean    $generateSurroundingHTML    Generate surrounding HTML style? (html { })
 715       * @return    array
 716       * @throws    PHPExcel_Writer_Exception
 717       */
 718  	public function buildCSS($generateSurroundingHTML = true) {
 719          // PHPExcel object known?
 720          if (is_null($this->_phpExcel)) {
 721              throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
 722          }
 723  
 724          // Cached?
 725          if (!is_null($this->_cssStyles)) {
 726              return $this->_cssStyles;
 727          }
 728  
 729          // Ensure that spans have been calculated
 730          if (!$this->_spansAreCalculated) {
 731              $this->_calculateSpans();
 732          }
 733  
 734          // Construct CSS
 735          $css = array();
 736  
 737          // Start styles
 738          if ($generateSurroundingHTML) {
 739              // html { }
 740              $css['html']['font-family']      = 'Calibri, Arial, Helvetica, sans-serif';
 741              $css['html']['font-size']        = '11pt';
 742              $css['html']['background-color'] = 'white';
 743          }
 744  
 745  
 746          // table { }
 747          $css['table']['border-collapse']  = 'collapse';
 748          if (!$this->_isPdf) {
 749              $css['table']['page-break-after'] = 'always';
 750          }
 751  
 752          // .gridlines td { }
 753          $css['.gridlines td']['border'] = '1px dotted black';
 754  
 755          // .b {}
 756          $css['.b']['text-align'] = 'center'; // BOOL
 757  
 758          // .e {}
 759          $css['.e']['text-align'] = 'center'; // ERROR
 760  
 761          // .f {}
 762          $css['.f']['text-align'] = 'right'; // FORMULA
 763  
 764          // .inlineStr {}
 765          $css['.inlineStr']['text-align'] = 'left'; // INLINE
 766  
 767          // .n {}
 768          $css['.n']['text-align'] = 'right'; // NUMERIC
 769  
 770          // .s {}
 771          $css['.s']['text-align'] = 'left'; // STRING
 772  
 773          // Calculate cell style hashes
 774          foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) {
 775              $css['td.style' . $index] = $this->_createCSSStyle( $style );
 776          }
 777  
 778          // Fetch sheets
 779          $sheets = array();
 780          if (is_null($this->_sheetIndex)) {
 781              $sheets = $this->_phpExcel->getAllSheets();
 782          } else {
 783              $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
 784          }
 785  
 786          // Build styles per sheet
 787          foreach ($sheets as $sheet) {
 788              // Calculate hash code
 789              $sheetIndex = $sheet->getParent()->getIndex($sheet);
 790  
 791              // Build styles
 792              // Calculate column widths
 793              $sheet->calculateColumnWidths();
 794  
 795              // col elements, initialize
 796              $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1;
 797              $column = -1;
 798              while($column++ < $highestColumnIndex) {
 799                  $this->_columnWidths[$sheetIndex][$column] = 42; // approximation
 800                  $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt';
 801              }
 802  
 803              // col elements, loop through columnDimensions and set width
 804              foreach ($sheet->getColumnDimensions() as $columnDimension) {
 805                  if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) {
 806                      $width = PHPExcel_Shared_Drawing::pixelsToPoints($width);
 807                      $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1;
 808                      $this->_columnWidths[$sheetIndex][$column] = $width;
 809                      $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt';
 810  
 811                      if ($columnDimension->getVisible() === false) {
 812                          $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse';
 813                          $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7
 814                      }
 815                  }
 816              }
 817  
 818              // Default row height
 819              $rowDimension = $sheet->getDefaultRowDimension();
 820  
 821              // table.sheetN tr { }
 822              $css['table.sheet' . $sheetIndex . ' tr'] = array();
 823  
 824              if ($rowDimension->getRowHeight() == -1) {
 825                  $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont());
 826              } else {
 827                  $pt_height = $rowDimension->getRowHeight();
 828              }
 829              $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt';
 830              if ($rowDimension->getVisible() === false) {
 831                  $css['table.sheet' . $sheetIndex . ' tr']['display']    = 'none';
 832                  $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden';
 833              }
 834  
 835              // Calculate row heights
 836              foreach ($sheet->getRowDimensions() as $rowDimension) {
 837                  $row = $rowDimension->getRowIndex() - 1;
 838  
 839                  // table.sheetN tr.rowYYYYYY { }
 840                  $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array();
 841  
 842                  if ($rowDimension->getRowHeight() == -1) {
 843                      $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont());
 844                  } else {
 845                      $pt_height = $rowDimension->getRowHeight();
 846                  }
 847                  $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt';
 848                  if ($rowDimension->getVisible() === false) {
 849                      $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none';
 850                      $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden';
 851                  }
 852              }
 853          }
 854  
 855          // Cache
 856          if (is_null($this->_cssStyles)) {
 857              $this->_cssStyles = $css;
 858          }
 859  
 860          // Return
 861          return $css;
 862      }
 863  
 864      /**
 865       * Create CSS style
 866       *
 867       * @param    PHPExcel_Style        $pStyle            PHPExcel_Style
 868       * @return    array
 869       */
 870  	private function _createCSSStyle(PHPExcel_Style $pStyle) {
 871          // Construct CSS
 872          $css = '';
 873  
 874          // Create CSS
 875          $css = array_merge(
 876              $this->_createCSSStyleAlignment($pStyle->getAlignment())
 877              , $this->_createCSSStyleBorders($pStyle->getBorders())
 878              , $this->_createCSSStyleFont($pStyle->getFont())
 879              , $this->_createCSSStyleFill($pStyle->getFill())
 880          );
 881  
 882          // Return
 883          return $css;
 884      }
 885  
 886      /**
 887       * Create CSS style (PHPExcel_Style_Alignment)
 888       *
 889       * @param    PHPExcel_Style_Alignment        $pStyle            PHPExcel_Style_Alignment
 890       * @return    array
 891       */
 892  	private function _createCSSStyleAlignment(PHPExcel_Style_Alignment $pStyle) {
 893          // Construct CSS
 894          $css = array();
 895  
 896          // Create CSS
 897          $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical());
 898          if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) {
 899              $css['text-align'] = $textAlign;
 900              if(in_array($textAlign,array('left','right')))
 901                  $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px';
 902          }
 903  
 904          // Return
 905          return $css;
 906      }
 907  
 908      /**
 909       * Create CSS style (PHPExcel_Style_Font)
 910       *
 911       * @param    PHPExcel_Style_Font        $pStyle            PHPExcel_Style_Font
 912       * @return    array
 913       */
 914  	private function _createCSSStyleFont(PHPExcel_Style_Font $pStyle) {
 915          // Construct CSS
 916          $css = array();
 917  
 918          // Create CSS
 919          if ($pStyle->getBold()) {
 920              $css['font-weight'] = 'bold';
 921          }
 922          if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE && $pStyle->getStrikethrough()) {
 923              $css['text-decoration'] = 'underline line-through';
 924          } else if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE) {
 925              $css['text-decoration'] = 'underline';
 926          } else if ($pStyle->getStrikethrough()) {
 927              $css['text-decoration'] = 'line-through';
 928          }
 929          if ($pStyle->getItalic()) {
 930              $css['font-style'] = 'italic';
 931          }
 932  
 933          $css['color']        = '#' . $pStyle->getColor()->getRGB();
 934          $css['font-family']    = '\'' . $pStyle->getName() . '\'';
 935          $css['font-size']    = $pStyle->getSize() . 'pt';
 936  
 937          // Return
 938          return $css;
 939      }
 940  
 941      /**
 942       * Create CSS style (PHPExcel_Style_Borders)
 943       *
 944       * @param    PHPExcel_Style_Borders        $pStyle            PHPExcel_Style_Borders
 945       * @return    array
 946       */
 947  	private function _createCSSStyleBorders(PHPExcel_Style_Borders $pStyle) {
 948          // Construct CSS
 949          $css = array();
 950  
 951          // Create CSS
 952          $css['border-bottom']    = $this->_createCSSStyleBorder($pStyle->getBottom());
 953          $css['border-top']        = $this->_createCSSStyleBorder($pStyle->getTop());
 954          $css['border-left']        = $this->_createCSSStyleBorder($pStyle->getLeft());
 955          $css['border-right']    = $this->_createCSSStyleBorder($pStyle->getRight());
 956  
 957          // Return
 958          return $css;
 959      }
 960  
 961      /**
 962       * Create CSS style (PHPExcel_Style_Border)
 963       *
 964       * @param    PHPExcel_Style_Border        $pStyle            PHPExcel_Style_Border
 965       * @return    string
 966       */
 967  	private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) {
 968          // Create CSS
 969  //        $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB();
 970          //    Create CSS - add !important to non-none border styles for merged cells  
 971          $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle());  
 972          $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); 
 973  
 974          // Return
 975          return $css;
 976      }
 977  
 978      /**
 979       * Create CSS style (PHPExcel_Style_Fill)
 980       *
 981       * @param    PHPExcel_Style_Fill        $pStyle            PHPExcel_Style_Fill
 982       * @return    array
 983       */
 984  	private function _createCSSStyleFill(PHPExcel_Style_Fill $pStyle) {
 985          // Construct HTML
 986          $css = array();
 987  
 988          // Create CSS
 989          $value = $pStyle->getFillType() == PHPExcel_Style_Fill::FILL_NONE ?
 990              'white' : '#' . $pStyle->getStartColor()->getRGB();
 991          $css['background-color'] = $value;
 992  
 993          // Return
 994          return $css;
 995      }
 996  
 997      /**
 998       * Generate HTML footer
 999       */
1000  	public function generateHTMLFooter() {
1001          // Construct HTML
1002          $html = '';
1003          $html .= '  </body>' . PHP_EOL;
1004          $html .= '</html>' . PHP_EOL;
1005  
1006          // Return
1007          return $html;
1008      }
1009  
1010      /**
1011       * Generate table header
1012       *
1013       * @param    PHPExcel_Worksheet    $pSheet        The worksheet for the table we are writing
1014       * @return    string
1015       * @throws    PHPExcel_Writer_Exception
1016       */
1017  	private function _generateTableHeader($pSheet) {
1018          $sheetIndex = $pSheet->getParent()->getIndex($pSheet);
1019  
1020          // Construct HTML
1021          $html = '';
1022          $html .= $this->_setMargins($pSheet);
1023              
1024          if (!$this->_useInlineCss) {
1025              $gridlines = $pSheet->getShowGridlines() ? ' gridlines' : '';
1026              $html .= '    <table border="0" cellpadding="0" cellspacing="0" id="sheet' . $sheetIndex . '" class="sheet' . $sheetIndex . $gridlines . '">' . PHP_EOL;
1027          } else {
1028              $style = isset($this->_cssStyles['table']) ?
1029                  $this->_assembleCSS($this->_cssStyles['table']) : '';
1030  
1031              if ($this->_isPdf && $pSheet->getShowGridlines()) {
1032                  $html .= '    <table border="1" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="1" style="' . $style . '">' . PHP_EOL;
1033              } else {
1034                  $html .= '    <table border="0" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL;
1035              }
1036          }
1037  
1038          // Write <col> elements
1039          $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1;
1040          $i = -1;
1041          while($i++ < $highestColumnIndex) {
1042              if (!$this->_isPdf) {
1043                  if (!$this->_useInlineCss) {
1044                      $html .= '        <col class="col' . $i . '">' . PHP_EOL;
1045                  } else {
1046                      $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) ?
1047                          $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : '';
1048                      $html .= '        <col style="' . $style . '">' . PHP_EOL;
1049                  }
1050              }
1051          }
1052  
1053          // Return
1054          return $html;
1055      }
1056  
1057      /**
1058       * Generate table footer
1059       *
1060       * @throws    PHPExcel_Writer_Exception
1061       */
1062  	private function _generateTableFooter() {
1063          // Construct HTML
1064          $html = '';
1065          $html .= '    </table>' . PHP_EOL;
1066  
1067          // Return
1068          return $html;
1069      }
1070  
1071      /**
1072       * Generate row
1073       *
1074       * @param    PHPExcel_Worksheet    $pSheet            PHPExcel_Worksheet
1075       * @param    array                $pValues        Array containing cells in a row
1076       * @param    int                    $pRow            Row number (0-based)
1077       * @return    string
1078       * @throws    PHPExcel_Writer_Exception
1079       */
1080  	private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0) {
1081          if (is_array($pValues)) {
1082              // Construct HTML
1083              $html = '';
1084  
1085              // Sheet index
1086              $sheetIndex = $pSheet->getParent()->getIndex($pSheet);
1087  
1088              // DomPDF and breaks
1089              if ($this->_isPdf && count($pSheet->getBreaks()) > 0) {
1090                  $breaks = $pSheet->getBreaks();
1091  
1092                  // check if a break is needed before this row
1093                  if (isset($breaks['A' . $pRow])) {
1094                      // close table: </table>
1095                      $html .= $this->_generateTableFooter();
1096  
1097                      // insert page break
1098                      $html .= '<div style="page-break-before:always" />';
1099  
1100                      // open table again: <table> + <col> etc.
1101                      $html .= $this->_generateTableHeader($pSheet);
1102                  }
1103              }
1104  
1105              // Write row start
1106              if (!$this->_useInlineCss) {
1107                  $html .= '          <tr class="row' . $pRow . '">' . PHP_EOL;
1108              } else {
1109                  $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow])
1110                      ? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : '';
1111  
1112                  $html .= '          <tr style="' . $style . '">' . PHP_EOL;
1113              }
1114  
1115              // Write cells
1116              $colNum = 0;
1117              foreach ($pValues as $cellAddress) {
1118                  $cell = ($cellAddress > '') ? $pSheet->getCell($cellAddress) : '';
1119                  $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1);
1120                  if (!$this->_useInlineCss) {
1121                      $cssClass = '';
1122                      $cssClass = 'column' . $colNum;
1123                  } else {
1124                      $cssClass = array();
1125                      if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) {
1126                          $this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum];
1127                      }
1128                  }
1129                  $colSpan = 1;
1130                  $rowSpan = 1;
1131  
1132                  // initialize
1133                  $cellData = '&nbsp;';
1134  
1135                  // PHPExcel_Cell
1136                  if ($cell instanceof PHPExcel_Cell) {
1137                      $cellData = '';
1138                      if (is_null($cell->getParent())) {
1139                          $cell->attach($pSheet);
1140                      }
1141                      // Value
1142                      if ($cell->getValue() instanceof PHPExcel_RichText) {
1143                          // Loop through rich text elements
1144                          $elements = $cell->getValue()->getRichTextElements();
1145                          foreach ($elements as $element) {
1146                              // Rich text start?
1147                              if ($element instanceof PHPExcel_RichText_Run) {
1148                                  $cellData .= '<span style="' . $this->_assembleCSS($this->_createCSSStyleFont($element->getFont())) . '">';
1149  
1150                                  if ($element->getFont()->getSuperScript()) {
1151                                      $cellData .= '<sup>';
1152                                  } else if ($element->getFont()->getSubScript()) {
1153                                      $cellData .= '<sub>';
1154                                  }
1155                              }
1156  
1157                              // Convert UTF8 data to PCDATA
1158                              $cellText = $element->getText();
1159                              $cellData .= htmlspecialchars($cellText);
1160  
1161                              if ($element instanceof PHPExcel_RichText_Run) {
1162                                  if ($element->getFont()->getSuperScript()) {
1163                                      $cellData .= '</sup>';
1164                                  } else if ($element->getFont()->getSubScript()) {
1165                                      $cellData .= '</sub>';
1166                                  }
1167  
1168                                  $cellData .= '</span>';
1169                              }
1170                          }
1171                      } else {
1172                          if ($this->_preCalculateFormulas) {
1173                              $cellData = PHPExcel_Style_NumberFormat::toFormattedString(
1174                                  $cell->getCalculatedValue(),
1175                                  $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(),
1176                                  array($this, 'formatColor')
1177                              );
1178                          } else {
1179                              $cellData = PHPExcel_Style_NumberFormat::ToFormattedString(
1180                                  $cell->getValue(),
1181                                  $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(),
1182                                  array($this, 'formatColor')
1183                              );
1184                          }
1185                          $cellData = htmlspecialchars($cellData);
1186                          if ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) {
1187                              $cellData = '<sup>'.$cellData.'</sup>';
1188                          } elseif ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) {
1189                              $cellData = '<sub>'.$cellData.'</sub>';
1190                          }
1191                      }
1192  
1193                      // Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp;
1194                      // Example: "  Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world"
1195                      $cellData = preg_replace("/(?m)(?:^|\\G) /", '&nbsp;', $cellData);
1196  
1197                      // convert newline "\n" to '<br>'
1198                      $cellData = nl2br($cellData);
1199  
1200                      // Extend CSS class?
1201                      if (!$this->_useInlineCss) {
1202                          $cssClass .= ' style' . $cell->getXfIndex();
1203                          $cssClass .= ' ' . $cell->getDataType();
1204                      } else {
1205                          if (isset($this->_cssStyles['td.style' . $cell->getXfIndex()])) {
1206                              $cssClass = array_merge($cssClass, $this->_cssStyles['td.style' . $cell->getXfIndex()]);
1207                          }
1208  
1209                          // General horizontal alignment: Actual horizontal alignment depends on dataType
1210                          $sharedStyle = $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() );
1211                          if ($sharedStyle->getAlignment()->getHorizontal() == PHPExcel_Style_Alignment::HORIZONTAL_GENERAL
1212                              && isset($this->_cssStyles['.' . $cell->getDataType()]['text-align']))
1213                          {
1214                              $cssClass['text-align'] = $this->_cssStyles['.' . $cell->getDataType()]['text-align'];
1215                          }
1216                      }
1217                  }
1218  
1219                  // Hyperlink?
1220                  if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) {
1221                      $cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>';
1222                  }
1223  
1224                  // Should the cell be written or is it swallowed by a rowspan or colspan?
1225                  $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])
1226                              && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] );
1227  
1228                  // Colspan and Rowspan
1229                  $colspan = 1;
1230                  $rowspan = 1;
1231                  if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) {
1232                      $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum];
1233                      $rowSpan = $spans['rowspan'];
1234                      $colSpan = $spans['colspan'];
1235  
1236                      //    Also apply style from last cell in merge to fix borders -
1237                      //        relies on !important for non-none border declarations in _createCSSStyleBorder
1238                      $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan);
1239                      if (!$this->_useInlineCss) {
1240                          $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex();
1241                      }
1242                  }
1243  
1244                  // Write
1245                  if ($writeCell) {
1246                      // Column start
1247                      $html .= '            <td';
1248                          if (!$this->_useInlineCss) {
1249                              $html .= ' class="' . $cssClass . '"';
1250                          } else {
1251                              //** Necessary redundant code for the sake of PHPExcel_Writer_PDF **
1252                              // We must explicitly write the width of the <td> element because TCPDF
1253                              // does not recognize e.g. <col style="width:42pt">
1254                              $width = 0;
1255                              $i = $colNum - 1;
1256                              $e = $colNum + $colSpan - 1;
1257                              while($i++ < $e) {
1258                                  if (isset($this->_columnWidths[$sheetIndex][$i])) {
1259                                      $width += $this->_columnWidths[$sheetIndex][$i];
1260                                  }
1261                              }
1262                              $cssClass['width'] = $width . 'pt';
1263  
1264                              // We must also explicitly write the height of the <td> element because TCPDF
1265                              // does not recognize e.g. <tr style="height:50pt">
1266                              if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) {
1267                                  $height = $this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'];
1268                                  $cssClass['height'] = $height;
1269                              }
1270                              //** end of redundant code **
1271  
1272                              $html .= ' style="' . $this->_assembleCSS($cssClass) . '"';
1273                          }
1274                          if ($colSpan > 1) {
1275                              $html .= ' colspan="' . $colSpan . '"';
1276                          }
1277                          if ($rowSpan > 1) {
1278                              $html .= ' rowspan="' . $rowSpan . '"';
1279                          }
1280                      $html .= '>';
1281  
1282                      // Image?
1283                      $html .= $this->_writeImageInCell($pSheet, $coordinate);
1284  
1285                      // Chart?
1286                      if ($this->_includeCharts) {
1287                          $html .= $this->_writeChartInCell($pSheet, $coordinate);
1288                      }
1289  
1290                      // Cell data
1291                      $html .= $cellData;
1292  
1293                      // Column end
1294                      $html .= '</td>' . PHP_EOL;
1295                  }
1296  
1297                  // Next column
1298                  ++$colNum;
1299              }
1300  
1301              // Write row end
1302              $html .= '          </tr>' . PHP_EOL;
1303  
1304              // Return
1305              return $html;
1306          } else {
1307              throw new PHPExcel_Writer_Exception("Invalid parameters passed.");
1308          }
1309      }
1310  
1311      /**
1312       * Takes array where of CSS properties / values and converts to CSS string
1313       *
1314       * @param array
1315       * @return string
1316       */
1317  	private function _assembleCSS($pValue = array())
1318      {
1319          $pairs = array();
1320          foreach ($pValue as $property => $value) {
1321              $pairs[] = $property . ':' . $value;
1322          }
1323          $string = implode('; ', $pairs);
1324  
1325          return $string;
1326      }
1327  
1328      /**
1329       * Get images root
1330       *
1331       * @return string
1332       */
1333  	public function getImagesRoot() {
1334          return $this->_imagesRoot;
1335      }
1336  
1337      /**
1338       * Set images root
1339       *
1340       * @param string $pValue
1341       * @return PHPExcel_Writer_HTML
1342       */
1343  	public function setImagesRoot($pValue = '.') {
1344          $this->_imagesRoot = $pValue;
1345          return $this;
1346      }
1347  
1348      /**
1349       * Get embed images
1350       *
1351       * @return boolean
1352       */
1353  	public function getEmbedImages() {
1354          return $this->_embedImages;
1355      }
1356  
1357      /**
1358       * Set embed images
1359       *
1360       * @param boolean $pValue
1361       * @return PHPExcel_Writer_HTML
1362       */
1363  	public function setEmbedImages($pValue = '.') {
1364          $this->_embedImages = $pValue;
1365          return $this;
1366      }
1367  
1368      /**
1369       * Get use inline CSS?
1370       *
1371       * @return boolean
1372       */
1373  	public function getUseInlineCss() {
1374          return $this->_useInlineCss;
1375      }
1376  
1377      /**
1378       * Set use inline CSS?
1379       *
1380       * @param boolean $pValue
1381       * @return PHPExcel_Writer_HTML
1382       */
1383  	public function setUseInlineCss($pValue = false) {
1384          $this->_useInlineCss = $pValue;
1385          return $this;
1386      }
1387  
1388      /**
1389       * Add color to formatted string as inline style
1390       *
1391       * @param string $pValue Plain formatted value without color
1392       * @param string $pFormat Format code
1393       * @return string
1394       */
1395  	public function formatColor($pValue, $pFormat)
1396      {
1397          // Color information, e.g. [Red] is always at the beginning
1398          $color = null; // initialize
1399          $matches = array();
1400  
1401          $color_regex = '/^\\[[a-zA-Z]+\\]/';
1402          if (preg_match($color_regex, $pFormat, $matches)) {
1403              $color = str_replace('[', '', $matches[0]);
1404              $color = str_replace(']', '', $color);
1405              $color = strtolower($color);
1406          }
1407  
1408          // convert to PCDATA
1409          $value = htmlspecialchars($pValue);
1410  
1411          // color span tag
1412          if ($color !== null) {
1413              $value = '<span style="color:' . $color . '">' . $value . '</span>';
1414          }
1415  
1416          return $value;
1417      }
1418  
1419      /**
1420       * Calculate information about HTML colspan and rowspan which is not always the same as Excel's
1421       */
1422  	private function _calculateSpans()
1423      {
1424          // Identify all cells that should be omitted in HTML due to cell merge.
1425          // In HTML only the upper-left cell should be written and it should have
1426          //   appropriate rowspan / colspan attribute
1427          $sheetIndexes = $this->_sheetIndex !== null ?
1428              array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1);
1429  
1430          foreach ($sheetIndexes as $sheetIndex) {
1431              $sheet = $this->_phpExcel->getSheet($sheetIndex);
1432  
1433              $candidateSpannedRow  = array();
1434  
1435              // loop through all Excel merged cells
1436              foreach ($sheet->getMergeCells() as $cells) {
1437                  list($cells, ) = PHPExcel_Cell::splitRange($cells);
1438                  $first = $cells[0];
1439                  $last  = $cells[1];
1440  
1441                  list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first);
1442                  $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1;
1443  
1444                  list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last);
1445                  $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1;
1446  
1447                  // loop through the individual cells in the individual merge
1448                  $r = $fr - 1;
1449                  while($r++ < $lr) {
1450                      // also, flag this row as a HTML row that is candidate to be omitted
1451                      $candidateSpannedRow[$r] = $r;
1452  
1453                      $c = $fc - 1;
1454                      while($c++ < $lc) {
1455                          if ( !($c == $fc && $r == $fr) ) {
1456                              // not the upper-left cell (should not be written in HTML)
1457                              $this->_isSpannedCell[$sheetIndex][$r][$c] = array(
1458                                  'baseCell' => array($fr, $fc),
1459                              );
1460                          } else {
1461                              // upper-left is the base cell that should hold the colspan/rowspan attribute
1462                              $this->_isBaseCell[$sheetIndex][$r][$c] = array(
1463                                  'xlrowspan' => $lr - $fr + 1, // Excel rowspan
1464                                  'rowspan'   => $lr - $fr + 1, // HTML rowspan, value may change
1465                                  'xlcolspan' => $lc - $fc + 1, // Excel colspan
1466                                  'colspan'   => $lc - $fc + 1, // HTML colspan, value may change
1467                              );
1468                          }
1469                      }
1470                  }
1471              }
1472  
1473              // Identify which rows should be omitted in HTML. These are the rows where all the cells
1474              //   participate in a merge and the where base cells are somewhere above.
1475              $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn());
1476              foreach ($candidateSpannedRow as $rowIndex) {
1477                  if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) {
1478                      if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) {
1479                          $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex;
1480                      };
1481                  }
1482              }
1483  
1484              // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1
1485              if ( isset($this->_isSpannedRow[$sheetIndex]) ) {
1486                  foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) {
1487                      $adjustedBaseCells = array();
1488                      $c = -1;
1489                      $e = $countColumns - 1;
1490                      while($c++ < $e) {
1491                          $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell'];
1492  
1493                          if ( !in_array($baseCell, $adjustedBaseCells) ) {
1494                              // subtract rowspan by 1
1495                              --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan'];
1496                              $adjustedBaseCells[] = $baseCell;
1497                          }
1498                      }
1499                  }
1500              }
1501  
1502              // TODO: Same for columns
1503          }
1504  
1505          // We have calculated the spans
1506          $this->_spansAreCalculated = true;
1507      }
1508  
1509  	private function _setMargins(PHPExcel_Worksheet $pSheet) {
1510          $htmlPage = '@page { ';
1511          $htmlBody = 'body { ';
1512  
1513          $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; ';
1514          $htmlPage .= 'left-margin: ' . $left;
1515          $htmlBody .= 'left-margin: ' . $left;
1516          $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; ';
1517          $htmlPage .= 'right-margin: ' . $right;
1518          $htmlBody .= 'right-margin: ' . $right;
1519          $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; ';
1520          $htmlPage .= 'top-margin: ' . $top;
1521          $htmlBody .= 'top-margin: ' . $top;
1522          $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; ';
1523          $htmlPage .= 'bottom-margin: ' . $bottom;
1524          $htmlBody .= 'bottom-margin: ' . $bottom;
1525  
1526          $htmlPage .= "}\n";
1527          $htmlBody .= "}\n";
1528  
1529          return "<style>\n" . $htmlPage . $htmlBody . "</style>\n";
1530      }
1531      
1532  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1