ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Content.php
Go to the documentation of this file.
1<?php
2
4
16
20class Content extends WriterPart
21{
23 const NUMBER_ROWS_REPEATED_MAX = 1048576;
24
26
30 public function __construct(Ods $writer)
31 {
32 parent::__construct($writer);
33
34 $this->formulaConvertor = new Formula($this->getParentWriter()->getSpreadsheet()->getDefinedNames());
35 }
36
42 public function write(): string
43 {
44 $objWriter = null;
45 if ($this->getParentWriter()->getUseDiskCaching()) {
47 } else {
48 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
49 }
50
51 // XML header
52 $objWriter->startDocument('1.0', 'UTF-8');
53
54 // Content
55 $objWriter->startElement('office:document-content');
56 $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
57 $objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
58 $objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
59 $objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
60 $objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
61 $objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
62 $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
63 $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
64 $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
65 $objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
66 $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0');
67 $objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
68 $objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0');
69 $objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0');
70 $objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML');
71 $objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0');
72 $objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0');
73 $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
74 $objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer');
75 $objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc');
76 $objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events');
77 $objWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms');
78 $objWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
79 $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
80 $objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report');
81 $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2');
82 $objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
83 $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
84 $objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table');
85 $objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0');
86 $objWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0');
87 $objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/');
88 $objWriter->writeAttribute('office:version', '1.2');
89
90 $objWriter->writeElement('office:scripts');
91 $objWriter->writeElement('office:font-face-decls');
92
93 // Styles XF
94 $objWriter->startElement('office:automatic-styles');
95 $this->writeXfStyles($objWriter, $this->getParentWriter()->getSpreadsheet());
96 $objWriter->endElement();
97
98 $objWriter->startElement('office:body');
99 $objWriter->startElement('office:spreadsheet');
100 $objWriter->writeElement('table:calculation-settings');
101
102 $this->writeSheets($objWriter);
103
104 (new AutoFilters($objWriter, $this->getParentWriter()->getSpreadsheet()))->write();
105 // Defined names (ranges and formulae)
106 (new NamedExpressions($objWriter, $this->getParentWriter()->getSpreadsheet(), $this->formulaConvertor))->write();
107
108 $objWriter->endElement();
109 $objWriter->endElement();
110 $objWriter->endElement();
111
112 return $objWriter->getData();
113 }
114
118 private function writeSheets(XMLWriter $objWriter): void
119 {
120 $spreadsheet = $this->getParentWriter()->getSpreadsheet();
121 $sheetCount = $spreadsheet->getSheetCount();
122 for ($i = 0; $i < $sheetCount; ++$i) {
123 $objWriter->startElement('table:table');
124 $objWriter->writeAttribute('table:name', $spreadsheet->getSheet($i)->getTitle());
125 $objWriter->writeElement('office:forms');
126 $objWriter->startElement('table:table-column');
127 $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
128 $objWriter->endElement();
129 $this->writeRows($objWriter, $spreadsheet->getSheet($i));
130 $objWriter->endElement();
131 }
132 }
133
137 private function writeRows(XMLWriter $objWriter, Worksheet $sheet): void
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
170 private function writeCells(XMLWriter $objWriter, Row $row): void
171 {
172 $numberColsRepeated = self::NUMBER_COLS_REPEATED_MAX;
173 $prevColumn = -1;
174 $cells = $row->getCellIterator();
175 while ($cells->valid()) {
177 $cell = $cells->current();
178 $column = Coordinate::columnIndexFromString($cell->getColumn()) - 1;
179
180 $this->writeCellSpan($objWriter, $column, $prevColumn);
181 $objWriter->startElement('table:table-cell');
182 $this->writeCellMerge($objWriter, $cell);
183
184 // Style XF
185 $style = $cell->getXfIndex();
186 if ($style !== null) {
187 $objWriter->writeAttribute('table:style-name', Style::CELL_STYLE_PREFIX . $style);
188 }
189
190 switch ($cell->getDataType()) {
192 $objWriter->writeAttribute('office:value-type', 'boolean');
193 $objWriter->writeAttribute('office:value', $cell->getValue());
194 $objWriter->writeElement('text:p', $cell->getValue());
195
196 break;
198 $objWriter->writeAttribute('table:formula', 'of:=#NULL!');
199 $objWriter->writeAttribute('office:value-type', 'string');
200 $objWriter->writeAttribute('office:string-value', '');
201 $objWriter->writeElement('text:p', '#NULL!');
202
203 break;
205 $formulaValue = $cell->getValue();
207 try {
208 $formulaValue = $cell->getCalculatedValue();
209 } catch (Exception $e) {
210 // don't do anything
211 }
212 }
213 $objWriter->writeAttribute('table:formula', $this->formulaConvertor->convertFormula($cell->getValue()));
214 if (is_numeric($formulaValue)) {
215 $objWriter->writeAttribute('office:value-type', 'float');
216 } else {
217 $objWriter->writeAttribute('office:value-type', 'string');
218 }
219 $objWriter->writeAttribute('office:value', $formulaValue);
220 $objWriter->writeElement('text:p', $formulaValue);
221
222 break;
224 $objWriter->writeAttribute('office:value-type', 'float');
225 $objWriter->writeAttribute('office:value', $cell->getValue());
226 $objWriter->writeElement('text:p', $cell->getValue());
227
228 break;
230 // break intentionally omitted
232 $objWriter->writeAttribute('office:value-type', 'string');
233 $objWriter->writeElement('text:p', $cell->getValue());
234
235 break;
236 }
237 Comment::write($objWriter, $cell);
238 $objWriter->endElement();
239 $prevColumn = $column;
240 $cells->next();
241 }
242 $numberColsRepeated = $numberColsRepeated - $prevColumn - 1;
243 if ($numberColsRepeated > 0) {
244 if ($numberColsRepeated > 1) {
245 $objWriter->startElement('table:table-cell');
246 $objWriter->writeAttribute('table:number-columns-repeated', $numberColsRepeated);
247 $objWriter->endElement();
248 } else {
249 $objWriter->writeElement('table:table-cell');
250 }
251 }
252 }
253
260 private function writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn): void
261 {
262 $diff = $curColumn - $prevColumn - 1;
263 if (1 === $diff) {
264 $objWriter->writeElement('table:table-cell');
265 } elseif ($diff > 1) {
266 $objWriter->startElement('table:table-cell');
267 $objWriter->writeAttribute('table:number-columns-repeated', $diff);
268 $objWriter->endElement();
269 }
270 }
271
275 private function writeXfStyles(XMLWriter $writer, Spreadsheet $spreadsheet): void
276 {
277 $styleWriter = new Style($writer);
278 foreach ($spreadsheet->getCellXfCollection() as $style) {
279 $styleWriter->write($style);
280 }
281 }
282
286 private function writeCellMerge(XMLWriter $objWriter, Cell $cell): void
287 {
288 if (!$cell->isMergeRangeValueCell()) {
289 return;
290 }
291
292 $mergeRange = Coordinate::splitRange($cell->getMergeRange());
293 [$startCell, $endCell] = $mergeRange[0];
297 $rowSpan = ((int) $end[1]) - ((int) $start[1]) + 1;
298
299 $objWriter->writeAttribute('table:number-columns-spanned', $columnSpan);
300 $objWriter->writeAttribute('table:number-rows-spanned', $rowSpan);
301 }
302}
An exception for terminatinating execution or to throw for unit testing.
getMergeRange()
If this cell is in a merge range, then return the range.
Definition: Cell.php:517
isMergeRangeValueCell()
Is this cell the master (top left cell) in a merge range (that holds the actual data value).
Definition: Cell.php:499
Helper class to manipulate cell coordinates.
Definition: Coordinate.php:15
static coordinateFromString($pCoordinateString)
Coordinate from string.
Definition: Coordinate.php:32
static columnIndexFromString($pString)
Column index from string.
Definition: Coordinate.php:265
static splitRange($pRange)
Split range into coordinate strings.
Definition: Coordinate.php:140
const STORAGE_MEMORY
Temporary storage method.
Definition: XMLWriter.php:10
getCellXfCollection()
Get the workbook collection of cellXfs.
getPreCalculateFormulas()
Get Pre-Calculate Formulas flag If this is true (the default), then the writer will recalculate all f...
Definition: BaseWriter.php:60
getDiskCachingDirectory()
Get disk caching directory.
Definition: BaseWriter.php:92
getUseDiskCaching()
Get use disk caching where possible?
Definition: BaseWriter.php:72
static write(XMLWriter $objWriter, Cell $cell)
Definition: Comment.php:13
__construct(Ods $writer)
Set parent Ods writer.
Definition: Content.php:30
writeXfStyles(XMLWriter $writer, Spreadsheet $spreadsheet)
Write XF cell styles.
Definition: Content.php:275
write()
Write content.xml to XML format.
Definition: Content.php:42
writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn)
Write span.
Definition: Content.php:260
writeRows(XMLWriter $objWriter, Worksheet $sheet)
Write rows of the specified sheet.
Definition: Content.php:137
writeCellMerge(XMLWriter $objWriter, Cell $cell)
Write attributes for merged cell.
Definition: Content.php:286
getSpreadsheet()
Get Spreadsheet object.
Definition: Ods.php:174
$i
Definition: disco.tpl.php:19
$style
Definition: example_012.php:70
$row
$start
Definition: bench.php:8
$rows
Definition: xhr_table.php:10