Skip to content

Commit

Permalink
Ods Writer support for setting column width/row height (including Aut…
Browse files Browse the repository at this point in the history
…osizing)
  • Loading branch information
MarkBaker committed Apr 17, 2022
1 parent de173d4 commit 7a2f5c4
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).

### Added

- Ods Writer support for setting column width/row height (including the use of AutoSize) [Issue #2346](https://github.com/PHPOffice/PhpSpreadsheet/issues/2346) [PR #2753](https://github.com/PHPOffice/PhpSpreadsheet/pull/2753)
- Introduced CellAddress, CellRange, RowRange and ColumnRange value objects that can be used as an alternative to a string value (e.g. `'C5'`, `'B2:D4'`, `'2:2'` or `'B:C'`) in appropriate contexts.
- Implementation of the FILTER(), SORT(), SORTBY() and UNIQUE() Lookup/Reference (array) functions.
- Implementation of the ISREF() Information function.
Expand Down
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4675,11 +4675,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Writer/Ods/Content.php

-
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#"
count: 4
path: src/PhpSpreadsheet/Writer/Ods/Content.php

-
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int\\<2, max\\> given\\.$#"
count: 3
Expand Down
62 changes: 62 additions & 0 deletions src/PhpSpreadsheet/Writer/Ods/Cell/Style.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@

namespace PhpOffice\PhpSpreadsheet\Writer\Ods\Cell;

use PhpOffice\PhpSpreadsheet\Helper\Dimension;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Font;
use PhpOffice\PhpSpreadsheet\Style\Style as CellStyle;
use PhpOffice\PhpSpreadsheet\Worksheet\ColumnDimension;
use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension;

class Style
{
public const CELL_STYLE_PREFIX = 'ce';
public const COLUMN_STYLE_PREFIX = 'co';
public const ROW_STYLE_PREFIX = 'ro';

private $writer;

Expand Down Expand Up @@ -159,6 +164,63 @@ protected function writeTextProperties(CellStyle $style): void
$this->writer->endElement(); // Close style:text-properties
}

protected function writeColumnProperties(ColumnDimension $columnDimension): void
{
$this->writer->startElement('style:table-column-properties');
$this->writer->writeAttribute(
'style:column-width',
round($columnDimension->getWidth(Dimension::UOM_CENTIMETERS), 3) . 'cm'
);
$this->writer->writeAttribute('fo:break-before', 'auto');

// End
$this->writer->endElement(); // Close style:table-column-properties
}

public function writeColumnStyles(ColumnDimension $columnDimension, int $sheetId): void
{
$this->writer->startElement('style:style');
$this->writer->writeAttribute('style:family', 'table-column');
$this->writer->writeAttribute(
'style:name',
sprintf('%s_%d_%d', self::COLUMN_STYLE_PREFIX, $sheetId, $columnDimension->getColumnNumeric())
);

$this->writeColumnProperties($columnDimension);

// End
$this->writer->endElement(); // Close style:style
}

protected function writeRowProperties(RowDimension $rowDimension): void
{
$this->writer->startElement('style:table-row-properties');
$this->writer->writeAttribute(
'style:row-height',
round($rowDimension->getRowHeight(Dimension::UOM_CENTIMETERS), 3) . 'cm'
);
$this->writer->writeAttribute('style:use-optimal-row-height', 'true');
$this->writer->writeAttribute('fo:break-before', 'auto');

// End
$this->writer->endElement(); // Close style:table-row-properties
}

public function writeRowStyles(RowDimension $rowDimension, int $sheetId): void
{
$this->writer->startElement('style:style');
$this->writer->writeAttribute('style:family', 'table-row');
$this->writer->writeAttribute(
'style:name',
sprintf('%s_%d_%d', self::ROW_STYLE_PREFIX, $sheetId, $rowDimension->getRowIndex())
);

$this->writeRowProperties($rowDimension);

// End
$this->writer->endElement(); // Close style:style
}

public function write(CellStyle $style): void
{
$this->writer->startElement('style:style');
Expand Down
51 changes: 41 additions & 10 deletions src/PhpSpreadsheet/Writer/Ods/Content.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,22 +119,29 @@ private function writeSheets(XMLWriter $objWriter): void
{
$spreadsheet = $this->getParentWriter()->getSpreadsheet(); /** @var Spreadsheet $spreadsheet */
$sheetCount = $spreadsheet->getSheetCount();
for ($i = 0; $i < $sheetCount; ++$i) {
for ($sheetIndex = 0; $sheetIndex < $sheetCount; ++$sheetIndex) {
$objWriter->startElement('table:table');
$objWriter->writeAttribute('table:name', $spreadsheet->getSheet($i)->getTitle());
$objWriter->writeAttribute('table:name', $spreadsheet->getSheet($sheetIndex)->getTitle());
$objWriter->writeElement('office:forms');
$objWriter->startElement('table:table-column');
$objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
$objWriter->endElement();
$this->writeRows($objWriter, $spreadsheet->getSheet($i));
foreach ($spreadsheet->getSheet($sheetIndex)->getColumnDimensions() as $columnDimension) {
$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): void
private function writeRows(XMLWriter $objWriter, Worksheet $sheet, int $sheetIndex): void
{
$numberRowsRepeated = self::NUMBER_ROWS_REPEATED_MAX;
$span_row = 0;
Expand All @@ -148,8 +155,14 @@ private function writeRows(XMLWriter $objWriter, Worksheet $sheet): void
if ($span_row > 1) {
$objWriter->writeAttribute('table:number-rows-repeated', $span_row);
}
if ($sheet->getRowDimension($row->getRowIndex())->getRowHeight() > 0) {
$objWriter->writeAttribute(
'table:style_name',
sprintf('%s_%d_%d', Style::ROW_STYLE_PREFIX, $sheetIndex, $row->getRowIndex())
);
}
$objWriter->startElement('table:table-cell');
$objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
$objWriter->writeAttribute('table:number-columns-repeated', (string) self::NUMBER_COLS_REPEATED_MAX);
$objWriter->endElement();
$objWriter->endElement();
$span_row = 0;
Expand Down Expand Up @@ -275,6 +288,24 @@ private function writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn): v
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);
$worksheet->calculateColumnWidths();
foreach ($worksheet->getColumnDimensions() as $columnDimension) {
$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);
}
Expand All @@ -296,7 +327,7 @@ private function writeCellMerge(XMLWriter $objWriter, Cell $cell): void
$columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1;
$rowSpan = ((int) $end[1]) - ((int) $start[1]) + 1;

$objWriter->writeAttribute('table:number-columns-spanned', $columnSpan);
$objWriter->writeAttribute('table:number-rows-spanned', $rowSpan);
$objWriter->writeAttribute('table:number-columns-spanned', (string) $columnSpan);
$objWriter->writeAttribute('table:number-rows-spanned', (string) $rowSpan);
}
}
2 changes: 1 addition & 1 deletion tests/PhpSpreadsheetTests/Writer/PreCalcTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private static function verifyA2(Calculation $calculation, string $title, ?bool
}
}

private const AUTOSIZE_TYPES = ['Xlsx', 'Xls', 'Html'];
private const AUTOSIZE_TYPES = ['Xlsx', 'Xls', 'Html', 'Ods'];

private static function verifyA3B2(Calculation $calculation, string $title, ?bool $preCalc, string $type): void
{
Expand Down
1 change: 0 additions & 1 deletion tests/data/Writer/Ods/content-empty.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<table:calculation-settings />
<table:table table:name="Worksheet">
<office:forms />
<table:table-column table:number-columns-repeated="1024" />
<table:table-row>
<table:table-cell table:style-name="ce0" />
<table:table-cell table:number-columns-repeated="1023" />
Expand Down
2 changes: 0 additions & 2 deletions tests/data/Writer/Ods/content-with-data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
<table:calculation-settings/>
<table:table table:name="Worksheet">
<office:forms/>
<table:table-column table:number-columns-repeated="1024"/>
<table:table-row>
<table:table-cell office:value="1" office:value-type="float" table:style-name="ce2">
<text:p>1</text:p>
Expand Down Expand Up @@ -110,7 +109,6 @@
</table:table>
<table:table table:name="New Worksheet">
<office:forms/>
<table:table-column table:number-columns-repeated="1024"/>
<table:table-row>
<table:table-cell office:value="2" office:value-type="float" table:style-name="ce0">
<text:p>2</text:p>
Expand Down

0 comments on commit 7a2f5c4

Please sign in to comment.