PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.0.3
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.0.3
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / phpoffice / phpexcel / Classes / PHPExcel / Writer / HTML.php

HTML.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.0.3, at vendor/phpoffice/phpexcel/Classes/PHPExcel/Writer/HTML.php

1,549 lines 45.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 $cellType = 'th';
416 }
417
418 // <tbody> ?
419 if ($row == $tbodyStart) {
420 $html .= ' <tbody>' . PHP_EOL;
421 $cellType = 'td';
422 }
423
424 // Write row if there are HTML table cells in it
425 if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) {
426 // Start a new rowData
427 $rowData = array();
428 // Loop through columns
429 $column = $dimension[0][0] - 1;
430 while($column++ < $dimension[1][0]) {
431 // Cell exists?
432 if ($sheet->cellExistsByColumnAndRow($column, $row)) {
433 $rowData[$column] = PHPExcel_Cell::stringFromColumnIndex($column) . $row;
434 } else {
435 $rowData[$column] = '';
436 }
437 }
438 $html .= $this->_generateRow($sheet, $rowData, $row - 1, $cellType);
439 }
440
441 // </thead> ?
442 if ($row == $theadEnd) {
443 $html .= ' </thead>' . PHP_EOL;
444 }
445 }
446 $html .= $this->_extendRowsForChartsAndImages($sheet, $row);
447
448 // Close table body.
449 $html .= ' </tbody>' . PHP_EOL;
450
451 // Write table footer
452 $html .= $this->_generateTableFooter();
453
454 // Writing PDF?
455 if ($this->_isPdf) {
456 if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) {
457 $html .= '<div style="page-break-before:always" />';
458 }
459 }
460
461 // Next sheet
462 ++$sheetId;
463 }
464
465 // Return
466 return $html;
467 }
468
469 /**
470 * Generate sheet tabs
471 *
472 * @return string
473 * @throws PHPExcel_Writer_Exception
474 */
475 public function generateNavigation()
476 {
477 // PHPExcel object known?
478 if (is_null($this->_phpExcel)) {
479 throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
480 }
481
482 // Fetch sheets
483 $sheets = array();
484 if (is_null($this->_sheetIndex)) {
485 $sheets = $this->_phpExcel->getAllSheets();
486 } else {
487 $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
488 }
489
490 // Construct HTML
491 $html = '';
492
493 // Only if there are more than 1 sheets
494 if (count($sheets) > 1) {
495 // Loop all sheets
496 $sheetId = 0;
497
498 $html .= '<ul class="navigation">' . PHP_EOL;
499
500 foreach ($sheets as $sheet) {
501 $html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL;
502 ++$sheetId;
503 }
504
505 $html .= '</ul>' . PHP_EOL;
506 }
507
508 return $html;
509 }
510
511 private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) {
512 $rowMax = $row;
513 $colMax = 'A';
514 if ($this->_includeCharts) {
515 foreach ($pSheet->getChartCollection() as $chart) {
516 if ($chart instanceof PHPExcel_Chart) {
517 $chartCoordinates = $chart->getTopLeftPosition();
518 $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']);
519 $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]);
520 if ($chartTL[1] > $rowMax) {
521 $rowMax = $chartTL[1];
522 if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) {
523 $colMax = $chartTL[0];
524 }
525 }
526 }
527 }
528 }
529
530 foreach ($pSheet->getDrawingCollection() as $drawing) {
531 if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
532 $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates());
533 $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]);
534 if ($imageTL[1] > $rowMax) {
535 $rowMax = $imageTL[1];
536 if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) {
537 $colMax = $imageTL[0];
538 }
539 }
540 }
541 }
542 $html = '';
543 $colMax++;
544 while ($row < $rowMax) {
545 $html .= '<tr>';
546 for ($col = 'A'; $col != $colMax; ++$col) {
547 $html .= '<td>';
548 $html .= $this->_writeImageInCell($pSheet, $col.$row);
549 if ($this->_includeCharts) {
550 $html .= $this->_writeChartInCell($pSheet, $col.$row);
551 }
552 $html .= '</td>';
553 }
554 ++$row;
555 $html .= '</tr>';
556 }
557 return $html;
558 }
559
560
561 /**
562 * Generate image tag in cell
563 *
564 * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet
565 * @param string $coordinates Cell coordinates
566 * @return string
567 * @throws PHPExcel_Writer_Exception
568 */
569 private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) {
570 // Construct HTML
571 $html = '';
572
573 // Write images
574 foreach ($pSheet->getDrawingCollection() as $drawing) {
575 if ($drawing instanceof PHPExcel_Worksheet_Drawing) {
576 if ($drawing->getCoordinates() == $coordinates) {
577 $filename = $drawing->getPath();
578
579 // Strip off eventual '.'
580 if (substr($filename, 0, 1) == '.') {
581 $filename = substr($filename, 1);
582 }
583
584 // Prepend images root
585 $filename = $this->getImagesRoot() . $filename;
586
587 // Strip off eventual '.'
588 if (substr($filename, 0, 1) == '.' && substr($filename, 0, 2) != './') {
589 $filename = substr($filename, 1);
590 }
591
592 // Convert UTF8 data to PCDATA
593 $filename = htmlspecialchars($filename);
594
595 $html .= PHP_EOL;
596 if ((!$this->_embedImages) || ($this->_isPdf)) {
597 $imageData = $filename;
598 } else {
599 $imageDetails = getimagesize($filename);
600 if ($fp = fopen($filename,"rb", 0)) {
601 $picture = fread($fp,filesize($filename));
602 fclose($fp);
603 // base64 encode the binary data, then break it
604 // into chunks according to RFC 2045 semantics
605 $base64 = chunk_split(base64_encode($picture));
606 $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64;
607 } else {
608 $imageData = $filename;
609 }
610 }
611
612 $html .= '<div style="position: relative;">';
613 $html .= '<img style="position: absolute; z-index: 1; left: ' .
614 $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' .
615 $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' .
616 $imageData . '" border="0" />';
617 $html .= '</div>';
618 }
619 }
620 }
621
622 // Return
623 return $html;
624 }
625
626 /**
627 * Generate chart tag in cell
628 *
629 * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet
630 * @param string $coordinates Cell coordinates
631 * @return string
632 * @throws PHPExcel_Writer_Exception
633 */
634 private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) {
635 // Construct HTML
636 $html = '';
637
638 // Write charts
639 foreach ($pSheet->getChartCollection() as $chart) {
640 if ($chart instanceof PHPExcel_Chart) {
641 $chartCoordinates = $chart->getTopLeftPosition();
642 if ($chartCoordinates['cell'] == $coordinates) {
643 $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png';
644 if (!$chart->render($chartFileName)) {
645 return;
646 }
647
648 $html .= PHP_EOL;
649 $imageDetails = getimagesize($chartFileName);
650 if ($fp = fopen($chartFileName,"rb", 0)) {
651 $picture = fread($fp,filesize($chartFileName));
652 fclose($fp);
653 // base64 encode the binary data, then break it
654 // into chunks according to RFC 2045 semantics
655 $base64 = chunk_split(base64_encode($picture));
656 $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64;
657
658 $html .= '<div style="position: relative;">';
659 $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;
660 $html .= '</div>';
661
662 unlink($chartFileName);
663 }
664 }
665 }
666 }
667
668 // Return
669 return $html;
670 }
671
672 /**
673 * Generate CSS styles
674 *
675 * @param boolean $generateSurroundingHTML Generate surrounding HTML tags? (&lt;style&gt; and &lt;/style&gt;)
676 * @return string
677 * @throws PHPExcel_Writer_Exception
678 */
679 public function generateStyles($generateSurroundingHTML = true) {
680 // PHPExcel object known?
681 if (is_null($this->_phpExcel)) {
682 throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.');
683 }
684
685 // Build CSS
686 $css = $this->buildCSS($generateSurroundingHTML);
687
688 // Construct HTML
689 $html = '';
690
691 // Start styles
692 if ($generateSurroundingHTML) {
693 $html .= ' <style type="text/css">' . PHP_EOL;
694 $html .= ' html { ' . $this->_assembleCSS($css['html']) . ' }' . PHP_EOL;
695 }
696
697 // Write all other styles
698 foreach ($css as $styleName => $styleDefinition) {
699 if ($styleName != 'html') {
700 $html .= ' ' . $styleName . ' { ' . $this->_assembleCSS($styleDefinition) . ' }' . PHP_EOL;
701 }
702 }
703
704 // End styles
705 if ($generateSurroundingHTML) {
706 $html .= ' </style>' . PHP_EOL;
707 }
708
709 // Return
710 return $html;
711 }
712
713 /**
714 * Build CSS styles
715 *
716 * @param boolean $generateSurroundingHTML Generate surrounding HTML style? (html { })
717 * @return array
718 * @throws PHPExcel_Writer_Exception
719 */
720 public function buildCSS($generateSurroundingHTML = true) {
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 // Cached?
727 if (!is_null($this->_cssStyles)) {
728 return $this->_cssStyles;
729 }
730
731 // Ensure that spans have been calculated
732 if (!$this->_spansAreCalculated) {
733 $this->_calculateSpans();
734 }
735
736 // Construct CSS
737 $css = array();
738
739 // Start styles
740 if ($generateSurroundingHTML) {
741 // html { }
742 $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif';
743 $css['html']['font-size'] = '11pt';
744 $css['html']['background-color'] = 'white';
745 }
746
747
748 // table { }
749 $css['table']['border-collapse'] = 'collapse';
750 if (!$this->_isPdf) {
751 $css['table']['page-break-after'] = 'always';
752 }
753
754 // .gridlines td { }
755 $css['.gridlines td']['border'] = '1px dotted black';
756 $css['.gridlines th']['border'] = '1px dotted black';
757
758 // .b {}
759 $css['.b']['text-align'] = 'center'; // BOOL
760
761 // .e {}
762 $css['.e']['text-align'] = 'center'; // ERROR
763
764 // .f {}
765 $css['.f']['text-align'] = 'right'; // FORMULA
766
767 // .inlineStr {}
768 $css['.inlineStr']['text-align'] = 'left'; // INLINE
769
770 // .n {}
771 $css['.n']['text-align'] = 'right'; // NUMERIC
772
773 // .s {}
774 $css['.s']['text-align'] = 'left'; // STRING
775
776 // Calculate cell style hashes
777 foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) {
778 $css['td.style' . $index] = $this->_createCSSStyle( $style );
779 $css['th.style' . $index] = $this->_createCSSStyle( $style );
780 }
781
782 // Fetch sheets
783 $sheets = array();
784 if (is_null($this->_sheetIndex)) {
785 $sheets = $this->_phpExcel->getAllSheets();
786 } else {
787 $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex);
788 }
789
790 // Build styles per sheet
791 foreach ($sheets as $sheet) {
792 // Calculate hash code
793 $sheetIndex = $sheet->getParent()->getIndex($sheet);
794
795 // Build styles
796 // Calculate column widths
797 $sheet->calculateColumnWidths();
798
799 // col elements, initialize
800 $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1;
801 $column = -1;
802 while($column++ < $highestColumnIndex) {
803 $this->_columnWidths[$sheetIndex][$column] = 42; // approximation
804 $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt';
805 }
806
807 // col elements, loop through columnDimensions and set width
808 foreach ($sheet->getColumnDimensions() as $columnDimension) {
809 if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) {
810 $width = PHPExcel_Shared_Drawing::pixelsToPoints($width);
811 $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1;
812 $this->_columnWidths[$sheetIndex][$column] = $width;
813 $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt';
814
815 if ($columnDimension->getVisible() === false) {
816 $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse';
817 $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7
818 }
819 }
820 }
821
822 // Default row height
823 $rowDimension = $sheet->getDefaultRowDimension();
824
825 // table.sheetN tr { }
826 $css['table.sheet' . $sheetIndex . ' tr'] = array();
827
828 if ($rowDimension->getRowHeight() == -1) {
829 $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont());
830 } else {
831 $pt_height = $rowDimension->getRowHeight();
832 }
833 $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt';
834 if ($rowDimension->getVisible() === false) {
835 $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none';
836 $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden';
837 }
838
839 // Calculate row heights
840 foreach ($sheet->getRowDimensions() as $rowDimension) {
841 $row = $rowDimension->getRowIndex() - 1;
842
843 // table.sheetN tr.rowYYYYYY { }
844 $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array();
845
846 if ($rowDimension->getRowHeight() == -1) {
847 $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont());
848 } else {
849 $pt_height = $rowDimension->getRowHeight();
850 }
851 $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt';
852 if ($rowDimension->getVisible() === false) {
853 $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none';
854 $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden';
855 }
856 }
857 }
858
859 // Cache
860 if (is_null($this->_cssStyles)) {
861 $this->_cssStyles = $css;
862 }
863
864 // Return
865 return $css;
866 }
867
868 /**
869 * Create CSS style
870 *
871 * @param PHPExcel_Style $pStyle PHPExcel_Style
872 * @return array
873 */
874 private function _createCSSStyle(PHPExcel_Style $pStyle) {
875 // Construct CSS
876 $css = '';
877
878 // Create CSS
879 $css = array_merge(
880 $this->_createCSSStyleAlignment($pStyle->getAlignment())
881 , $this->_createCSSStyleBorders($pStyle->getBorders())
882 , $this->_createCSSStyleFont($pStyle->getFont())
883 , $this->_createCSSStyleFill($pStyle->getFill())
884 );
885
886 // Return
887 return $css;
888 }
889
890 /**
891 * Create CSS style (PHPExcel_Style_Alignment)
892 *
893 * @param PHPExcel_Style_Alignment $pStyle PHPExcel_Style_Alignment
894 * @return array
895 */
896 private function _createCSSStyleAlignment(PHPExcel_Style_Alignment $pStyle) {
897 // Construct CSS
898 $css = array();
899
900 // Create CSS
901 $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical());
902 if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) {
903 $css['text-align'] = $textAlign;
904 if(in_array($textAlign,array('left','right')))
905 $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px';
906 }
907
908 // Return
909 return $css;
910 }
911
912 /**
913 * Create CSS style (PHPExcel_Style_Font)
914 *
915 * @param PHPExcel_Style_Font $pStyle PHPExcel_Style_Font
916 * @return array
917 */
918 private function _createCSSStyleFont(PHPExcel_Style_Font $pStyle) {
919 // Construct CSS
920 $css = array();
921
922 // Create CSS
923 if ($pStyle->getBold()) {
924 $css['font-weight'] = 'bold';
925 }
926 if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE && $pStyle->getStrikethrough()) {
927 $css['text-decoration'] = 'underline line-through';
928 } else if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE) {
929 $css['text-decoration'] = 'underline';
930 } else if ($pStyle->getStrikethrough()) {
931 $css['text-decoration'] = 'line-through';
932 }
933 if ($pStyle->getItalic()) {
934 $css['font-style'] = 'italic';
935 }
936
937 $css['color'] = '#' . $pStyle->getColor()->getRGB();
938 $css['font-family'] = '\'' . $pStyle->getName() . '\'';
939 $css['font-size'] = $pStyle->getSize() . 'pt';
940
941 // Return
942 return $css;
943 }
944
945 /**
946 * Create CSS style (PHPExcel_Style_Borders)
947 *
948 * @param PHPExcel_Style_Borders $pStyle PHPExcel_Style_Borders
949 * @return array
950 */
951 private function _createCSSStyleBorders(PHPExcel_Style_Borders $pStyle) {
952 // Construct CSS
953 $css = array();
954
955 // Create CSS
956 $css['border-bottom'] = $this->_createCSSStyleBorder($pStyle->getBottom());
957 $css['border-top'] = $this->_createCSSStyleBorder($pStyle->getTop());
958 $css['border-left'] = $this->_createCSSStyleBorder($pStyle->getLeft());
959 $css['border-right'] = $this->_createCSSStyleBorder($pStyle->getRight());
960
961 // Return
962 return $css;
963 }
964
965 /**
966 * Create CSS style (PHPExcel_Style_Border)
967 *
968 * @param PHPExcel_Style_Border $pStyle PHPExcel_Style_Border
969 * @return string
970 */
971 private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) {
972 // Create CSS
973 // $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB();
974 // Create CSS - add !important to non-none border styles for merged cells
975 $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle());
976 $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important');
977
978 // Return
979 return $css;
980 }
981
982 /**
983 * Create CSS style (PHPExcel_Style_Fill)
984 *
985 * @param PHPExcel_Style_Fill $pStyle PHPExcel_Style_Fill
986 * @return array
987 */
988 private function _createCSSStyleFill(PHPExcel_Style_Fill $pStyle) {
989 // Construct HTML
990 $css = array();
991
992 // Create CSS
993 $value = $pStyle->getFillType() == PHPExcel_Style_Fill::FILL_NONE ?
994 'white' : '#' . $pStyle->getStartColor()->getRGB();
995 $css['background-color'] = $value;
996
997 // Return
998 return $css;
999 }
1000
1001 /**
1002 * Generate HTML footer
1003 */
1004 public function generateHTMLFooter() {
1005 // Construct HTML
1006 $html = '';
1007 $html .= ' </body>' . PHP_EOL;
1008 $html .= '</html>' . PHP_EOL;
1009
1010 // Return
1011 return $html;
1012 }
1013
1014 /**
1015 * Generate table header
1016 *
1017 * @param PHPExcel_Worksheet $pSheet The worksheet for the table we are writing
1018 * @return string
1019 * @throws PHPExcel_Writer_Exception
1020 */
1021 private function _generateTableHeader($pSheet) {
1022 $sheetIndex = $pSheet->getParent()->getIndex($pSheet);
1023
1024 // Construct HTML
1025 $html = '';
1026 $html .= $this->_setMargins($pSheet);
1027
1028 if (!$this->_useInlineCss) {
1029 $gridlines = $pSheet->getShowGridlines() ? ' gridlines' : '';
1030 $html .= ' <table border="0" cellpadding="0" cellspacing="0" id="sheet' . $sheetIndex . '" class="sheet' . $sheetIndex . $gridlines . '">' . PHP_EOL;
1031 } else {
1032 $style = isset($this->_cssStyles['table']) ?
1033 $this->_assembleCSS($this->_cssStyles['table']) : '';
1034
1035 if ($this->_isPdf && $pSheet->getShowGridlines()) {
1036 $html .= ' <table border="1" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="1" style="' . $style . '">' . PHP_EOL;
1037 } else {
1038 $html .= ' <table border="0" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL;
1039 }
1040 }
1041
1042 // Write <col> elements
1043 $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1;
1044 $i = -1;
1045 while($i++ < $highestColumnIndex) {
1046 if (!$this->_isPdf) {
1047 if (!$this->_useInlineCss) {
1048 $html .= ' <col class="col' . $i . '">' . PHP_EOL;
1049 } else {
1050 $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) ?
1051 $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : '';
1052 $html .= ' <col style="' . $style . '">' . PHP_EOL;
1053 }
1054 }
1055 }
1056
1057 // Return
1058 return $html;
1059 }
1060
1061 /**
1062 * Generate table footer
1063 *
1064 * @throws PHPExcel_Writer_Exception
1065 */
1066 private function _generateTableFooter() {
1067 // Construct HTML
1068 $html = '';
1069 $html .= ' </table>' . PHP_EOL;
1070
1071 // Return
1072 return $html;
1073 }
1074
1075 /**
1076 * Generate row
1077 *
1078 * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet
1079 * @param array $pValues Array containing cells in a row
1080 * @param int $pRow Row number (0-based)
1081 * @return string
1082 * @throws PHPExcel_Writer_Exception
1083 */
1084 private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0, $cellType = 'td') {
1085 if (is_array($pValues)) {
1086 // Construct HTML
1087 $html = '';
1088
1089 // Sheet index
1090 $sheetIndex = $pSheet->getParent()->getIndex($pSheet);
1091
1092 // DomPDF and breaks
1093 if ($this->_isPdf && count($pSheet->getBreaks()) > 0) {
1094 $breaks = $pSheet->getBreaks();
1095
1096 // check if a break is needed before this row
1097 if (isset($breaks['A' . $pRow])) {
1098 // close table: </table>
1099 $html .= $this->_generateTableFooter();
1100
1101 // insert page break
1102 $html .= '<div style="page-break-before:always" />';
1103
1104 // open table again: <table> + <col> etc.
1105 $html .= $this->_generateTableHeader($pSheet);
1106 }
1107 }
1108
1109 // Write row start
1110 if (!$this->_useInlineCss) {
1111 $html .= ' <tr class="row' . $pRow . '">' . PHP_EOL;
1112 } else {
1113 $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow])
1114 ? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : '';
1115
1116 $html .= ' <tr style="' . $style . '">' . PHP_EOL;
1117 }
1118
1119 // Write cells
1120 $colNum = 0;
1121 foreach ($pValues as $cellAddress) {
1122 $cell = ($cellAddress > '') ? $pSheet->getCell($cellAddress) : '';
1123 $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1);
1124 if (!$this->_useInlineCss) {
1125 $cssClass = '';
1126 $cssClass = 'column' . $colNum;
1127 } else {
1128 $cssClass = array();
1129 if ($cellType == 'th') {
1130 if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum])) {
1131 $this->_cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum];
1132 }
1133 } else {
1134 if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) {
1135 $this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum];
1136 }
1137 }
1138 }
1139 $colSpan = 1;
1140 $rowSpan = 1;
1141
1142 // initialize
1143 $cellData = '&nbsp;';
1144
1145 // PHPExcel_Cell
1146 if ($cell instanceof PHPExcel_Cell) {
1147 $cellData = '';
1148 if (is_null($cell->getParent())) {
1149 $cell->attach($pSheet);
1150 }
1151 // Value
1152 if ($cell->getValue() instanceof PHPExcel_RichText) {
1153 // Loop through rich text elements
1154 $elements = $cell->getValue()->getRichTextElements();
1155 foreach ($elements as $element) {
1156 // Rich text start?
1157 if ($element instanceof PHPExcel_RichText_Run) {
1158 $cellData .= '<span style="' . $this->_assembleCSS($this->_createCSSStyleFont($element->getFont())) . '">';
1159
1160 if ($element->getFont()->getSuperScript()) {
1161 $cellData .= '<sup>';
1162 } else if ($element->getFont()->getSubScript()) {
1163 $cellData .= '<sub>';
1164 }
1165 }
1166
1167 // Convert UTF8 data to PCDATA
1168 $cellText = $element->getText();
1169 $cellData .= htmlspecialchars($cellText);
1170
1171 if ($element instanceof PHPExcel_RichText_Run) {
1172 if ($element->getFont()->getSuperScript()) {
1173 $cellData .= '</sup>';
1174 } else if ($element->getFont()->getSubScript()) {
1175 $cellData .= '</sub>';
1176 }
1177
1178 $cellData .= '</span>';
1179 }
1180 }
1181 } else {
1182 if ($this->_preCalculateFormulas) {
1183 $cellData = PHPExcel_Style_NumberFormat::toFormattedString(
1184 $cell->getCalculatedValue(),
1185 $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(),
1186 array($this, 'formatColor')
1187 );
1188 } else {
1189 $cellData = PHPExcel_Style_NumberFormat::toFormattedString(
1190 $cell->getValue(),
1191 $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(),
1192 array($this, 'formatColor')
1193 );
1194 }
1195 $cellData = htmlspecialchars($cellData);
1196 if ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) {
1197 $cellData = '<sup>'.$cellData.'</sup>';
1198 } elseif ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) {
1199 $cellData = '<sub>'.$cellData.'</sub>';
1200 }
1201 }
1202
1203 // Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp;
1204 // Example: " Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world"
1205 $cellData = preg_replace("/(?m)(?:^|\\G) /", '&nbsp;', $cellData);
1206
1207 // convert newline "\n" to '<br>'
1208 $cellData = nl2br($cellData);
1209
1210 // Extend CSS class?
1211 if (!$this->_useInlineCss) {
1212 $cssClass .= ' style' . $cell->getXfIndex();
1213 $cssClass .= ' ' . $cell->getDataType();
1214 } else {
1215 if ($cellType == 'th') {
1216 if (isset($this->_cssStyles['th.style' . $cell->getXfIndex()])) {
1217 $cssClass = array_merge($cssClass, $this->_cssStyles['th.style' . $cell->getXfIndex()]);
1218 }
1219 } else {
1220 if (isset($this->_cssStyles['td.style' . $cell->getXfIndex()])) {
1221 $cssClass = array_merge($cssClass, $this->_cssStyles['td.style' . $cell->getXfIndex()]);
1222 }
1223 }
1224
1225 // General horizontal alignment: Actual horizontal alignment depends on dataType
1226 $sharedStyle = $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() );
1227 if ($sharedStyle->getAlignment()->getHorizontal() == PHPExcel_Style_Alignment::HORIZONTAL_GENERAL
1228 && isset($this->_cssStyles['.' . $cell->getDataType()]['text-align']))
1229 {
1230 $cssClass['text-align'] = $this->_cssStyles['.' . $cell->getDataType()]['text-align'];
1231 }
1232 }
1233 }
1234
1235 // Hyperlink?
1236 if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) {
1237 $cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>';
1238 }
1239
1240 // Should the cell be written or is it swallowed by a rowspan or colspan?
1241 $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])
1242 && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] );
1243
1244 // Colspan and Rowspan
1245 $colspan = 1;
1246 $rowspan = 1;
1247 if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) {
1248 $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum];
1249 $rowSpan = $spans['rowspan'];
1250 $colSpan = $spans['colspan'];
1251
1252 // Also apply style from last cell in merge to fix borders -
1253 // relies on !important for non-none border declarations in _createCSSStyleBorder
1254 $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan);
1255 if (!$this->_useInlineCss) {
1256 $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex();
1257 }
1258 }
1259
1260 // Write
1261 if ($writeCell) {
1262 // Column start
1263 $html .= ' <' . $cellType;
1264 if (!$this->_useInlineCss) {
1265 $html .= ' class="' . $cssClass . '"';
1266 } else {
1267 //** Necessary redundant code for the sake of PHPExcel_Writer_PDF **
1268 // We must explicitly write the width of the <td> element because TCPDF
1269 // does not recognize e.g. <col style="width:42pt">
1270 $width = 0;
1271 $i = $colNum - 1;
1272 $e = $colNum + $colSpan - 1;
1273 while($i++ < $e) {
1274 if (isset($this->_columnWidths[$sheetIndex][$i])) {
1275 $width += $this->_columnWidths[$sheetIndex][$i];
1276 }
1277 }
1278 $cssClass['width'] = $width . 'pt';
1279
1280 // We must also explicitly write the height of the <td> element because TCPDF
1281 // does not recognize e.g. <tr style="height:50pt">
1282 if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) {
1283 $height = $this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'];
1284 $cssClass['height'] = $height;
1285 }
1286 //** end of redundant code **
1287
1288 $html .= ' style="' . $this->_assembleCSS($cssClass) . '"';
1289 }
1290 if ($colSpan > 1) {
1291 $html .= ' colspan="' . $colSpan . '"';
1292 }
1293 if ($rowSpan > 1) {
1294 $html .= ' rowspan="' . $rowSpan . '"';
1295 }
1296 $html .= '>';
1297
1298 // Image?
1299 $html .= $this->_writeImageInCell($pSheet, $coordinate);
1300
1301 // Chart?
1302 if ($this->_includeCharts) {
1303 $html .= $this->_writeChartInCell($pSheet, $coordinate);
1304 }
1305
1306 // Cell data
1307 $html .= $cellData;
1308
1309 // Column end
1310 $html .= '</'.$cellType.'>' . PHP_EOL;
1311 }
1312
1313 // Next column
1314 ++$colNum;
1315 }
1316
1317 // Write row end
1318 $html .= ' </tr>' . PHP_EOL;
1319
1320 // Return
1321 return $html;
1322 } else {
1323 throw new PHPExcel_Writer_Exception("Invalid parameters passed.");
1324 }
1325 }
1326
1327 /**
1328 * Takes array where of CSS properties / values and converts to CSS string
1329 *
1330 * @param array
1331 * @return string
1332 */
1333 private function _assembleCSS($pValue = array())
1334 {
1335 $pairs = array();
1336 foreach ($pValue as $property => $value) {
1337 $pairs[] = $property . ':' . $value;
1338 }
1339 $string = implode('; ', $pairs);
1340
1341 return $string;
1342 }
1343
1344 /**
1345 * Get images root
1346 *
1347 * @return string
1348 */
1349 public function getImagesRoot() {
1350 return $this->_imagesRoot;
1351 }
1352
1353 /**
1354 * Set images root
1355 *
1356 * @param string $pValue
1357 * @return PHPExcel_Writer_HTML
1358 */
1359 public function setImagesRoot($pValue = '.') {
1360 $this->_imagesRoot = $pValue;
1361 return $this;
1362 }
1363
1364 /**
1365 * Get embed images
1366 *
1367 * @return boolean
1368 */
1369 public function getEmbedImages() {
1370 return $this->_embedImages;
1371 }
1372
1373 /**
1374 * Set embed images
1375 *
1376 * @param boolean $pValue
1377 * @return PHPExcel_Writer_HTML
1378 */
1379 public function setEmbedImages($pValue = '.') {
1380 $this->_embedImages = $pValue;
1381 return $this;
1382 }
1383
1384 /**
1385 * Get use inline CSS?
1386 *
1387 * @return boolean
1388 */
1389 public function getUseInlineCss() {
1390 return $this->_useInlineCss;
1391 }
1392
1393 /**
1394 * Set use inline CSS?
1395 *
1396 * @param boolean $pValue
1397 * @return PHPExcel_Writer_HTML
1398 */
1399 public function setUseInlineCss($pValue = false) {
1400 $this->_useInlineCss = $pValue;
1401 return $this;
1402 }
1403
1404 /**
1405 * Add color to formatted string as inline style
1406 *
1407 * @param string $pValue Plain formatted value without color
1408 * @param string $pFormat Format code
1409 * @return string
1410 */
1411 public function formatColor($pValue, $pFormat)
1412 {
1413 // Color information, e.g. [Red] is always at the beginning
1414 $color = null; // initialize
1415 $matches = array();
1416
1417 $color_regex = '/^\\[[a-zA-Z]+\\]/';
1418 if (preg_match($color_regex, $pFormat, $matches)) {
1419 $color = str_replace('[', '', $matches[0]);
1420 $color = str_replace(']', '', $color);
1421 $color = strtolower($color);
1422 }
1423
1424 // convert to PCDATA
1425 $value = htmlspecialchars($pValue);
1426
1427 // color span tag
1428 if ($color !== null) {
1429 $value = '<span style="color:' . $color . '">' . $value . '</span>';
1430 }
1431
1432 return $value;
1433 }
1434
1435 /**
1436 * Calculate information about HTML colspan and rowspan which is not always the same as Excel's
1437 */
1438 private function _calculateSpans()
1439 {
1440 // Identify all cells that should be omitted in HTML due to cell merge.
1441 // In HTML only the upper-left cell should be written and it should have
1442 // appropriate rowspan / colspan attribute
1443 $sheetIndexes = $this->_sheetIndex !== null ?
1444 array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1);
1445
1446 foreach ($sheetIndexes as $sheetIndex) {
1447 $sheet = $this->_phpExcel->getSheet($sheetIndex);
1448
1449 $candidateSpannedRow = array();
1450
1451 // loop through all Excel merged cells
1452 foreach ($sheet->getMergeCells() as $cells) {
1453 list($cells, ) = PHPExcel_Cell::splitRange($cells);
1454 $first = $cells[0];
1455 $last = $cells[1];
1456
1457 list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first);
1458 $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1;
1459
1460 list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last);
1461 $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1;
1462
1463 // loop through the individual cells in the individual merge
1464 $r = $fr - 1;
1465 while($r++ < $lr) {
1466 // also, flag this row as a HTML row that is candidate to be omitted
1467 $candidateSpannedRow[$r] = $r;
1468
1469 $c = $fc - 1;
1470 while($c++ < $lc) {
1471 if ( !($c == $fc && $r == $fr) ) {
1472 // not the upper-left cell (should not be written in HTML)
1473 $this->_isSpannedCell[$sheetIndex][$r][$c] = array(
1474 'baseCell' => array($fr, $fc),
1475 );
1476 } else {
1477 // upper-left is the base cell that should hold the colspan/rowspan attribute
1478 $this->_isBaseCell[$sheetIndex][$r][$c] = array(
1479 'xlrowspan' => $lr - $fr + 1, // Excel rowspan
1480 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change
1481 'xlcolspan' => $lc - $fc + 1, // Excel colspan
1482 'colspan' => $lc - $fc + 1, // HTML colspan, value may change
1483 );
1484 }
1485 }
1486 }
1487 }
1488
1489 // Identify which rows should be omitted in HTML. These are the rows where all the cells
1490 // participate in a merge and the where base cells are somewhere above.
1491 $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn());
1492 foreach ($candidateSpannedRow as $rowIndex) {
1493 if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) {
1494 if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) {
1495 $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex;
1496 };
1497 }
1498 }
1499
1500 // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1
1501 if ( isset($this->_isSpannedRow[$sheetIndex]) ) {
1502 foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) {
1503 $adjustedBaseCells = array();
1504 $c = -1;
1505 $e = $countColumns - 1;
1506 while($c++ < $e) {
1507 $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell'];
1508
1509 if ( !in_array($baseCell, $adjustedBaseCells) ) {
1510 // subtract rowspan by 1
1511 --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan'];
1512 $adjustedBaseCells[] = $baseCell;
1513 }
1514 }
1515 }
1516 }
1517
1518 // TODO: Same for columns
1519 }
1520
1521 // We have calculated the spans
1522 $this->_spansAreCalculated = true;
1523 }
1524
1525 private function _setMargins(PHPExcel_Worksheet $pSheet) {
1526 $htmlPage = '@page { ';
1527 $htmlBody = 'body { ';
1528
1529 $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; ';
1530 $htmlPage .= 'left-margin: ' . $left;
1531 $htmlBody .= 'left-margin: ' . $left;
1532 $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; ';
1533 $htmlPage .= 'right-margin: ' . $right;
1534 $htmlBody .= 'right-margin: ' . $right;
1535 $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; ';
1536 $htmlPage .= 'top-margin: ' . $top;
1537 $htmlBody .= 'top-margin: ' . $top;
1538 $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; ';
1539 $htmlPage .= 'bottom-margin: ' . $bottom;
1540 $htmlBody .= 'bottom-margin: ' . $bottom;
1541
1542 $htmlPage .= "}\n";
1543 $htmlBody .= "}\n";
1544
1545 return "<style>\n" . $htmlPage . $htmlBody . "</style>\n";
1546 }
1547
1548 }
1549