Skip to content

Commit 00ccce4

Browse files
authored
Merge pull request #1 from damianed/addsetwithcolumns
add cell size modification
2 parents 8459666 + 85af814 commit 00ccce4

15 files changed

+678
-21
lines changed

src/Spout/Writer/Common/Entity/Options.php

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ abstract class Options
2020

2121
// XLSX specific options
2222
public const SHOULD_USE_INLINE_STRINGS = 'shouldUseInlineStrings';
23+
24+
// Cell size options
25+
const DEFAULT_COLUMN_WIDTH = 'defaultColumnWidth';
26+
const DEFAULT_ROW_HEIGHT = 'defaultRowHeight';
27+
const COLUMN_WIDTHS = 'columnWidthDefinition';
2328
}

src/Spout/Writer/Common/Entity/Worksheet.php

+20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ class Worksheet
2323
/** @var int Index of the last written row */
2424
private $lastWrittenRowIndex;
2525

26+
/** @var bool has the sheet data header been written */
27+
private $sheetDataStarted = false;
28+
2629
/**
2730
* Worksheet constructor.
2831
*
@@ -36,6 +39,7 @@ public function __construct($worksheetFilePath, Sheet $externalSheet)
3639
$this->externalSheet = $externalSheet;
3740
$this->maxNumColumns = 0;
3841
$this->lastWrittenRowIndex = 0;
42+
$this->sheetDataStarted = false;
3943
}
4044

4145
/**
@@ -110,4 +114,20 @@ public function getId()
110114
// sheet index is zero-based, while ID is 1-based
111115
return $this->externalSheet->getIndex() + 1;
112116
}
117+
118+
/**
119+
* @return bool
120+
*/
121+
public function getSheetDataStarted()
122+
{
123+
return $this->sheetDataStarted;
124+
}
125+
126+
/**
127+
* @param bool $sheetDataStarted
128+
*/
129+
public function setSheetDataStarted($sheetDataStarted)
130+
{
131+
$this->sheetDataStarted = $sheetDataStarted;
132+
}
113133
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Box\Spout\Writer\Common\Manager;
4+
5+
trait ManagesCellSize
6+
{
7+
/** @var float|null The default column width to use */
8+
private $defaultColumnWidth;
9+
10+
/** @var float|null The default row height to use */
11+
private $defaultRowHeight;
12+
13+
/** @var array Array of min-max-width arrays */
14+
private $columnWidths = [];
15+
16+
/**
17+
* @param float|null $width
18+
*/
19+
public function setDefaultColumnWidth($width)
20+
{
21+
$this->defaultColumnWidth = $width;
22+
}
23+
24+
/**
25+
* @param float|null $height
26+
*/
27+
public function setDefaultRowHeight($height)
28+
{
29+
$this->defaultRowHeight = $height;
30+
}
31+
32+
/**
33+
* @param float $width
34+
* @param array $columns One or more columns with this width
35+
*/
36+
public function setColumnWidth(float $width, ...$columns)
37+
{
38+
// Gather sequences
39+
$sequence = [];
40+
foreach ($columns as $i) {
41+
$sequenceLength = count($sequence);
42+
if ($sequenceLength > 0) {
43+
$previousValue = $sequence[$sequenceLength - 1];
44+
if ($i !== $previousValue + 1) {
45+
$this->setColumnWidthForRange($width, $sequence[0], $previousValue);
46+
$sequence = [];
47+
}
48+
}
49+
$sequence[] = $i;
50+
}
51+
$this->setColumnWidthForRange($width, $sequence[0], $sequence[count($sequence) - 1]);
52+
}
53+
54+
/**
55+
* @param float $width The width to set
56+
* @param int $start First column index of the range
57+
* @param int $end Last column index of the range
58+
*/
59+
public function setColumnWidthForRange(float $width, int $start, int $end)
60+
{
61+
$this->columnWidths[] = [$start, $end, $width];
62+
}
63+
}

src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php

+50-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface;
1616
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
1717
use Box\Spout\Writer\Exception\SheetNotFoundException;
18-
use Box\Spout\Writer\Exception\WriterException;
1918

2019
/**
2120
* Class WorkbookManagerAbstract
@@ -117,7 +116,7 @@ public function addNewSheetAndMakeItCurrent()
117116
/**
118117
* Creates a new sheet in the workbook. The current sheet remains unchanged.
119118
*
120-
* @throws \Box\Spout\Common\Exception\IOException If unable to open the sheet for writing
119+
* @throws IOException
121120
* @return Worksheet The created sheet
122121
*/
123122
private function addNewSheet()
@@ -157,6 +156,16 @@ public function getCurrentWorksheet()
157156
return $this->currentWorksheet;
158157
}
159158

159+
/**
160+
* Starts the current sheet and opens the file pointer
161+
*
162+
* @throws IOException
163+
*/
164+
public function startCurrentSheet()
165+
{
166+
$this->worksheetManager->startSheet($this->getCurrentWorksheet());
167+
}
168+
160169
/**
161170
* Sets the given sheet as the current one. New data will be written to this sheet.
162171
* The writing will resume where it stopped (i.e. data won't be truncated).
@@ -211,7 +220,7 @@ private function getWorksheetFromExternalSheet($sheet)
211220
*
212221
* @param Row $row The row to be added
213222
* @throws IOException If trying to create a new sheet and unable to open the sheet for writing
214-
* @throws WriterException If unable to write data
223+
* @throws \Box\Spout\Common\Exception\InvalidArgumentException
215224
* @return void
216225
*/
217226
public function addRowToCurrentWorksheet(Row $row)
@@ -250,6 +259,9 @@ private function hasCurrentWorksheetReachedMaxRows()
250259
* @param Worksheet $worksheet Worksheet to write the row to
251260
* @param Row $row The row to be added
252261
* @throws WriterException If unable to write data
262+
*
263+
* @throws IOException
264+
* @throws \Box\Spout\Common\Exception\InvalidArgumentException
253265
* @return void
254266
*/
255267
private function addRowToWorksheet(Worksheet $worksheet, Row $row)
@@ -276,6 +288,41 @@ private function applyDefaultRowStyle(Row $row)
276288
}
277289
}
278290

291+
/**
292+
* @param float $width
293+
*/
294+
public function setDefaultColumnWidth(float $width)
295+
{
296+
$this->worksheetManager->setDefaultColumnWidth($width);
297+
}
298+
299+
/**
300+
* @param float $height
301+
*/
302+
public function setDefaultRowHeight(float $height)
303+
{
304+
$this->worksheetManager->setDefaultRowHeight($height);
305+
}
306+
307+
/**
308+
* @param float $width
309+
* @param array $columns One or more columns with this width
310+
*/
311+
public function setColumnWidth(float $width, ...$columns)
312+
{
313+
$this->worksheetManager->setColumnWidth($width, ...$columns);
314+
}
315+
316+
/**
317+
* @param float $width The width to set
318+
* @param int $start First column index of the range
319+
* @param int $end Last column index of the range
320+
*/
321+
public function setColumnWidthForRange(float $width, int $start, int $end)
322+
{
323+
$this->worksheetManager->setColumnWidthForRange($width, $start, $end);
324+
}
325+
279326
/**
280327
* Closes the workbook and all its associated sheets.
281328
* All the necessary files are written to disk and zipped together to create the final file.

src/Spout/Writer/Common/Manager/WorkbookManagerInterface.php

+15
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,21 @@ public function getWorksheets();
4242
*/
4343
public function getCurrentWorksheet();
4444

45+
/**
46+
* Starts the current sheet and opens its file pointer
47+
*/
48+
public function startCurrentSheet();
49+
50+
/**
51+
* @param float $width
52+
*/
53+
public function setDefaultColumnWidth(float $width);
54+
55+
/**
56+
* @param float $height
57+
*/
58+
public function setDefaultRowHeight(float $height);
59+
4560
/**
4661
* Sets the given sheet as the current one. New data will be written to this sheet.
4762
* The writing will resume where it stopped (i.e. data won't be truncated).

src/Spout/Writer/Common/Manager/WorksheetManagerInterface.php

+23
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,29 @@
1111
*/
1212
interface WorksheetManagerInterface
1313
{
14+
/**
15+
* @param float|null $width
16+
*/
17+
public function setDefaultColumnWidth($width);
18+
19+
/**
20+
* @param float|null $height
21+
*/
22+
public function setDefaultRowHeight($height);
23+
24+
/**
25+
* @param float $width
26+
* @param array $columns One or more columns with this width
27+
*/
28+
public function setColumnWidth(float $width, ...$columns);
29+
30+
/**
31+
* @param float $width The width to set
32+
* @param int $start First column index of the range
33+
* @param int $end Last column index of the range
34+
*/
35+
public function setColumnWidthForRange(float $width, int $start, int $end);
36+
1437
/**
1538
* Adds a row to the worksheet.
1639
*

src/Spout/Writer/ODS/Creator/ManagerFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ private function createStyleManager(OptionsManagerInterface $optionsManager)
9393
{
9494
$styleRegistry = $this->createStyleRegistry($optionsManager);
9595

96-
return new StyleManager($styleRegistry);
96+
return new StyleManager($styleRegistry, $optionsManager);
9797
}
9898

9999
/**

src/Spout/Writer/ODS/Manager/OptionsManager.php

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ protected function getSupportedOptions()
3434
Options::TEMP_FOLDER,
3535
Options::DEFAULT_ROW_STYLE,
3636
Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY,
37+
Options::DEFAULT_COLUMN_WIDTH,
38+
Options::DEFAULT_ROW_HEIGHT,
39+
Options::COLUMN_WIDTHS,
3740
];
3841
}
3942

src/Spout/Writer/ODS/Manager/Style/StyleManager.php

+72-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
use Box\Spout\Common\Entity\Style\BorderPart;
66
use Box\Spout\Common\Entity\Style\CellAlignment;
7+
use Box\Spout\Common\Manager\OptionsManagerInterface;
8+
use Box\Spout\Writer\Common\Entity\Options;
79
use Box\Spout\Writer\Common\Entity\Worksheet;
10+
use Box\Spout\Writer\Common\Manager\ManagesCellSize;
811
use Box\Spout\Writer\ODS\Helper\BorderHelper;
912

1013
/**
@@ -13,9 +16,22 @@
1316
*/
1417
class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
1518
{
19+
use ManagesCellSize;
20+
1621
/** @var StyleRegistry */
1722
protected $styleRegistry;
1823

24+
/**
25+
* @param StyleRegistry $styleRegistry
26+
*/
27+
public function __construct(StyleRegistry $styleRegistry, OptionsManagerInterface $optionsManager)
28+
{
29+
parent::__construct($styleRegistry);
30+
$this->setDefaultColumnWidth($optionsManager->getOption(Options::DEFAULT_COLUMN_WIDTH));
31+
$this->setDefaultRowHeight($optionsManager->getOption(Options::DEFAULT_ROW_HEIGHT));
32+
$this->columnWidths = $optionsManager->getOption(Options::COLUMN_WIDTHS) ?? [];
33+
}
34+
1935
/**
2036
* Returns the content of the "styles.xml" file, given a list of styles.
2137
*
@@ -162,12 +178,16 @@ public function getContentXmlAutomaticStylesSectionContent($worksheets)
162178
$content .= $this->getStyleSectionContent($style);
163179
}
164180

165-
$content .= <<<'EOD'
166-
<style:style style:family="table-column" style:name="co1">
167-
<style:table-column-properties fo:break-before="auto"/>
181+
$useOptimalRowHeight = empty($this->defaultRowHeight) ? 'true' : 'false';
182+
$defaultRowHeight = empty($this->defaultRowHeight) ? '15pt' : "{$this->defaultRowHeight}pt";
183+
$defaultColumnWidth = empty($this->defaultColumnWidth) ? '' : "style:column-width=\"{$this->defaultColumnWidth}pt\"";
184+
185+
$content .= <<<EOD
186+
<style:style style:family="table-column" style:name="default-column-style">
187+
<style:table-column-properties fo:break-before="auto" {$defaultColumnWidth}/>
168188
</style:style>
169189
<style:style style:family="table-row" style:name="ro1">
170-
<style:table-row-properties fo:break-before="auto" style:row-height="15pt" style:use-optimal-row-height="true"/>
190+
<style:table-row-properties fo:break-before="auto" style:row-height="{$defaultRowHeight}" style:use-optimal-row-height="{$useOptimalRowHeight}"/>
171191
</style:style>
172192
EOD;
173193

@@ -182,6 +202,16 @@ public function getContentXmlAutomaticStylesSectionContent($worksheets)
182202
EOD;
183203
}
184204

205+
// Sort column widths since ODS cares about order
206+
usort($this->columnWidths, function ($a, $b) {
207+
if ($a[0] === $b[0]) {
208+
return 0;
209+
}
210+
211+
return ($a[0] < $b[0]) ? -1 : 1;
212+
});
213+
$content .= $this->getTableColumnStylesXMLContent();
214+
185215
$content .= '</office:automatic-styles>';
186216

187217
return $content;
@@ -381,4 +411,42 @@ private function getBackgroundColorXMLContent($style)
381411
{
382412
return \sprintf(' fo:background-color="#%s" ', $style->getBackgroundColor());
383413
}
414+
415+
public function getTableColumnStylesXMLContent() : string
416+
{
417+
if (empty($this->columnWidths)) {
418+
return '';
419+
}
420+
421+
$content = '';
422+
foreach ($this->columnWidths as $styleIndex => $entry) {
423+
$content .= <<<EOD
424+
<style:style style:family="table-column" style:name="co{$styleIndex}">
425+
<style:table-column-properties fo:break-before="auto" style:use-optimal-column-width="false" style:column-width="{$entry[2]}pt"/>
426+
</style:style>
427+
EOD;
428+
}
429+
430+
return $content;
431+
}
432+
433+
public function getStyledTableColumnXMLContent(int $maxNumColumns) : string
434+
{
435+
if (empty($this->columnWidths)) {
436+
return '';
437+
}
438+
439+
$content = '';
440+
foreach ($this->columnWidths as $styleIndex => $entry) {
441+
$numCols = $entry[1] - $entry[0] + 1;
442+
$content .= <<<EOD
443+
<table:table-column table:default-cell-style-name='Default' table:style-name="co{$styleIndex}" table:number-columns-repeated="{$numCols}"/>
444+
EOD;
445+
}
446+
// Note: This assumes the column widths are contiguous and default width is
447+
// only applied to columns after the last custom column with a custom width
448+
$content .= '<table:table-column table:default-cell-style-name="ce1" table:style-name="default-column-style" table:number-columns-repeated="' . ($maxNumColumns - $entry[1]) . '"/>';
449+
450+
return $content;
451+
}
384452
}

0 commit comments

Comments
 (0)