nfTlWNl rn Ѻq$³*4A8t+SjįF)&y8n6$Mýy#| gFky eC#֒Hnn!V5qR1ΪfvP̎`eT4Pb^p Ѻq$³*p5,ҮFL].R]fWQ_#1Iķխ}`MKϊ&Vޢ݌ XHda\`Lٔ*ܝIc.3E`tD]}Na<ᰉmy>V^7NSo!֔|дI^蚣@>xs80#A\on6$Mýy#|T;+P,7p =-f0ߗʍ(o_B=d_DZ"8,USdgn&aIYui5蟇@Uwߜ.ܜΘ@ tRU~#Z}>>  ]U]/TBw@B h47eMOFB\Ì d'%π@ CI3fZQJ+ uXY@:VԂBЙh2}|Ӧ.؈P=Mb 2PT@]V,7V4>_#f=]0D%vX\1B]^  /VѺ[~uZ_Tb&_ -Nd "<[EN5崐؝ZoU'W~0[>6Ekcql#Y 7PVk @_4b+FtϺF! *^Yr}ոݢik˸  p:@-z_n5i*s4ͅVxv< 55B?̱Oa.gDXKSajJ(mYvn4zCէD. 0;ezԳY2g[zse70qx 煡I|^-0PyL8c\X9Udx)^y m/Μ"NmsL䮌n 頏@_3.mkGT /|y$f*,:@"2}ufĂDHuvcP{ȭ?Ao+v* 2XP_XJ]ZXP׎XFx٢1ekc+Nu(k<~Ѵ.A7:rZi!xlW.nʆ'0E{rALrPBM6L4ae5Z T _?SW0Mp݂.?hbg\F8?cQ-aCL)9b%$Kꏣ,؆7N%579#٦~kV gق* C,~_RVlmq1 M5_#m„,ܐw5xިi+4fvd`GNu1P'V`H:N؎a97(%T`s='ՔB(Qu;rKV"3FrALrPBM6L4ae5ddnTGdB>dz [ZxTQ"'Rܣ&d݄\wrZmgE5Δek*h ]6)6x+K,0%̒-Isz5.b f@YO,@"P ך8}0jY`5}pWbĕJ}zZ3e`ԨNbr`NTH|i!C+_`da ;vF|W+k =]ecAj5O!b.i"]Ss!Zu,v8l:eГS;yȎkf>x-k-I^ mNW\jw\4nZ7nc2N却)\#H 4Ǧ+_\:xk[?&+1y ]>->c Wh IE[Jj-~hl]֝U)R_R>R0 H|fF@8 !핟Ղ w 贄7jj;p܀` .!C+_`da ;vF|W+k =]e_ M/5xިi+4fvd`GNu1cV`b 0?fdB>dz [Zx؁v)Lyw/bP\|ўtXOtc^O7m]H.֨CDžܾ_i2V 6ĵZד-I^ mNW\jw\4nZ7n맡'ebX !핟Ղ w 贄7yt.Ԗ0XN؎a97(%T`s='Ք 6ttg<8yI)<#)ɷ!-1Pǜ◍ڍ?l 'P./(qu?aJw;P36"9rJ}zZ3e`ԨNbr`N$<2{ˊļݷp[YXy\Ɲ9BMEAzHrq0~^ h"Ct䜝f~G,#Qt|lΪlgTsl>YSZ^7%窓mE^vCP+_\:xk[?&+1y ]>-$X P"jw60>1ⷠvc$'2l !핟Ղ w 贄7<}8fŻ.B™W|^aZ9We[hEAzHrq0~^ h"Ct䜝f~GDAf̌}PzHz dB>dz [Zx؀^i4eGS-Ń)d3[FQ0s Ák]+sYu@t8񴾖GH˴XRD<᧫KI*#)ɷ!-1 t4?>Ze9iC&cnoffice.org/2005/report'); $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2'); $objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml'); $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); $objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table'); $objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'); $objWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0'); $objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/'); $objWriter->writeAttribute('office:version', '1.2'); $objWriter->writeElement('office:scripts'); $objWriter->writeElement('office:font-face-decls'); // Styles XF $objWriter->startElement('office:automatic-styles'); $this->writeXfStyles($objWriter, $this->getParentWriter()->getSpreadsheet()); $objWriter->endElement(); $objWriter->startElement('office:body'); $objWriter->startElement('office:spreadsheet'); $objWriter->writeElement('table:calculation-settings'); $this->writeSheets($objWriter); (new AutoFilters($objWriter, $this->getParentWriter()->getSpreadsheet()))->write(); // Defined names (ranges and formulae) (new NamedExpressions($objWriter, $this->getParentWriter()->getSpreadsheet(), $this->formulaConvertor))->write(); $objWriter->endElement(); $objWriter->endElement(); $objWriter->endElement(); return $objWriter->getData(); } /** * Write sheets. */ private function writeSheets(XMLWriter $objWriter): void { $spreadsheet = $this->getParentWriter()->getSpreadsheet(); /** @var Spreadsheet $spreadsheet */ $sheetCount = $spreadsheet->getSheetCount(); for ($sheetIndex = 0; $sheetIndex < $sheetCount; ++$sheetIndex) { $objWriter->startElement('table:table'); $objWriter->writeAttribute('table:name', $spreadsheet->getSheet($sheetIndex)->getTitle()); $objWriter->writeAttribute('table:style-name', Style::TABLE_STYLE_PREFIX . (string) ($sheetIndex + 1)); $objWriter->writeElement('office:forms'); $lastColumn = 0; foreach ($spreadsheet->getSheet($sheetIndex)->getColumnDimensions() as $columnDimension) { $thisColumn = $columnDimension->getColumnNumeric(); $emptyColumns = $thisColumn - $lastColumn - 1; if ($emptyColumns > 0) { $objWriter->startElement('table:table-column'); $objWriter->writeAttribute('table:number-columns-repeated', (string) $emptyColumns); $objWriter->endElement(); } $lastColumn = $thisColumn; $objWriter->startElement('table:table-column'); $objWriter->writeAttribute( 'table:style-name', sprintf('%s_%d_%d', Style::COLUMN_STYLE_PREFIX, $sheetIndex, $columnDimension->getColumnNumeric()) ); $objWriter->writeAttribute('table:default-cell-style-name', 'ce0'); // $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX); $objWriter->endElement(); } $this->writeRows($objWriter, $spreadsheet->getSheet($sheetIndex), $sheetIndex); $objWriter->endElement(); } } /** * Write rows of the specified sheet. */ private function writeRows(XMLWriter $objWriter, Worksheet $sheet, int $sheetIndex): void { $numberRowsRepeated = self::NUMBER_ROWS_REPEATED_MAX; $span_row = 0; $rows = $sheet->getRowIterator(); foreach ($rows as $row) { $cellIterator = $row->getCellIterator(); --$numberRowsRepeated; if ($cellIterator->valid()) { $objWriter->startElement('table:table-row'); if ($span_row) { if ($span_row > 1) { $objWriter->writeAttribute('table:number-rows-repeated', (string) $span_row); } $objWriter->startElement('table:table-cell'); $objWriter->writeAttribute('table:number-columns-repeated', (string) self::NUMBER_COLS_REPEATED_MAX); $objWriter->endElement(); $span_row = 0; } else { if ($sheet->getRowDimension($row->getRowIndex())->getRowHeight() > 0) { $objWriter->writeAttribute( 'table:style-name', sprintf('%s_%d_%d', Style::ROW_STYLE_PREFIX, $sheetIndex, $row->getRowIndex()) ); } $this->writeCells($objWriter, $cellIterator); } $objWriter->endElement(); } else { ++$span_row; } } } /** * Write cells of the specified row. */ private function writeCells(XMLWriter $objWriter, RowCellIterator $cells): void { $numberColsRepeated = self::NUMBER_COLS_REPEATED_MAX; $prevColumn = -1; foreach ($cells as $cell) { /** @var \PhpOffice\PhpSpreadsheet\Cell\Cell $cell */ $column = Coordinate::columnIndexFromString($cell->getColumn()) - 1; $this->writeCellSpan($objWriter, $column, $prevColumn); $objWriter->startElement('table:table-cell'); $this->writeCellMerge($objWriter, $cell); // Style XF $style = $cell->getXfIndex(); if ($style !== null) { $objWriter->writeAttribute('table:style-name', Style::CELL_STYLE_PREFIX . $style); } switch ($cell->getDataType()) { case DataType::TYPE_BOOL: $objWriter->writeAttribute('office:value-type', 'boolean'); $objWriter->writeAttribute('office:value', $cell->getValue()); $objWriter->writeElement('text:p', $cell->getValue()); break; case DataType::TYPE_ERROR: $objWriter->writeAttribute('table:formula', 'of:=#NULL!'); $objWriter->writeAttribute('office:value-type', 'string'); $objWriter->writeAttribute('office:string-value', ''); $objWriter->writeElement('text:p', '#NULL!'); break; case DataType::TYPE_FORMULA: $formulaValue = $cell->getValue(); if ($this->getParentWriter()->getPreCalculateFormulas()) { try { $formulaValue = $cell->getCalculatedValue(); } catch (Exception $e) { // don't do anything } } $objWriter->writeAttribute('table:formula', $this->formulaConvertor->convertFormula($cell->getValue())); if (is_numeric($formulaValue)) { $objWriter->writeAttribute('office:value-type', 'float'); } else { $objWriter->writeAttribute('office:value-type', 'string'); } $objWriter->writeAttribute('office:value', $formulaValue); $objWriter->writeElement('text:p', $formulaValue); break; case DataType::TYPE_NUMERIC: $objWriter->writeAttribute('office:value-type', 'float'); $objWriter->writeAttribute('office:value', $cell->getValue()); $objWriter->writeElement('text:p', $cell->getValue()); break; case DataType::TYPE_INLINE: // break intentionally omitted case DataType::TYPE_STRING: $objWriter->writeAttribute('office:value-type', 'string'); $objWriter->writeElement('text:p', $cell->getValue()); break; } Comment::write($objWriter, $cell); $objWriter->endElement(); $prevColumn = $column; } $numberColsRepeated = $numberColsRepeated - $prevColumn - 1; if ($numberColsRepeated > 0) { if ($numberColsRepeated > 1) { $objWriter->startElement('table:table-cell'); $objWriter->writeAttribute('table:number-columns-repeated', (string) $numberColsRepeated); $objWriter->endElement(); } else { $objWriter->writeElement('table:table-cell'); } } } /** * Write span. * * @param int $curColumn * @param int $prevColumn */ private function writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn): void { $diff = $curColumn - $prevColumn - 1; if (1 === $diff) { $objWriter->writeElement('table:table-cell'); } elseif ($diff > 1) { $objWriter->startElement('table:table-cell'); $objWriter->writeAttribute('table:number-columns-repeated', (string) $diff); $objWriter->endElement(); } } /** * Write XF cell styles. */ private function writeXfStyles(XMLWriter $writer, Spreadsheet $spreadsheet): void { $styleWriter = new Style($writer); $sheetCount = $spreadsheet->getSheetCount(); for ($i = 0; $i < $sheetCount; ++$i) { $worksheet = $spreadsheet->getSheet($i); $styleWriter->writeTableStyle($worksheet, $i + 1); $worksheet->calculateColumnWidths(); foreach ($worksheet->getColumnDimensions() as $columnDimension) { if ($columnDimension->getWidth() !== -1.0) { $styleWriter->writeColumnStyles($columnDimension, $i); } } } for ($i = 0; $i < $sheetCount; ++$i) { $worksheet = $spreadsheet->getSheet($i); foreach ($worksheet->getRowDimensions() as $rowDimension) { if ($rowDimension->getRowHeight() > 0.0) { $styleWriter->writeRowStyles($rowDimension, $i); } } } foreach ($spreadsheet->getCellXfCollection() as $style) { $styleWriter->write($style); } } /** * Write attributes for merged cell. */ private function writeCellMerge(XMLWriter $objWriter, Cell $cell): void { if (!$cell->isMergeRangeValueCell()) { return; } $mergeRange = Coordinate::splitRange((string) $cell->getMergeRange()); [$startCell, $endCell] = $mergeRange[0]; $start = Coordinate::coordinateFromString($startCell); $end = Coordinate::coordinateFromString($endCell); $columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1; $rowSpan = ((int) $end[1]) - ((int) $start[1]) + 1; $objWriter->writeAttribute('table:number-columns-spanned', (string) $columnSpan); $objWriter->writeAttribute('table:number-rows-spanned', (string) $rowSpan); } }