Skip to content

Commit ad76cae

Browse files
authored
Merge pull request #4581 from oleibman/maxwidth
Maximum Column Width
2 parents 3c28bf4 + 31502b0 commit ad76cae

File tree

6 files changed

+130
-4
lines changed

6 files changed

+130
-4
lines changed

docs/topics/reading-and-writing-to-file.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,26 @@ Because of a bug in the Office2003 compatibility pack, there can be some
181181
small issues when opening Xlsx spreadsheets (mostly related to formula
182182
calculation). You can enable Office2003 compatibility with the following
183183
code:
184-
184+
```php
185185
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
186186
$writer->setOffice2003Compatibility(true);
187187
$writer->save("05featuredemo.xlsx");
188+
```
188189

189190
**Office2003 compatibility option should only be used when needed** because
190191
it disables several Office2007 file format options, resulting in a
191192
lower-featured Office2007 spreadsheet.
192193

194+
#### Maximum Column Width
195+
196+
In the Xlsx User Interface, the user cannot set a column width > 255.
197+
Nevertheless, it will honor a higher value if supplied in the Xml.
198+
PhpSpreadsheet will, by default, allow values > 255 to be written.
199+
However, Excel's behavior, restricting the value to 255, can be emulated:
200+
```php
201+
$writer->setRestrictMaxColumnWidth(true);
202+
```
203+
193204
### Form Control Fields
194205

195206
PhpSpreadsheet offers limited support for Forms Controls (buttons,

src/PhpSpreadsheet/Worksheet/ColumnDimension.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
class ColumnDimension extends Dimension
99
{
10+
public const EXCEL_MAX_WIDTH = 255.0;
11+
1012
/**
1113
* Column index.
1214
*/
@@ -89,6 +91,11 @@ public function getWidth(?string $unitOfMeasure = null): float
8991
: (new CssDimension((string) $this->width))->toUnit($unitOfMeasure);
9092
}
9193

94+
public function getWidthForOutput(bool $restrictMax): float
95+
{
96+
return ($restrictMax && $this->width > self::EXCEL_MAX_WIDTH) ? self::EXCEL_MAX_WIDTH : $this->width;
97+
}
98+
9299
/**
93100
* Set Width.
94101
*

src/PhpSpreadsheet/Writer/Xls/Worksheet.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public function close(): void
270270
if (isset($columnDimensions[$columnLetter])) {
271271
$columnDimension = $columnDimensions[$columnLetter];
272272
if ($columnDimension->getWidth() >= 0) {
273-
$width = $columnDimension->getWidth();
273+
$width = $columnDimension->getWidthForOutput(true);
274274
}
275275
$hidden = $columnDimension->getVisible() ? 0 : 1;
276276
$level = $columnDimension->getOutlineLevel();

src/PhpSpreadsheet/Writer/Xlsx.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ class Xlsx extends BaseWriter
146146
// Default changed from null in PhpSpreadsheet 4.0.0.
147147
private ?bool $forceFullCalc = self::DEFAULT_FORCE_FULL_CALC;
148148

149+
protected bool $restrictMaxColumnWidth = false;
150+
149151
/**
150152
* Create a new Xlsx Writer.
151153
*/
@@ -818,4 +820,27 @@ public function setForceFullCalc(?bool $forceFullCalc): self
818820

819821
return $this;
820822
}
823+
824+
/**
825+
* Excel has a nominal width limint of 255 for a column.
826+
* Surprisingly, Xlsx can read and write larger values,
827+
* and the file will appear as desired,
828+
* but the User Interface does not allow you to set the width beyond 255,
829+
* either directly or though auto-fit width.
830+
* Xls sets its own value when the width is beyond 255.
831+
* This method gets whether PhpSpreadsheet should restrict the
832+
* column widths which it writes to the Excel limit, for formats
833+
* which allow it to exceed 255.
834+
*/
835+
public function setRestrictMaxColumnWidth(bool $restrictMaxColumnWidth): self
836+
{
837+
$this->restrictMaxColumnWidth = $restrictMaxColumnWidth;
838+
839+
return $this;
840+
}
841+
842+
public function getRestrictMaxColumnWidth(): bool
843+
{
844+
return $this->restrictMaxColumnWidth;
845+
}
821846
}

src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class Worksheet extends WriterPart
3838

3939
private bool $useDynamicArrays = false;
4040

41+
private bool $restrictMaxColumnWidth = false;
42+
4143
/**
4244
* Write worksheet to XML format.
4345
*
@@ -63,6 +65,7 @@ public function writeWorksheet(PhpspreadsheetWorksheet $worksheet, array $string
6365
} else {
6466
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
6567
}
68+
$this->restrictMaxColumnWidth = $this->getParentWriter()->getRestrictMaxColumnWidth();
6669

6770
// XML header
6871
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
@@ -436,7 +439,7 @@ private function writeSheetFormatPr(XMLWriter $objWriter, PhpspreadsheetWorkshee
436439

437440
// Default column width
438441
if ($worksheet->getDefaultColumnDimension()->getWidth() >= 0) {
439-
$objWriter->writeAttribute('defaultColWidth', StringHelper::formatNumber($worksheet->getDefaultColumnDimension()->getWidth()));
442+
$objWriter->writeAttribute('defaultColWidth', StringHelper::formatNumber($worksheet->getDefaultColumnDimension()->getWidthForOutput($this->restrictMaxColumnWidth)));
440443
}
441444

442445
// Outline level - row
@@ -483,7 +486,7 @@ private function writeCols(XMLWriter $objWriter, PhpspreadsheetWorksheet $worksh
483486
$objWriter->writeAttribute('width', '9.10');
484487
} else {
485488
// Width set
486-
$objWriter->writeAttribute('width', StringHelper::formatNumber($colDimension->getWidth()));
489+
$objWriter->writeAttribute('width', StringHelper::formatNumber($colDimension->getWidthForOutput($this->restrictMaxColumnWidth)));
487490
}
488491

489492
// Column visibility
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
6+
7+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
8+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
9+
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
10+
11+
class ColumnDimension3Test extends AbstractFunctional
12+
{
13+
public function testXlsxDefault(): void
14+
{
15+
$spreadsheet = new Spreadsheet();
16+
$sheet = $spreadsheet->getActiveSheet();
17+
$sheet->getCell('B1')->setValue('hello');
18+
$sheet->getCell('C1')->setValue(2);
19+
$sheet->getCell('A1')->setValue('=REPT("ABCDEFGHIJKLMNOPQRS*",13)');
20+
$sheet->getStyle('A1')->getFont()
21+
->setSize(11)
22+
->setName('Courier New');
23+
$sheet->getColumnDimension('A')->setAutoSize(true);
24+
$sheet->getColumnDimension('B')->setAutoSize(true);
25+
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
26+
$spreadsheet->disconnectWorksheets();
27+
$sheet = $reloadedSpreadsheet->getActiveSheet();
28+
self::assertGreaterThan(255.0, $sheet->getColumnDimension('A')->getWidth());
29+
self::assertLessThan(255.0, $sheet->getColumnDimension('B')->getWidth());
30+
self::assertSame(-1.0, $sheet->getColumnDimension('C')->getWidth());
31+
$reloadedSpreadsheet->disconnectWorksheets();
32+
}
33+
34+
public function testXlsxRestrict(): void
35+
{
36+
$spreadsheet = new Spreadsheet();
37+
$sheet = $spreadsheet->getActiveSheet();
38+
$sheet->getCell('B1')->setValue('hello');
39+
$sheet->getCell('C1')->setValue(2);
40+
$sheet->getCell('A1')->setValue('=REPT("ABCDEFGHIJKLMNOPQRS*",13)');
41+
$sheet->getStyle('A1')->getFont()
42+
->setSize(11)
43+
->setName('Courier New');
44+
$sheet->getColumnDimension('A')->setAutoSize(true);
45+
$sheet->getColumnDimension('B')->setAutoSize(true);
46+
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', null, [self::class, 'restrictWidth']);
47+
$spreadsheet->disconnectWorksheets();
48+
$sheet = $reloadedSpreadsheet->getActiveSheet();
49+
self::assertSame(255.0, $sheet->getColumnDimension('A')->getWidth());
50+
self::assertLessThan(255.0, $sheet->getColumnDimension('B')->getWidth());
51+
self::assertSame(-1.0, $sheet->getColumnDimension('C')->getWidth());
52+
$reloadedSpreadsheet->disconnectWorksheets();
53+
}
54+
55+
public function testXls(): void
56+
{
57+
$spreadsheet = new Spreadsheet();
58+
$sheet = $spreadsheet->getActiveSheet();
59+
$sheet->getCell('B1')->setValue('hello');
60+
$sheet->getCell('C1')->setValue(2);
61+
$sheet->getCell('A1')->setValue('=REPT("ABCDEFGHIJKLMNOPQRS*",13)');
62+
$sheet->getStyle('A1')->getFont()
63+
->setSize(11)
64+
->setName('Courier New');
65+
$sheet->getColumnDimension('A')->setAutoSize(true);
66+
$sheet->getColumnDimension('B')->setAutoSize(true);
67+
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xls');
68+
$spreadsheet->disconnectWorksheets();
69+
$sheet = $reloadedSpreadsheet->getActiveSheet();
70+
self::assertSame(255.0, $sheet->getColumnDimension('A')->getWidth());
71+
self::assertLessThan(255.0, $sheet->getColumnDimension('B')->getWidth());
72+
self::assertLessThan(255.0, $sheet->getColumnDimension('C')->getWidth());
73+
$reloadedSpreadsheet->disconnectWorksheets();
74+
}
75+
76+
public static function restrictWidth(XlsxWriter $writer): void
77+
{
78+
$writer->setRestrictMaxColumnWidth(true);
79+
}
80+
}

0 commit comments

Comments
 (0)