@@ -33,131 +33,131 @@ discard block |
||
33 | 33 | |
34 | 34 | class Html extends BaseWriter |
35 | 35 | { |
36 | - private const DEFAULT_CELL_WIDTH_POINTS = 42; |
|
37 | - |
|
38 | - private const DEFAULT_CELL_WIDTH_PIXELS = 56; |
|
39 | - |
|
40 | - /** |
|
41 | - * Migration aid to tell if html tags will be treated as plaintext in comments. |
|
42 | - * if ( |
|
43 | - * defined( |
|
44 | - * \PhpOffice\PhpSpreadsheet\Writer\Html::class |
|
45 | - * . '::COMMENT_HTML_TAGS_PLAINTEXT' |
|
46 | - * ) |
|
47 | - * ) { |
|
48 | - * new logic with styling in TextRun elements |
|
49 | - * } else { |
|
50 | - * old logic with styling via Html tags |
|
51 | - * }. |
|
52 | - */ |
|
53 | - public const COMMENT_HTML_TAGS_PLAINTEXT = true; |
|
54 | - |
|
55 | - /** |
|
56 | - * Spreadsheet object. |
|
57 | - */ |
|
58 | - protected Spreadsheet $spreadsheet; |
|
59 | - |
|
60 | - /** |
|
61 | - * Sheet index to write. |
|
62 | - */ |
|
63 | - private null| int | array $sheetIndex = 0; |
|
64 | - |
|
65 | - /** |
|
66 | - * Images root. |
|
67 | - */ |
|
68 | - private string $imagesRoot = ''; |
|
69 | - |
|
70 | - /** |
|
71 | - * embed images, or link to images. |
|
72 | - */ |
|
73 | - protected bool $embedImages = false; |
|
74 | - |
|
75 | - /** |
|
76 | - * Use inline CSS? |
|
77 | - */ |
|
78 | - private bool $useInlineCss = false; |
|
79 | - |
|
80 | - /** |
|
81 | - * Array of CSS styles. |
|
82 | - */ |
|
83 | - private ?array $cssStyles = null; |
|
84 | - |
|
85 | - /** |
|
86 | - * Array of column widths in points. |
|
87 | - */ |
|
88 | - private array $columnWidths; |
|
89 | - |
|
90 | - /** |
|
91 | - * Default font. |
|
92 | - */ |
|
93 | - private Font $defaultFont; |
|
94 | - |
|
95 | - /** |
|
96 | - * Flag whether spans have been calculated. |
|
97 | - */ |
|
98 | - private bool $spansAreCalculated = false; |
|
99 | - |
|
100 | - /** |
|
101 | - * Excel cells that should not be written as HTML cells. |
|
102 | - */ |
|
103 | - private array $isSpannedCell = []; |
|
104 | - |
|
105 | - /** |
|
106 | - * Excel cells that are upper-left corner in a cell merge. |
|
107 | - */ |
|
108 | - private array $isBaseCell = []; |
|
109 | - |
|
110 | - /** |
|
111 | - * Excel rows that should not be written as HTML rows. |
|
112 | - */ |
|
113 | - private array $isSpannedRow = []; |
|
114 | - |
|
115 | - /** |
|
116 | - * Is the current writer creating PDF? |
|
117 | - */ |
|
118 | - protected bool $isPdf = false; |
|
119 | - |
|
120 | - /** |
|
121 | - * Is the current writer creating mPDF? |
|
122 | - * |
|
123 | - * @deprecated 2.0.1 use instanceof Mpdf instead |
|
124 | - */ |
|
125 | - protected bool $isMPdf = false; |
|
126 | - |
|
127 | - /** |
|
128 | - * Generate the Navigation block. |
|
129 | - */ |
|
130 | - private bool $generateSheetNavigationBlock = true; |
|
131 | - |
|
132 | - /** |
|
133 | - * Callback for editing generated html. |
|
134 | - * |
|
135 | - * @var null|callable |
|
136 | - */ |
|
137 | - private $editHtmlCallback; |
|
138 | - |
|
139 | - /** @var BaseDrawing[] */ |
|
140 | - private $sheetDrawings; |
|
141 | - |
|
142 | - /** @var Chart[] */ |
|
143 | - private $sheetCharts; |
|
144 | - |
|
145 | - /** |
|
146 | - * Create a new HTML. |
|
147 | - */ |
|
148 | - public function __construct(Spreadsheet $spreadsheet) |
|
149 | - { |
|
36 | + private const DEFAULT_CELL_WIDTH_POINTS = 42; |
|
37 | + |
|
38 | + private const DEFAULT_CELL_WIDTH_PIXELS = 56; |
|
39 | + |
|
40 | + /** |
|
41 | + * Migration aid to tell if html tags will be treated as plaintext in comments. |
|
42 | + * if ( |
|
43 | + * defined( |
|
44 | + * \PhpOffice\PhpSpreadsheet\Writer\Html::class |
|
45 | + * . '::COMMENT_HTML_TAGS_PLAINTEXT' |
|
46 | + * ) |
|
47 | + * ) { |
|
48 | + * new logic with styling in TextRun elements |
|
49 | + * } else { |
|
50 | + * old logic with styling via Html tags |
|
51 | + * }. |
|
52 | + */ |
|
53 | + public const COMMENT_HTML_TAGS_PLAINTEXT = true; |
|
54 | + |
|
55 | + /** |
|
56 | + * Spreadsheet object. |
|
57 | + */ |
|
58 | + protected Spreadsheet $spreadsheet; |
|
59 | + |
|
60 | + /** |
|
61 | + * Sheet index to write. |
|
62 | + */ |
|
63 | + private null| int | array $sheetIndex = 0; |
|
64 | + |
|
65 | + /** |
|
66 | + * Images root. |
|
67 | + */ |
|
68 | + private string $imagesRoot = ''; |
|
69 | + |
|
70 | + /** |
|
71 | + * embed images, or link to images. |
|
72 | + */ |
|
73 | + protected bool $embedImages = false; |
|
74 | + |
|
75 | + /** |
|
76 | + * Use inline CSS? |
|
77 | + */ |
|
78 | + private bool $useInlineCss = false; |
|
79 | + |
|
80 | + /** |
|
81 | + * Array of CSS styles. |
|
82 | + */ |
|
83 | + private ?array $cssStyles = null; |
|
84 | + |
|
85 | + /** |
|
86 | + * Array of column widths in points. |
|
87 | + */ |
|
88 | + private array $columnWidths; |
|
89 | + |
|
90 | + /** |
|
91 | + * Default font. |
|
92 | + */ |
|
93 | + private Font $defaultFont; |
|
94 | + |
|
95 | + /** |
|
96 | + * Flag whether spans have been calculated. |
|
97 | + */ |
|
98 | + private bool $spansAreCalculated = false; |
|
99 | + |
|
100 | + /** |
|
101 | + * Excel cells that should not be written as HTML cells. |
|
102 | + */ |
|
103 | + private array $isSpannedCell = []; |
|
104 | + |
|
105 | + /** |
|
106 | + * Excel cells that are upper-left corner in a cell merge. |
|
107 | + */ |
|
108 | + private array $isBaseCell = []; |
|
109 | + |
|
110 | + /** |
|
111 | + * Excel rows that should not be written as HTML rows. |
|
112 | + */ |
|
113 | + private array $isSpannedRow = []; |
|
114 | + |
|
115 | + /** |
|
116 | + * Is the current writer creating PDF? |
|
117 | + */ |
|
118 | + protected bool $isPdf = false; |
|
119 | + |
|
120 | + /** |
|
121 | + * Is the current writer creating mPDF? |
|
122 | + * |
|
123 | + * @deprecated 2.0.1 use instanceof Mpdf instead |
|
124 | + */ |
|
125 | + protected bool $isMPdf = false; |
|
126 | + |
|
127 | + /** |
|
128 | + * Generate the Navigation block. |
|
129 | + */ |
|
130 | + private bool $generateSheetNavigationBlock = true; |
|
131 | + |
|
132 | + /** |
|
133 | + * Callback for editing generated html. |
|
134 | + * |
|
135 | + * @var null|callable |
|
136 | + */ |
|
137 | + private $editHtmlCallback; |
|
138 | + |
|
139 | + /** @var BaseDrawing[] */ |
|
140 | + private $sheetDrawings; |
|
141 | + |
|
142 | + /** @var Chart[] */ |
|
143 | + private $sheetCharts; |
|
144 | + |
|
145 | + /** |
|
146 | + * Create a new HTML. |
|
147 | + */ |
|
148 | + public function __construct(Spreadsheet $spreadsheet) |
|
149 | + { |
|
150 | 150 | $this->spreadsheet = $spreadsheet; |
151 | 151 | $this->defaultFont = $this->spreadsheet->getDefaultStyle()->getFont(); |
152 | - } |
|
153 | - |
|
154 | - /** |
|
155 | - * Save Spreadsheet to file. |
|
156 | - * |
|
157 | - * @param resource|string $filename |
|
158 | - */ |
|
159 | - public function save($filename, int $flags = 0): void |
|
160 | - { |
|
152 | + } |
|
153 | + |
|
154 | + /** |
|
155 | + * Save Spreadsheet to file. |
|
156 | + * |
|
157 | + * @param resource|string $filename |
|
158 | + */ |
|
159 | + public function save($filename, int $flags = 0): void |
|
160 | + { |
|
161 | 161 | $this->processFlags($flags); |
162 | 162 | |
163 | 163 | // Open file |
@@ -168,16 +168,16 @@ discard block |
||
168 | 168 | |
169 | 169 | // Close file |
170 | 170 | $this->maybeCloseFileHandle(); |
171 | - } |
|
171 | + } |
|
172 | 172 | |
173 | - /** |
|
174 | - * Save Spreadsheet as html to variable. |
|
175 | - */ |
|
176 | - public function generateHtmlAll(): string |
|
177 | - { |
|
173 | + /** |
|
174 | + * Save Spreadsheet as html to variable. |
|
175 | + */ |
|
176 | + public function generateHtmlAll(): string |
|
177 | + { |
|
178 | 178 | $sheets = $this->generateSheetPrep(); |
179 | 179 | foreach ($sheets as $sheet) { |
180 | - $sheet->calculateArrays($this->preCalculateFormulas); |
|
180 | + $sheet->calculateArrays($this->preCalculateFormulas); |
|
181 | 181 | } |
182 | 182 | // garbage collect |
183 | 183 | $this->spreadsheet->garbageCollect(); |
@@ -195,7 +195,7 @@ discard block |
||
195 | 195 | |
196 | 196 | // Write navigation (tabs) |
197 | 197 | if ((!$this->isPdf) && ($this->generateSheetNavigationBlock)) { |
198 | - $html .= $this->generateNavigation(); |
|
198 | + $html .= $this->generateNavigation(); |
|
199 | 199 | } |
200 | 200 | |
201 | 201 | // Write data |
@@ -205,47 +205,47 @@ discard block |
||
205 | 205 | $html .= $this->generateHTMLFooter(); |
206 | 206 | $callback = $this->editHtmlCallback; |
207 | 207 | if ($callback) { |
208 | - $html = $callback($html); |
|
208 | + $html = $callback($html); |
|
209 | 209 | } |
210 | 210 | |
211 | 211 | Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); |
212 | 212 | |
213 | 213 | return $html; |
214 | - } |
|
215 | - |
|
216 | - /** |
|
217 | - * Set a callback to edit the entire HTML. |
|
218 | - * |
|
219 | - * The callback must accept the HTML as string as first parameter, |
|
220 | - * and it must return the edited HTML as string. |
|
221 | - */ |
|
222 | - public function setEditHtmlCallback(?callable $callback): void |
|
223 | - { |
|
214 | + } |
|
215 | + |
|
216 | + /** |
|
217 | + * Set a callback to edit the entire HTML. |
|
218 | + * |
|
219 | + * The callback must accept the HTML as string as first parameter, |
|
220 | + * and it must return the edited HTML as string. |
|
221 | + */ |
|
222 | + public function setEditHtmlCallback(?callable $callback): void |
|
223 | + { |
|
224 | 224 | $this->editHtmlCallback = $callback; |
225 | - } |
|
226 | - |
|
227 | - /** |
|
228 | - * Map VAlign. |
|
229 | - * |
|
230 | - * @param string $vAlign Vertical alignment |
|
231 | - */ |
|
232 | - private function mapVAlign(string $vAlign): string |
|
233 | - { |
|
225 | + } |
|
226 | + |
|
227 | + /** |
|
228 | + * Map VAlign. |
|
229 | + * |
|
230 | + * @param string $vAlign Vertical alignment |
|
231 | + */ |
|
232 | + private function mapVAlign(string $vAlign): string |
|
233 | + { |
|
234 | 234 | return Alignment::VERTICAL_ALIGNMENT_FOR_HTML[$vAlign] ?? ''; |
235 | - } |
|
236 | - |
|
237 | - /** |
|
238 | - * Map HAlign. |
|
239 | - * |
|
240 | - * @param string $hAlign Horizontal alignment |
|
241 | - */ |
|
242 | - private function mapHAlign(string $hAlign): string |
|
243 | - { |
|
235 | + } |
|
236 | + |
|
237 | + /** |
|
238 | + * Map HAlign. |
|
239 | + * |
|
240 | + * @param string $hAlign Horizontal alignment |
|
241 | + */ |
|
242 | + private function mapHAlign(string $hAlign): string |
|
243 | + { |
|
244 | 244 | return Alignment::HORIZONTAL_ALIGNMENT_FOR_HTML[$hAlign] ?? ''; |
245 | - } |
|
245 | + } |
|
246 | 246 | |
247 | - const BORDER_NONE = 'none'; |
|
248 | - const BORDER_ARR = [ |
|
247 | + const BORDER_NONE = 'none'; |
|
248 | + const BORDER_ARR = [ |
|
249 | 249 | Border::BORDER_NONE => self::BORDER_NONE, |
250 | 250 | Border::BORDER_DASHDOT => '1px dashed', |
251 | 251 | Border::BORDER_DASHDOTDOT => '1px dotted', |
@@ -258,98 +258,98 @@ discard block |
||
258 | 258 | Border::BORDER_MEDIUMDASHDOTDOT => '2px dotted', |
259 | 259 | Border::BORDER_SLANTDASHDOT => '2px dashed', |
260 | 260 | Border::BORDER_THICK => '3px solid', |
261 | - ]; |
|
262 | - |
|
263 | - /** |
|
264 | - * Map border style. |
|
265 | - * |
|
266 | - * @param int|string $borderStyle Sheet index |
|
267 | - */ |
|
268 | - private function mapBorderStyle($borderStyle): string |
|
269 | - { |
|
261 | + ]; |
|
262 | + |
|
263 | + /** |
|
264 | + * Map border style. |
|
265 | + * |
|
266 | + * @param int|string $borderStyle Sheet index |
|
267 | + */ |
|
268 | + private function mapBorderStyle($borderStyle): string |
|
269 | + { |
|
270 | 270 | return self::BORDER_ARR[$borderStyle] ?? '1px solid'; |
271 | - } |
|
271 | + } |
|
272 | 272 | |
273 | - /** |
|
274 | - * Get sheet index. |
|
275 | - */ |
|
276 | - public function getSheetIndex(): null | int | array |
|
277 | - { |
|
273 | + /** |
|
274 | + * Get sheet index. |
|
275 | + */ |
|
276 | + public function getSheetIndex(): null | int | array |
|
277 | + { |
|
278 | 278 | return $this->sheetIndex; |
279 | - } |
|
280 | - |
|
281 | - /** |
|
282 | - * Set sheet index. |
|
283 | - * |
|
284 | - * @param int $sheetIndex Sheet index |
|
285 | - * |
|
286 | - * @return $this |
|
287 | - */ |
|
288 | - public function setSheetIndex(int | array $sheetIndex): static |
|
289 | - { |
|
279 | + } |
|
280 | + |
|
281 | + /** |
|
282 | + * Set sheet index. |
|
283 | + * |
|
284 | + * @param int $sheetIndex Sheet index |
|
285 | + * |
|
286 | + * @return $this |
|
287 | + */ |
|
288 | + public function setSheetIndex(int | array $sheetIndex): static |
|
289 | + { |
|
290 | 290 | $this->sheetIndex = $sheetIndex; |
291 | 291 | |
292 | 292 | return $this; |
293 | - } |
|
293 | + } |
|
294 | 294 | |
295 | - /** |
|
296 | - * Get sheet index. |
|
297 | - */ |
|
298 | - public function getGenerateSheetNavigationBlock(): bool |
|
299 | - { |
|
295 | + /** |
|
296 | + * Get sheet index. |
|
297 | + */ |
|
298 | + public function getGenerateSheetNavigationBlock(): bool |
|
299 | + { |
|
300 | 300 | return $this->generateSheetNavigationBlock; |
301 | - } |
|
302 | - |
|
303 | - /** |
|
304 | - * Set sheet index. |
|
305 | - * |
|
306 | - * @param bool $generateSheetNavigationBlock Flag indicating whether the sheet navigation block should be generated or not |
|
307 | - * |
|
308 | - * @return $this |
|
309 | - */ |
|
310 | - public function setGenerateSheetNavigationBlock(bool $generateSheetNavigationBlock): static |
|
311 | - { |
|
301 | + } |
|
302 | + |
|
303 | + /** |
|
304 | + * Set sheet index. |
|
305 | + * |
|
306 | + * @param bool $generateSheetNavigationBlock Flag indicating whether the sheet navigation block should be generated or not |
|
307 | + * |
|
308 | + * @return $this |
|
309 | + */ |
|
310 | + public function setGenerateSheetNavigationBlock(bool $generateSheetNavigationBlock): static |
|
311 | + { |
|
312 | 312 | $this->generateSheetNavigationBlock = (bool) $generateSheetNavigationBlock; |
313 | 313 | |
314 | 314 | return $this; |
315 | - } |
|
316 | - |
|
317 | - /** |
|
318 | - * Write all sheets (resets sheetIndex to NULL). |
|
319 | - * |
|
320 | - * @return $this |
|
321 | - */ |
|
322 | - public function writeAllSheets(): static |
|
323 | - { |
|
315 | + } |
|
316 | + |
|
317 | + /** |
|
318 | + * Write all sheets (resets sheetIndex to NULL). |
|
319 | + * |
|
320 | + * @return $this |
|
321 | + */ |
|
322 | + public function writeAllSheets(): static |
|
323 | + { |
|
324 | 324 | $this->sheetIndex = null; |
325 | 325 | |
326 | 326 | return $this; |
327 | - } |
|
327 | + } |
|
328 | 328 | |
329 | - private static function generateMeta(?string $val, string $desc): string |
|
330 | - { |
|
329 | + private static function generateMeta(?string $val, string $desc): string |
|
330 | + { |
|
331 | 331 | return ($val || $val === '0') |
332 | 332 | ? (' <meta name="' . $desc . '" content="' . htmlspecialchars($val, Settings::htmlEntityFlags()) . '" />' . PHP_EOL) |
333 | 333 | : ''; |
334 | - } |
|
334 | + } |
|
335 | 335 | |
336 | - public const BODY_LINE = ' <body>' . PHP_EOL; |
|
336 | + public const BODY_LINE = ' <body>' . PHP_EOL; |
|
337 | 337 | |
338 | - private const CUSTOM_TO_META = [ |
|
338 | + private const CUSTOM_TO_META = [ |
|
339 | 339 | Properties::PROPERTY_TYPE_BOOLEAN => 'bool', |
340 | 340 | Properties::PROPERTY_TYPE_DATE => 'date', |
341 | 341 | Properties::PROPERTY_TYPE_FLOAT => 'float', |
342 | 342 | Properties::PROPERTY_TYPE_INTEGER => 'int', |
343 | 343 | Properties::PROPERTY_TYPE_STRING => 'string', |
344 | - ]; |
|
345 | - |
|
346 | - /** |
|
347 | - * Generate HTML header. |
|
348 | - * |
|
349 | - * @param bool $includeStyles Include styles? |
|
350 | - */ |
|
351 | - public function generateHTMLHeader(bool $includeStyles = false): string |
|
352 | - { |
|
344 | + ]; |
|
345 | + |
|
346 | + /** |
|
347 | + * Generate HTML header. |
|
348 | + * |
|
349 | + * @param bool $includeStyles Include styles? |
|
350 | + */ |
|
351 | + public function generateHTMLHeader(bool $includeStyles = false): string |
|
352 | + { |
|
353 | 353 | // Construct HTML |
354 | 354 | $properties = $this->spreadsheet->getProperties(); |
355 | 355 | $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . PHP_EOL; |
@@ -359,7 +359,7 @@ discard block |
||
359 | 359 | $html .= ' <meta name="generator" content="PhpSpreadsheet, https://github.com/PHPOffice/PhpSpreadsheet" />' . PHP_EOL; |
360 | 360 | $title = $properties->getTitle(); |
361 | 361 | if ($title === '') { |
362 | - $title = $this->spreadsheet->getActiveSheet()->getTitle(); |
|
362 | + $title = $this->spreadsheet->getActiveSheet()->getTitle(); |
|
363 | 363 | } |
364 | 364 | $html .= ' <title>' . htmlspecialchars($title, Settings::htmlEntityFlags()) . '</title>' . PHP_EOL; |
365 | 365 | $html .= self::generateMeta($properties->getCreator(), 'author'); |
@@ -381,25 +381,25 @@ discard block |
||
381 | 381 | |
382 | 382 | $customProperties = $properties->getCustomProperties(); |
383 | 383 | foreach ($customProperties as $customProperty) { |
384 | - $propertyValue = $properties->getCustomPropertyValue($customProperty); |
|
385 | - $propertyType = $properties->getCustomPropertyType($customProperty); |
|
386 | - $propertyQualifier = self::CUSTOM_TO_META[$propertyType] ?? null; |
|
387 | - if ($propertyQualifier !== null) { |
|
384 | + $propertyValue = $properties->getCustomPropertyValue($customProperty); |
|
385 | + $propertyType = $properties->getCustomPropertyType($customProperty); |
|
386 | + $propertyQualifier = self::CUSTOM_TO_META[$propertyType] ?? null; |
|
387 | + if ($propertyQualifier !== null) { |
|
388 | 388 | if ($propertyType === Properties::PROPERTY_TYPE_BOOLEAN) { |
389 | - $propertyValue = $propertyValue ? '1' : '0'; |
|
389 | + $propertyValue = $propertyValue ? '1' : '0'; |
|
390 | 390 | } elseif ($propertyType === Properties::PROPERTY_TYPE_DATE) { |
391 | - $date = Date::dateTimeFromTimestamp((string) $propertyValue); |
|
392 | - $date->setTimeZone(Date::getDefaultOrLocalTimeZone()); |
|
393 | - $propertyValue = $date->format(DATE_W3C); |
|
391 | + $date = Date::dateTimeFromTimestamp((string) $propertyValue); |
|
392 | + $date->setTimeZone(Date::getDefaultOrLocalTimeZone()); |
|
393 | + $propertyValue = $date->format(DATE_W3C); |
|
394 | 394 | } else { |
395 | - $propertyValue = (string) $propertyValue; |
|
395 | + $propertyValue = (string) $propertyValue; |
|
396 | 396 | } |
397 | 397 | $html .= self::generateMeta($propertyValue, "custom.$propertyQualifier.$customProperty"); |
398 | - } |
|
398 | + } |
|
399 | 399 | } |
400 | 400 | |
401 | 401 | if (!empty($properties->getHyperlinkBase())) { |
402 | - $html .= ' <base href="' . $properties->getHyperlinkBase() . '" />' . PHP_EOL; |
|
402 | + $html .= ' <base href="' . $properties->getHyperlinkBase() . '" />' . PHP_EOL; |
|
403 | 403 | } |
404 | 404 | |
405 | 405 | $html .= $includeStyles ? $this->generateStyles(true) : $this->generatePageDeclarations(true); |
@@ -409,63 +409,63 @@ discard block |
||
409 | 409 | $html .= self::BODY_LINE; |
410 | 410 | |
411 | 411 | return $html; |
412 | - } |
|
412 | + } |
|
413 | 413 | |
414 | - /** @return Worksheet[] */ |
|
415 | - private function generateSheetPrep(): array |
|
416 | - { |
|
414 | + /** @return Worksheet[] */ |
|
415 | + private function generateSheetPrep(): array |
|
416 | + { |
|
417 | 417 | // Fetch sheets |
418 | 418 | if (is_array($this->sheetIndex)) { |
419 | - $sheets = []; |
|
420 | - foreach ($this->sheetIndex as $sheetIndex) { |
|
419 | + $sheets = []; |
|
420 | + foreach ($this->sheetIndex as $sheetIndex) { |
|
421 | 421 | $sheets[] = $this->spreadsheet->getSheet($sheetIndex); |
422 | - } |
|
422 | + } |
|
423 | 423 | } elseif ($this->sheetIndex === null) { |
424 | - $sheets = $this->spreadsheet->getAllSheets(); |
|
424 | + $sheets = $this->spreadsheet->getAllSheets(); |
|
425 | 425 | } else { |
426 | - $sheets = [$this->spreadsheet->getSheet($this->sheetIndex)]; |
|
426 | + $sheets = [$this->spreadsheet->getSheet($this->sheetIndex)]; |
|
427 | 427 | } |
428 | 428 | |
429 | 429 | return $sheets; |
430 | - } |
|
430 | + } |
|
431 | 431 | |
432 | - private function generateSheetStarts(Worksheet $sheet, int $rowMin): array |
|
433 | - { |
|
432 | + private function generateSheetStarts(Worksheet $sheet, int $rowMin): array |
|
433 | + { |
|
434 | 434 | // calculate start of <tbody>, <thead> |
435 | 435 | $tbodyStart = $rowMin; |
436 | 436 | $theadStart = $theadEnd = 0; // default: no <thead> no </thead> |
437 | 437 | if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { |
438 | - $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); |
|
438 | + $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); |
|
439 | 439 | |
440 | - // we can only support repeating rows that start at top row |
|
441 | - if ($rowsToRepeatAtTop[0] == 1) { |
|
440 | + // we can only support repeating rows that start at top row |
|
441 | + if ($rowsToRepeatAtTop[0] == 1) { |
|
442 | 442 | $theadStart = $rowsToRepeatAtTop[0]; |
443 | 443 | $theadEnd = $rowsToRepeatAtTop[1]; |
444 | 444 | $tbodyStart = $rowsToRepeatAtTop[1] + 1; |
445 | - } |
|
445 | + } |
|
446 | 446 | } |
447 | 447 | |
448 | 448 | return [$theadStart, $theadEnd, $tbodyStart]; |
449 | - } |
|
449 | + } |
|
450 | 450 | |
451 | - private function generateSheetTags(int $row, int $theadStart, int $theadEnd, int $tbodyStart): array |
|
452 | - { |
|
451 | + private function generateSheetTags(int $row, int $theadStart, int $theadEnd, int $tbodyStart): array |
|
452 | + { |
|
453 | 453 | // <thead> ? |
454 | 454 | $startTag = ($row == $theadStart) ? (' <thead>' . PHP_EOL) : ''; |
455 | 455 | if (!$startTag) { |
456 | - $startTag = ($row == $tbodyStart) ? (' <tbody>' . PHP_EOL) : ''; |
|
456 | + $startTag = ($row == $tbodyStart) ? (' <tbody>' . PHP_EOL) : ''; |
|
457 | 457 | } |
458 | 458 | $endTag = ($row == $theadEnd) ? (' </thead>' . PHP_EOL) : ''; |
459 | 459 | $cellType = ($row >= $tbodyStart) ? 'td' : 'th'; |
460 | 460 | |
461 | 461 | return [$cellType, $startTag, $endTag]; |
462 | - } |
|
462 | + } |
|
463 | 463 | |
464 | - /** |
|
465 | - * Generate sheet data. |
|
466 | - */ |
|
467 | - public function generateSheetData(): string |
|
468 | - { |
|
464 | + /** |
|
465 | + * Generate sheet data. |
|
466 | + */ |
|
467 | + public function generateSheetData(): string |
|
468 | + { |
|
469 | 469 | // Ensure that Spans have been calculated? |
470 | 470 | $this->calculateSpans(); |
471 | 471 | $sheets = $this->generateSheetPrep(); |
@@ -476,74 +476,74 @@ discard block |
||
476 | 476 | // Loop all sheets |
477 | 477 | $sheetId = 0; |
478 | 478 | foreach ($sheets as $sheet) { |
479 | - // Write table header |
|
480 | - $html .= $this->generateTableHeader($sheet); |
|
481 | - $this->sheetCharts = []; |
|
482 | - $this->sheetDrawings = []; |
|
483 | - |
|
484 | - // Get worksheet dimension |
|
485 | - [$min, $max] = explode(':', $sheet->calculateWorksheetDataDimension()); |
|
486 | - [$minCol, $minRow, $minColString] = Coordinate::indexesFromString($min); |
|
487 | - [$maxCol, $maxRow] = Coordinate::indexesFromString($max); |
|
488 | - $this->extendRowsAndColumns($sheet, $maxCol, $maxRow); |
|
489 | - |
|
490 | - [$theadStart, $theadEnd, $tbodyStart] = $this->generateSheetStarts($sheet, $minRow); |
|
491 | - |
|
492 | - // Loop through cells |
|
493 | - $row = $minRow - 1; |
|
494 | - while ($row++ < $maxRow) { |
|
479 | + // Write table header |
|
480 | + $html .= $this->generateTableHeader($sheet); |
|
481 | + $this->sheetCharts = []; |
|
482 | + $this->sheetDrawings = []; |
|
483 | + |
|
484 | + // Get worksheet dimension |
|
485 | + [$min, $max] = explode(':', $sheet->calculateWorksheetDataDimension()); |
|
486 | + [$minCol, $minRow, $minColString] = Coordinate::indexesFromString($min); |
|
487 | + [$maxCol, $maxRow] = Coordinate::indexesFromString($max); |
|
488 | + $this->extendRowsAndColumns($sheet, $maxCol, $maxRow); |
|
489 | + |
|
490 | + [$theadStart, $theadEnd, $tbodyStart] = $this->generateSheetStarts($sheet, $minRow); |
|
491 | + |
|
492 | + // Loop through cells |
|
493 | + $row = $minRow - 1; |
|
494 | + while ($row++ < $maxRow) { |
|
495 | 495 | [$cellType, $startTag, $endTag] = $this->generateSheetTags($row, $theadStart, $theadEnd, $tbodyStart); |
496 | 496 | $html .= $startTag; |
497 | 497 | |
498 | 498 | // Write row if there are HTML table cells in it |
499 | 499 | if ($this->shouldGenerateRow($sheet, $row) && !isset($this->isSpannedRow[$sheet->getParentOrThrow()->getIndex($sheet)][$row])) { |
500 | - // Start a new rowData |
|
501 | - $rowData = []; |
|
502 | - // Loop through columns |
|
503 | - $column = $minCol; |
|
504 | - $colStr = $minColString; |
|
505 | - while ($column <= $maxCol) { |
|
500 | + // Start a new rowData |
|
501 | + $rowData = []; |
|
502 | + // Loop through columns |
|
503 | + $column = $minCol; |
|
504 | + $colStr = $minColString; |
|
505 | + while ($column <= $maxCol) { |
|
506 | 506 | // Cell exists? |
507 | 507 | $cellAddress = Coordinate::stringFromColumnIndex($column) . $row; |
508 | 508 | if ($this->shouldGenerateColumn($sheet, $colStr)) { |
509 | - $rowData[$column] = ($sheet->getCellCollection()->has($cellAddress)) ? $cellAddress : ''; |
|
509 | + $rowData[$column] = ($sheet->getCellCollection()->has($cellAddress)) ? $cellAddress : ''; |
|
510 | 510 | } |
511 | 511 | ++$column; |
512 | 512 | ++$colStr; |
513 | - } |
|
514 | - $html .= $this->generateRow($sheet, $rowData, $row - 1, $cellType); |
|
513 | + } |
|
514 | + $html .= $this->generateRow($sheet, $rowData, $row - 1, $cellType); |
|
515 | 515 | } |
516 | 516 | |
517 | 517 | $html .= $endTag; |
518 | - } |
|
518 | + } |
|
519 | 519 | |
520 | - // Write table footer |
|
521 | - $html .= $this->generateTableFooter(); |
|
522 | - // Writing PDF? |
|
523 | - if ($this->isPdf && $this->useInlineCss) { |
|
520 | + // Write table footer |
|
521 | + $html .= $this->generateTableFooter(); |
|
522 | + // Writing PDF? |
|
523 | + if ($this->isPdf && $this->useInlineCss) { |
|
524 | 524 | if ($this->sheetIndex === null && $sheetId + 1 < $this->spreadsheet->getSheetCount()) { |
525 | - $html .= '<div style="page-break-before:always" ></div>'; |
|
525 | + $html .= '<div style="page-break-before:always" ></div>'; |
|
526 | + } |
|
526 | 527 | } |
527 | - } |
|
528 | 528 | |
529 | - // Next sheet |
|
530 | - ++$sheetId; |
|
529 | + // Next sheet |
|
530 | + ++$sheetId; |
|
531 | 531 | } |
532 | 532 | |
533 | 533 | return $html; |
534 | - } |
|
534 | + } |
|
535 | 535 | |
536 | - /** |
|
537 | - * Generate sheet tabs. |
|
538 | - */ |
|
539 | - public function generateNavigation(): string |
|
540 | - { |
|
536 | + /** |
|
537 | + * Generate sheet tabs. |
|
538 | + */ |
|
539 | + public function generateNavigation(): string |
|
540 | + { |
|
541 | 541 | // Fetch sheets |
542 | 542 | $sheets = []; |
543 | 543 | if ($this->sheetIndex === null) { |
544 | - $sheets = $this->spreadsheet->getAllSheets(); |
|
544 | + $sheets = $this->spreadsheet->getAllSheets(); |
|
545 | 545 | } else { |
546 | - $sheets[] = $this->spreadsheet->getSheet($this->sheetIndex); |
|
546 | + $sheets[] = $this->spreadsheet->getSheet($this->sheetIndex); |
|
547 | 547 | } |
548 | 548 | |
549 | 549 | // Construct HTML |
@@ -551,86 +551,86 @@ discard block |
||
551 | 551 | |
552 | 552 | // Only if there are more than 1 sheets |
553 | 553 | if (count($sheets) > 1) { |
554 | - // Loop all sheets |
|
555 | - $sheetId = 0; |
|
554 | + // Loop all sheets |
|
555 | + $sheetId = 0; |
|
556 | 556 | |
557 | - $html .= '<ul class="navigation">' . PHP_EOL; |
|
557 | + $html .= '<ul class="navigation">' . PHP_EOL; |
|
558 | 558 | |
559 | - foreach ($sheets as $sheet) { |
|
559 | + foreach ($sheets as $sheet) { |
|
560 | 560 | $html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL; |
561 | 561 | ++$sheetId; |
562 | - } |
|
562 | + } |
|
563 | 563 | |
564 | - $html .= '</ul>' . PHP_EOL; |
|
564 | + $html .= '</ul>' . PHP_EOL; |
|
565 | 565 | } |
566 | 566 | |
567 | 567 | return $html; |
568 | - } |
|
568 | + } |
|
569 | 569 | |
570 | - private function extendRowsAndColumns(Worksheet $worksheet, int &$colMax, int &$rowMax): void |
|
571 | - { |
|
570 | + private function extendRowsAndColumns(Worksheet $worksheet, int &$colMax, int &$rowMax): void |
|
571 | + { |
|
572 | 572 | if ($this->includeCharts) { |
573 | - foreach ($worksheet->getChartCollection() as $chart) { |
|
573 | + foreach ($worksheet->getChartCollection() as $chart) { |
|
574 | 574 | if ($chart instanceof Chart) { |
575 | - $chartCoordinates = $chart->getTopLeftPosition(); |
|
576 | - $this->sheetCharts[$chartCoordinates['cell']] = $chart; |
|
577 | - $chartTL = Coordinate::indexesFromString($chartCoordinates['cell']); |
|
578 | - if ($chartTL[1] > $rowMax) { |
|
575 | + $chartCoordinates = $chart->getTopLeftPosition(); |
|
576 | + $this->sheetCharts[$chartCoordinates['cell']] = $chart; |
|
577 | + $chartTL = Coordinate::indexesFromString($chartCoordinates['cell']); |
|
578 | + if ($chartTL[1] > $rowMax) { |
|
579 | 579 | $rowMax = $chartTL[1]; |
580 | - } |
|
581 | - if ($chartTL[0] > $colMax) { |
|
580 | + } |
|
581 | + if ($chartTL[0] > $colMax) { |
|
582 | 582 | $colMax = $chartTL[0]; |
583 | - } |
|
583 | + } |
|
584 | + } |
|
584 | 585 | } |
585 | - } |
|
586 | 586 | } |
587 | 587 | foreach ($worksheet->getDrawingCollection() as $drawing) { |
588 | - if ($drawing instanceof Drawing && $drawing->getPath() === '') { |
|
588 | + if ($drawing instanceof Drawing && $drawing->getPath() === '') { |
|
589 | 589 | continue; |
590 | - } |
|
591 | - $imageTL = Coordinate::indexesFromString($drawing->getCoordinates()); |
|
592 | - $this->sheetDrawings[$drawing->getCoordinates()] = $drawing; |
|
593 | - if ($imageTL[1] > $rowMax) { |
|
590 | + } |
|
591 | + $imageTL = Coordinate::indexesFromString($drawing->getCoordinates()); |
|
592 | + $this->sheetDrawings[$drawing->getCoordinates()] = $drawing; |
|
593 | + if ($imageTL[1] > $rowMax) { |
|
594 | 594 | $rowMax = $imageTL[1]; |
595 | - } |
|
596 | - if ($imageTL[0] > $colMax) { |
|
595 | + } |
|
596 | + if ($imageTL[0] > $colMax) { |
|
597 | 597 | $colMax = $imageTL[0]; |
598 | - } |
|
598 | + } |
|
599 | + } |
|
599 | 600 | } |
600 | - } |
|
601 | 601 | |
602 | - /** |
|
603 | - * Convert Windows file name to file protocol URL. |
|
604 | - * |
|
605 | - * @param string $filename file name on local system |
|
606 | - */ |
|
607 | - public static function winFileToUrl(string $filename, bool $mpdf = false): string |
|
608 | - { |
|
602 | + /** |
|
603 | + * Convert Windows file name to file protocol URL. |
|
604 | + * |
|
605 | + * @param string $filename file name on local system |
|
606 | + */ |
|
607 | + public static function winFileToUrl(string $filename, bool $mpdf = false): string |
|
608 | + { |
|
609 | 609 | // Windows filename |
610 | 610 | if (substr($filename, 1, 2) === ':\\') { |
611 | - $protocol = $mpdf ? '' : 'file:///'; |
|
612 | - $filename = $protocol . str_replace('\\', '/', $filename); |
|
611 | + $protocol = $mpdf ? '' : 'file:///'; |
|
612 | + $filename = $protocol . str_replace('\\', '/', $filename); |
|
613 | 613 | } |
614 | 614 | |
615 | 615 | return $filename; |
616 | - } |
|
617 | - |
|
618 | - /** |
|
619 | - * Generate image tag in cell. |
|
620 | - * |
|
621 | - * @param string $coordinates Cell coordinates |
|
622 | - */ |
|
623 | - private function writeImageInCell(string $coordinates): string |
|
624 | - { |
|
616 | + } |
|
617 | + |
|
618 | + /** |
|
619 | + * Generate image tag in cell. |
|
620 | + * |
|
621 | + * @param string $coordinates Cell coordinates |
|
622 | + */ |
|
623 | + private function writeImageInCell(string $coordinates): string |
|
624 | + { |
|
625 | 625 | // Construct HTML |
626 | 626 | $html = ''; |
627 | 627 | |
628 | 628 | // Write images |
629 | 629 | $drawing = $this->sheetDrawings[$coordinates] ?? null; |
630 | 630 | if ($drawing !== null) { |
631 | - $filedesc = $drawing->getDescription(); |
|
632 | - $filedesc = $filedesc ? htmlspecialchars($filedesc, ENT_QUOTES) : 'Embedded image'; |
|
633 | - if ($drawing instanceof Drawing && $drawing->getPath() !== '') { |
|
631 | + $filedesc = $drawing->getDescription(); |
|
632 | + $filedesc = $filedesc ? htmlspecialchars($filedesc, ENT_QUOTES) : 'Embedded image'; |
|
633 | + if ($drawing instanceof Drawing && $drawing->getPath() !== '') { |
|
634 | 634 | $filename = $drawing->getPath(); |
635 | 635 | |
636 | 636 | // Strip off eventual '.' |
@@ -649,147 +649,147 @@ discard block |
||
649 | 649 | $imageData = self::winFileToUrl($filename, $this instanceof Pdf\Mpdf); |
650 | 650 | |
651 | 651 | if ($this->embedImages || str_starts_with($imageData, 'zip://')) { |
652 | - $imageData = 'data:,'; |
|
653 | - $picture = @file_get_contents($filename); |
|
654 | - if ($picture !== false) { |
|
652 | + $imageData = 'data:,'; |
|
653 | + $picture = @file_get_contents($filename); |
|
654 | + if ($picture !== false) { |
|
655 | 655 | $mimeContentType = (string) @mime_content_type($filename); |
656 | 656 | if (str_starts_with($mimeContentType, 'image/')) { |
657 | - // base64 encode the binary data |
|
658 | - $base64 = base64_encode($picture); |
|
659 | - $imageData = 'data:' . $mimeContentType . ';base64,' . $base64; |
|
657 | + // base64 encode the binary data |
|
658 | + $base64 = base64_encode($picture); |
|
659 | + $imageData = 'data:' . $mimeContentType . ';base64,' . $base64; |
|
660 | + } |
|
660 | 661 | } |
661 | - } |
|
662 | 662 | } |
663 | 663 | |
664 | 664 | $html .= '<img style="position: absolute; z-index: 1; left: ' |
665 | - . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' |
|
666 | - . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' |
|
667 | - . $imageData . '" alt="' . $filedesc . '" />'; |
|
668 | - } elseif ($drawing instanceof MemoryDrawing) { |
|
665 | + . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' |
|
666 | + . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' |
|
667 | + . $imageData . '" alt="' . $filedesc . '" />'; |
|
668 | + } elseif ($drawing instanceof MemoryDrawing) { |
|
669 | 669 | $imageResource = $drawing->getImageResource(); |
670 | 670 | if ($imageResource) { |
671 | - ob_start(); // Let's start output buffering. |
|
672 | - imagepng($imageResource); // This will normally output the image, but because of ob_start(), it won't. |
|
673 | - $contents = (string) ob_get_contents(); // Instead, output above is saved to $contents |
|
674 | - ob_end_clean(); // End the output buffer. |
|
675 | - |
|
676 | - $dataUri = 'data:image/png;base64,' . base64_encode($contents); |
|
677 | - |
|
678 | - // Because of the nature of tables, width is more important than height. |
|
679 | - // max-width: 100% ensures that image doesnt overflow containing cell |
|
680 | - // However, PR #3535 broke test |
|
681 | - // 25_In_memory_image, apparently because |
|
682 | - // of the use of max-with. In addition, |
|
683 | - // non-memory-drawings don't use max-width. |
|
684 | - // Its use here is suspect and is being eliminated. |
|
685 | - // width: X sets width of supplied image. |
|
686 | - // As a result, images bigger than cell will be contained and images smaller will not get stretched |
|
687 | - $html .= '<img alt="' . $filedesc . '" src="' . $dataUri . '" style="width:' . $drawing->getWidth() . 'px;left: ' |
|
671 | + ob_start(); // Let's start output buffering. |
|
672 | + imagepng($imageResource); // This will normally output the image, but because of ob_start(), it won't. |
|
673 | + $contents = (string) ob_get_contents(); // Instead, output above is saved to $contents |
|
674 | + ob_end_clean(); // End the output buffer. |
|
675 | + |
|
676 | + $dataUri = 'data:image/png;base64,' . base64_encode($contents); |
|
677 | + |
|
678 | + // Because of the nature of tables, width is more important than height. |
|
679 | + // max-width: 100% ensures that image doesnt overflow containing cell |
|
680 | + // However, PR #3535 broke test |
|
681 | + // 25_In_memory_image, apparently because |
|
682 | + // of the use of max-with. In addition, |
|
683 | + // non-memory-drawings don't use max-width. |
|
684 | + // Its use here is suspect and is being eliminated. |
|
685 | + // width: X sets width of supplied image. |
|
686 | + // As a result, images bigger than cell will be contained and images smaller will not get stretched |
|
687 | + $html .= '<img alt="' . $filedesc . '" src="' . $dataUri . '" style="width:' . $drawing->getWidth() . 'px;left: ' |
|
688 | 688 | . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px;position: absolute; z-index: 1;" />'; |
689 | 689 | } |
690 | - } |
|
690 | + } |
|
691 | 691 | } |
692 | 692 | |
693 | 693 | return $html; |
694 | - } |
|
695 | - |
|
696 | - /** |
|
697 | - * Generate chart tag in cell. |
|
698 | - * This code should be exercised by sample: |
|
699 | - * Chart/32_Chart_read_write_PDF.php. |
|
700 | - */ |
|
701 | - private function writeChartInCell(Worksheet $worksheet, string $coordinates): string |
|
702 | - { |
|
694 | + } |
|
695 | + |
|
696 | + /** |
|
697 | + * Generate chart tag in cell. |
|
698 | + * This code should be exercised by sample: |
|
699 | + * Chart/32_Chart_read_write_PDF.php. |
|
700 | + */ |
|
701 | + private function writeChartInCell(Worksheet $worksheet, string $coordinates): string |
|
702 | + { |
|
703 | 703 | // Construct HTML |
704 | 704 | $html = ''; |
705 | 705 | |
706 | 706 | // Write charts |
707 | 707 | $chart = $this->sheetCharts[$coordinates] ?? null; |
708 | 708 | if ($chart !== null) { |
709 | - $chartCoordinates = $chart->getTopLeftPosition(); |
|
710 | - $chartFileName = File::sysGetTempDir() . '/' . uniqid('', true) . '.png'; |
|
711 | - $renderedWidth = $chart->getRenderedWidth(); |
|
712 | - $renderedHeight = $chart->getRenderedHeight(); |
|
713 | - if ($renderedWidth === null || $renderedHeight === null) { |
|
709 | + $chartCoordinates = $chart->getTopLeftPosition(); |
|
710 | + $chartFileName = File::sysGetTempDir() . '/' . uniqid('', true) . '.png'; |
|
711 | + $renderedWidth = $chart->getRenderedWidth(); |
|
712 | + $renderedHeight = $chart->getRenderedHeight(); |
|
713 | + if ($renderedWidth === null || $renderedHeight === null) { |
|
714 | 714 | $this->adjustRendererPositions($chart, $worksheet); |
715 | - } |
|
716 | - $title = $chart->getTitle(); |
|
717 | - $caption = null; |
|
718 | - $filedesc = ''; |
|
719 | - if ($title !== null) { |
|
715 | + } |
|
716 | + $title = $chart->getTitle(); |
|
717 | + $caption = null; |
|
718 | + $filedesc = ''; |
|
719 | + if ($title !== null) { |
|
720 | 720 | $calculatedTitle = $title->getCalculatedTitle($worksheet->getParent()); |
721 | 721 | if ($calculatedTitle !== null) { |
722 | - $caption = $title->getCaption(); |
|
723 | - $title->setCaption($calculatedTitle); |
|
722 | + $caption = $title->getCaption(); |
|
723 | + $title->setCaption($calculatedTitle); |
|
724 | 724 | } |
725 | 725 | $filedesc = $title->getCaptionText($worksheet->getParent()); |
726 | - } |
|
727 | - $renderSuccessful = $chart->render($chartFileName); |
|
728 | - $chart->setRenderedWidth($renderedWidth); |
|
729 | - $chart->setRenderedHeight($renderedHeight); |
|
730 | - if (isset($title, $caption)) { |
|
726 | + } |
|
727 | + $renderSuccessful = $chart->render($chartFileName); |
|
728 | + $chart->setRenderedWidth($renderedWidth); |
|
729 | + $chart->setRenderedHeight($renderedHeight); |
|
730 | + if (isset($title, $caption)) { |
|
731 | 731 | $title->setCaption($caption); |
732 | - } |
|
733 | - if (!$renderSuccessful) { |
|
732 | + } |
|
733 | + if (!$renderSuccessful) { |
|
734 | 734 | return ''; |
735 | - } |
|
735 | + } |
|
736 | 736 | |
737 | - $html .= PHP_EOL; |
|
738 | - $imageDetails = getimagesize($chartFileName) ?: ['', '', 'mime' => '']; |
|
737 | + $html .= PHP_EOL; |
|
738 | + $imageDetails = getimagesize($chartFileName) ?: ['', '', 'mime' => '']; |
|
739 | 739 | |
740 | - $filedesc = $filedesc ? htmlspecialchars($filedesc, ENT_QUOTES) : 'Embedded chart'; |
|
741 | - $picture = file_get_contents($chartFileName); |
|
742 | - unlink($chartFileName); |
|
743 | - if ($picture !== false) { |
|
740 | + $filedesc = $filedesc ? htmlspecialchars($filedesc, ENT_QUOTES) : 'Embedded chart'; |
|
741 | + $picture = file_get_contents($chartFileName); |
|
742 | + unlink($chartFileName); |
|
743 | + if ($picture !== false) { |
|
744 | 744 | $base64 = base64_encode($picture); |
745 | 745 | $imageData = 'data:' . $imageDetails['mime'] . ';base64,' . $base64; |
746 | 746 | |
747 | 747 | $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 . '" alt="' . $filedesc . '" />' . PHP_EOL; |
748 | - } |
|
748 | + } |
|
749 | 749 | } |
750 | 750 | |
751 | 751 | // Return |
752 | 752 | return $html; |
753 | - } |
|
753 | + } |
|
754 | 754 | |
755 | - private function adjustRendererPositions(Chart $chart, Worksheet $sheet): void |
|
756 | - { |
|
755 | + private function adjustRendererPositions(Chart $chart, Worksheet $sheet): void |
|
756 | + { |
|
757 | 757 | $topLeft = $chart->getTopLeftPosition(); |
758 | 758 | $bottomRight = $chart->getBottomRightPosition(); |
759 | 759 | $tlCell = $topLeft['cell']; |
760 | 760 | $brCell = $bottomRight['cell']; |
761 | 761 | if ($tlCell !== '' && $brCell !== '') { |
762 | - $tlCoordinate = Coordinate::indexesFromString($tlCell); |
|
763 | - $brCoordinate = Coordinate::indexesFromString($brCell); |
|
764 | - $totalHeight = 0.0; |
|
765 | - $totalWidth = 0.0; |
|
766 | - $defaultRowHeight = $sheet->getDefaultRowDimension()->getRowHeight(); |
|
767 | - $defaultRowHeight = SharedDrawing::pointsToPixels(($defaultRowHeight >= 0) ? $defaultRowHeight : SharedFont::getDefaultRowHeightByFont($this->defaultFont)); |
|
768 | - if ($tlCoordinate[1] <= $brCoordinate[1] && $tlCoordinate[0] <= $brCoordinate[0]) { |
|
762 | + $tlCoordinate = Coordinate::indexesFromString($tlCell); |
|
763 | + $brCoordinate = Coordinate::indexesFromString($brCell); |
|
764 | + $totalHeight = 0.0; |
|
765 | + $totalWidth = 0.0; |
|
766 | + $defaultRowHeight = $sheet->getDefaultRowDimension()->getRowHeight(); |
|
767 | + $defaultRowHeight = SharedDrawing::pointsToPixels(($defaultRowHeight >= 0) ? $defaultRowHeight : SharedFont::getDefaultRowHeightByFont($this->defaultFont)); |
|
768 | + if ($tlCoordinate[1] <= $brCoordinate[1] && $tlCoordinate[0] <= $brCoordinate[0]) { |
|
769 | 769 | for ($row = $tlCoordinate[1]; $row <= $brCoordinate[1]; ++$row) { |
770 | - $height = $sheet->getRowDimension($row)->getRowHeight('pt'); |
|
771 | - $totalHeight += ($height >= 0) ? $height : $defaultRowHeight; |
|
770 | + $height = $sheet->getRowDimension($row)->getRowHeight('pt'); |
|
771 | + $totalHeight += ($height >= 0) ? $height : $defaultRowHeight; |
|
772 | 772 | } |
773 | 773 | $rightEdge = $brCoordinate[2]; |
774 | 774 | ++$rightEdge; |
775 | 775 | for ($column = $tlCoordinate[2]; $column !== $rightEdge; ++$column) { |
776 | - $width = $sheet->getColumnDimension($column)->getWidth(); |
|
777 | - $width = ($width < 0) ? self::DEFAULT_CELL_WIDTH_PIXELS : SharedDrawing::cellDimensionToPixels($sheet->getColumnDimension($column)->getWidth(), $this->defaultFont); |
|
778 | - $totalWidth += $width; |
|
776 | + $width = $sheet->getColumnDimension($column)->getWidth(); |
|
777 | + $width = ($width < 0) ? self::DEFAULT_CELL_WIDTH_PIXELS : SharedDrawing::cellDimensionToPixels($sheet->getColumnDimension($column)->getWidth(), $this->defaultFont); |
|
778 | + $totalWidth += $width; |
|
779 | 779 | } |
780 | 780 | $chart->setRenderedWidth($totalWidth); |
781 | 781 | $chart->setRenderedHeight($totalHeight); |
782 | - } |
|
782 | + } |
|
783 | + } |
|
783 | 784 | } |
784 | - } |
|
785 | 785 | |
786 | - /** |
|
787 | - * Generate CSS styles. |
|
788 | - * |
|
789 | - * @param bool $generateSurroundingHTML Generate surrounding HTML tags? (<style> and </style>) |
|
790 | - */ |
|
791 | - public function generateStyles(bool $generateSurroundingHTML = true): string |
|
792 | - { |
|
786 | + /** |
|
787 | + * Generate CSS styles. |
|
788 | + * |
|
789 | + * @param bool $generateSurroundingHTML Generate surrounding HTML tags? (<style> and </style>) |
|
790 | + */ |
|
791 | + public function generateStyles(bool $generateSurroundingHTML = true): string |
|
792 | + { |
|
793 | 793 | // Build CSS |
794 | 794 | $css = $this->buildCSS($generateSurroundingHTML); |
795 | 795 | |
@@ -798,60 +798,60 @@ discard block |
||
798 | 798 | |
799 | 799 | // Start styles |
800 | 800 | if ($generateSurroundingHTML) { |
801 | - $html .= ' <style type="text/css">' . PHP_EOL; |
|
802 | - $html .= (array_key_exists('html', $css)) ? (' html { ' . $this->assembleCSS($css['html']) . ' }' . PHP_EOL) : ''; |
|
801 | + $html .= ' <style type="text/css">' . PHP_EOL; |
|
802 | + $html .= (array_key_exists('html', $css)) ? (' html { ' . $this->assembleCSS($css['html']) . ' }' . PHP_EOL) : ''; |
|
803 | 803 | } |
804 | 804 | |
805 | 805 | // Write all other styles |
806 | 806 | foreach ($css as $styleName => $styleDefinition) { |
807 | - if ($styleName != 'html') { |
|
807 | + if ($styleName != 'html') { |
|
808 | 808 | $html .= ' ' . $styleName . ' { ' . $this->assembleCSS($styleDefinition) . ' }' . PHP_EOL; |
809 | - } |
|
809 | + } |
|
810 | 810 | } |
811 | 811 | $html .= $this->generatePageDeclarations(false); |
812 | 812 | |
813 | 813 | // End styles |
814 | 814 | if ($generateSurroundingHTML) { |
815 | - $html .= ' </style>' . PHP_EOL; |
|
815 | + $html .= ' </style>' . PHP_EOL; |
|
816 | 816 | } |
817 | 817 | |
818 | 818 | // Return |
819 | 819 | return $html; |
820 | - } |
|
820 | + } |
|
821 | 821 | |
822 | - private function buildCssRowHeights(Worksheet $sheet, array &$css, int $sheetIndex): void |
|
823 | - { |
|
822 | + private function buildCssRowHeights(Worksheet $sheet, array &$css, int $sheetIndex): void |
|
823 | + { |
|
824 | 824 | // Calculate row heights |
825 | 825 | foreach ($sheet->getRowDimensions() as $rowDimension) { |
826 | - $row = $rowDimension->getRowIndex() - 1; |
|
826 | + $row = $rowDimension->getRowIndex() - 1; |
|
827 | 827 | |
828 | - // table.sheetN tr.rowYYYYYY { } |
|
829 | - $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = []; |
|
828 | + // table.sheetN tr.rowYYYYYY { } |
|
829 | + $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = []; |
|
830 | 830 | |
831 | - if ($rowDimension->getRowHeight() != -1) { |
|
831 | + if ($rowDimension->getRowHeight() != -1) { |
|
832 | 832 | $pt_height = $rowDimension->getRowHeight(); |
833 | 833 | $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; |
834 | - } |
|
835 | - if ($rowDimension->getVisible() === false) { |
|
834 | + } |
|
835 | + if ($rowDimension->getVisible() === false) { |
|
836 | 836 | $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; |
837 | 837 | $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden'; |
838 | - } |
|
838 | + } |
|
839 | + } |
|
839 | 840 | } |
840 | - } |
|
841 | 841 | |
842 | - private function buildCssPerSheet(Worksheet $sheet, array &$css): void |
|
843 | - { |
|
842 | + private function buildCssPerSheet(Worksheet $sheet, array &$css): void |
|
843 | + { |
|
844 | 844 | // Calculate hash code |
845 | 845 | $sheetIndex = $sheet->getParentOrThrow()->getIndex($sheet); |
846 | 846 | $setup = $sheet->getPageSetup(); |
847 | 847 | if ($setup->getFitToPage() && $setup->getFitToHeight() === 1) { |
848 | - $css["table.sheet$sheetIndex"]['page-break-inside'] = 'avoid'; |
|
849 | - $css["table.sheet$sheetIndex"]['break-inside'] = 'avoid'; |
|
848 | + $css["table.sheet$sheetIndex"]['page-break-inside'] = 'avoid'; |
|
849 | + $css["table.sheet$sheetIndex"]['break-inside'] = 'avoid'; |
|
850 | 850 | } |
851 | 851 | $picture = $sheet->getBackgroundImage(); |
852 | 852 | if ($picture !== '') { |
853 | - $base64 = base64_encode($picture); |
|
854 | - $css["table.sheet$sheetIndex"]['background-image'] = 'url(data:' . $sheet->getBackgroundMime() . ';base64,' . $base64 . ')'; |
|
853 | + $base64 = base64_encode($picture); |
|
854 | + $css["table.sheet$sheetIndex"]['background-image'] = 'url(data:' . $sheet->getBackgroundMime() . ';base64,' . $base64 . ')'; |
|
855 | 855 | } |
856 | 856 | |
857 | 857 | // Build styles |
@@ -863,28 +863,28 @@ discard block |
||
863 | 863 | $column = -1; |
864 | 864 | $colStr = 'A'; |
865 | 865 | while ($column++ < $highestColumnIndex) { |
866 | - $this->columnWidths[$sheetIndex][$column] = self::DEFAULT_CELL_WIDTH_POINTS; // approximation |
|
867 | - if ($this->shouldGenerateColumn($sheet, $colStr)) { |
|
866 | + $this->columnWidths[$sheetIndex][$column] = self::DEFAULT_CELL_WIDTH_POINTS; // approximation |
|
867 | + if ($this->shouldGenerateColumn($sheet, $colStr)) { |
|
868 | 868 | $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = self::DEFAULT_CELL_WIDTH_POINTS . 'pt'; |
869 | - } |
|
870 | - ++$colStr; |
|
869 | + } |
|
870 | + ++$colStr; |
|
871 | 871 | } |
872 | 872 | |
873 | 873 | // col elements, loop through columnDimensions and set width |
874 | 874 | foreach ($sheet->getColumnDimensions() as $columnDimension) { |
875 | - $column = Coordinate::columnIndexFromString($columnDimension->getColumnIndex()) - 1; |
|
876 | - $width = SharedDrawing::cellDimensionToPixels($columnDimension->getWidth(), $this->defaultFont); |
|
877 | - $width = SharedDrawing::pixelsToPoints($width); |
|
878 | - if ($columnDimension->getVisible() === false) { |
|
875 | + $column = Coordinate::columnIndexFromString($columnDimension->getColumnIndex()) - 1; |
|
876 | + $width = SharedDrawing::cellDimensionToPixels($columnDimension->getWidth(), $this->defaultFont); |
|
877 | + $width = SharedDrawing::pixelsToPoints($width); |
|
878 | + if ($columnDimension->getVisible() === false) { |
|
879 | 879 | $css['table.sheet' . $sheetIndex . ' .column' . $column]['display'] = 'none'; |
880 | 880 | // This would be better but Firefox has an 11-year-old bug. |
881 | 881 | // https://bugzilla.mozilla.org/show_bug.cgi?id=819045 |
882 | 882 | //$css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse'; |
883 | - } |
|
884 | - if ($width >= 0) { |
|
883 | + } |
|
884 | + if ($width >= 0) { |
|
885 | 885 | $this->columnWidths[$sheetIndex][$column] = $width; |
886 | 886 | $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt'; |
887 | - } |
|
887 | + } |
|
888 | 888 | } |
889 | 889 | |
890 | 890 | // Default row height |
@@ -894,29 +894,29 @@ discard block |
||
894 | 894 | $css['table.sheet' . $sheetIndex . ' tr'] = []; |
895 | 895 | |
896 | 896 | if ($rowDimension->getRowHeight() == -1) { |
897 | - $pt_height = SharedFont::getDefaultRowHeightByFont($this->spreadsheet->getDefaultStyle()->getFont()); |
|
897 | + $pt_height = SharedFont::getDefaultRowHeightByFont($this->spreadsheet->getDefaultStyle()->getFont()); |
|
898 | 898 | } else { |
899 | - $pt_height = $rowDimension->getRowHeight(); |
|
899 | + $pt_height = $rowDimension->getRowHeight(); |
|
900 | 900 | } |
901 | 901 | $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; |
902 | 902 | if ($rowDimension->getVisible() === false) { |
903 | - $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; |
|
904 | - $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden'; |
|
903 | + $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; |
|
904 | + $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden'; |
|
905 | 905 | } |
906 | 906 | |
907 | 907 | $this->buildCssRowHeights($sheet, $css, $sheetIndex); |
908 | - } |
|
909 | - |
|
910 | - /** |
|
911 | - * Build CSS styles. |
|
912 | - * |
|
913 | - * @param bool $generateSurroundingHTML Generate surrounding HTML style? (html { }) |
|
914 | - */ |
|
915 | - public function buildCSS(bool $generateSurroundingHTML = true): array |
|
916 | - { |
|
908 | + } |
|
909 | + |
|
910 | + /** |
|
911 | + * Build CSS styles. |
|
912 | + * |
|
913 | + * @param bool $generateSurroundingHTML Generate surrounding HTML style? (html { }) |
|
914 | + */ |
|
915 | + public function buildCSS(bool $generateSurroundingHTML = true): array |
|
916 | + { |
|
917 | 917 | // Cached? |
918 | 918 | if ($this->cssStyles !== null) { |
919 | - return $this->cssStyles; |
|
919 | + return $this->cssStyles; |
|
920 | 920 | } |
921 | 921 | |
922 | 922 | // Ensure that spans have been calculated |
@@ -927,27 +927,27 @@ discard block |
||
927 | 927 | |
928 | 928 | // Start styles |
929 | 929 | if ($generateSurroundingHTML) { |
930 | - // html { } |
|
931 | - $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif'; |
|
932 | - $css['html']['font-size'] = '11pt'; |
|
933 | - $css['html']['background-color'] = 'white'; |
|
930 | + // html { } |
|
931 | + $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif'; |
|
932 | + $css['html']['font-size'] = '11pt'; |
|
933 | + $css['html']['background-color'] = 'white'; |
|
934 | 934 | } |
935 | 935 | |
936 | 936 | // CSS for comments as found in LibreOffice |
937 | 937 | $css['a.comment-indicator:hover + div.comment'] = [ |
938 | - 'background' => '#ffd', |
|
939 | - 'position' => 'absolute', |
|
940 | - 'display' => 'block', |
|
941 | - 'border' => '1px solid black', |
|
942 | - 'padding' => '0.5em', |
|
938 | + 'background' => '#ffd', |
|
939 | + 'position' => 'absolute', |
|
940 | + 'display' => 'block', |
|
941 | + 'border' => '1px solid black', |
|
942 | + 'padding' => '0.5em', |
|
943 | 943 | ]; |
944 | 944 | |
945 | 945 | $css['a.comment-indicator'] = [ |
946 | - 'background' => 'red', |
|
947 | - 'display' => 'inline-block', |
|
948 | - 'border' => '1px solid black', |
|
949 | - 'width' => '0.5em', |
|
950 | - 'height' => '0.5em', |
|
946 | + 'background' => 'red', |
|
947 | + 'display' => 'inline-block', |
|
948 | + 'border' => '1px solid black', |
|
949 | + 'width' => '0.5em', |
|
950 | + 'height' => '0.5em', |
|
951 | 951 | ]; |
952 | 952 | |
953 | 953 | $css['div.comment']['display'] = 'none'; |
@@ -975,103 +975,103 @@ discard block |
||
975 | 975 | |
976 | 976 | // Calculate cell style hashes |
977 | 977 | foreach ($this->spreadsheet->getCellXfCollection() as $index => $style) { |
978 | - $css['td.style' . $index . ', th.style' . $index] = $this->createCSSStyle($style); |
|
979 | - //$css['th.style' . $index] = $this->createCSSStyle($style); |
|
978 | + $css['td.style' . $index . ', th.style' . $index] = $this->createCSSStyle($style); |
|
979 | + //$css['th.style' . $index] = $this->createCSSStyle($style); |
|
980 | 980 | } |
981 | 981 | |
982 | 982 | // Fetch sheets |
983 | 983 | $sheets = []; |
984 | 984 | if (is_array($this->sheetIndex)) { |
985 | - foreach ($this->sheetIndex as $sheetIndex) { |
|
985 | + foreach ($this->sheetIndex as $sheetIndex) { |
|
986 | 986 | $sheets[] = $this->spreadsheet->getSheet($sheetIndex); |
987 | - } |
|
987 | + } |
|
988 | 988 | } elseif ($this->sheetIndex === null) { |
989 | - $sheets = $this->spreadsheet->getAllSheets(); |
|
989 | + $sheets = $this->spreadsheet->getAllSheets(); |
|
990 | 990 | } else { |
991 | - $sheets[] = $this->spreadsheet->getSheet($this->sheetIndex); |
|
991 | + $sheets[] = $this->spreadsheet->getSheet($this->sheetIndex); |
|
992 | 992 | } |
993 | 993 | |
994 | 994 | // Build styles per sheet |
995 | 995 | foreach ($sheets as $sheet) { |
996 | - $this->buildCssPerSheet($sheet, $css); |
|
996 | + $this->buildCssPerSheet($sheet, $css); |
|
997 | 997 | } |
998 | 998 | |
999 | 999 | // Cache |
1000 | 1000 | if ($this->cssStyles === null) { |
1001 | - $this->cssStyles = $css; |
|
1001 | + $this->cssStyles = $css; |
|
1002 | 1002 | } |
1003 | 1003 | |
1004 | 1004 | // Return |
1005 | 1005 | return $css; |
1006 | - } |
|
1006 | + } |
|
1007 | 1007 | |
1008 | - /** |
|
1009 | - * Create CSS style. |
|
1010 | - */ |
|
1011 | - private function createCSSStyle(Style $style): array |
|
1012 | - { |
|
1008 | + /** |
|
1009 | + * Create CSS style. |
|
1010 | + */ |
|
1011 | + private function createCSSStyle(Style $style): array |
|
1012 | + { |
|
1013 | 1013 | // Create CSS |
1014 | 1014 | return array_merge( |
1015 | - $this->createCSSStyleAlignment($style->getAlignment()), |
|
1016 | - $this->createCSSStyleBorders($style->getBorders()), |
|
1017 | - $this->createCSSStyleFont($style->getFont()), |
|
1018 | - $this->createCSSStyleFill($style->getFill()) |
|
1015 | + $this->createCSSStyleAlignment($style->getAlignment()), |
|
1016 | + $this->createCSSStyleBorders($style->getBorders()), |
|
1017 | + $this->createCSSStyleFont($style->getFont()), |
|
1018 | + $this->createCSSStyleFill($style->getFill()) |
|
1019 | 1019 | ); |
1020 | - } |
|
1020 | + } |
|
1021 | 1021 | |
1022 | - /** |
|
1023 | - * Create CSS style. |
|
1024 | - */ |
|
1025 | - private function createCSSStyleAlignment(Alignment $alignment): array |
|
1026 | - { |
|
1022 | + /** |
|
1023 | + * Create CSS style. |
|
1024 | + */ |
|
1025 | + private function createCSSStyleAlignment(Alignment $alignment): array |
|
1026 | + { |
|
1027 | 1027 | // Construct CSS |
1028 | 1028 | $css = []; |
1029 | 1029 | |
1030 | 1030 | // Create CSS |
1031 | 1031 | $verticalAlign = $this->mapVAlign($alignment->getVertical() ?? ''); |
1032 | 1032 | if ($verticalAlign) { |
1033 | - $css['vertical-align'] = $verticalAlign; |
|
1033 | + $css['vertical-align'] = $verticalAlign; |
|
1034 | 1034 | } |
1035 | 1035 | $textAlign = $this->mapHAlign($alignment->getHorizontal() ?? ''); |
1036 | 1036 | if ($textAlign) { |
1037 | - $css['text-align'] = $textAlign; |
|
1038 | - if (in_array($textAlign, ['left', 'right'])) { |
|
1037 | + $css['text-align'] = $textAlign; |
|
1038 | + if (in_array($textAlign, ['left', 'right'])) { |
|
1039 | 1039 | $css['padding-' . $textAlign] = (string) ((int) $alignment->getIndent() * 9) . 'px'; |
1040 | - } |
|
1040 | + } |
|
1041 | 1041 | } |
1042 | 1042 | $rotation = $alignment->getTextRotation(); |
1043 | 1043 | if ($rotation !== 0 && $rotation !== Alignment::TEXTROTATION_STACK_PHPSPREADSHEET) { |
1044 | - if ($this instanceof Pdf\Mpdf) { |
|
1044 | + if ($this instanceof Pdf\Mpdf) { |
|
1045 | 1045 | $css['text-rotate'] = "$rotation"; |
1046 | - } else { |
|
1046 | + } else { |
|
1047 | 1047 | $css['transform'] = "rotate({$rotation}deg)"; |
1048 | - } |
|
1048 | + } |
|
1049 | 1049 | } |
1050 | 1050 | |
1051 | 1051 | return $css; |
1052 | - } |
|
1052 | + } |
|
1053 | 1053 | |
1054 | - /** |
|
1055 | - * Create CSS style. |
|
1056 | - */ |
|
1057 | - private function createCSSStyleFont(Font $font): array |
|
1058 | - { |
|
1054 | + /** |
|
1055 | + * Create CSS style. |
|
1056 | + */ |
|
1057 | + private function createCSSStyleFont(Font $font): array |
|
1058 | + { |
|
1059 | 1059 | // Construct CSS |
1060 | 1060 | $css = []; |
1061 | 1061 | |
1062 | 1062 | // Create CSS |
1063 | 1063 | if ($font->getBold()) { |
1064 | - $css['font-weight'] = 'bold'; |
|
1064 | + $css['font-weight'] = 'bold'; |
|
1065 | 1065 | } |
1066 | 1066 | if ($font->getUnderline() != Font::UNDERLINE_NONE && $font->getStrikethrough()) { |
1067 | - $css['text-decoration'] = 'underline line-through'; |
|
1067 | + $css['text-decoration'] = 'underline line-through'; |
|
1068 | 1068 | } elseif ($font->getUnderline() != Font::UNDERLINE_NONE) { |
1069 | - $css['text-decoration'] = 'underline'; |
|
1069 | + $css['text-decoration'] = 'underline'; |
|
1070 | 1070 | } elseif ($font->getStrikethrough()) { |
1071 | - $css['text-decoration'] = 'line-through'; |
|
1071 | + $css['text-decoration'] = 'line-through'; |
|
1072 | 1072 | } |
1073 | 1073 | if ($font->getItalic()) { |
1074 | - $css['font-style'] = 'italic'; |
|
1074 | + $css['font-style'] = 'italic'; |
|
1075 | 1075 | } |
1076 | 1076 | |
1077 | 1077 | $css['color'] = '#' . $font->getColor()->getRGB(); |
@@ -1079,137 +1079,137 @@ discard block |
||
1079 | 1079 | $css['font-size'] = $font->getSize() . 'pt'; |
1080 | 1080 | |
1081 | 1081 | return $css; |
1082 | - } |
|
1083 | - |
|
1084 | - /** |
|
1085 | - * Create CSS style. |
|
1086 | - * |
|
1087 | - * @param Borders $borders Borders |
|
1088 | - */ |
|
1089 | - private function createCSSStyleBorders(Borders $borders): array |
|
1090 | - { |
|
1082 | + } |
|
1083 | + |
|
1084 | + /** |
|
1085 | + * Create CSS style. |
|
1086 | + * |
|
1087 | + * @param Borders $borders Borders |
|
1088 | + */ |
|
1089 | + private function createCSSStyleBorders(Borders $borders): array |
|
1090 | + { |
|
1091 | 1091 | // Construct CSS |
1092 | 1092 | $css = []; |
1093 | 1093 | |
1094 | 1094 | // Create CSS |
1095 | 1095 | if (!($this instanceof Pdf\Mpdf)) { |
1096 | - $css['border-bottom'] = $this->createCSSStyleBorder($borders->getBottom()); |
|
1097 | - $css['border-top'] = $this->createCSSStyleBorder($borders->getTop()); |
|
1098 | - $css['border-left'] = $this->createCSSStyleBorder($borders->getLeft()); |
|
1099 | - $css['border-right'] = $this->createCSSStyleBorder($borders->getRight()); |
|
1096 | + $css['border-bottom'] = $this->createCSSStyleBorder($borders->getBottom()); |
|
1097 | + $css['border-top'] = $this->createCSSStyleBorder($borders->getTop()); |
|
1098 | + $css['border-left'] = $this->createCSSStyleBorder($borders->getLeft()); |
|
1099 | + $css['border-right'] = $this->createCSSStyleBorder($borders->getRight()); |
|
1100 | 1100 | } else { |
1101 | - // Mpdf doesn't process !important, so omit unimportant border none |
|
1102 | - if ($borders->getBottom()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1101 | + // Mpdf doesn't process !important, so omit unimportant border none |
|
1102 | + if ($borders->getBottom()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1103 | 1103 | $css['border-bottom'] = $this->createCSSStyleBorder($borders->getBottom()); |
1104 | - } |
|
1105 | - if ($borders->getTop()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1104 | + } |
|
1105 | + if ($borders->getTop()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1106 | 1106 | $css['border-top'] = $this->createCSSStyleBorder($borders->getTop()); |
1107 | - } |
|
1108 | - if ($borders->getLeft()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1107 | + } |
|
1108 | + if ($borders->getLeft()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1109 | 1109 | $css['border-left'] = $this->createCSSStyleBorder($borders->getLeft()); |
1110 | - } |
|
1111 | - if ($borders->getRight()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1110 | + } |
|
1111 | + if ($borders->getRight()->getBorderStyle() !== Border::BORDER_NONE) { |
|
1112 | 1112 | $css['border-right'] = $this->createCSSStyleBorder($borders->getRight()); |
1113 | - } |
|
1113 | + } |
|
1114 | 1114 | } |
1115 | 1115 | |
1116 | 1116 | return $css; |
1117 | - } |
|
1118 | - |
|
1119 | - /** |
|
1120 | - * Create CSS style. |
|
1121 | - * |
|
1122 | - * @param Border $border Border |
|
1123 | - */ |
|
1124 | - private function createCSSStyleBorder(Border $border): string |
|
1125 | - { |
|
1117 | + } |
|
1118 | + |
|
1119 | + /** |
|
1120 | + * Create CSS style. |
|
1121 | + * |
|
1122 | + * @param Border $border Border |
|
1123 | + */ |
|
1124 | + private function createCSSStyleBorder(Border $border): string |
|
1125 | + { |
|
1126 | 1126 | // Create CSS - add !important to non-none border styles for merged cells |
1127 | 1127 | $borderStyle = $this->mapBorderStyle($border->getBorderStyle()); |
1128 | 1128 | |
1129 | 1129 | return $borderStyle . ' #' . $border->getColor()->getRGB() . (($borderStyle === self::BORDER_NONE) ? '' : ' !important'); |
1130 | - } |
|
1131 | - |
|
1132 | - /** |
|
1133 | - * Create CSS style (Fill). |
|
1134 | - * |
|
1135 | - * @param Fill $fill Fill |
|
1136 | - */ |
|
1137 | - private function createCSSStyleFill(Fill $fill): array |
|
1138 | - { |
|
1130 | + } |
|
1131 | + |
|
1132 | + /** |
|
1133 | + * Create CSS style (Fill). |
|
1134 | + * |
|
1135 | + * @param Fill $fill Fill |
|
1136 | + */ |
|
1137 | + private function createCSSStyleFill(Fill $fill): array |
|
1138 | + { |
|
1139 | 1139 | // Construct HTML |
1140 | 1140 | $css = []; |
1141 | 1141 | |
1142 | 1142 | // Create CSS |
1143 | 1143 | if ($fill->getFillType() !== Fill::FILL_NONE) { |
1144 | - $value = $fill->getFillType() == Fill::FILL_NONE |
|
1144 | + $value = $fill->getFillType() == Fill::FILL_NONE |
|
1145 | 1145 | ? 'white' : '#' . $fill->getStartColor()->getRGB(); |
1146 | - $css['background-color'] = $value; |
|
1146 | + $css['background-color'] = $value; |
|
1147 | 1147 | } |
1148 | 1148 | |
1149 | 1149 | return $css; |
1150 | - } |
|
1150 | + } |
|
1151 | 1151 | |
1152 | - /** |
|
1153 | - * Generate HTML footer. |
|
1154 | - */ |
|
1155 | - public function generateHTMLFooter(): string |
|
1156 | - { |
|
1152 | + /** |
|
1153 | + * Generate HTML footer. |
|
1154 | + */ |
|
1155 | + public function generateHTMLFooter(): string |
|
1156 | + { |
|
1157 | 1157 | // Construct HTML |
1158 | 1158 | $html = ''; |
1159 | 1159 | $html .= ' </body>' . PHP_EOL; |
1160 | 1160 | $html .= '</html>' . PHP_EOL; |
1161 | 1161 | |
1162 | 1162 | return $html; |
1163 | - } |
|
1163 | + } |
|
1164 | 1164 | |
1165 | - private function generateTableTagInline(Worksheet $worksheet, string $id): string |
|
1166 | - { |
|
1165 | + private function generateTableTagInline(Worksheet $worksheet, string $id): string |
|
1166 | + { |
|
1167 | 1167 | $style = isset($this->cssStyles['table']) |
1168 | 1168 | ? $this->assembleCSS($this->cssStyles['table']) : ''; |
1169 | 1169 | |
1170 | 1170 | $prntgrid = $worksheet->getPrintGridlines(); |
1171 | 1171 | $viewgrid = $this->isPdf ? $prntgrid : $worksheet->getShowGridlines(); |
1172 | 1172 | if ($viewgrid && $prntgrid) { |
1173 | - $html = " <table border='1' cellpadding='1' $id cellspacing='1' style='$style' class='gridlines gridlinesp'>" . PHP_EOL; |
|
1173 | + $html = " <table border='1' cellpadding='1' $id cellspacing='1' style='$style' class='gridlines gridlinesp'>" . PHP_EOL; |
|
1174 | 1174 | } elseif ($viewgrid) { |
1175 | - $html = " <table border='0' cellpadding='0' $id cellspacing='0' style='$style' class='gridlines'>" . PHP_EOL; |
|
1175 | + $html = " <table border='0' cellpadding='0' $id cellspacing='0' style='$style' class='gridlines'>" . PHP_EOL; |
|
1176 | 1176 | } elseif ($prntgrid) { |
1177 | - $html = " <table border='0' cellpadding='0' $id cellspacing='0' style='$style' class='gridlinesp'>" . PHP_EOL; |
|
1177 | + $html = " <table border='0' cellpadding='0' $id cellspacing='0' style='$style' class='gridlinesp'>" . PHP_EOL; |
|
1178 | 1178 | } else { |
1179 | - $html = " <table border='0' cellpadding='1' $id cellspacing='0' style='$style'>" . PHP_EOL; |
|
1179 | + $html = " <table border='0' cellpadding='1' $id cellspacing='0' style='$style'>" . PHP_EOL; |
|
1180 | 1180 | } |
1181 | 1181 | |
1182 | 1182 | return $html; |
1183 | - } |
|
1183 | + } |
|
1184 | 1184 | |
1185 | - private function generateTableTag(Worksheet $worksheet, string $id, string &$html, int $sheetIndex): void |
|
1186 | - { |
|
1185 | + private function generateTableTag(Worksheet $worksheet, string $id, string &$html, int $sheetIndex): void |
|
1186 | + { |
|
1187 | 1187 | if (!$this->useInlineCss) { |
1188 | - $gridlines = $worksheet->getShowGridlines() ? ' gridlines' : ''; |
|
1189 | - $gridlinesp = $worksheet->getPrintGridlines() ? ' gridlinesp' : ''; |
|
1190 | - $html .= " <table border='0' cellpadding='0' cellspacing='0' $id class='sheet$sheetIndex$gridlines$gridlinesp'>" . PHP_EOL; |
|
1188 | + $gridlines = $worksheet->getShowGridlines() ? ' gridlines' : ''; |
|
1189 | + $gridlinesp = $worksheet->getPrintGridlines() ? ' gridlinesp' : ''; |
|
1190 | + $html .= " <table border='0' cellpadding='0' cellspacing='0' $id class='sheet$sheetIndex$gridlines$gridlinesp'>" . PHP_EOL; |
|
1191 | 1191 | } else { |
1192 | - $html .= $this->generateTableTagInline($worksheet, $id); |
|
1193 | - } |
|
1194 | - } |
|
1195 | - |
|
1196 | - /** |
|
1197 | - * Generate table header. |
|
1198 | - * |
|
1199 | - * @param Worksheet $worksheet The worksheet for the table we are writing |
|
1200 | - * @param bool $showid whether or not to add id to table tag |
|
1201 | - */ |
|
1202 | - private function generateTableHeader(Worksheet $worksheet, bool $showid = true): string |
|
1203 | - { |
|
1192 | + $html .= $this->generateTableTagInline($worksheet, $id); |
|
1193 | + } |
|
1194 | + } |
|
1195 | + |
|
1196 | + /** |
|
1197 | + * Generate table header. |
|
1198 | + * |
|
1199 | + * @param Worksheet $worksheet The worksheet for the table we are writing |
|
1200 | + * @param bool $showid whether or not to add id to table tag |
|
1201 | + */ |
|
1202 | + private function generateTableHeader(Worksheet $worksheet, bool $showid = true): string |
|
1203 | + { |
|
1204 | 1204 | $sheetIndex = $worksheet->getParentOrThrow()->getIndex($worksheet); |
1205 | 1205 | |
1206 | 1206 | // Construct HTML |
1207 | 1207 | $html = ''; |
1208 | 1208 | $id = $showid ? "id='sheet$sheetIndex'" : ''; |
1209 | 1209 | if ($showid) { |
1210 | - $html .= "<div style='page: page$sheetIndex'>" . PHP_EOL; |
|
1210 | + $html .= "<div style='page: page$sheetIndex'>" . PHP_EOL; |
|
1211 | 1211 | } else { |
1212 | - $html .= "<div style='page: page$sheetIndex' class='scrpgbrk'>" . PHP_EOL; |
|
1212 | + $html .= "<div style='page: page$sheetIndex' class='scrpgbrk'>" . PHP_EOL; |
|
1213 | 1213 | } |
1214 | 1214 | |
1215 | 1215 | $this->generateTableTag($worksheet, $id, $html, $sheetIndex); |
@@ -1218,112 +1218,112 @@ discard block |
||
1218 | 1218 | $highestColumnIndex = Coordinate::columnIndexFromString($worksheet->getHighestColumn()) - 1; |
1219 | 1219 | $i = -1; |
1220 | 1220 | while ($i++ < $highestColumnIndex) { |
1221 | - if (!$this->useInlineCss) { |
|
1221 | + if (!$this->useInlineCss) { |
|
1222 | 1222 | $html .= ' <col class="col' . $i . '" />' . PHP_EOL; |
1223 | - } else { |
|
1223 | + } else { |
|
1224 | 1224 | $style = isset($this->cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) |
1225 | 1225 | ? $this->assembleCSS($this->cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : ''; |
1226 | 1226 | $html .= ' <col style="' . $style . '" />' . PHP_EOL; |
1227 | - } |
|
1227 | + } |
|
1228 | 1228 | } |
1229 | 1229 | |
1230 | 1230 | return $html; |
1231 | - } |
|
1231 | + } |
|
1232 | 1232 | |
1233 | - /** |
|
1234 | - * Generate table footer. |
|
1235 | - */ |
|
1236 | - private function generateTableFooter(): string |
|
1237 | - { |
|
1233 | + /** |
|
1234 | + * Generate table footer. |
|
1235 | + */ |
|
1236 | + private function generateTableFooter(): string |
|
1237 | + { |
|
1238 | 1238 | return ' </tbody></table>' . PHP_EOL . '</div>' . PHP_EOL; |
1239 | - } |
|
1240 | - |
|
1241 | - /** |
|
1242 | - * Generate row start. |
|
1243 | - * |
|
1244 | - * @param int $sheetIndex Sheet index (0-based) |
|
1245 | - * @param int $row row number |
|
1246 | - */ |
|
1247 | - private function generateRowStart(Worksheet $worksheet, int $sheetIndex, int $row): string |
|
1248 | - { |
|
1239 | + } |
|
1240 | + |
|
1241 | + /** |
|
1242 | + * Generate row start. |
|
1243 | + * |
|
1244 | + * @param int $sheetIndex Sheet index (0-based) |
|
1245 | + * @param int $row row number |
|
1246 | + */ |
|
1247 | + private function generateRowStart(Worksheet $worksheet, int $sheetIndex, int $row): string |
|
1248 | + { |
|
1249 | 1249 | $html = ''; |
1250 | 1250 | if (count($worksheet->getBreaks()) > 0) { |
1251 | - $breaks = $worksheet->getRowBreaks(); |
|
1251 | + $breaks = $worksheet->getRowBreaks(); |
|
1252 | 1252 | |
1253 | - // check if a break is needed before this row |
|
1254 | - if (isset($breaks['A' . $row])) { |
|
1253 | + // check if a break is needed before this row |
|
1254 | + if (isset($breaks['A' . $row])) { |
|
1255 | 1255 | // close table: </table> |
1256 | 1256 | $html .= $this->generateTableFooter(); |
1257 | 1257 | if ($this->isPdf && $this->useInlineCss) { |
1258 | - $html .= '<div style="page-break-before:always" />'; |
|
1258 | + $html .= '<div style="page-break-before:always" />'; |
|
1259 | 1259 | } |
1260 | 1260 | |
1261 | 1261 | // open table again: <table> + <col> etc. |
1262 | 1262 | $html .= $this->generateTableHeader($worksheet, false); |
1263 | 1263 | $html .= '<tbody>' . PHP_EOL; |
1264 | - } |
|
1264 | + } |
|
1265 | 1265 | } |
1266 | 1266 | |
1267 | 1267 | // Write row start |
1268 | 1268 | if (!$this->useInlineCss) { |
1269 | - $html .= ' <tr class="row' . $row . '">' . PHP_EOL; |
|
1269 | + $html .= ' <tr class="row' . $row . '">' . PHP_EOL; |
|
1270 | 1270 | } else { |
1271 | - $style = isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $row]) |
|
1271 | + $style = isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $row]) |
|
1272 | 1272 | ? $this->assembleCSS($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $row]) : ''; |
1273 | 1273 | |
1274 | - $html .= ' <tr style="' . $style . '">' . PHP_EOL; |
|
1274 | + $html .= ' <tr style="' . $style . '">' . PHP_EOL; |
|
1275 | 1275 | } |
1276 | 1276 | |
1277 | 1277 | return $html; |
1278 | - } |
|
1278 | + } |
|
1279 | 1279 | |
1280 | - private function generateRowCellCss(Worksheet $worksheet, string $cellAddress, int $row, int $columnNumber): array |
|
1281 | - { |
|
1280 | + private function generateRowCellCss(Worksheet $worksheet, string $cellAddress, int $row, int $columnNumber): array |
|
1281 | + { |
|
1282 | 1282 | $cell = ($cellAddress > '') ? $worksheet->getCellCollection()->get($cellAddress) : ''; |
1283 | 1283 | $coordinate = Coordinate::stringFromColumnIndex($columnNumber + 1) . ($row + 1); |
1284 | 1284 | if (!$this->useInlineCss) { |
1285 | - $cssClass = 'column' . $columnNumber; |
|
1285 | + $cssClass = 'column' . $columnNumber; |
|
1286 | 1286 | } else { |
1287 | - $cssClass = []; |
|
1288 | - // The statements below do nothing. |
|
1289 | - // Commenting out the code rather than deleting it |
|
1290 | - // in case someone can figure out what their intent was. |
|
1291 | - //if ($cellType == 'th') { |
|
1292 | - // if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum])) { |
|
1293 | - // $this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum]; |
|
1294 | - // } |
|
1295 | - //} else { |
|
1296 | - // if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) { |
|
1297 | - // $this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum]; |
|
1298 | - // } |
|
1299 | - //} |
|
1300 | - // End of mystery statements. |
|
1287 | + $cssClass = []; |
|
1288 | + // The statements below do nothing. |
|
1289 | + // Commenting out the code rather than deleting it |
|
1290 | + // in case someone can figure out what their intent was. |
|
1291 | + //if ($cellType == 'th') { |
|
1292 | + // if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum])) { |
|
1293 | + // $this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum]; |
|
1294 | + // } |
|
1295 | + //} else { |
|
1296 | + // if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) { |
|
1297 | + // $this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum]; |
|
1298 | + // } |
|
1299 | + //} |
|
1300 | + // End of mystery statements. |
|
1301 | 1301 | } |
1302 | 1302 | |
1303 | 1303 | return [$cell, $cssClass, $coordinate]; |
1304 | - } |
|
1304 | + } |
|
1305 | 1305 | |
1306 | - private function generateRowCellDataValueRich(RichText $richText): string |
|
1307 | - { |
|
1306 | + private function generateRowCellDataValueRich(RichText $richText): string |
|
1307 | + { |
|
1308 | 1308 | $cellData = ''; |
1309 | 1309 | // Loop through rich text elements |
1310 | 1310 | $elements = $richText->getRichTextElements(); |
1311 | 1311 | foreach ($elements as $element) { |
1312 | - // Rich text start? |
|
1313 | - if ($element instanceof Run) { |
|
1312 | + // Rich text start? |
|
1313 | + if ($element instanceof Run) { |
|
1314 | 1314 | $cellEnd = ''; |
1315 | 1315 | if ($element->getFont() !== null) { |
1316 | - $cellData .= '<span style="' . $this->assembleCSS($this->createCSSStyleFont($element->getFont())) . '">'; |
|
1316 | + $cellData .= '<span style="' . $this->assembleCSS($this->createCSSStyleFont($element->getFont())) . '">'; |
|
1317 | 1317 | |
1318 | - if ($element->getFont()->getSuperscript()) { |
|
1318 | + if ($element->getFont()->getSuperscript()) { |
|
1319 | 1319 | $cellData .= '<sup>'; |
1320 | 1320 | $cellEnd = '</sup>'; |
1321 | - } elseif ($element->getFont()->getSubscript()) { |
|
1321 | + } elseif ($element->getFont()->getSubscript()) { |
|
1322 | 1322 | $cellData .= '<sub>'; |
1323 | 1323 | $cellEnd = '</sub>'; |
1324 | - } |
|
1324 | + } |
|
1325 | 1325 | } else { |
1326 | - $cellData .= '<span>'; |
|
1326 | + $cellData .= '<span>'; |
|
1327 | 1327 | } |
1328 | 1328 | |
1329 | 1329 | // Convert UTF8 data to PCDATA |
@@ -1333,105 +1333,105 @@ discard block |
||
1333 | 1333 | $cellData .= $cellEnd; |
1334 | 1334 | |
1335 | 1335 | $cellData .= '</span>'; |
1336 | - } else { |
|
1336 | + } else { |
|
1337 | 1337 | // Convert UTF8 data to PCDATA |
1338 | 1338 | $cellText = $element->getText(); |
1339 | 1339 | $cellData .= htmlspecialchars($cellText, Settings::htmlEntityFlags()); |
1340 | - } |
|
1340 | + } |
|
1341 | 1341 | } |
1342 | 1342 | |
1343 | 1343 | return nl2br($cellData); |
1344 | - } |
|
1344 | + } |
|
1345 | 1345 | |
1346 | - private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, string &$cellData): void |
|
1347 | - { |
|
1346 | + private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, string &$cellData): void |
|
1347 | + { |
|
1348 | 1348 | if ($cell->getValue() instanceof RichText) { |
1349 | - $cellData .= $this->generateRowCellDataValueRich($cell->getValue()); |
|
1349 | + $cellData .= $this->generateRowCellDataValueRich($cell->getValue()); |
|
1350 | 1350 | } else { |
1351 | - $origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue(); |
|
1352 | - $origData2 = $this->preCalculateFormulas ? $cell->getCalculatedValueString() : $cell->getValueString(); |
|
1353 | - $formatCode = $worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(); |
|
1351 | + $origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue(); |
|
1352 | + $origData2 = $this->preCalculateFormulas ? $cell->getCalculatedValueString() : $cell->getValueString(); |
|
1353 | + $formatCode = $worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(); |
|
1354 | 1354 | |
1355 | - $cellData = NumberFormat::toFormattedString( |
|
1355 | + $cellData = NumberFormat::toFormattedString( |
|
1356 | 1356 | $origData2, |
1357 | 1357 | $formatCode ?? NumberFormat::FORMAT_GENERAL, |
1358 | 1358 | [$this, 'formatColor'] |
1359 | - ); |
|
1359 | + ); |
|
1360 | 1360 | |
1361 | - if ($cellData === $origData) { |
|
1361 | + if ($cellData === $origData) { |
|
1362 | 1362 | $cellData = htmlspecialchars($cellData, Settings::htmlEntityFlags()); |
1363 | - } |
|
1364 | - if ($worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperscript()) { |
|
1363 | + } |
|
1364 | + if ($worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperscript()) { |
|
1365 | 1365 | $cellData = '<sup>' . $cellData . '</sup>'; |
1366 | - } elseif ($worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSubscript()) { |
|
1366 | + } elseif ($worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSubscript()) { |
|
1367 | 1367 | $cellData = '<sub>' . $cellData . '</sub>'; |
1368 | - } |
|
1368 | + } |
|
1369 | + } |
|
1369 | 1370 | } |
1370 | - } |
|
1371 | 1371 | |
1372 | - private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cell, array|string &$cssClass): string |
|
1373 | - { |
|
1372 | + private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cell, array|string &$cssClass): string |
|
1373 | + { |
|
1374 | 1374 | $cellData = ' '; |
1375 | 1375 | if ($cell instanceof Cell) { |
1376 | - $cellData = ''; |
|
1377 | - // Don't know what this does, and no test cases. |
|
1378 | - //if ($cell->getParent() === null) { |
|
1379 | - // $cell->attach($worksheet); |
|
1380 | - //} |
|
1381 | - // Value |
|
1382 | - $this->generateRowCellDataValue($worksheet, $cell, $cellData); |
|
1383 | - |
|
1384 | - // Converts the cell content so that spaces occuring at beginning of each new line are replaced by |
|
1385 | - // Example: " Hello\n to the world" is converted to " Hello\n to the world" |
|
1386 | - $cellData = (string) preg_replace('/(?m)(?:^|\\G) /', ' ', $cellData); |
|
1387 | - |
|
1388 | - // convert newline "\n" to '<br>' |
|
1389 | - $cellData = nl2br($cellData); |
|
1390 | - |
|
1391 | - // Extend CSS class? |
|
1392 | - if (!$this->useInlineCss && is_string($cssClass)) { |
|
1376 | + $cellData = ''; |
|
1377 | + // Don't know what this does, and no test cases. |
|
1378 | + //if ($cell->getParent() === null) { |
|
1379 | + // $cell->attach($worksheet); |
|
1380 | + //} |
|
1381 | + // Value |
|
1382 | + $this->generateRowCellDataValue($worksheet, $cell, $cellData); |
|
1383 | + |
|
1384 | + // Converts the cell content so that spaces occuring at beginning of each new line are replaced by |
|
1385 | + // Example: " Hello\n to the world" is converted to " Hello\n to the world" |
|
1386 | + $cellData = (string) preg_replace('/(?m)(?:^|\\G) /', ' ', $cellData); |
|
1387 | + |
|
1388 | + // convert newline "\n" to '<br>' |
|
1389 | + $cellData = nl2br($cellData); |
|
1390 | + |
|
1391 | + // Extend CSS class? |
|
1392 | + if (!$this->useInlineCss && is_string($cssClass)) { |
|
1393 | 1393 | $cssClass .= ' style' . $cell->getXfIndex(); |
1394 | 1394 | $cssClass .= ' ' . $cell->getDataType(); |
1395 | - } elseif (is_array($cssClass)) { |
|
1395 | + } elseif (is_array($cssClass)) { |
|
1396 | 1396 | $index = $cell->getXfIndex(); |
1397 | 1397 | $styleIndex = 'td.style' . $index . ', th.style' . $index; |
1398 | 1398 | if (isset($this->cssStyles[$styleIndex])) { |
1399 | - $cssClass = array_merge($cssClass, $this->cssStyles[$styleIndex]); |
|
1399 | + $cssClass = array_merge($cssClass, $this->cssStyles[$styleIndex]); |
|
1400 | 1400 | } |
1401 | 1401 | |
1402 | 1402 | // General horizontal alignment: Actual horizontal alignment depends on dataType |
1403 | 1403 | $sharedStyle = $worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex()); |
1404 | 1404 | if ( |
1405 | - $sharedStyle->getAlignment()->getHorizontal() == Alignment::HORIZONTAL_GENERAL |
|
1405 | + $sharedStyle->getAlignment()->getHorizontal() == Alignment::HORIZONTAL_GENERAL |
|
1406 | 1406 | && isset($this->cssStyles['.' . $cell->getDataType()]['text-align']) |
1407 | 1407 | ) { |
1408 | - $cssClass['text-align'] = $this->cssStyles['.' . $cell->getDataType()]['text-align']; |
|
1408 | + $cssClass['text-align'] = $this->cssStyles['.' . $cell->getDataType()]['text-align']; |
|
1409 | + } |
|
1409 | 1410 | } |
1410 | - } |
|
1411 | 1411 | } else { |
1412 | - // Use default borders for empty cell |
|
1413 | - if (is_string($cssClass)) { |
|
1412 | + // Use default borders for empty cell |
|
1413 | + if (is_string($cssClass)) { |
|
1414 | 1414 | $cssClass .= ' style0'; |
1415 | - } |
|
1415 | + } |
|
1416 | 1416 | } |
1417 | 1417 | |
1418 | 1418 | return $cellData; |
1419 | - } |
|
1419 | + } |
|
1420 | 1420 | |
1421 | - private function generateRowIncludeCharts(Worksheet $worksheet, string $coordinate): string |
|
1422 | - { |
|
1421 | + private function generateRowIncludeCharts(Worksheet $worksheet, string $coordinate): string |
|
1422 | + { |
|
1423 | 1423 | return $this->includeCharts ? $this->writeChartInCell($worksheet, $coordinate) : ''; |
1424 | - } |
|
1424 | + } |
|
1425 | 1425 | |
1426 | - private function generateRowSpans(string $html, int $rowSpan, int $colSpan): string |
|
1427 | - { |
|
1426 | + private function generateRowSpans(string $html, int $rowSpan, int $colSpan): string |
|
1427 | + { |
|
1428 | 1428 | $html .= ($colSpan > 1) ? (' colspan="' . $colSpan . '"') : ''; |
1429 | 1429 | $html .= ($rowSpan > 1) ? (' rowspan="' . $rowSpan . '"') : ''; |
1430 | 1430 | |
1431 | 1431 | return $html; |
1432 | - } |
|
1432 | + } |
|
1433 | 1433 | |
1434 | - private function generateRowWriteCell( |
|
1434 | + private function generateRowWriteCell( |
|
1435 | 1435 | string &$html, |
1436 | 1436 | Worksheet $worksheet, |
1437 | 1437 | string $coordinate, |
@@ -1443,7 +1443,7 @@ discard block |
||
1443 | 1443 | int $colNum, |
1444 | 1444 | int $sheetIndex, |
1445 | 1445 | int $row |
1446 | - ): void { |
|
1446 | + ): void { |
|
1447 | 1447 | // Image? |
1448 | 1448 | $htmlx = $this->writeImageInCell($coordinate); |
1449 | 1449 | // Chart? |
@@ -1451,53 +1451,53 @@ discard block |
||
1451 | 1451 | // Column start |
1452 | 1452 | $html .= ' <' . $cellType; |
1453 | 1453 | if (!$this->useInlineCss && !$this->isPdf && is_string($cssClass)) { |
1454 | - $html .= ' class="' . $cssClass . '"'; |
|
1455 | - if ($htmlx) { |
|
1454 | + $html .= ' class="' . $cssClass . '"'; |
|
1455 | + if ($htmlx) { |
|
1456 | 1456 | $html .= " style='position: relative;'"; |
1457 | - } |
|
1457 | + } |
|
1458 | 1458 | } else { |
1459 | - //** Necessary redundant code for the sake of \PhpOffice\PhpSpreadsheet\Writer\Pdf ** |
|
1460 | - // We must explicitly write the width of the <td> element because TCPDF |
|
1461 | - // does not recognize e.g. <col style="width:42pt"> |
|
1462 | - if ($this->useInlineCss) { |
|
1459 | + //** Necessary redundant code for the sake of \PhpOffice\PhpSpreadsheet\Writer\Pdf ** |
|
1460 | + // We must explicitly write the width of the <td> element because TCPDF |
|
1461 | + // does not recognize e.g. <col style="width:42pt"> |
|
1462 | + if ($this->useInlineCss) { |
|
1463 | 1463 | $xcssClass = is_array($cssClass) ? $cssClass : []; |
1464 | - } else { |
|
1464 | + } else { |
|
1465 | 1465 | if (is_string($cssClass)) { |
1466 | - $html .= ' class="' . $cssClass . '"'; |
|
1466 | + $html .= ' class="' . $cssClass . '"'; |
|
1467 | 1467 | } |
1468 | 1468 | $xcssClass = []; |
1469 | - } |
|
1470 | - $width = 0; |
|
1471 | - $i = $colNum - 1; |
|
1472 | - $e = $colNum + $colSpan - 1; |
|
1473 | - while ($i++ < $e) { |
|
1469 | + } |
|
1470 | + $width = 0; |
|
1471 | + $i = $colNum - 1; |
|
1472 | + $e = $colNum + $colSpan - 1; |
|
1473 | + while ($i++ < $e) { |
|
1474 | 1474 | if (isset($this->columnWidths[$sheetIndex][$i])) { |
1475 | - $width += $this->columnWidths[$sheetIndex][$i]; |
|
1475 | + $width += $this->columnWidths[$sheetIndex][$i]; |
|
1476 | 1476 | } |
1477 | - } |
|
1478 | - $xcssClass['width'] = (string) $width . 'pt'; |
|
1479 | - // We must also explicitly write the height of the <td> element because TCPDF |
|
1480 | - // does not recognize e.g. <tr style="height:50pt"> |
|
1481 | - if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'])) { |
|
1477 | + } |
|
1478 | + $xcssClass['width'] = (string) $width . 'pt'; |
|
1479 | + // We must also explicitly write the height of the <td> element because TCPDF |
|
1480 | + // does not recognize e.g. <tr style="height:50pt"> |
|
1481 | + if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'])) { |
|
1482 | 1482 | $height = $this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $row]['height']; |
1483 | 1483 | $xcssClass['height'] = $height; |
1484 | - } |
|
1485 | - //** end of redundant code ** |
|
1486 | - if ($this->useInlineCss) { |
|
1484 | + } |
|
1485 | + //** end of redundant code ** |
|
1486 | + if ($this->useInlineCss) { |
|
1487 | 1487 | foreach (['border-top', 'border-bottom', 'border-right', 'border-left'] as $borderType) { |
1488 | - if (($xcssClass[$borderType] ?? '') === 'none #000000') { |
|
1488 | + if (($xcssClass[$borderType] ?? '') === 'none #000000') { |
|
1489 | 1489 | unset($xcssClass[$borderType]); |
1490 | - } |
|
1490 | + } |
|
1491 | + } |
|
1491 | 1492 | } |
1492 | - } |
|
1493 | 1493 | |
1494 | - if ($htmlx) { |
|
1494 | + if ($htmlx) { |
|
1495 | 1495 | $xcssClass['position'] = 'relative'; |
1496 | - } |
|
1497 | - $html .= ' style="' . $this->assembleCSS($xcssClass) . '"'; |
|
1498 | - if ($this->useInlineCss) { |
|
1496 | + } |
|
1497 | + $html .= ' style="' . $this->assembleCSS($xcssClass) . '"'; |
|
1498 | + if ($this->useInlineCss) { |
|
1499 | 1499 | $html .= ' class="gridlines gridlinesp"'; |
1500 | - } |
|
1500 | + } |
|
1501 | 1501 | } |
1502 | 1502 | $html = $this->generateRowSpans($html, $rowSpan, $colSpan); |
1503 | 1503 | |
@@ -1511,17 +1511,17 @@ discard block |
||
1511 | 1511 | |
1512 | 1512 | // Column end |
1513 | 1513 | $html .= '</' . $cellType . '>' . PHP_EOL; |
1514 | - } |
|
1515 | - |
|
1516 | - /** |
|
1517 | - * Generate row. |
|
1518 | - * |
|
1519 | - * @param array $values Array containing cells in a row |
|
1520 | - * @param int $row Row number (0-based) |
|
1521 | - * @param string $cellType eg: 'td' |
|
1522 | - */ |
|
1523 | - private function generateRow(Worksheet $worksheet, array $values, int $row, string $cellType): string |
|
1524 | - { |
|
1514 | + } |
|
1515 | + |
|
1516 | + /** |
|
1517 | + * Generate row. |
|
1518 | + * |
|
1519 | + * @param array $values Array containing cells in a row |
|
1520 | + * @param int $row Row number (0-based) |
|
1521 | + * @param string $cellType eg: 'td' |
|
1522 | + */ |
|
1523 | + private function generateRow(Worksheet $worksheet, array $values, int $row, string $cellType): string |
|
1524 | + { |
|
1525 | 1525 | // Sheet index |
1526 | 1526 | $sheetIndex = $worksheet->getParentOrThrow()->getIndex($worksheet); |
1527 | 1527 | $html = $this->generateRowStart($worksheet, $sheetIndex, $row); |
@@ -1529,31 +1529,31 @@ discard block |
||
1529 | 1529 | // Write cells |
1530 | 1530 | $colNum = 0; |
1531 | 1531 | foreach ($values as $cellAddress) { |
1532 | - [$cell, $cssClass, $coordinate] = $this->generateRowCellCss($worksheet, $cellAddress, $row, $colNum); |
|
1532 | + [$cell, $cssClass, $coordinate] = $this->generateRowCellCss($worksheet, $cellAddress, $row, $colNum); |
|
1533 | 1533 | |
1534 | - // Cell Data |
|
1535 | - $cellData = $this->generateRowCellData($worksheet, $cell, $cssClass); |
|
1534 | + // Cell Data |
|
1535 | + $cellData = $this->generateRowCellData($worksheet, $cell, $cssClass); |
|
1536 | 1536 | |
1537 | - // Hyperlink? |
|
1538 | - if ($worksheet->hyperlinkExists($coordinate) && !$worksheet->getHyperlink($coordinate)->isInternal()) { |
|
1537 | + // Hyperlink? |
|
1538 | + if ($worksheet->hyperlinkExists($coordinate) && !$worksheet->getHyperlink($coordinate)->isInternal()) { |
|
1539 | 1539 | $url = $worksheet->getHyperlink($coordinate)->getUrl(); |
1540 | 1540 | $urldecode = strtolower(html_entity_decode(trim($url), encoding: 'UTF-8')); |
1541 | 1541 | $parseScheme = preg_match('/^(\\w+):/', $urldecode, $matches); |
1542 | 1542 | if ($parseScheme === 1 && !in_array($matches[1], ['http', 'https', 'file', 'ftp', 's3'], true)) { |
1543 | - $cellData = htmlspecialchars($url, Settings::htmlEntityFlags()); |
|
1543 | + $cellData = htmlspecialchars($url, Settings::htmlEntityFlags()); |
|
1544 | 1544 | } else { |
1545 | - $cellData = '<a href="' . htmlspecialchars($url, Settings::htmlEntityFlags()) . '" title="' . htmlspecialchars($worksheet->getHyperlink($coordinate)->getTooltip(), Settings::htmlEntityFlags()) . '">' . $cellData . '</a>'; |
|
1545 | + $cellData = '<a href="' . htmlspecialchars($url, Settings::htmlEntityFlags()) . '" title="' . htmlspecialchars($worksheet->getHyperlink($coordinate)->getTooltip(), Settings::htmlEntityFlags()) . '">' . $cellData . '</a>'; |
|
1546 | + } |
|
1546 | 1547 | } |
1547 | - } |
|
1548 | 1548 | |
1549 | - // Should the cell be written or is it swallowed by a rowspan or colspan? |
|
1550 | - $writeCell = !(isset($this->isSpannedCell[$worksheet->getParentOrThrow()->getIndex($worksheet)][$row + 1][$colNum]) |
|
1549 | + // Should the cell be written or is it swallowed by a rowspan or colspan? |
|
1550 | + $writeCell = !(isset($this->isSpannedCell[$worksheet->getParentOrThrow()->getIndex($worksheet)][$row + 1][$colNum]) |
|
1551 | 1551 | && $this->isSpannedCell[$worksheet->getParentOrThrow()->getIndex($worksheet)][$row + 1][$colNum]); |
1552 | 1552 | |
1553 | - // Colspan and Rowspan |
|
1554 | - $colSpan = 1; |
|
1555 | - $rowSpan = 1; |
|
1556 | - if (isset($this->isBaseCell[$worksheet->getParentOrThrow()->getIndex($worksheet)][$row + 1][$colNum])) { |
|
1553 | + // Colspan and Rowspan |
|
1554 | + $colSpan = 1; |
|
1555 | + $rowSpan = 1; |
|
1556 | + if (isset($this->isBaseCell[$worksheet->getParentOrThrow()->getIndex($worksheet)][$row + 1][$colNum])) { |
|
1557 | 1557 | $spans = $this->isBaseCell[$worksheet->getParentOrThrow()->getIndex($worksheet)][$row + 1][$colNum]; |
1558 | 1558 | $rowSpan = $spans['rowspan']; |
1559 | 1559 | $colSpan = $spans['colspan']; |
@@ -1562,25 +1562,25 @@ discard block |
||
1562 | 1562 | // relies on !important for non-none border declarations in createCSSStyleBorder |
1563 | 1563 | $endCellCoord = Coordinate::stringFromColumnIndex($colNum + $colSpan) . ($row + $rowSpan); |
1564 | 1564 | if (!$this->useInlineCss) { |
1565 | - $cssClass .= ' style' . $worksheet->getCell($endCellCoord)->getXfIndex(); |
|
1565 | + $cssClass .= ' style' . $worksheet->getCell($endCellCoord)->getXfIndex(); |
|
1566 | 1566 | } else { |
1567 | - $endBorders = $this->spreadsheet->getCellXfByIndex($worksheet->getCell($endCellCoord)->getXfIndex())->getBorders(); |
|
1568 | - $altBorders = $this->createCSSStyleBorders($endBorders); |
|
1569 | - foreach ($altBorders as $altKey => $altValue) { |
|
1567 | + $endBorders = $this->spreadsheet->getCellXfByIndex($worksheet->getCell($endCellCoord)->getXfIndex())->getBorders(); |
|
1568 | + $altBorders = $this->createCSSStyleBorders($endBorders); |
|
1569 | + foreach ($altBorders as $altKey => $altValue) { |
|
1570 | 1570 | if (str_contains($altValue, '!important')) { |
1571 | - $cssClass[$altKey] = $altValue; |
|
1571 | + $cssClass[$altKey] = $altValue; |
|
1572 | 1572 | } |
1573 | - } |
|
1573 | + } |
|
1574 | + } |
|
1574 | 1575 | } |
1575 | - } |
|
1576 | 1576 | |
1577 | - // Write |
|
1578 | - if ($writeCell) { |
|
1577 | + // Write |
|
1578 | + if ($writeCell) { |
|
1579 | 1579 | $this->generateRowWriteCell($html, $worksheet, $coordinate, $cellType, $cellData, $colSpan, $rowSpan, $cssClass, $colNum, $sheetIndex, $row); |
1580 | - } |
|
1580 | + } |
|
1581 | 1581 | |
1582 | - // Next column |
|
1583 | - ++$colNum; |
|
1582 | + // Next column |
|
1583 | + ++$colNum; |
|
1584 | 1584 | } |
1585 | 1585 | |
1586 | 1586 | // Write row end |
@@ -1588,98 +1588,98 @@ discard block |
||
1588 | 1588 | |
1589 | 1589 | // Return |
1590 | 1590 | return $html; |
1591 | - } |
|
1591 | + } |
|
1592 | 1592 | |
1593 | - /** |
|
1594 | - * Takes array where of CSS properties / values and converts to CSS string. |
|
1595 | - */ |
|
1596 | - private function assembleCSS(array $values = []): string |
|
1597 | - { |
|
1593 | + /** |
|
1594 | + * Takes array where of CSS properties / values and converts to CSS string. |
|
1595 | + */ |
|
1596 | + private function assembleCSS(array $values = []): string |
|
1597 | + { |
|
1598 | 1598 | $pairs = []; |
1599 | 1599 | foreach ($values as $property => $value) { |
1600 | - $pairs[] = $property . ':' . $value; |
|
1600 | + $pairs[] = $property . ':' . $value; |
|
1601 | 1601 | } |
1602 | 1602 | $string = implode('; ', $pairs); |
1603 | 1603 | |
1604 | 1604 | return $string; |
1605 | - } |
|
1605 | + } |
|
1606 | 1606 | |
1607 | - /** |
|
1608 | - * Get images root. |
|
1609 | - */ |
|
1610 | - public function getImagesRoot(): string |
|
1611 | - { |
|
1607 | + /** |
|
1608 | + * Get images root. |
|
1609 | + */ |
|
1610 | + public function getImagesRoot(): string |
|
1611 | + { |
|
1612 | 1612 | return $this->imagesRoot; |
1613 | - } |
|
1614 | - |
|
1615 | - /** |
|
1616 | - * Set images root. |
|
1617 | - * |
|
1618 | - * @return $this |
|
1619 | - */ |
|
1620 | - public function setImagesRoot(string $imagesRoot): static |
|
1621 | - { |
|
1613 | + } |
|
1614 | + |
|
1615 | + /** |
|
1616 | + * Set images root. |
|
1617 | + * |
|
1618 | + * @return $this |
|
1619 | + */ |
|
1620 | + public function setImagesRoot(string $imagesRoot): static |
|
1621 | + { |
|
1622 | 1622 | $this->imagesRoot = $imagesRoot; |
1623 | 1623 | |
1624 | 1624 | return $this; |
1625 | - } |
|
1625 | + } |
|
1626 | 1626 | |
1627 | - /** |
|
1628 | - * Get embed images. |
|
1629 | - */ |
|
1630 | - public function getEmbedImages(): bool |
|
1631 | - { |
|
1627 | + /** |
|
1628 | + * Get embed images. |
|
1629 | + */ |
|
1630 | + public function getEmbedImages(): bool |
|
1631 | + { |
|
1632 | 1632 | return $this->embedImages; |
1633 | - } |
|
1634 | - |
|
1635 | - /** |
|
1636 | - * Set embed images. |
|
1637 | - * |
|
1638 | - * @return $this |
|
1639 | - */ |
|
1640 | - public function setEmbedImages(bool $embedImages): static |
|
1641 | - { |
|
1633 | + } |
|
1634 | + |
|
1635 | + /** |
|
1636 | + * Set embed images. |
|
1637 | + * |
|
1638 | + * @return $this |
|
1639 | + */ |
|
1640 | + public function setEmbedImages(bool $embedImages): static |
|
1641 | + { |
|
1642 | 1642 | $this->embedImages = $embedImages; |
1643 | 1643 | |
1644 | 1644 | return $this; |
1645 | - } |
|
1645 | + } |
|
1646 | 1646 | |
1647 | - /** |
|
1648 | - * Get use inline CSS? |
|
1649 | - */ |
|
1650 | - public function getUseInlineCss(): bool |
|
1651 | - { |
|
1647 | + /** |
|
1648 | + * Get use inline CSS? |
|
1649 | + */ |
|
1650 | + public function getUseInlineCss(): bool |
|
1651 | + { |
|
1652 | 1652 | return $this->useInlineCss; |
1653 | - } |
|
1654 | - |
|
1655 | - /** |
|
1656 | - * Set use inline CSS? |
|
1657 | - * |
|
1658 | - * @return $this |
|
1659 | - */ |
|
1660 | - public function setUseInlineCss(bool $useInlineCss): static |
|
1661 | - { |
|
1653 | + } |
|
1654 | + |
|
1655 | + /** |
|
1656 | + * Set use inline CSS? |
|
1657 | + * |
|
1658 | + * @return $this |
|
1659 | + */ |
|
1660 | + public function setUseInlineCss(bool $useInlineCss): static |
|
1661 | + { |
|
1662 | 1662 | $this->useInlineCss = $useInlineCss; |
1663 | 1663 | |
1664 | 1664 | return $this; |
1665 | - } |
|
1666 | - |
|
1667 | - /** |
|
1668 | - * Add color to formatted string as inline style. |
|
1669 | - * |
|
1670 | - * @param string $value Plain formatted value without color |
|
1671 | - * @param string $format Format code |
|
1672 | - */ |
|
1673 | - public function formatColor(string $value, string $format): string |
|
1674 | - { |
|
1665 | + } |
|
1666 | + |
|
1667 | + /** |
|
1668 | + * Add color to formatted string as inline style. |
|
1669 | + * |
|
1670 | + * @param string $value Plain formatted value without color |
|
1671 | + * @param string $format Format code |
|
1672 | + */ |
|
1673 | + public function formatColor(string $value, string $format): string |
|
1674 | + { |
|
1675 | 1675 | // Color information, e.g. [Red] is always at the beginning |
1676 | 1676 | $color = null; // initialize |
1677 | 1677 | $matches = []; |
1678 | 1678 | |
1679 | 1679 | $color_regex = '/^\\[[a-zA-Z]+\\]/'; |
1680 | 1680 | if (preg_match($color_regex, $format, $matches)) { |
1681 | - $color = str_replace(['[', ']'], '', $matches[0]); |
|
1682 | - $color = strtolower($color); |
|
1681 | + $color = str_replace(['[', ']'], '', $matches[0]); |
|
1682 | + $color = strtolower($color); |
|
1683 | 1683 | } |
1684 | 1684 | |
1685 | 1685 | // convert to PCDATA |
@@ -1687,37 +1687,37 @@ discard block |
||
1687 | 1687 | |
1688 | 1688 | // color span tag |
1689 | 1689 | if ($color !== null) { |
1690 | - $result = '<span style="color:' . $color . '">' . $result . '</span>'; |
|
1690 | + $result = '<span style="color:' . $color . '">' . $result . '</span>'; |
|
1691 | 1691 | } |
1692 | 1692 | |
1693 | 1693 | return $result; |
1694 | - } |
|
1694 | + } |
|
1695 | 1695 | |
1696 | - /** |
|
1697 | - * Calculate information about HTML colspan and rowspan which is not always the same as Excel's. |
|
1698 | - */ |
|
1699 | - private function calculateSpans(): void |
|
1700 | - { |
|
1696 | + /** |
|
1697 | + * Calculate information about HTML colspan and rowspan which is not always the same as Excel's. |
|
1698 | + */ |
|
1699 | + private function calculateSpans(): void |
|
1700 | + { |
|
1701 | 1701 | if ($this->spansAreCalculated) { |
1702 | - return; |
|
1702 | + return; |
|
1703 | 1703 | } |
1704 | 1704 | // Identify all cells that should be omitted in HTML due to cell merge. |
1705 | 1705 | // In HTML only the upper-left cell should be written and it should have |
1706 | 1706 | // appropriate rowspan / colspan attribute |
1707 | 1707 | if (is_array($this->sheetIndex)) { |
1708 | - $sheetIndexes = $this->sheetIndex; |
|
1708 | + $sheetIndexes = $this->sheetIndex; |
|
1709 | 1709 | } else { |
1710 | - $sheetIndexes = $this->sheetIndex !== null |
|
1710 | + $sheetIndexes = $this->sheetIndex !== null |
|
1711 | 1711 | ? [$this->sheetIndex] : range(0, $this->spreadsheet->getSheetCount() - 1); |
1712 | 1712 | } |
1713 | 1713 | |
1714 | 1714 | foreach ($sheetIndexes as $sheetIndex) { |
1715 | - $sheet = $this->spreadsheet->getSheet($sheetIndex); |
|
1715 | + $sheet = $this->spreadsheet->getSheet($sheetIndex); |
|
1716 | 1716 | |
1717 | - $candidateSpannedRow = []; |
|
1717 | + $candidateSpannedRow = []; |
|
1718 | 1718 | |
1719 | - // loop through all Excel merged cells |
|
1720 | - foreach ($sheet->getMergeCells() as $cells) { |
|
1719 | + // loop through all Excel merged cells |
|
1720 | + foreach ($sheet->getMergeCells() as $cells) { |
|
1721 | 1721 | [$cells] = Coordinate::splitRange($cells); |
1722 | 1722 | $first = $cells[0]; |
1723 | 1723 | $last = $cells[1]; |
@@ -1731,120 +1731,120 @@ discard block |
||
1731 | 1731 | // loop through the individual cells in the individual merge |
1732 | 1732 | $r = $fr - 1; |
1733 | 1733 | while ($r++ < $lr) { |
1734 | - // also, flag this row as a HTML row that is candidate to be omitted |
|
1735 | - $candidateSpannedRow[$r] = $r; |
|
1734 | + // also, flag this row as a HTML row that is candidate to be omitted |
|
1735 | + $candidateSpannedRow[$r] = $r; |
|
1736 | 1736 | |
1737 | - $c = $fc - 1; |
|
1738 | - while ($c++ < $lc) { |
|
1737 | + $c = $fc - 1; |
|
1738 | + while ($c++ < $lc) { |
|
1739 | 1739 | if (!($c == $fc && $r == $fr)) { |
1740 | - // not the upper-left cell (should not be written in HTML) |
|
1741 | - $this->isSpannedCell[$sheetIndex][$r][$c] = [ |
|
1740 | + // not the upper-left cell (should not be written in HTML) |
|
1741 | + $this->isSpannedCell[$sheetIndex][$r][$c] = [ |
|
1742 | 1742 | 'baseCell' => [$fr, $fc], |
1743 | - ]; |
|
1743 | + ]; |
|
1744 | 1744 | } else { |
1745 | - // upper-left is the base cell that should hold the colspan/rowspan attribute |
|
1746 | - $this->isBaseCell[$sheetIndex][$r][$c] = [ |
|
1745 | + // upper-left is the base cell that should hold the colspan/rowspan attribute |
|
1746 | + $this->isBaseCell[$sheetIndex][$r][$c] = [ |
|
1747 | 1747 | 'xlrowspan' => $lr - $fr + 1, // Excel rowspan |
1748 | 1748 | 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change |
1749 | 1749 | 'xlcolspan' => $lc - $fc + 1, // Excel colspan |
1750 | 1750 | 'colspan' => $lc - $fc + 1, // HTML colspan, value may change |
1751 | - ]; |
|
1751 | + ]; |
|
1752 | + } |
|
1752 | 1753 | } |
1753 | - } |
|
1754 | 1754 | } |
1755 | - } |
|
1755 | + } |
|
1756 | 1756 | |
1757 | - $this->calculateSpansOmitRows($sheet, $sheetIndex, $candidateSpannedRow); |
|
1757 | + $this->calculateSpansOmitRows($sheet, $sheetIndex, $candidateSpannedRow); |
|
1758 | 1758 | |
1759 | - // TODO: Same for columns |
|
1759 | + // TODO: Same for columns |
|
1760 | 1760 | } |
1761 | 1761 | |
1762 | 1762 | // We have calculated the spans |
1763 | 1763 | $this->spansAreCalculated = true; |
1764 | - } |
|
1764 | + } |
|
1765 | 1765 | |
1766 | - private function calculateSpansOmitRows(Worksheet $sheet, int $sheetIndex, array $candidateSpannedRow): void |
|
1767 | - { |
|
1766 | + private function calculateSpansOmitRows(Worksheet $sheet, int $sheetIndex, array $candidateSpannedRow): void |
|
1767 | + { |
|
1768 | 1768 | // Identify which rows should be omitted in HTML. These are the rows where all the cells |
1769 | 1769 | // participate in a merge and the where base cells are somewhere above. |
1770 | 1770 | $countColumns = Coordinate::columnIndexFromString($sheet->getHighestColumn()); |
1771 | 1771 | foreach ($candidateSpannedRow as $rowIndex) { |
1772 | - if (isset($this->isSpannedCell[$sheetIndex][$rowIndex])) { |
|
1772 | + if (isset($this->isSpannedCell[$sheetIndex][$rowIndex])) { |
|
1773 | 1773 | if (count($this->isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { |
1774 | - $this->isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; |
|
1774 | + $this->isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; |
|
1775 | + } |
|
1775 | 1776 | } |
1776 | - } |
|
1777 | 1777 | } |
1778 | 1778 | |
1779 | 1779 | // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 |
1780 | 1780 | if (isset($this->isSpannedRow[$sheetIndex])) { |
1781 | - foreach ($this->isSpannedRow[$sheetIndex] as $rowIndex) { |
|
1781 | + foreach ($this->isSpannedRow[$sheetIndex] as $rowIndex) { |
|
1782 | 1782 | $adjustedBaseCells = []; |
1783 | 1783 | $c = -1; |
1784 | 1784 | $e = $countColumns - 1; |
1785 | 1785 | while ($c++ < $e) { |
1786 | - $baseCell = $this->isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; |
|
1786 | + $baseCell = $this->isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; |
|
1787 | 1787 | |
1788 | - if (!in_array($baseCell, $adjustedBaseCells, true)) { |
|
1788 | + if (!in_array($baseCell, $adjustedBaseCells, true)) { |
|
1789 | 1789 | // subtract rowspan by 1 |
1790 | 1790 | --$this->isBaseCell[$sheetIndex][$baseCell[0]][$baseCell[1]]['rowspan']; |
1791 | 1791 | $adjustedBaseCells[] = $baseCell; |
1792 | - } |
|
1792 | + } |
|
1793 | 1793 | } |
1794 | - } |
|
1794 | + } |
|
1795 | + } |
|
1795 | 1796 | } |
1796 | - } |
|
1797 | 1797 | |
1798 | - /** |
|
1799 | - * Write a comment in the same format as LibreOffice. |
|
1800 | - * |
|
1801 | - * @see https://github.com/LibreOffice/core/blob/9fc9bf3240f8c62ad7859947ab8a033ac1fe93fa/sc/source/filter/html/htmlexp.cxx#L1073-L1092 |
|
1802 | - */ |
|
1803 | - private function writeComment(Worksheet $worksheet, string $coordinate): string |
|
1804 | - { |
|
1798 | + /** |
|
1799 | + * Write a comment in the same format as LibreOffice. |
|
1800 | + * |
|
1801 | + * @see https://github.com/LibreOffice/core/blob/9fc9bf3240f8c62ad7859947ab8a033ac1fe93fa/sc/source/filter/html/htmlexp.cxx#L1073-L1092 |
|
1802 | + */ |
|
1803 | + private function writeComment(Worksheet $worksheet, string $coordinate): string |
|
1804 | + { |
|
1805 | 1805 | $result = ''; |
1806 | 1806 | if (!$this->isPdf && isset($worksheet->getComments()[$coordinate])) { |
1807 | - $sanitizedString = $this->generateRowCellDataValueRich($worksheet->getComment($coordinate)->getText()); |
|
1808 | - $dir = ($worksheet->getComment($coordinate)->getTextboxDirection() === Comment::TEXTBOX_DIRECTION_RTL) ? ' dir="rtl"' : ''; |
|
1809 | - $align = strtolower($worksheet->getComment($coordinate)->getAlignment()); |
|
1810 | - $alignment = Alignment::HORIZONTAL_ALIGNMENT_FOR_HTML[$align] ?? ''; |
|
1811 | - if ($alignment !== '') { |
|
1807 | + $sanitizedString = $this->generateRowCellDataValueRich($worksheet->getComment($coordinate)->getText()); |
|
1808 | + $dir = ($worksheet->getComment($coordinate)->getTextboxDirection() === Comment::TEXTBOX_DIRECTION_RTL) ? ' dir="rtl"' : ''; |
|
1809 | + $align = strtolower($worksheet->getComment($coordinate)->getAlignment()); |
|
1810 | + $alignment = Alignment::HORIZONTAL_ALIGNMENT_FOR_HTML[$align] ?? ''; |
|
1811 | + if ($alignment !== '') { |
|
1812 | 1812 | $alignment = " style=\"text-align:$alignment\""; |
1813 | - } |
|
1814 | - if ($sanitizedString !== '') { |
|
1813 | + } |
|
1814 | + if ($sanitizedString !== '') { |
|
1815 | 1815 | $result .= '<a class="comment-indicator"></a>'; |
1816 | 1816 | $result .= "<div class=\"comment\"$dir$alignment>" . $sanitizedString . '</div>'; |
1817 | 1817 | $result .= PHP_EOL; |
1818 | - } |
|
1818 | + } |
|
1819 | 1819 | } |
1820 | 1820 | |
1821 | 1821 | return $result; |
1822 | - } |
|
1822 | + } |
|
1823 | 1823 | |
1824 | - public function getOrientation(): ?string |
|
1825 | - { |
|
1824 | + public function getOrientation(): ?string |
|
1825 | + { |
|
1826 | 1826 | // Expect Pdf classes to override this method. |
1827 | 1827 | return $this->isPdf ? PageSetup::ORIENTATION_PORTRAIT : null; |
1828 | - } |
|
1828 | + } |
|
1829 | 1829 | |
1830 | - /** |
|
1831 | - * Generate @page declarations. |
|
1832 | - */ |
|
1833 | - private function generatePageDeclarations(bool $generateSurroundingHTML): string |
|
1834 | - { |
|
1830 | + /** |
|
1831 | + * Generate @page declarations. |
|
1832 | + */ |
|
1833 | + private function generatePageDeclarations(bool $generateSurroundingHTML): string |
|
1834 | + { |
|
1835 | 1835 | // Ensure that Spans have been calculated? |
1836 | 1836 | $this->calculateSpans(); |
1837 | 1837 | |
1838 | 1838 | // Fetch sheets |
1839 | 1839 | $sheets = []; |
1840 | 1840 | if (is_array($this->sheetIndex)) { |
1841 | - foreach ($this->sheetIndex as $sheetIndex) { |
|
1841 | + foreach ($this->sheetIndex as $sheetIndex) { |
|
1842 | 1842 | $sheets[] = $this->spreadsheet->getSheet($sheetIndex); |
1843 | - } |
|
1843 | + } |
|
1844 | 1844 | } elseif ($this->sheetIndex === null) { |
1845 | - $sheets = $this->spreadsheet->getAllSheets(); |
|
1845 | + $sheets = $this->spreadsheet->getAllSheets(); |
|
1846 | 1846 | } else { |
1847 | - $sheets[] = $this->spreadsheet->getSheet($this->sheetIndex); |
|
1847 | + $sheets[] = $this->spreadsheet->getSheet($this->sheetIndex); |
|
1848 | 1848 | } |
1849 | 1849 | |
1850 | 1850 | // Construct HTML |
@@ -1853,64 +1853,64 @@ discard block |
||
1853 | 1853 | // Loop all sheets |
1854 | 1854 | $sheetId = 0; |
1855 | 1855 | foreach ($sheets as $worksheet) { |
1856 | - $htmlPage .= "@page page$sheetId { "; |
|
1857 | - $left = StringHelper::formatNumber($worksheet->getPageMargins()->getLeft()) . 'in; '; |
|
1858 | - $htmlPage .= 'margin-left: ' . $left; |
|
1859 | - $right = StringHelper::FormatNumber($worksheet->getPageMargins()->getRight()) . 'in; '; |
|
1860 | - $htmlPage .= 'margin-right: ' . $right; |
|
1861 | - $top = StringHelper::FormatNumber($worksheet->getPageMargins()->getTop()) . 'in; '; |
|
1862 | - $htmlPage .= 'margin-top: ' . $top; |
|
1863 | - $bottom = StringHelper::FormatNumber($worksheet->getPageMargins()->getBottom()) . 'in; '; |
|
1864 | - $htmlPage .= 'margin-bottom: ' . $bottom; |
|
1865 | - $orientation = $this->getOrientation() ?? $worksheet->getPageSetup()->getOrientation(); |
|
1866 | - if ($orientation === PageSetup::ORIENTATION_LANDSCAPE) { |
|
1856 | + $htmlPage .= "@page page$sheetId { "; |
|
1857 | + $left = StringHelper::formatNumber($worksheet->getPageMargins()->getLeft()) . 'in; '; |
|
1858 | + $htmlPage .= 'margin-left: ' . $left; |
|
1859 | + $right = StringHelper::FormatNumber($worksheet->getPageMargins()->getRight()) . 'in; '; |
|
1860 | + $htmlPage .= 'margin-right: ' . $right; |
|
1861 | + $top = StringHelper::FormatNumber($worksheet->getPageMargins()->getTop()) . 'in; '; |
|
1862 | + $htmlPage .= 'margin-top: ' . $top; |
|
1863 | + $bottom = StringHelper::FormatNumber($worksheet->getPageMargins()->getBottom()) . 'in; '; |
|
1864 | + $htmlPage .= 'margin-bottom: ' . $bottom; |
|
1865 | + $orientation = $this->getOrientation() ?? $worksheet->getPageSetup()->getOrientation(); |
|
1866 | + if ($orientation === PageSetup::ORIENTATION_LANDSCAPE) { |
|
1867 | 1867 | $htmlPage .= 'size: landscape; '; |
1868 | - } elseif ($orientation === PageSetup::ORIENTATION_PORTRAIT) { |
|
1868 | + } elseif ($orientation === PageSetup::ORIENTATION_PORTRAIT) { |
|
1869 | 1869 | $htmlPage .= 'size: portrait; '; |
1870 | - } |
|
1871 | - $htmlPage .= '}' . PHP_EOL; |
|
1872 | - ++$sheetId; |
|
1870 | + } |
|
1871 | + $htmlPage .= '}' . PHP_EOL; |
|
1872 | + ++$sheetId; |
|
1873 | 1873 | } |
1874 | 1874 | $htmlPage .= implode(PHP_EOL, [ |
1875 | - '.navigation {page-break-after: always;}', |
|
1876 | - '.scrpgbrk, div + div {page-break-before: always;}', |
|
1877 | - '@media screen {', |
|
1878 | - ' .gridlines td {border: 1px solid black;}', |
|
1879 | - ' .gridlines th {border: 1px solid black;}', |
|
1880 | - ' body>div {margin-top: 5px;}', |
|
1881 | - ' body>div:first-child {margin-top: 0;}', |
|
1882 | - ' .scrpgbrk {margin-top: 1px;}', |
|
1883 | - '}', |
|
1884 | - '@media print {', |
|
1885 | - ' .gridlinesp td {border: 1px solid black;}', |
|
1886 | - ' .gridlinesp th {border: 1px solid black;}', |
|
1887 | - ' .navigation {display: none;}', |
|
1888 | - '}', |
|
1889 | - '', |
|
1875 | + '.navigation {page-break-after: always;}', |
|
1876 | + '.scrpgbrk, div + div {page-break-before: always;}', |
|
1877 | + '@media screen {', |
|
1878 | + ' .gridlines td {border: 1px solid black;}', |
|
1879 | + ' .gridlines th {border: 1px solid black;}', |
|
1880 | + ' body>div {margin-top: 5px;}', |
|
1881 | + ' body>div:first-child {margin-top: 0;}', |
|
1882 | + ' .scrpgbrk {margin-top: 1px;}', |
|
1883 | + '}', |
|
1884 | + '@media print {', |
|
1885 | + ' .gridlinesp td {border: 1px solid black;}', |
|
1886 | + ' .gridlinesp th {border: 1px solid black;}', |
|
1887 | + ' .navigation {display: none;}', |
|
1888 | + '}', |
|
1889 | + '', |
|
1890 | 1890 | ]); |
1891 | 1891 | $htmlPage .= $generateSurroundingHTML ? ('</style>' . PHP_EOL) : ''; |
1892 | 1892 | |
1893 | 1893 | return $htmlPage; |
1894 | - } |
|
1894 | + } |
|
1895 | 1895 | |
1896 | - private function shouldGenerateRow(Worksheet $sheet, int $row): bool |
|
1897 | - { |
|
1896 | + private function shouldGenerateRow(Worksheet $sheet, int $row): bool |
|
1897 | + { |
|
1898 | 1898 | if (!($this instanceof Pdf\Mpdf || $this instanceof Pdf\Tcpdf)) { |
1899 | - return true; |
|
1899 | + return true; |
|
1900 | 1900 | } |
1901 | 1901 | |
1902 | 1902 | return $sheet->isRowVisible($row); |
1903 | - } |
|
1903 | + } |
|
1904 | 1904 | |
1905 | - private function shouldGenerateColumn(Worksheet $sheet, string $colStr): bool |
|
1906 | - { |
|
1905 | + private function shouldGenerateColumn(Worksheet $sheet, string $colStr): bool |
|
1906 | + { |
|
1907 | 1907 | if (!($this instanceof Pdf\Mpdf || $this instanceof Pdf\Tcpdf)) { |
1908 | - return true; |
|
1908 | + return true; |
|
1909 | 1909 | } |
1910 | 1910 | if (!$sheet->columnDimensionExists($colStr)) { |
1911 | - return true; |
|
1911 | + return true; |
|
1912 | 1912 | } |
1913 | 1913 | |
1914 | 1914 | return $sheet->getColumnDimension($colStr)->getVisible(); |
1915 | - } |
|
1915 | + } |
|
1916 | 1916 | } |
@@ -60,7 +60,7 @@ discard block |
||
60 | 60 | /** |
61 | 61 | * Sheet index to write. |
62 | 62 | */ |
63 | - private null| int | array $sheetIndex = 0; |
|
63 | + private null | int | array $sheetIndex = 0; |
|
64 | 64 | |
65 | 65 | /** |
66 | 66 | * Images root. |
@@ -1369,7 +1369,7 @@ discard block |
||
1369 | 1369 | } |
1370 | 1370 | } |
1371 | 1371 | |
1372 | - private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cell, array|string &$cssClass): string |
|
1372 | + private function generateRowCellData(Worksheet $worksheet, null | Cell | string $cell, array | string &$cssClass): string |
|
1373 | 1373 | { |
1374 | 1374 | $cellData = ' '; |
1375 | 1375 | if ($cell instanceof Cell) { |
@@ -1439,7 +1439,7 @@ discard block |
||
1439 | 1439 | string $cellData, |
1440 | 1440 | int $colSpan, |
1441 | 1441 | int $rowSpan, |
1442 | - array|string $cssClass, |
|
1442 | + array | string $cssClass, |
|
1443 | 1443 | int $colNum, |
1444 | 1444 | int $sheetIndex, |
1445 | 1445 | int $row |