Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add cell size modification #1

Merged
merged 1 commit into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Spout/Writer/Common/Entity/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ abstract class Options

// XLSX specific options
public const SHOULD_USE_INLINE_STRINGS = 'shouldUseInlineStrings';

// Cell size options
const DEFAULT_COLUMN_WIDTH = 'defaultColumnWidth';
const DEFAULT_ROW_HEIGHT = 'defaultRowHeight';
const COLUMN_WIDTHS = 'columnWidthDefinition';
}
20 changes: 20 additions & 0 deletions src/Spout/Writer/Common/Entity/Worksheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class Worksheet
/** @var int Index of the last written row */
private $lastWrittenRowIndex;

/** @var bool has the sheet data header been written */
private $sheetDataStarted = false;

/**
* Worksheet constructor.
*
Expand All @@ -36,6 +39,7 @@ public function __construct($worksheetFilePath, Sheet $externalSheet)
$this->externalSheet = $externalSheet;
$this->maxNumColumns = 0;
$this->lastWrittenRowIndex = 0;
$this->sheetDataStarted = false;
}

/**
Expand Down Expand Up @@ -110,4 +114,20 @@ public function getId()
// sheet index is zero-based, while ID is 1-based
return $this->externalSheet->getIndex() + 1;
}

/**
* @return bool
*/
public function getSheetDataStarted()
{
return $this->sheetDataStarted;
}

/**
* @param bool $sheetDataStarted
*/
public function setSheetDataStarted($sheetDataStarted)
{
$this->sheetDataStarted = $sheetDataStarted;
}
}
63 changes: 63 additions & 0 deletions src/Spout/Writer/Common/Manager/ManagesCellSize.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace Box\Spout\Writer\Common\Manager;

trait ManagesCellSize
{
/** @var float|null The default column width to use */
private $defaultColumnWidth;

/** @var float|null The default row height to use */
private $defaultRowHeight;

/** @var array Array of min-max-width arrays */
private $columnWidths = [];

/**
* @param float|null $width
*/
public function setDefaultColumnWidth($width)
{
$this->defaultColumnWidth = $width;
}

/**
* @param float|null $height
*/
public function setDefaultRowHeight($height)
{
$this->defaultRowHeight = $height;
}

/**
* @param float $width
* @param array $columns One or more columns with this width
*/
public function setColumnWidth(float $width, ...$columns)
{
// Gather sequences
$sequence = [];
foreach ($columns as $i) {
$sequenceLength = count($sequence);
if ($sequenceLength > 0) {
$previousValue = $sequence[$sequenceLength - 1];
if ($i !== $previousValue + 1) {
$this->setColumnWidthForRange($width, $sequence[0], $previousValue);
$sequence = [];
}
}
$sequence[] = $i;
}
$this->setColumnWidthForRange($width, $sequence[0], $sequence[count($sequence) - 1]);
}

/**
* @param float $width The width to set
* @param int $start First column index of the range
* @param int $end Last column index of the range
*/
public function setColumnWidthForRange(float $width, int $start, int $end)
{
$this->columnWidths[] = [$start, $end, $width];
}
}
53 changes: 50 additions & 3 deletions src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface;
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
use Box\Spout\Writer\Exception\SheetNotFoundException;
use Box\Spout\Writer\Exception\WriterException;

/**
* Class WorkbookManagerAbstract
Expand Down Expand Up @@ -117,7 +116,7 @@ public function addNewSheetAndMakeItCurrent()
/**
* Creates a new sheet in the workbook. The current sheet remains unchanged.
*
* @throws \Box\Spout\Common\Exception\IOException If unable to open the sheet for writing
* @throws IOException
* @return Worksheet The created sheet
*/
private function addNewSheet()
Expand Down Expand Up @@ -157,6 +156,16 @@ public function getCurrentWorksheet()
return $this->currentWorksheet;
}

/**
* Starts the current sheet and opens the file pointer
*
* @throws IOException
*/
public function startCurrentSheet()
{
$this->worksheetManager->startSheet($this->getCurrentWorksheet());
}

/**
* Sets the given sheet as the current one. New data will be written to this sheet.
* The writing will resume where it stopped (i.e. data won't be truncated).
Expand Down Expand Up @@ -211,7 +220,7 @@ private function getWorksheetFromExternalSheet($sheet)
*
* @param Row $row The row to be added
* @throws IOException If trying to create a new sheet and unable to open the sheet for writing
* @throws WriterException If unable to write data
* @throws \Box\Spout\Common\Exception\InvalidArgumentException
* @return void
*/
public function addRowToCurrentWorksheet(Row $row)
Expand Down Expand Up @@ -250,6 +259,9 @@ private function hasCurrentWorksheetReachedMaxRows()
* @param Worksheet $worksheet Worksheet to write the row to
* @param Row $row The row to be added
* @throws WriterException If unable to write data
*
* @throws IOException
* @throws \Box\Spout\Common\Exception\InvalidArgumentException
* @return void
*/
private function addRowToWorksheet(Worksheet $worksheet, Row $row)
Expand All @@ -276,6 +288,41 @@ private function applyDefaultRowStyle(Row $row)
}
}

/**
* @param float $width
*/
public function setDefaultColumnWidth(float $width)
{
$this->worksheetManager->setDefaultColumnWidth($width);
}

/**
* @param float $height
*/
public function setDefaultRowHeight(float $height)
{
$this->worksheetManager->setDefaultRowHeight($height);
}

/**
* @param float $width
* @param array $columns One or more columns with this width
*/
public function setColumnWidth(float $width, ...$columns)
{
$this->worksheetManager->setColumnWidth($width, ...$columns);
}

/**
* @param float $width The width to set
* @param int $start First column index of the range
* @param int $end Last column index of the range
*/
public function setColumnWidthForRange(float $width, int $start, int $end)
{
$this->worksheetManager->setColumnWidthForRange($width, $start, $end);
}

/**
* Closes the workbook and all its associated sheets.
* All the necessary files are written to disk and zipped together to create the final file.
Expand Down
15 changes: 15 additions & 0 deletions src/Spout/Writer/Common/Manager/WorkbookManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ public function getWorksheets();
*/
public function getCurrentWorksheet();

/**
* Starts the current sheet and opens its file pointer
*/
public function startCurrentSheet();

/**
* @param float $width
*/
public function setDefaultColumnWidth(float $width);

/**
* @param float $height
*/
public function setDefaultRowHeight(float $height);

/**
* Sets the given sheet as the current one. New data will be written to this sheet.
* The writing will resume where it stopped (i.e. data won't be truncated).
Expand Down
23 changes: 23 additions & 0 deletions src/Spout/Writer/Common/Manager/WorksheetManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@
*/
interface WorksheetManagerInterface
{
/**
* @param float|null $width
*/
public function setDefaultColumnWidth($width);

/**
* @param float|null $height
*/
public function setDefaultRowHeight($height);

/**
* @param float $width
* @param array $columns One or more columns with this width
*/
public function setColumnWidth(float $width, ...$columns);

/**
* @param float $width The width to set
* @param int $start First column index of the range
* @param int $end Last column index of the range
*/
public function setColumnWidthForRange(float $width, int $start, int $end);

/**
* Adds a row to the worksheet.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Spout/Writer/ODS/Creator/ManagerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private function createStyleManager(OptionsManagerInterface $optionsManager)
{
$styleRegistry = $this->createStyleRegistry($optionsManager);

return new StyleManager($styleRegistry);
return new StyleManager($styleRegistry, $optionsManager);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/Spout/Writer/ODS/Manager/OptionsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ protected function getSupportedOptions()
Options::TEMP_FOLDER,
Options::DEFAULT_ROW_STYLE,
Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY,
Options::DEFAULT_COLUMN_WIDTH,
Options::DEFAULT_ROW_HEIGHT,
Options::COLUMN_WIDTHS,
];
}

Expand Down
76 changes: 72 additions & 4 deletions src/Spout/Writer/ODS/Manager/Style/StyleManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

use Box\Spout\Common\Entity\Style\BorderPart;
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Manager\ManagesCellSize;
use Box\Spout\Writer\ODS\Helper\BorderHelper;

/**
Expand All @@ -13,9 +16,22 @@
*/
class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
{
use ManagesCellSize;

/** @var StyleRegistry */
protected $styleRegistry;

/**
* @param StyleRegistry $styleRegistry
*/
public function __construct(StyleRegistry $styleRegistry, OptionsManagerInterface $optionsManager)
{
parent::__construct($styleRegistry);
$this->setDefaultColumnWidth($optionsManager->getOption(Options::DEFAULT_COLUMN_WIDTH));
$this->setDefaultRowHeight($optionsManager->getOption(Options::DEFAULT_ROW_HEIGHT));
$this->columnWidths = $optionsManager->getOption(Options::COLUMN_WIDTHS) ?? [];
}

/**
* Returns the content of the "styles.xml" file, given a list of styles.
*
Expand Down Expand Up @@ -162,12 +178,16 @@ public function getContentXmlAutomaticStylesSectionContent($worksheets)
$content .= $this->getStyleSectionContent($style);
}

$content .= <<<'EOD'
<style:style style:family="table-column" style:name="co1">
<style:table-column-properties fo:break-before="auto"/>
$useOptimalRowHeight = empty($this->defaultRowHeight) ? 'true' : 'false';
$defaultRowHeight = empty($this->defaultRowHeight) ? '15pt' : "{$this->defaultRowHeight}pt";
$defaultColumnWidth = empty($this->defaultColumnWidth) ? '' : "style:column-width=\"{$this->defaultColumnWidth}pt\"";

$content .= <<<EOD
<style:style style:family="table-column" style:name="default-column-style">
<style:table-column-properties fo:break-before="auto" {$defaultColumnWidth}/>
</style:style>
<style:style style:family="table-row" style:name="ro1">
<style:table-row-properties fo:break-before="auto" style:row-height="15pt" style:use-optimal-row-height="true"/>
<style:table-row-properties fo:break-before="auto" style:row-height="{$defaultRowHeight}" style:use-optimal-row-height="{$useOptimalRowHeight}"/>
</style:style>
EOD;

Expand All @@ -182,6 +202,16 @@ public function getContentXmlAutomaticStylesSectionContent($worksheets)
EOD;
}

// Sort column widths since ODS cares about order
usort($this->columnWidths, function ($a, $b) {
if ($a[0] === $b[0]) {
return 0;
}

return ($a[0] < $b[0]) ? -1 : 1;
});
$content .= $this->getTableColumnStylesXMLContent();

$content .= '</office:automatic-styles>';

return $content;
Expand Down Expand Up @@ -381,4 +411,42 @@ private function getBackgroundColorXMLContent($style)
{
return \sprintf(' fo:background-color="#%s" ', $style->getBackgroundColor());
}

public function getTableColumnStylesXMLContent() : string
{
if (empty($this->columnWidths)) {
return '';
}

$content = '';
foreach ($this->columnWidths as $styleIndex => $entry) {
$content .= <<<EOD
<style:style style:family="table-column" style:name="co{$styleIndex}">
<style:table-column-properties fo:break-before="auto" style:use-optimal-column-width="false" style:column-width="{$entry[2]}pt"/>
</style:style>
EOD;
}

return $content;
}

public function getStyledTableColumnXMLContent(int $maxNumColumns) : string
{
if (empty($this->columnWidths)) {
return '';
}

$content = '';
foreach ($this->columnWidths as $styleIndex => $entry) {
$numCols = $entry[1] - $entry[0] + 1;
$content .= <<<EOD
<table:table-column table:default-cell-style-name='Default' table:style-name="co{$styleIndex}" table:number-columns-repeated="{$numCols}"/>
EOD;
}
// Note: This assumes the column widths are contiguous and default width is
// only applied to columns after the last custom column with a custom width
$content .= '<table:table-column table:default-cell-style-name="ce1" table:style-name="default-column-style" table:number-columns-repeated="' . ($maxNumColumns - $entry[1]) . '"/>';

return $content;
}
}
Loading