[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

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

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1