ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Worksheet.php
Go to the documentation of this file.
1 <?php
2 
4 
17 
18 class Worksheet extends WriterPart
19 {
28  public function writeWorksheet(PhpspreadsheetWorksheet $pSheet, $pStringTable = null, $includeCharts = false)
29  {
30  // Create XML writer
31  $objWriter = null;
32  if ($this->getParentWriter()->getUseDiskCaching()) {
33  $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
34  } else {
35  $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
36  }
37 
38  // XML header
39  $objWriter->startDocument('1.0', 'UTF-8', 'yes');
40 
41  // Worksheet
42  $objWriter->startElement('worksheet');
43  $objWriter->writeAttribute('xml:space', 'preserve');
44  $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
45  $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
46 
47  $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
48  $objWriter->writeAttribute('xmlns:x14', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main');
49  $objWriter->writeAttribute('xmlns:xm', 'http://schemas.microsoft.com/office/excel/2006/main');
50  $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006');
51  $objWriter->writeAttribute('mc:Ignorable', 'x14ac');
52  $objWriter->writeAttribute('xmlns:x14ac', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac');
53 
54  // sheetPr
55  $this->writeSheetPr($objWriter, $pSheet);
56 
57  // Dimension
58  $this->writeDimension($objWriter, $pSheet);
59 
60  // sheetViews
61  $this->writeSheetViews($objWriter, $pSheet);
62 
63  // sheetFormatPr
64  $this->writeSheetFormatPr($objWriter, $pSheet);
65 
66  // cols
67  $this->writeCols($objWriter, $pSheet);
68 
69  // sheetData
70  $this->writeSheetData($objWriter, $pSheet, $pStringTable);
71 
72  // sheetProtection
73  $this->writeSheetProtection($objWriter, $pSheet);
74 
75  // protectedRanges
76  $this->writeProtectedRanges($objWriter, $pSheet);
77 
78  // autoFilter
79  $this->writeAutoFilter($objWriter, $pSheet);
80 
81  // mergeCells
82  $this->writeMergeCells($objWriter, $pSheet);
83 
84  // conditionalFormatting
85  $this->writeConditionalFormatting($objWriter, $pSheet);
86 
87  // dataValidations
88  $this->writeDataValidations($objWriter, $pSheet);
89 
90  // hyperlinks
91  $this->writeHyperlinks($objWriter, $pSheet);
92 
93  // Print options
94  $this->writePrintOptions($objWriter, $pSheet);
95 
96  // Page margins
97  $this->writePageMargins($objWriter, $pSheet);
98 
99  // Page setup
100  $this->writePageSetup($objWriter, $pSheet);
101 
102  // Header / footer
103  $this->writeHeaderFooter($objWriter, $pSheet);
104 
105  // Breaks
106  $this->writeBreaks($objWriter, $pSheet);
107 
108  // Drawings and/or Charts
109  $this->writeDrawings($objWriter, $pSheet, $includeCharts);
110 
111  // LegacyDrawing
112  $this->writeLegacyDrawing($objWriter, $pSheet);
113 
114  // LegacyDrawingHF
115  $this->writeLegacyDrawingHF($objWriter, $pSheet);
116 
117  // AlternateContent
118  $this->writeAlternateContent($objWriter, $pSheet);
119 
120  // ConditionalFormattingRuleExtensionList
121  // (Must be inserted last. Not insert last, an Excel parse error will occur)
122  $this->writeExtLst($objWriter, $pSheet);
123 
124  $objWriter->endElement();
125 
126  // Return
127  return $objWriter->getData();
128  }
129 
136  private function writeSheetPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
137  {
138  // sheetPr
139  $objWriter->startElement('sheetPr');
140  if ($pSheet->getParent()->hasMacros()) {
141  //if the workbook have macros, we need to have codeName for the sheet
142  if (!$pSheet->hasCodeName()) {
143  $pSheet->setCodeName($pSheet->getTitle());
144  }
145  $objWriter->writeAttribute('codeName', $pSheet->getCodeName());
146  }
147  $autoFilterRange = $pSheet->getAutoFilter()->getRange();
148  if (!empty($autoFilterRange)) {
149  $objWriter->writeAttribute('filterMode', 1);
150  $pSheet->getAutoFilter()->showHideRows();
151  }
152 
153  // tabColor
154  if ($pSheet->isTabColorSet()) {
155  $objWriter->startElement('tabColor');
156  $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB());
157  $objWriter->endElement();
158  }
159 
160  // outlinePr
161  $objWriter->startElement('outlinePr');
162  $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0'));
163  $objWriter->writeAttribute('summaryRight', ($pSheet->getShowSummaryRight() ? '1' : '0'));
164  $objWriter->endElement();
165 
166  // pageSetUpPr
167  if ($pSheet->getPageSetup()->getFitToPage()) {
168  $objWriter->startElement('pageSetUpPr');
169  $objWriter->writeAttribute('fitToPage', '1');
170  $objWriter->endElement();
171  }
172 
173  $objWriter->endElement();
174  }
175 
182  private function writeDimension(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
183  {
184  // dimension
185  $objWriter->startElement('dimension');
186  $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension());
187  $objWriter->endElement();
188  }
189 
196  private function writeSheetViews(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
197  {
198  // sheetViews
199  $objWriter->startElement('sheetViews');
200 
201  // Sheet selected?
202  $sheetSelected = false;
203  if ($this->getParentWriter()->getSpreadsheet()->getIndex($pSheet) == $this->getParentWriter()->getSpreadsheet()->getActiveSheetIndex()) {
204  $sheetSelected = true;
205  }
206 
207  // sheetView
208  $objWriter->startElement('sheetView');
209  $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0');
210  $objWriter->writeAttribute('workbookViewId', '0');
211 
212  // Zoom scales
213  if ($pSheet->getSheetView()->getZoomScale() != 100) {
214  $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale());
215  }
216  if ($pSheet->getSheetView()->getZoomScaleNormal() != 100) {
217  $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal());
218  }
219 
220  // Show zeros (Excel also writes this attribute only if set to false)
221  if ($pSheet->getSheetView()->getShowZeros() === false) {
222  $objWriter->writeAttribute('showZeros', 0);
223  }
224 
225  // View Layout Type
226  if ($pSheet->getSheetView()->getView() !== SheetView::SHEETVIEW_NORMAL) {
227  $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView());
228  }
229 
230  // Gridlines
231  if ($pSheet->getShowGridlines()) {
232  $objWriter->writeAttribute('showGridLines', 'true');
233  } else {
234  $objWriter->writeAttribute('showGridLines', 'false');
235  }
236 
237  // Row and column headers
238  if ($pSheet->getShowRowColHeaders()) {
239  $objWriter->writeAttribute('showRowColHeaders', '1');
240  } else {
241  $objWriter->writeAttribute('showRowColHeaders', '0');
242  }
243 
244  // Right-to-left
245  if ($pSheet->getRightToLeft()) {
246  $objWriter->writeAttribute('rightToLeft', 'true');
247  }
248 
249  $activeCell = $pSheet->getActiveCell();
250  $sqref = $pSheet->getSelectedCells();
251 
252  // Pane
253  $pane = '';
254  if ($pSheet->getFreezePane()) {
255  [$xSplit, $ySplit] = Coordinate::coordinateFromString($pSheet->getFreezePane());
256  $xSplit = Coordinate::columnIndexFromString($xSplit);
257  --$xSplit;
258  --$ySplit;
259 
260  $topLeftCell = $pSheet->getTopLeftCell();
261 
262  // pane
263  $pane = 'topRight';
264  $objWriter->startElement('pane');
265  if ($xSplit > 0) {
266  $objWriter->writeAttribute('xSplit', $xSplit);
267  }
268  if ($ySplit > 0) {
269  $objWriter->writeAttribute('ySplit', $ySplit);
270  $pane = ($xSplit > 0) ? 'bottomRight' : 'bottomLeft';
271  }
272  $objWriter->writeAttribute('topLeftCell', $topLeftCell);
273  $objWriter->writeAttribute('activePane', $pane);
274  $objWriter->writeAttribute('state', 'frozen');
275  $objWriter->endElement();
276 
277  if (($xSplit > 0) && ($ySplit > 0)) {
278  // Write additional selections if more than two panes (ie both an X and a Y split)
279  $objWriter->startElement('selection');
280  $objWriter->writeAttribute('pane', 'topRight');
281  $objWriter->endElement();
282  $objWriter->startElement('selection');
283  $objWriter->writeAttribute('pane', 'bottomLeft');
284  $objWriter->endElement();
285  }
286  }
287 
288  // Selection
289  // Only need to write selection element if we have a split pane
290  // We cheat a little by over-riding the active cell selection, setting it to the split cell
291  $objWriter->startElement('selection');
292  if ($pane != '') {
293  $objWriter->writeAttribute('pane', $pane);
294  }
295  $objWriter->writeAttribute('activeCell', $activeCell);
296  $objWriter->writeAttribute('sqref', $sqref);
297  $objWriter->endElement();
298 
299  $objWriter->endElement();
300 
301  $objWriter->endElement();
302  }
303 
310  private function writeSheetFormatPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
311  {
312  // sheetFormatPr
313  $objWriter->startElement('sheetFormatPr');
314 
315  // Default row height
316  if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) {
317  $objWriter->writeAttribute('customHeight', 'true');
318  $objWriter->writeAttribute('defaultRowHeight', StringHelper::formatNumber($pSheet->getDefaultRowDimension()->getRowHeight()));
319  } else {
320  $objWriter->writeAttribute('defaultRowHeight', '14.4');
321  }
322 
323  // Set Zero Height row
324  if (
325  (string) $pSheet->getDefaultRowDimension()->getZeroHeight() === '1' ||
326  strtolower((string) $pSheet->getDefaultRowDimension()->getZeroHeight()) == 'true'
327  ) {
328  $objWriter->writeAttribute('zeroHeight', '1');
329  }
330 
331  // Default column width
332  if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) {
333  $objWriter->writeAttribute('defaultColWidth', StringHelper::formatNumber($pSheet->getDefaultColumnDimension()->getWidth()));
334  }
335 
336  // Outline level - row
337  $outlineLevelRow = 0;
338  foreach ($pSheet->getRowDimensions() as $dimension) {
339  if ($dimension->getOutlineLevel() > $outlineLevelRow) {
340  $outlineLevelRow = $dimension->getOutlineLevel();
341  }
342  }
343  $objWriter->writeAttribute('outlineLevelRow', (int) $outlineLevelRow);
344 
345  // Outline level - column
346  $outlineLevelCol = 0;
347  foreach ($pSheet->getColumnDimensions() as $dimension) {
348  if ($dimension->getOutlineLevel() > $outlineLevelCol) {
349  $outlineLevelCol = $dimension->getOutlineLevel();
350  }
351  }
352  $objWriter->writeAttribute('outlineLevelCol', (int) $outlineLevelCol);
353 
354  $objWriter->endElement();
355  }
356 
363  private function writeCols(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
364  {
365  // cols
366  if (count($pSheet->getColumnDimensions()) > 0) {
367  $objWriter->startElement('cols');
368 
369  $pSheet->calculateColumnWidths();
370 
371  // Loop through column dimensions
372  foreach ($pSheet->getColumnDimensions() as $colDimension) {
373  // col
374  $objWriter->startElement('col');
375  $objWriter->writeAttribute('min', Coordinate::columnIndexFromString($colDimension->getColumnIndex()));
376  $objWriter->writeAttribute('max', Coordinate::columnIndexFromString($colDimension->getColumnIndex()));
377 
378  if ($colDimension->getWidth() < 0) {
379  // No width set, apply default of 10
380  $objWriter->writeAttribute('width', '9.10');
381  } else {
382  // Width set
383  $objWriter->writeAttribute('width', StringHelper::formatNumber($colDimension->getWidth()));
384  }
385 
386  // Column visibility
387  if ($colDimension->getVisible() === false) {
388  $objWriter->writeAttribute('hidden', 'true');
389  }
390 
391  // Auto size?
392  if ($colDimension->getAutoSize()) {
393  $objWriter->writeAttribute('bestFit', 'true');
394  }
395 
396  // Custom width?
397  if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) {
398  $objWriter->writeAttribute('customWidth', 'true');
399  }
400 
401  // Collapsed
402  if ($colDimension->getCollapsed() === true) {
403  $objWriter->writeAttribute('collapsed', 'true');
404  }
405 
406  // Outline level
407  if ($colDimension->getOutlineLevel() > 0) {
408  $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel());
409  }
410 
411  // Style
412  $objWriter->writeAttribute('style', $colDimension->getXfIndex());
413 
414  $objWriter->endElement();
415  }
416 
417  $objWriter->endElement();
418  }
419  }
420 
427  private function writeSheetProtection(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
428  {
429  // sheetProtection
430  $objWriter->startElement('sheetProtection');
431 
432  $protection = $pSheet->getProtection();
433 
434  if ($protection->getAlgorithm()) {
435  $objWriter->writeAttribute('algorithmName', $protection->getAlgorithm());
436  $objWriter->writeAttribute('hashValue', $protection->getPassword());
437  $objWriter->writeAttribute('saltValue', $protection->getSalt());
438  $objWriter->writeAttribute('spinCount', $protection->getSpinCount());
439  } elseif ($protection->getPassword() !== '') {
440  $objWriter->writeAttribute('password', $protection->getPassword());
441  }
442 
443  $objWriter->writeAttribute('sheet', ($protection->getSheet() ? 'true' : 'false'));
444  $objWriter->writeAttribute('objects', ($protection->getObjects() ? 'true' : 'false'));
445  $objWriter->writeAttribute('scenarios', ($protection->getScenarios() ? 'true' : 'false'));
446  $objWriter->writeAttribute('formatCells', ($protection->getFormatCells() ? 'true' : 'false'));
447  $objWriter->writeAttribute('formatColumns', ($protection->getFormatColumns() ? 'true' : 'false'));
448  $objWriter->writeAttribute('formatRows', ($protection->getFormatRows() ? 'true' : 'false'));
449  $objWriter->writeAttribute('insertColumns', ($protection->getInsertColumns() ? 'true' : 'false'));
450  $objWriter->writeAttribute('insertRows', ($protection->getInsertRows() ? 'true' : 'false'));
451  $objWriter->writeAttribute('insertHyperlinks', ($protection->getInsertHyperlinks() ? 'true' : 'false'));
452  $objWriter->writeAttribute('deleteColumns', ($protection->getDeleteColumns() ? 'true' : 'false'));
453  $objWriter->writeAttribute('deleteRows', ($protection->getDeleteRows() ? 'true' : 'false'));
454  $objWriter->writeAttribute('selectLockedCells', ($protection->getSelectLockedCells() ? 'true' : 'false'));
455  $objWriter->writeAttribute('sort', ($protection->getSort() ? 'true' : 'false'));
456  $objWriter->writeAttribute('autoFilter', ($protection->getAutoFilter() ? 'true' : 'false'));
457  $objWriter->writeAttribute('pivotTables', ($protection->getPivotTables() ? 'true' : 'false'));
458  $objWriter->writeAttribute('selectUnlockedCells', ($protection->getSelectUnlockedCells() ? 'true' : 'false'));
459  $objWriter->endElement();
460  }
461 
462  private static function writeAttributeIf(XMLWriter $objWriter, $condition, string $attr, string $val): void
463  {
464  if ($condition) {
465  $objWriter->writeAttribute($attr, $val);
466  }
467  }
468 
469  private static function writeElementIf(XMLWriter $objWriter, $condition, string $attr, string $val): void
470  {
471  if ($condition) {
472  $objWriter->writeElement($attr, $val);
473  }
474  }
475 
476  private static function writeOtherCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate): void
477  {
478  if (
479  $conditional->getConditionType() == Conditional::CONDITION_CELLIS
480  || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
481  || $conditional->getConditionType() == Conditional::CONDITION_EXPRESSION
482  ) {
483  foreach ($conditional->getConditions() as $formula) {
484  // Formula
485  $objWriter->writeElement('formula', Xlfn::addXlfn($formula));
486  }
487  } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSBLANKS) {
488  // formula copied from ms xlsx xml source file
489  $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))=0');
490  } elseif ($conditional->getConditionType() == Conditional::CONDITION_NOTCONTAINSBLANKS) {
491  // formula copied from ms xlsx xml source file
492  $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))>0');
493  }
494  }
495 
496  private static function writeTextCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate): void
497  {
498  $txt = $conditional->getText();
499  if ($txt !== null) {
500  $objWriter->writeAttribute('text', $txt);
501  if ($conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT) {
502  $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $txt . '",' . $cellCoordinate . ')))');
503  } elseif ($conditional->getOperatorType() == Conditional::OPERATOR_BEGINSWITH) {
504  $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($txt) . ')="' . $txt . '"');
505  } elseif ($conditional->getOperatorType() == Conditional::OPERATOR_ENDSWITH) {
506  $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($txt) . ')="' . $txt . '"');
507  } elseif ($conditional->getOperatorType() == Conditional::OPERATOR_NOTCONTAINS) {
508  $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $txt . '",' . $cellCoordinate . '))');
509  }
510  }
511  }
512 
513  private static function writeExtConditionalFormattingElements(XMLWriter $objWriter, ConditionalFormattingRuleExtension $ruleExtension): void
514  {
515  $prefix = 'x14';
516  $objWriter->startElementNs($prefix, 'conditionalFormatting', null);
517 
518  $objWriter->startElementNs($prefix, 'cfRule', null);
519  $objWriter->writeAttribute('type', $ruleExtension->getCfRule());
520  $objWriter->writeAttribute('id', $ruleExtension->getId());
521  $objWriter->startElementNs($prefix, 'dataBar', null);
522  $dataBar = $ruleExtension->getDataBarExt();
523  foreach ($dataBar->getXmlAttributes() as $attrKey => $val) {
524  $objWriter->writeAttribute($attrKey, $val);
525  }
526  $minCfvo = $dataBar->getMinimumConditionalFormatValueObject();
527  if ($minCfvo) {
528  $objWriter->startElementNs($prefix, 'cfvo', null);
529  $objWriter->writeAttribute('type', $minCfvo->getType());
530  if ($minCfvo->getCellFormula()) {
531  $objWriter->writeElement('xm:f', $minCfvo->getCellFormula());
532  }
533  $objWriter->endElement(); //end cfvo
534  }
535 
536  $maxCfvo = $dataBar->getMaximumConditionalFormatValueObject();
537  if ($maxCfvo) {
538  $objWriter->startElementNs($prefix, 'cfvo', null);
539  $objWriter->writeAttribute('type', $maxCfvo->getType());
540  if ($maxCfvo->getCellFormula()) {
541  $objWriter->writeElement('xm:f', $maxCfvo->getCellFormula());
542  }
543  $objWriter->endElement(); //end cfvo
544  }
545 
546  foreach ($dataBar->getXmlElements() as $elmKey => $elmAttr) {
547  $objWriter->startElementNs($prefix, $elmKey, null);
548  foreach ($elmAttr as $attrKey => $attrVal) {
549  $objWriter->writeAttribute($attrKey, $attrVal);
550  }
551  $objWriter->endElement(); //end elmKey
552  }
553  $objWriter->endElement(); //end dataBar
554  $objWriter->endElement(); //end cfRule
555  $objWriter->writeElement('xm:sqref', $ruleExtension->getSqref());
556  $objWriter->endElement(); //end conditionalFormatting
557  }
558 
559  private static function writeDataBarElements(XMLWriter $objWriter, $dataBar): void
560  {
562  if ($dataBar) {
563  $objWriter->startElement('dataBar');
564  self::writeAttributeIf($objWriter, null !== $dataBar->getShowValue(), 'showValue', $dataBar->getShowValue() ? '1' : '0');
565 
566  $minCfvo = $dataBar->getMinimumConditionalFormatValueObject();
567  if ($minCfvo) {
568  $objWriter->startElement('cfvo');
569  self::writeAttributeIf($objWriter, $minCfvo->getType(), 'type', (string) $minCfvo->getType());
570  self::writeAttributeIf($objWriter, $minCfvo->getValue(), 'val', (string) $minCfvo->getValue());
571  $objWriter->endElement();
572  }
573  $maxCfvo = $dataBar->getMaximumConditionalFormatValueObject();
574  if ($maxCfvo) {
575  $objWriter->startElement('cfvo');
576  self::writeAttributeIf($objWriter, $maxCfvo->getType(), 'type', (string) $maxCfvo->getType());
577  self::writeAttributeIf($objWriter, $maxCfvo->getValue(), 'val', (string) $maxCfvo->getValue());
578  $objWriter->endElement();
579  }
580  if ($dataBar->getColor()) {
581  $objWriter->startElement('color');
582  $objWriter->writeAttribute('rgb', $dataBar->getColor());
583  $objWriter->endElement();
584  }
585  $objWriter->endElement(); // end dataBar
586 
587  if ($dataBar->getConditionalFormattingRuleExt()) {
588  $objWriter->startElement('extLst');
589  $extension = $dataBar->getConditionalFormattingRuleExt();
590  $objWriter->startElement('ext');
591  $objWriter->writeAttribute('uri', '{B025F937-C7B1-47D3-B67F-A62EFF666E3E}');
592  $objWriter->startElementNs('x14', 'id', null);
593  $objWriter->text($extension->getId());
594  $objWriter->endElement();
595  $objWriter->endElement();
596  $objWriter->endElement(); //end extLst
597  }
598  }
599  }
600 
607  private function writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
608  {
609  // Conditional id
610  $id = 1;
611 
612  // Loop through styles in the current worksheet
613  foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
614  foreach ($conditionalStyles as $conditional) {
615  // WHY was this again?
616  // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()) == '') {
617  // continue;
618  // }
619  if ($conditional->getConditionType() != Conditional::CONDITION_NONE) {
620  // conditionalFormatting
621  $objWriter->startElement('conditionalFormatting');
622  $objWriter->writeAttribute('sqref', $cellCoordinate);
623 
624  // cfRule
625  $objWriter->startElement('cfRule');
626  $objWriter->writeAttribute('type', $conditional->getConditionType());
627  self::writeAttributeIf(
628  $objWriter,
629  ($conditional->getConditionType() != Conditional::CONDITION_DATABAR),
630  'dxfId',
631  $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode())
632  );
633  $objWriter->writeAttribute('priority', $id++);
634 
635  self::writeAttributeif(
636  $objWriter,
637  (
638  $conditional->getConditionType() === Conditional::CONDITION_CELLIS
639  || $conditional->getConditionType() === Conditional::CONDITION_CONTAINSTEXT
640  || $conditional->getConditionType() === Conditional::CONDITION_NOTCONTAINSTEXT
641  ) && $conditional->getOperatorType() !== Conditional::OPERATOR_NONE,
642  'operator',
643  $conditional->getOperatorType()
644  );
645 
646  self::writeAttributeIf($objWriter, $conditional->getStopIfTrue(), 'stopIfTrue', '1');
647 
648  if (
649  $conditional->getConditionType() === Conditional::CONDITION_CONTAINSTEXT
650  || $conditional->getConditionType() === Conditional::CONDITION_NOTCONTAINSTEXT
651  ) {
652  self::writeTextCondElements($objWriter, $conditional, $cellCoordinate);
653  } else {
654  self::writeOtherCondElements($objWriter, $conditional, $cellCoordinate);
655  }
656 
657  //<dataBar>
658  self::writeDataBarElements($objWriter, $conditional->getDataBar());
659 
660  $objWriter->endElement(); //end cfRule
661 
662  $objWriter->endElement();
663  }
664  }
665  }
666  }
667 
674  private function writeDataValidations(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
675  {
676  // Datavalidation collection
677  $dataValidationCollection = $pSheet->getDataValidationCollection();
678 
679  // Write data validations?
680  if (!empty($dataValidationCollection)) {
681  $dataValidationCollection = Coordinate::mergeRangesInCollection($dataValidationCollection);
682  $objWriter->startElement('dataValidations');
683  $objWriter->writeAttribute('count', count($dataValidationCollection));
684 
685  foreach ($dataValidationCollection as $coordinate => $dv) {
686  $objWriter->startElement('dataValidation');
687 
688  if ($dv->getType() != '') {
689  $objWriter->writeAttribute('type', $dv->getType());
690  }
691 
692  if ($dv->getErrorStyle() != '') {
693  $objWriter->writeAttribute('errorStyle', $dv->getErrorStyle());
694  }
695 
696  if ($dv->getOperator() != '') {
697  $objWriter->writeAttribute('operator', $dv->getOperator());
698  }
699 
700  $objWriter->writeAttribute('allowBlank', ($dv->getAllowBlank() ? '1' : '0'));
701  $objWriter->writeAttribute('showDropDown', (!$dv->getShowDropDown() ? '1' : '0'));
702  $objWriter->writeAttribute('showInputMessage', ($dv->getShowInputMessage() ? '1' : '0'));
703  $objWriter->writeAttribute('showErrorMessage', ($dv->getShowErrorMessage() ? '1' : '0'));
704 
705  if ($dv->getErrorTitle() !== '') {
706  $objWriter->writeAttribute('errorTitle', $dv->getErrorTitle());
707  }
708  if ($dv->getError() !== '') {
709  $objWriter->writeAttribute('error', $dv->getError());
710  }
711  if ($dv->getPromptTitle() !== '') {
712  $objWriter->writeAttribute('promptTitle', $dv->getPromptTitle());
713  }
714  if ($dv->getPrompt() !== '') {
715  $objWriter->writeAttribute('prompt', $dv->getPrompt());
716  }
717 
718  $objWriter->writeAttribute('sqref', $coordinate);
719 
720  if ($dv->getFormula1() !== '') {
721  $objWriter->writeElement('formula1', $dv->getFormula1());
722  }
723  if ($dv->getFormula2() !== '') {
724  $objWriter->writeElement('formula2', $dv->getFormula2());
725  }
726 
727  $objWriter->endElement();
728  }
729 
730  $objWriter->endElement();
731  }
732  }
733 
740  private function writeHyperlinks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
741  {
742  // Hyperlink collection
743  $hyperlinkCollection = $pSheet->getHyperlinkCollection();
744 
745  // Relation ID
746  $relationId = 1;
747 
748  // Write hyperlinks?
749  if (!empty($hyperlinkCollection)) {
750  $objWriter->startElement('hyperlinks');
751 
752  foreach ($hyperlinkCollection as $coordinate => $hyperlink) {
753  $objWriter->startElement('hyperlink');
754 
755  $objWriter->writeAttribute('ref', $coordinate);
756  if (!$hyperlink->isInternal()) {
757  $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId);
758  ++$relationId;
759  } else {
760  $objWriter->writeAttribute('location', str_replace('sheet://', '', $hyperlink->getUrl()));
761  }
762 
763  if ($hyperlink->getTooltip() !== '') {
764  $objWriter->writeAttribute('tooltip', $hyperlink->getTooltip());
765  $objWriter->writeAttribute('display', $hyperlink->getTooltip());
766  }
767 
768  $objWriter->endElement();
769  }
770 
771  $objWriter->endElement();
772  }
773  }
774 
781  private function writeProtectedRanges(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
782  {
783  if (count($pSheet->getProtectedCells()) > 0) {
784  // protectedRanges
785  $objWriter->startElement('protectedRanges');
786 
787  // Loop protectedRanges
788  foreach ($pSheet->getProtectedCells() as $protectedCell => $passwordHash) {
789  // protectedRange
790  $objWriter->startElement('protectedRange');
791  $objWriter->writeAttribute('name', 'p' . md5($protectedCell));
792  $objWriter->writeAttribute('sqref', $protectedCell);
793  if (!empty($passwordHash)) {
794  $objWriter->writeAttribute('password', $passwordHash);
795  }
796  $objWriter->endElement();
797  }
798 
799  $objWriter->endElement();
800  }
801  }
802 
809  private function writeMergeCells(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
810  {
811  if (count($pSheet->getMergeCells()) > 0) {
812  // mergeCells
813  $objWriter->startElement('mergeCells');
814 
815  // Loop mergeCells
816  foreach ($pSheet->getMergeCells() as $mergeCell) {
817  // mergeCell
818  $objWriter->startElement('mergeCell');
819  $objWriter->writeAttribute('ref', $mergeCell);
820  $objWriter->endElement();
821  }
822 
823  $objWriter->endElement();
824  }
825  }
826 
833  private function writePrintOptions(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
834  {
835  // printOptions
836  $objWriter->startElement('printOptions');
837 
838  $objWriter->writeAttribute('gridLines', ($pSheet->getPrintGridlines() ? 'true' : 'false'));
839  $objWriter->writeAttribute('gridLinesSet', 'true');
840 
841  if ($pSheet->getPageSetup()->getHorizontalCentered()) {
842  $objWriter->writeAttribute('horizontalCentered', 'true');
843  }
844 
845  if ($pSheet->getPageSetup()->getVerticalCentered()) {
846  $objWriter->writeAttribute('verticalCentered', 'true');
847  }
848 
849  $objWriter->endElement();
850  }
851 
858  private function writePageMargins(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
859  {
860  // pageMargins
861  $objWriter->startElement('pageMargins');
862  $objWriter->writeAttribute('left', StringHelper::formatNumber($pSheet->getPageMargins()->getLeft()));
863  $objWriter->writeAttribute('right', StringHelper::formatNumber($pSheet->getPageMargins()->getRight()));
864  $objWriter->writeAttribute('top', StringHelper::formatNumber($pSheet->getPageMargins()->getTop()));
865  $objWriter->writeAttribute('bottom', StringHelper::formatNumber($pSheet->getPageMargins()->getBottom()));
866  $objWriter->writeAttribute('header', StringHelper::formatNumber($pSheet->getPageMargins()->getHeader()));
867  $objWriter->writeAttribute('footer', StringHelper::formatNumber($pSheet->getPageMargins()->getFooter()));
868  $objWriter->endElement();
869  }
870 
877  private function writeAutoFilter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
878  {
879  $autoFilterRange = $pSheet->getAutoFilter()->getRange();
880  if (!empty($autoFilterRange)) {
881  // autoFilter
882  $objWriter->startElement('autoFilter');
883 
884  // Strip any worksheet reference from the filter coordinates
885  $range = Coordinate::splitRange($autoFilterRange);
886  $range = $range[0];
887  // Strip any worksheet ref
888  [$ws, $range[0]] = PhpspreadsheetWorksheet::extractSheetTitle($range[0], true);
889  $range = implode(':', $range);
890 
891  $objWriter->writeAttribute('ref', str_replace('$', '', $range));
892 
893  $columns = $pSheet->getAutoFilter()->getColumns();
894  if (count($columns) > 0) {
895  foreach ($columns as $columnID => $column) {
896  $rules = $column->getRules();
897  if (count($rules) > 0) {
898  $objWriter->startElement('filterColumn');
899  $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID));
900 
901  $objWriter->startElement($column->getFilterType());
902  if ($column->getJoin() == Column::AUTOFILTER_COLUMN_JOIN_AND) {
903  $objWriter->writeAttribute('and', 1);
904  }
905 
906  foreach ($rules as $rule) {
907  if (
908  ($column->getFilterType() === Column::AUTOFILTER_FILTERTYPE_FILTER) &&
909  ($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_EQUAL) &&
910  ($rule->getValue() === '')
911  ) {
912  // Filter rule for Blanks
913  $objWriter->writeAttribute('blank', 1);
914  } elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) {
915  // Dynamic Filter Rule
916  $objWriter->writeAttribute('type', $rule->getGrouping());
917  $val = $column->getAttribute('val');
918  if ($val !== null) {
919  $objWriter->writeAttribute('val', $val);
920  }
921  $maxVal = $column->getAttribute('maxVal');
922  if ($maxVal !== null) {
923  $objWriter->writeAttribute('maxVal', $maxVal);
924  }
925  } elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) {
926  // Top 10 Filter Rule
927  $objWriter->writeAttribute('val', $rule->getValue());
928  $objWriter->writeAttribute('percent', (($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0'));
929  $objWriter->writeAttribute('top', (($rule->getGrouping() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1' : '0'));
930  } else {
931  // Filter, DateGroupItem or CustomFilter
932  $objWriter->startElement($rule->getRuleType());
933 
934  if ($rule->getOperator() !== Rule::AUTOFILTER_COLUMN_RULE_EQUAL) {
935  $objWriter->writeAttribute('operator', $rule->getOperator());
936  }
937  if ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DATEGROUP) {
938  // Date Group filters
939  foreach ($rule->getValue() as $key => $value) {
940  if ($value > '') {
941  $objWriter->writeAttribute($key, $value);
942  }
943  }
944  $objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping());
945  } else {
946  $objWriter->writeAttribute('val', $rule->getValue());
947  }
948 
949  $objWriter->endElement();
950  }
951  }
952 
953  $objWriter->endElement();
954 
955  $objWriter->endElement();
956  }
957  }
958  }
959  $objWriter->endElement();
960  }
961  }
962 
969  private function writePageSetup(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
970  {
971  // pageSetup
972  $objWriter->startElement('pageSetup');
973  $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize());
974  $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation());
975 
976  if ($pSheet->getPageSetup()->getScale() !== null) {
977  $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale());
978  }
979  if ($pSheet->getPageSetup()->getFitToHeight() !== null) {
980  $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight());
981  } else {
982  $objWriter->writeAttribute('fitToHeight', '0');
983  }
984  if ($pSheet->getPageSetup()->getFitToWidth() !== null) {
985  $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth());
986  } else {
987  $objWriter->writeAttribute('fitToWidth', '0');
988  }
989  if ($pSheet->getPageSetup()->getFirstPageNumber() !== null) {
990  $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber());
991  $objWriter->writeAttribute('useFirstPageNumber', '1');
992  }
993  $objWriter->writeAttribute('pageOrder', $pSheet->getPageSetup()->getPageOrder());
994 
995  $getUnparsedLoadedData = $pSheet->getParent()->getUnparsedLoadedData();
996  if (isset($getUnparsedLoadedData['sheets'][$pSheet->getCodeName()]['pageSetupRelId'])) {
997  $objWriter->writeAttribute('r:id', $getUnparsedLoadedData['sheets'][$pSheet->getCodeName()]['pageSetupRelId']);
998  }
999 
1000  $objWriter->endElement();
1001  }
1002 
1009  private function writeHeaderFooter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
1010  {
1011  // headerFooter
1012  $objWriter->startElement('headerFooter');
1013  $objWriter->writeAttribute('differentOddEven', ($pSheet->getHeaderFooter()->getDifferentOddEven() ? 'true' : 'false'));
1014  $objWriter->writeAttribute('differentFirst', ($pSheet->getHeaderFooter()->getDifferentFirst() ? 'true' : 'false'));
1015  $objWriter->writeAttribute('scaleWithDoc', ($pSheet->getHeaderFooter()->getScaleWithDocument() ? 'true' : 'false'));
1016  $objWriter->writeAttribute('alignWithMargins', ($pSheet->getHeaderFooter()->getAlignWithMargins() ? 'true' : 'false'));
1017 
1018  $objWriter->writeElement('oddHeader', $pSheet->getHeaderFooter()->getOddHeader());
1019  $objWriter->writeElement('oddFooter', $pSheet->getHeaderFooter()->getOddFooter());
1020  $objWriter->writeElement('evenHeader', $pSheet->getHeaderFooter()->getEvenHeader());
1021  $objWriter->writeElement('evenFooter', $pSheet->getHeaderFooter()->getEvenFooter());
1022  $objWriter->writeElement('firstHeader', $pSheet->getHeaderFooter()->getFirstHeader());
1023  $objWriter->writeElement('firstFooter', $pSheet->getHeaderFooter()->getFirstFooter());
1024  $objWriter->endElement();
1025  }
1026 
1033  private function writeBreaks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
1034  {
1035  // Get row and column breaks
1036  $aRowBreaks = [];
1037  $aColumnBreaks = [];
1038  foreach ($pSheet->getBreaks() as $cell => $breakType) {
1039  if ($breakType == PhpspreadsheetWorksheet::BREAK_ROW) {
1040  $aRowBreaks[] = $cell;
1041  } elseif ($breakType == PhpspreadsheetWorksheet::BREAK_COLUMN) {
1042  $aColumnBreaks[] = $cell;
1043  }
1044  }
1045 
1046  // rowBreaks
1047  if (!empty($aRowBreaks)) {
1048  $objWriter->startElement('rowBreaks');
1049  $objWriter->writeAttribute('count', count($aRowBreaks));
1050  $objWriter->writeAttribute('manualBreakCount', count($aRowBreaks));
1051 
1052  foreach ($aRowBreaks as $cell) {
1054 
1055  $objWriter->startElement('brk');
1056  $objWriter->writeAttribute('id', $coords[1]);
1057  $objWriter->writeAttribute('man', '1');
1058  $objWriter->endElement();
1059  }
1060 
1061  $objWriter->endElement();
1062  }
1063 
1064  // Second, write column breaks
1065  if (!empty($aColumnBreaks)) {
1066  $objWriter->startElement('colBreaks');
1067  $objWriter->writeAttribute('count', count($aColumnBreaks));
1068  $objWriter->writeAttribute('manualBreakCount', count($aColumnBreaks));
1069 
1070  foreach ($aColumnBreaks as $cell) {
1072 
1073  $objWriter->startElement('brk');
1074  $objWriter->writeAttribute('id', Coordinate::columnIndexFromString($coords[0]) - 1);
1075  $objWriter->writeAttribute('man', '1');
1076  $objWriter->endElement();
1077  }
1078 
1079  $objWriter->endElement();
1080  }
1081  }
1082 
1090  private function writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, array $pStringTable): void
1091  {
1092  // Flipped stringtable, for faster index searching
1093  $aFlippedStringTable = $this->getParentWriter()->getWriterPartstringtable()->flipStringTable($pStringTable);
1094 
1095  // sheetData
1096  $objWriter->startElement('sheetData');
1097 
1098  // Get column count
1099  $colCount = Coordinate::columnIndexFromString($pSheet->getHighestColumn());
1100 
1101  // Highest row number
1102  $highestRow = $pSheet->getHighestRow();
1103 
1104  // Loop through cells
1105  $cellsByRow = [];
1106  foreach ($pSheet->getCoordinates() as $coordinate) {
1107  $cellAddress = Coordinate::coordinateFromString($coordinate);
1108  $cellsByRow[$cellAddress[1]][] = $coordinate;
1109  }
1110 
1111  $currentRow = 0;
1112  while ($currentRow++ < $highestRow) {
1113  // Get row dimension
1114  $rowDimension = $pSheet->getRowDimension($currentRow);
1115 
1116  // Write current row?
1117  $writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null;
1118 
1119  if ($writeCurrentRow) {
1120  // Start a new row
1121  $objWriter->startElement('row');
1122  $objWriter->writeAttribute('r', $currentRow);
1123  $objWriter->writeAttribute('spans', '1:' . $colCount);
1124 
1125  // Row dimensions
1126  if ($rowDimension->getRowHeight() >= 0) {
1127  $objWriter->writeAttribute('customHeight', '1');
1128  $objWriter->writeAttribute('ht', StringHelper::formatNumber($rowDimension->getRowHeight()));
1129  }
1130 
1131  // Row visibility
1132  if (!$rowDimension->getVisible() === true) {
1133  $objWriter->writeAttribute('hidden', 'true');
1134  }
1135 
1136  // Collapsed
1137  if ($rowDimension->getCollapsed() === true) {
1138  $objWriter->writeAttribute('collapsed', 'true');
1139  }
1140 
1141  // Outline level
1142  if ($rowDimension->getOutlineLevel() > 0) {
1143  $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel());
1144  }
1145 
1146  // Style
1147  if ($rowDimension->getXfIndex() !== null) {
1148  $objWriter->writeAttribute('s', $rowDimension->getXfIndex());
1149  $objWriter->writeAttribute('customFormat', '1');
1150  }
1151 
1152  // Write cells
1153  if (isset($cellsByRow[$currentRow])) {
1154  foreach ($cellsByRow[$currentRow] as $cellAddress) {
1155  // Write cell
1156  $this->writeCell($objWriter, $pSheet, $cellAddress, $aFlippedStringTable);
1157  }
1158  }
1159 
1160  // End row
1161  $objWriter->endElement();
1162  }
1163  }
1164 
1165  $objWriter->endElement();
1166  }
1167 
1171  private function writeCellInlineStr(XMLWriter $objWriter, string $mappedType, $cellValue): void
1172  {
1173  $objWriter->writeAttribute('t', $mappedType);
1174  if (!$cellValue instanceof RichText) {
1175  $objWriter->writeElement('t', StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue)));
1176  } elseif ($cellValue instanceof RichText) {
1177  $objWriter->startElement('is');
1178  $this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $cellValue);
1179  $objWriter->endElement();
1180  }
1181  }
1182 
1187  private function writeCellString(XMLWriter $objWriter, string $mappedType, $cellValue, array $pFlippedStringTable): void
1188  {
1189  $objWriter->writeAttribute('t', $mappedType);
1190  if (!$cellValue instanceof RichText) {
1191  self::writeElementIf($objWriter, isset($pFlippedStringTable[$cellValue]), 'v', $pFlippedStringTable[$cellValue] ?? '');
1192  } else {
1193  $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]);
1194  }
1195  }
1196 
1200  private function writeCellNumeric(XMLWriter $objWriter, $cellValue): void
1201  {
1202  //force a decimal to be written if the type is float
1203  if (is_float($cellValue)) {
1204  // force point as decimal separator in case current locale uses comma
1205  $cellValue = str_replace(',', '.', (string) $cellValue);
1206  if (strpos($cellValue, '.') === false) {
1207  $cellValue = $cellValue . '.0';
1208  }
1209  }
1210  $objWriter->writeElement('v', $cellValue);
1211  }
1212 
1213  private function writeCellBoolean(XMLWriter $objWriter, string $mappedType, bool $cellValue): void
1214  {
1215  $objWriter->writeAttribute('t', $mappedType);
1216  $objWriter->writeElement('v', $cellValue ? '1' : '0');
1217  }
1218 
1219  private function writeCellError(XMLWriter $objWriter, string $mappedType, string $cellValue, string $formulaerr = '#NULL!'): void
1220  {
1221  $objWriter->writeAttribute('t', $mappedType);
1222  $cellIsFormula = substr($cellValue, 0, 1) === '=';
1223  self::writeElementIf($objWriter, $cellIsFormula, 'f', Xlfn::addXlfnStripEquals($cellValue));
1224  $objWriter->writeElement('v', $cellIsFormula ? $formulaerr : $cellValue);
1225  }
1226 
1227  private function writeCellFormula(XMLWriter $objWriter, string $cellValue, Cell $pCell): void
1228  {
1229  $calculatedValue = $this->getParentWriter()->getPreCalculateFormulas() ? $pCell->getCalculatedValue() : $cellValue;
1230  if (is_string($calculatedValue)) {
1231  if (\PhpOffice\PhpSpreadsheet\Calculation\Functions::isError($calculatedValue)) {
1232  $this->writeCellError($objWriter, 'e', $cellValue, $calculatedValue);
1233 
1234  return;
1235  }
1236  $objWriter->writeAttribute('t', 'str');
1237  } elseif (is_bool($calculatedValue)) {
1238  $objWriter->writeAttribute('t', 'b');
1239  $calculatedValue = (int) $calculatedValue;
1240  }
1241  // array values are not yet supported
1242  //$attributes = $pCell->getFormulaAttributes();
1243  //if (($attributes['t'] ?? null) === 'array') {
1244  // $objWriter->startElement('f');
1245  // $objWriter->writeAttribute('t', 'array');
1246  // $objWriter->writeAttribute('ref', $pCellAddress);
1247  // $objWriter->writeAttribute('aca', '1');
1248  // $objWriter->writeAttribute('ca', '1');
1249  // $objWriter->text(substr($cellValue, 1));
1250  // $objWriter->endElement();
1251  //} else {
1252  // $objWriter->writeElement('f', Xlfn::addXlfnStripEquals($cellValue));
1253  //}
1254  $objWriter->writeElement('f', Xlfn::addXlfnStripEquals($cellValue));
1255  self::writeElementIf(
1256  $objWriter,
1257  $this->getParentWriter()->getOffice2003Compatibility() === false,
1258  'v',
1259  ($this->getParentWriter()->getPreCalculateFormulas() && !is_array($calculatedValue) && substr($calculatedValue, 0, 1) !== '#')
1260  ? StringHelper::formatNumber($calculatedValue) : '0'
1261  );
1262  }
1263 
1272  private function writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, string $pCellAddress, array $pFlippedStringTable): void
1273  {
1274  // Cell
1275  $pCell = $pSheet->getCell($pCellAddress);
1276  $objWriter->startElement('c');
1277  $objWriter->writeAttribute('r', $pCellAddress);
1278 
1279  // Sheet styles
1280  $xfi = $pCell->getXfIndex();
1281  self::writeAttributeIf($objWriter, $xfi, 's', $xfi);
1282 
1283  // If cell value is supplied, write cell value
1284  $cellValue = $pCell->getValue();
1285  if (is_object($cellValue) || $cellValue !== '') {
1286  // Map type
1287  $mappedType = $pCell->getDataType();
1288 
1289  // Write data depending on its type
1290  switch (strtolower($mappedType)) {
1291  case 'inlinestr': // Inline string
1292  $this->writeCellInlineStr($objWriter, $mappedType, $cellValue);
1293 
1294  break;
1295  case 's': // String
1296  $this->writeCellString($objWriter, $mappedType, $cellValue, $pFlippedStringTable);
1297 
1298  break;
1299  case 'f': // Formula
1300  $this->writeCellFormula($objWriter, $cellValue, $pCell);
1301 
1302  break;
1303  case 'n': // Numeric
1304  $this->writeCellNumeric($objWriter, $cellValue);
1305 
1306  break;
1307  case 'b': // Boolean
1308  $this->writeCellBoolean($objWriter, $mappedType, $cellValue);
1309 
1310  break;
1311  case 'e': // Error
1312  $this->writeCellError($objWriter, $mappedType, $cellValue);
1313  }
1314  }
1315 
1316  $objWriter->endElement();
1317  }
1318 
1326  private function writeDrawings(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, $includeCharts = false): void
1327  {
1328  $unparsedLoadedData = $pSheet->getParent()->getUnparsedLoadedData();
1329  $hasUnparsedDrawing = isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds']);
1330  $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0;
1331  if ($chartCount == 0 && $pSheet->getDrawingCollection()->count() == 0 && !$hasUnparsedDrawing) {
1332  return;
1333  }
1334 
1335  // If sheet contains drawings, add the relationships
1336  $objWriter->startElement('drawing');
1337 
1338  $rId = 'rId1';
1339  if (isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'])) {
1340  $drawingOriginalIds = $unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'];
1341  // take first. In future can be overriten
1342  // (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels::writeWorksheetRelationships)
1343  $rId = reset($drawingOriginalIds);
1344  }
1345 
1346  $objWriter->writeAttribute('r:id', $rId);
1347  $objWriter->endElement();
1348  }
1349 
1356  private function writeLegacyDrawing(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
1357  {
1358  // If sheet contains comments, add the relationships
1359  if (count($pSheet->getComments()) > 0) {
1360  $objWriter->startElement('legacyDrawing');
1361  $objWriter->writeAttribute('r:id', 'rId_comments_vml1');
1362  $objWriter->endElement();
1363  }
1364  }
1365 
1372  private function writeLegacyDrawingHF(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
1373  {
1374  // If sheet contains images, add the relationships
1375  if (count($pSheet->getHeaderFooter()->getImages()) > 0) {
1376  $objWriter->startElement('legacyDrawingHF');
1377  $objWriter->writeAttribute('r:id', 'rId_headerfooter_vml1');
1378  $objWriter->endElement();
1379  }
1380  }
1381 
1382  private function writeAlternateContent(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
1383  {
1384  if (empty($pSheet->getParent()->getUnparsedLoadedData()['sheets'][$pSheet->getCodeName()]['AlternateContents'])) {
1385  return;
1386  }
1387 
1388  foreach ($pSheet->getParent()->getUnparsedLoadedData()['sheets'][$pSheet->getCodeName()]['AlternateContents'] as $alternateContent) {
1389  $objWriter->writeRaw($alternateContent);
1390  }
1391  }
1392 
1399  private function writeExtLst(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
1400  {
1401  $conditionalFormattingRuleExtList = [];
1402  foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
1404  foreach ($conditionalStyles as $conditional) {
1405  $dataBar = $conditional->getDataBar();
1406  if ($dataBar && $dataBar->getConditionalFormattingRuleExt()) {
1407  $conditionalFormattingRuleExtList[] = $dataBar->getConditionalFormattingRuleExt();
1408  }
1409  }
1410  }
1411 
1412  if (count($conditionalFormattingRuleExtList) > 0) {
1413  $conditionalFormattingRuleExtNsPrefix = 'x14';
1414  $objWriter->startElement('extLst');
1415  $objWriter->startElement('ext');
1416  $objWriter->writeAttribute('uri', '{78C0D931-6437-407d-A8EE-F0AAD7539E65}');
1417  $objWriter->startElementNs($conditionalFormattingRuleExtNsPrefix, 'conditionalFormattings', null);
1418  foreach ($conditionalFormattingRuleExtList as $extension) {
1419  self::writeExtConditionalFormattingElements($objWriter, $extension);
1420  }
1421  $objWriter->endElement(); //end conditionalFormattings
1422  $objWriter->endElement(); //end ext
1423  $objWriter->endElement(); //end extLst
1424  }
1425  }
1426 }
static controlCharacterPHP2OOXML($value)
Convert from PHP control character to OpenXML escaped control character.
static splitRange($pRange)
Split range into coordinate strings.
Definition: Coordinate.php:140
writeCellFormula(XMLWriter $objWriter, string $cellValue, Cell $pCell)
Definition: Worksheet.php:1227
writeLegacyDrawingHF(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write LegacyDrawingHF.
Definition: Worksheet.php:1372
writeSheetProtection(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write SheetProtection.
Definition: Worksheet.php:427
writeSheetPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write SheetPr.
Definition: Worksheet.php:136
writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write ConditionalFormatting.
Definition: Worksheet.php:607
static writeElementIf(XMLWriter $objWriter, $condition, string $attr, string $val)
Definition: Worksheet.php:469
writePageSetup(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write PageSetup.
Definition: Worksheet.php:969
if(!array_key_exists('StateId', $_REQUEST)) $id
writeDataValidations(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write DataValidations.
Definition: Worksheet.php:674
writeSheetFormatPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write SheetFormatPr.
Definition: Worksheet.php:310
static formatNumber($value)
Formats a numeric value as a string for output in various output writers forcing point as decimal sep...
getDiskCachingDirectory()
Get disk caching directory.
Definition: BaseWriter.php:92
getOffice2003Compatibility()
Get Office2003 compatibility.
Definition: Xlsx.php:633
writeMergeCells(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write MergeCells.
Definition: Worksheet.php:809
writeCellInlineStr(XMLWriter $objWriter, string $mappedType, $cellValue)
Definition: Worksheet.php:1171
$coords
Definition: example_030.php:88
writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, string $pCellAddress, array $pFlippedStringTable)
Write Cell.
Definition: Worksheet.php:1272
static addXlfnStripEquals(string $funcstring)
Prefix function name in string with _xlfn.
Definition: Xlfn.php:162
writeBreaks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write Breaks.
Definition: Worksheet.php:1033
writeLegacyDrawing(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write LegacyDrawing.
Definition: Worksheet.php:1356
writeSheetViews(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write SheetViews.
Definition: Worksheet.php:196
getPreCalculateFormulas()
Get Pre-Calculate Formulas flag If this is true (the default), then the writer will recalculate all f...
Definition: BaseWriter.php:60
static writeOtherCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate)
Definition: Worksheet.php:476
$rule
Definition: showstats.php:43
writeHeaderFooter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write Header / Footer.
Definition: Worksheet.php:1009
getSpreadsheet()
Get Spreadsheet object.
Definition: Xlsx.php:529
writePageMargins(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write PageMargins.
Definition: Worksheet.php:858
writeProtectedRanges(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write ProtectedRanges.
Definition: Worksheet.php:781
writeCellBoolean(XMLWriter $objWriter, string $mappedType, bool $cellValue)
Definition: Worksheet.php:1213
writeCellNumeric(XMLWriter $objWriter, $cellValue)
Definition: Worksheet.php:1200
writeAlternateContent(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Definition: Worksheet.php:1382
writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, array $pStringTable)
Write SheetData.
Definition: Worksheet.php:1090
$txt
Definition: error.php:11
static coordinateFromString($pCoordinateString)
Coordinate from string.
Definition: Coordinate.php:32
writeHyperlinks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write Hyperlinks.
Definition: Worksheet.php:740
writeDrawings(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, $includeCharts=false)
Write Drawings.
Definition: Worksheet.php:1326
static mergeRangesInCollection(array $pCoordCollection)
Convert an associative array of single cell coordinates to values to an associative array of cell ran...
Definition: Coordinate.php:463
static addXlfn(string $funcstring)
Prefix function name in string with _xlfn.
Definition: Xlfn.php:153
getCalculatedValue($resetLog=true)
Get calculated cell value.
Definition: Cell.php:251
writeDimension(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write Dimension.
Definition: Worksheet.php:182
static writeTextCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate)
Definition: Worksheet.php:496
getUseDiskCaching()
Get use disk caching where possible?
Definition: BaseWriter.php:72
static writeExtConditionalFormattingElements(XMLWriter $objWriter, ConditionalFormattingRuleExtension $ruleExtension)
Definition: Worksheet.php:513
static writeAttributeIf(XMLWriter $objWriter, $condition, string $attr, string $val)
Definition: Worksheet.php:462
writeCellString(XMLWriter $objWriter, string $mappedType, $cellValue, array $pFlippedStringTable)
Definition: Worksheet.php:1187
if(! $in) $columns
Definition: Utf8Test.php:45
static columnIndexFromString($pString)
Column index from string.
Definition: Coordinate.php:265
$key
Definition: croninfo.php:18
writeCellError(XMLWriter $objWriter, string $mappedType, string $cellValue, string $formulaerr='#NULL!')
Definition: Worksheet.php:1219
writeCols(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write Cols.
Definition: Worksheet.php:363
writeWorksheet(PhpspreadsheetWorksheet $pSheet, $pStringTable=null, $includeCharts=false)
Write worksheet to XML format.
Definition: Worksheet.php:28
writeAutoFilter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write AutoFilter.
Definition: Worksheet.php:877
writePrintOptions(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
Write PrintOptions.
Definition: Worksheet.php:833