PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.9.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.9.0
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / phpoffice / phpspreadsheet / src / PhpSpreadsheet / Writer / Ods / Content.php

Content.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.9.0, at vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php

396 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
4
5 use PhpOffice\PhpSpreadsheet\Cell\Cell;
6 use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
7 use PhpOffice\PhpSpreadsheet\Cell\DataType;
8 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
9 use PhpOffice\PhpSpreadsheet\Spreadsheet;
10 use PhpOffice\PhpSpreadsheet\Style\Fill;
11 use PhpOffice\PhpSpreadsheet\Style\Font;
12 use PhpOffice\PhpSpreadsheet\Worksheet\Row;
13 use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
14 use PhpOffice\PhpSpreadsheet\Writer\Exception;
15 use PhpOffice\PhpSpreadsheet\Writer\Ods;
16 use PhpOffice\PhpSpreadsheet\Writer\Ods\Cell\Comment;
17
18 /**
19 * @category PhpSpreadsheet
20 *
21 * @method Ods getParentWriter
22 *
23 * @copyright Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
24 * @author Alexander Pervakov <frost-nzcr4@jagmort.com>
25 */
26 class Content extends WriterPart
27 {
28 const NUMBER_COLS_REPEATED_MAX = 1024;
29 const NUMBER_ROWS_REPEATED_MAX = 1048576;
30 const CELL_STYLE_PREFIX = 'ce';
31
32 /**
33 * Write content.xml to XML format.
34 *
35 * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
36 *
37 * @return string XML Output
38 */
39 public function write()
40 {
41 $objWriter = null;
42 if ($this->getParentWriter()->getUseDiskCaching()) {
43 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
44 } else {
45 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
46 }
47
48 // XML header
49 $objWriter->startDocument('1.0', 'UTF-8');
50
51 // Content
52 $objWriter->startElement('office:document-content');
53 $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
54 $objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
55 $objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
56 $objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
57 $objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
58 $objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
59 $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
60 $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
61 $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
62 $objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
63 $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0');
64 $objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
65 $objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0');
66 $objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0');
67 $objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML');
68 $objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0');
69 $objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0');
70 $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
71 $objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer');
72 $objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc');
73 $objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events');
74 $objWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms');
75 $objWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
76 $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
77 $objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report');
78 $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2');
79 $objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
80 $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
81 $objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table');
82 $objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0');
83 $objWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0');
84 $objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/');
85 $objWriter->writeAttribute('office:version', '1.2');
86
87 $objWriter->writeElement('office:scripts');
88 $objWriter->writeElement('office:font-face-decls');
89
90 // Styles XF
91 $objWriter->startElement('office:automatic-styles');
92 $this->writeXfStyles($objWriter, $this->getParentWriter()->getSpreadsheet());
93 $objWriter->endElement();
94
95 $objWriter->startElement('office:body');
96 $objWriter->startElement('office:spreadsheet');
97 $objWriter->writeElement('table:calculation-settings');
98
99 $this->writeSheets($objWriter);
100
101 $objWriter->writeElement('table:named-expressions');
102 $objWriter->endElement();
103 $objWriter->endElement();
104 $objWriter->endElement();
105
106 return $objWriter->getData();
107 }
108
109 /**
110 * Write sheets.
111 *
112 * @param XMLWriter $objWriter
113 */
114 private function writeSheets(XMLWriter $objWriter)
115 {
116 $spreadsheet = $this->getParentWriter()->getSpreadsheet(); // @var $spreadsheet Spreadsheet
117
118 $sheetCount = $spreadsheet->getSheetCount();
119 for ($i = 0; $i < $sheetCount; ++$i) {
120 $objWriter->startElement('table:table');
121 $objWriter->writeAttribute('table:name', $spreadsheet->getSheet($i)->getTitle());
122 $objWriter->writeElement('office:forms');
123 $objWriter->startElement('table:table-column');
124 $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
125 $objWriter->endElement();
126 $this->writeRows($objWriter, $spreadsheet->getSheet($i));
127 $objWriter->endElement();
128 }
129 }
130
131 /**
132 * Write rows of the specified sheet.
133 *
134 * @param XMLWriter $objWriter
135 * @param Worksheet $sheet
136 */
137 private function writeRows(XMLWriter $objWriter, Worksheet $sheet)
138 {
139 $numberRowsRepeated = self::NUMBER_ROWS_REPEATED_MAX;
140 $span_row = 0;
141 $rows = $sheet->getRowIterator();
142 while ($rows->valid()) {
143 --$numberRowsRepeated;
144 $row = $rows->current();
145 if ($row->getCellIterator()->valid()) {
146 if ($span_row) {
147 $objWriter->startElement('table:table-row');
148 if ($span_row > 1) {
149 $objWriter->writeAttribute('table:number-rows-repeated', $span_row);
150 }
151 $objWriter->startElement('table:table-cell');
152 $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
153 $objWriter->endElement();
154 $objWriter->endElement();
155 $span_row = 0;
156 }
157 $objWriter->startElement('table:table-row');
158 $this->writeCells($objWriter, $row);
159 $objWriter->endElement();
160 } else {
161 ++$span_row;
162 }
163 $rows->next();
164 }
165 }
166
167 /**
168 * Write cells of the specified row.
169 *
170 * @param XMLWriter $objWriter
171 * @param Row $row
172 *
173 * @throws Exception
174 */
175 private function writeCells(XMLWriter $objWriter, Row $row)
176 {
177 $numberColsRepeated = self::NUMBER_COLS_REPEATED_MAX;
178 $prevColumn = -1;
179 $cells = $row->getCellIterator();
180 while ($cells->valid()) {
181 /** @var \PhpOffice\PhpSpreadsheet\Cell\Cell $cell */
182 $cell = $cells->current();
183 $column = Coordinate::columnIndexFromString($cell->getColumn()) - 1;
184
185 $this->writeCellSpan($objWriter, $column, $prevColumn);
186 $objWriter->startElement('table:table-cell');
187 $this->writeCellMerge($objWriter, $cell);
188
189 // Style XF
190 $style = $cell->getXfIndex();
191 if ($style !== null) {
192 $objWriter->writeAttribute('table:style-name', self::CELL_STYLE_PREFIX . $style);
193 }
194
195 switch ($cell->getDataType()) {
196 case DataType::TYPE_BOOL:
197 $objWriter->writeAttribute('office:value-type', 'boolean');
198 $objWriter->writeAttribute('office:value', $cell->getValue());
199 $objWriter->writeElement('text:p', $cell->getValue());
200
201 break;
202 case DataType::TYPE_ERROR:
203 throw new Exception('Writing of error not implemented yet.');
204
205 break;
206 case DataType::TYPE_FORMULA:
207 $formulaValue = $cell->getValue();
208 if ($this->getParentWriter()->getPreCalculateFormulas()) {
209 try {
210 $formulaValue = $cell->getCalculatedValue();
211 } catch (Exception $e) {
212 // don't do anything
213 }
214 }
215 $objWriter->writeAttribute('table:formula', 'of:' . $cell->getValue());
216 if (is_numeric($formulaValue)) {
217 $objWriter->writeAttribute('office:value-type', 'float');
218 } else {
219 $objWriter->writeAttribute('office:value-type', 'string');
220 }
221 $objWriter->writeAttribute('office:value', $formulaValue);
222 $objWriter->writeElement('text:p', $formulaValue);
223
224 break;
225 case DataType::TYPE_INLINE:
226 throw new Exception('Writing of inline not implemented yet.');
227
228 break;
229 case DataType::TYPE_NUMERIC:
230 $objWriter->writeAttribute('office:value-type', 'float');
231 $objWriter->writeAttribute('office:value', $cell->getValue());
232 $objWriter->writeElement('text:p', $cell->getValue());
233
234 break;
235 case DataType::TYPE_STRING:
236 $objWriter->writeAttribute('office:value-type', 'string');
237 $objWriter->writeElement('text:p', $cell->getValue());
238
239 break;
240 }
241 Comment::write($objWriter, $cell);
242 $objWriter->endElement();
243 $prevColumn = $column;
244 $cells->next();
245 }
246 $numberColsRepeated = $numberColsRepeated - $prevColumn - 1;
247 if ($numberColsRepeated > 0) {
248 if ($numberColsRepeated > 1) {
249 $objWriter->startElement('table:table-cell');
250 $objWriter->writeAttribute('table:number-columns-repeated', $numberColsRepeated);
251 $objWriter->endElement();
252 } else {
253 $objWriter->writeElement('table:table-cell');
254 }
255 }
256 }
257
258 /**
259 * Write span.
260 *
261 * @param XMLWriter $objWriter
262 * @param int $curColumn
263 * @param int $prevColumn
264 */
265 private function writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn)
266 {
267 $diff = $curColumn - $prevColumn - 1;
268 if (1 === $diff) {
269 $objWriter->writeElement('table:table-cell');
270 } elseif ($diff > 1) {
271 $objWriter->startElement('table:table-cell');
272 $objWriter->writeAttribute('table:number-columns-repeated', $diff);
273 $objWriter->endElement();
274 }
275 }
276
277 /**
278 * Write XF cell styles.
279 *
280 * @param XMLWriter $writer
281 * @param Spreadsheet $spreadsheet
282 */
283 private function writeXfStyles(XMLWriter $writer, Spreadsheet $spreadsheet)
284 {
285 foreach ($spreadsheet->getCellXfCollection() as $style) {
286 $writer->startElement('style:style');
287 $writer->writeAttribute('style:name', self::CELL_STYLE_PREFIX . $style->getIndex());
288 $writer->writeAttribute('style:family', 'table-cell');
289 $writer->writeAttribute('style:parent-style-name', 'Default');
290
291 // style:text-properties
292
293 // Font
294 $writer->startElement('style:text-properties');
295
296 $font = $style->getFont();
297
298 if ($font->getBold()) {
299 $writer->writeAttribute('fo:font-weight', 'bold');
300 $writer->writeAttribute('style:font-weight-complex', 'bold');
301 $writer->writeAttribute('style:font-weight-asian', 'bold');
302 }
303
304 if ($font->getItalic()) {
305 $writer->writeAttribute('fo:font-style', 'italic');
306 }
307
308 if ($color = $font->getColor()) {
309 $writer->writeAttribute('fo:color', sprintf('#%s', $color->getRGB()));
310 }
311
312 if ($family = $font->getName()) {
313 $writer->writeAttribute('fo:font-family', $family);
314 }
315
316 if ($size = $font->getSize()) {
317 $writer->writeAttribute('fo:font-size', sprintf('%.1fpt', $size));
318 }
319
320 if ($font->getUnderline() && $font->getUnderline() != Font::UNDERLINE_NONE) {
321 $writer->writeAttribute('style:text-underline-style', 'solid');
322 $writer->writeAttribute('style:text-underline-width', 'auto');
323 $writer->writeAttribute('style:text-underline-color', 'font-color');
324
325 switch ($font->getUnderline()) {
326 case Font::UNDERLINE_DOUBLE:
327 $writer->writeAttribute('style:text-underline-type', 'double');
328
329 break;
330 case Font::UNDERLINE_SINGLE:
331 $writer->writeAttribute('style:text-underline-type', 'single');
332
333 break;
334 }
335 }
336
337 $writer->endElement(); // Close style:text-properties
338
339 // style:table-cell-properties
340
341 $writer->startElement('style:table-cell-properties');
342 $writer->writeAttribute('style:rotation-align', 'none');
343
344 // Fill
345 if ($fill = $style->getFill()) {
346 switch ($fill->getFillType()) {
347 case Fill::FILL_SOLID:
348 $writer->writeAttribute('fo:background-color', sprintf(
349 '#%s',
350 strtolower($fill->getStartColor()->getRGB())
351 ));
352
353 break;
354 case Fill::FILL_GRADIENT_LINEAR:
355 case Fill::FILL_GRADIENT_PATH:
356 /// TODO :: To be implemented
357 break;
358 case Fill::FILL_NONE:
359 default:
360 }
361 }
362
363 $writer->endElement(); // Close style:table-cell-properties
364
365 // End
366
367 $writer->endElement(); // Close style:style
368 }
369 }
370
371 /**
372 * Write attributes for merged cell.
373 *
374 * @param XMLWriter $objWriter
375 * @param Cell $cell
376 *
377 * @throws \PhpOffice\PhpSpreadsheet\Exception
378 */
379 private function writeCellMerge(XMLWriter $objWriter, Cell $cell)
380 {
381 if (!$cell->isMergeRangeValueCell()) {
382 return;
383 }
384
385 $mergeRange = Coordinate::splitRange($cell->getMergeRange());
386 list($startCell, $endCell) = $mergeRange[0];
387 $start = Coordinate::coordinateFromString($startCell);
388 $end = Coordinate::coordinateFromString($endCell);
389 $columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1;
390 $rowSpan = $end[1] - $start[1] + 1;
391
392 $objWriter->writeAttribute('table:number-columns-spanned', $columnSpan);
393 $objWriter->writeAttribute('table:number-rows-spanned', $rowSpan);
394 }
395 }
396