* XLSX Image background in comments * XLSX-Image-Background-In-Comments (#1547) * Test fixes, convertion for comment sizes from px to pt, fix for setting image sizes from zip, set image type * Merge remote-tracking branch 'origin/XLSX-Image-Background-In-Comments' into XLSX-Image-Background-In-Comments * Tests to check reloaded document. Co-authored-by: Burkov Sergey
|
|
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
- Xlsx Writer Support for WMF Files [#2339](https://github.com/PHPOffice/PhpSpreadsheet/issues/2339)
|
- Xlsx Writer Support for WMF Files [#2339](https://github.com/PHPOffice/PhpSpreadsheet/issues/2339)
|
||||||
- Use standard temporary file for internal use of HTMLPurifier [#2383](https://github.com/PHPOffice/PhpSpreadsheet/issues/2383)
|
- Use standard temporary file for internal use of HTMLPurifier [#2383](https://github.com/PHPOffice/PhpSpreadsheet/issues/2383)
|
||||||
|
- Ability to add a picture to the background of the comment. Supports four image formats: png, jpeg, gif, bmp. A Comment method setSizeAsBackgroundImage for changing the size of a comment to the size of an background image. [Issue #1547](https://github.com/PHPOffice/PhpSpreadsheet/issues/1547) [PR #2422](https://github.com/PHPOffice/PhpSpreadsheet/pull/2422)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1255,7 +1255,7 @@
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding-left: 1em;">Rich Text</td>
|
<td style="padding-left: 2em;">Rich Text</td>
|
||||||
<td style="text-align: center; color: red;">✖ <sup>2</sup></td>
|
<td style="text-align: center; color: red;">✖ <sup>2</sup></td>
|
||||||
<td style="text-align: center; color: green;">✔</td>
|
<td style="text-align: center; color: green;">✔</td>
|
||||||
<td style="text-align: center; color: red;">✖</td>
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
|
@ -1273,7 +1273,7 @@
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding-left: 1em;">Alignment</td>
|
<td style="padding-left: 2em;">Alignment</td>
|
||||||
<td style="text-align: center; color: red;">✖ <sup>3</sup></td>
|
<td style="text-align: center; color: red;">✖ <sup>3</sup></td>
|
||||||
<td style="text-align: center; color: red;">✖</td>
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
<td style="text-align: center; color: red;">✖</td>
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
|
@ -1290,6 +1290,24 @@
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding-left: 2em;">Background Image</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: green;">✔</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: green;">✔</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td style="text-align: center; color: red;">✖</td>
|
||||||
|
<td>$comment->getBackgroundImage()</td>
|
||||||
|
<td>$comment->setBackgroundImage()</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Cell Validation</strong></td>
|
<td><strong>Cell Validation</strong></td>
|
||||||
<td style="text-align: center; color: green;">✔</td>
|
<td style="text-align: center; color: green;">✔</td>
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -957,9 +957,26 @@ $spreadsheet->getActiveSheet()
|
||||||
->getComment('E11')
|
->getComment('E11')
|
||||||
->getText()->createTextRun('Total amount on the current invoice, excluding VAT.');
|
->getText()->createTextRun('Total amount on the current invoice, excluding VAT.');
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Add a comment with background image to a cell
|
||||||
|
|
||||||
|
To add a comment with background image to a cell, use the following code:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValue('B5', 'Gibli Chromo');
|
||||||
|
// Add png image to comment background
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Gibli Chromo');
|
||||||
|
$drawing->setPath('/tmp/gibli_chromo.png');
|
||||||
|
$comment = $sheet->getComment('B5');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
// Set the size of the comment equal to the size of the image
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
## Apply autofilter to a range of cells
|
## Apply autofilter to a range of cells
|
||||||
|
|
||||||
To apply an autofilter to a range of cells, use the following code:
|
To apply an autofilter to a range of cells, use the following code:
|
||||||
|
|
|
||||||
|
|
@ -6045,11 +6045,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Worksheet/Column.php
|
path: src/PhpSpreadsheet/Worksheet/Column.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot use array destructuring on array\\|false\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Worksheet/Drawing.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet;
|
namespace PhpOffice\PhpSpreadsheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
use PhpOffice\PhpSpreadsheet\Helper\Size;
|
use PhpOffice\PhpSpreadsheet\Helper\Size;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||||
|
|
||||||
class Comment implements IComparable
|
class Comment implements IComparable
|
||||||
{
|
{
|
||||||
|
|
@ -72,6 +75,13 @@ class Comment implements IComparable
|
||||||
*/
|
*/
|
||||||
private $alignment;
|
private $alignment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Background image in comment.
|
||||||
|
*
|
||||||
|
* @var Drawing
|
||||||
|
*/
|
||||||
|
private $backgroundImage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Comment.
|
* Create a new Comment.
|
||||||
*/
|
*/
|
||||||
|
|
@ -82,6 +92,7 @@ class Comment implements IComparable
|
||||||
$this->text = new RichText();
|
$this->text = new RichText();
|
||||||
$this->fillColor = new Color('FFFFFFE1');
|
$this->fillColor = new Color('FFFFFFE1');
|
||||||
$this->alignment = Alignment::HORIZONTAL_GENERAL;
|
$this->alignment = Alignment::HORIZONTAL_GENERAL;
|
||||||
|
$this->backgroundImage = new Drawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -273,6 +284,7 @@ class Comment implements IComparable
|
||||||
($this->visible ? 1 : 0) .
|
($this->visible ? 1 : 0) .
|
||||||
$this->fillColor->getHashCode() .
|
$this->fillColor->getHashCode() .
|
||||||
$this->alignment .
|
$this->alignment .
|
||||||
|
($this->hasBackgroundImage() ? $this->backgroundImage->getHashCode() : '') .
|
||||||
__CLASS__
|
__CLASS__
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -299,4 +311,52 @@ class Comment implements IComparable
|
||||||
{
|
{
|
||||||
return $this->text->getPlainText();
|
return $this->text->getPlainText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check is background image exists.
|
||||||
|
*/
|
||||||
|
public function hasBackgroundImage(): bool
|
||||||
|
{
|
||||||
|
$path = $this->backgroundImage->getPath();
|
||||||
|
|
||||||
|
if (empty($path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getimagesize($path) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns background image.
|
||||||
|
*/
|
||||||
|
public function getBackgroundImage(): Drawing
|
||||||
|
{
|
||||||
|
return $this->backgroundImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets background image.
|
||||||
|
*/
|
||||||
|
public function setBackgroundImage(Drawing $objDrawing): self
|
||||||
|
{
|
||||||
|
if (!array_key_exists($objDrawing->getType(), Drawing::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||||
|
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
$this->backgroundImage = $objDrawing;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets size of comment as size of background image.
|
||||||
|
*/
|
||||||
|
public function setSizeAsBackgroundImage(): self
|
||||||
|
{
|
||||||
|
if ($this->hasBackgroundImage()) {
|
||||||
|
$this->setWidth(SharedDrawing::pixelsToPoints($this->backgroundImage->getWidth()) . 'pt');
|
||||||
|
$this->setHeight(SharedDrawing::pixelsToPoints($this->backgroundImage->getHeight()) . 'pt');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -984,6 +984,19 @@ class Xlsx extends BaseReader
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locate VML drawings image relations
|
||||||
|
$drowingImages = [];
|
||||||
|
$VMLDrawingsRelations = dirname($relPath) . '/_rels/' . basename($relPath) . '.rels';
|
||||||
|
if ($zip->locateName($VMLDrawingsRelations)) {
|
||||||
|
$relsVMLDrawing = $this->loadZip($VMLDrawingsRelations, Namespaces::RELATIONSHIPS);
|
||||||
|
foreach ($relsVMLDrawing->Relationship as $elex) {
|
||||||
|
$ele = self::getAttributes($elex);
|
||||||
|
if ($ele['Type'] == Namespaces::IMAGE) {
|
||||||
|
$drowingImages[(string) $ele['Id']] = (string) $ele['Target'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$shapes = self::xpathNoFalse($vmlCommentsFile, '//v:shape');
|
$shapes = self::xpathNoFalse($vmlCommentsFile, '//v:shape');
|
||||||
foreach ($shapes as $shape) {
|
foreach ($shapes as $shape) {
|
||||||
$shape->registerXPathNamespace('v', Namespaces::URN_VML);
|
$shape->registerXPathNamespace('v', Namespaces::URN_VML);
|
||||||
|
|
@ -993,6 +1006,8 @@ class Xlsx extends BaseReader
|
||||||
$fillColor = strtoupper(substr((string) $shape['fillcolor'], 1));
|
$fillColor = strtoupper(substr((string) $shape['fillcolor'], 1));
|
||||||
$column = null;
|
$column = null;
|
||||||
$row = null;
|
$row = null;
|
||||||
|
$fillImageRelId = null;
|
||||||
|
$fillImageTitle = '';
|
||||||
|
|
||||||
$clientData = $shape->xpath('.//x:ClientData');
|
$clientData = $shape->xpath('.//x:ClientData');
|
||||||
if (is_array($clientData) && !empty($clientData)) {
|
if (is_array($clientData) && !empty($clientData)) {
|
||||||
|
|
@ -1011,10 +1026,39 @@ class Xlsx extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fillImageRelNode = $shape->xpath('.//v:fill/@o:relid');
|
||||||
|
if (is_array($fillImageRelNode) && !empty($fillImageRelNode)) {
|
||||||
|
$fillImageRelNode = $fillImageRelNode[0];
|
||||||
|
|
||||||
|
if (isset($fillImageRelNode['relid'])) {
|
||||||
|
$fillImageRelId = (string) $fillImageRelNode['relid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$fillImageTitleNode = $shape->xpath('.//v:fill/@o:title');
|
||||||
|
if (is_array($fillImageTitleNode) && !empty($fillImageTitleNode)) {
|
||||||
|
$fillImageTitleNode = $fillImageTitleNode[0];
|
||||||
|
|
||||||
|
if (isset($fillImageTitleNode['title'])) {
|
||||||
|
$fillImageTitle = (string) $fillImageTitleNode['title'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (($column !== null) && ($row !== null)) {
|
if (($column !== null) && ($row !== null)) {
|
||||||
// Set comment properties
|
// Set comment properties
|
||||||
$comment = $docSheet->getCommentByColumnAndRow($column + 1, $row + 1);
|
$comment = $docSheet->getCommentByColumnAndRow($column + 1, $row + 1);
|
||||||
$comment->getFillColor()->setRGB($fillColor);
|
$comment->getFillColor()->setRGB($fillColor);
|
||||||
|
if (isset($drowingImages[$fillImageRelId])) {
|
||||||
|
$objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
|
||||||
|
$objDrawing->setName($fillImageTitle);
|
||||||
|
$imagePath = str_replace('../', 'xl/', $drowingImages[$fillImageRelId]);
|
||||||
|
$objDrawing->setPath(
|
||||||
|
'zip://' . File::realpath($filename) . '#' . $imagePath,
|
||||||
|
true,
|
||||||
|
$zip
|
||||||
|
);
|
||||||
|
$comment->setBackgroundImage($objDrawing);
|
||||||
|
}
|
||||||
|
|
||||||
// Parse style
|
// Parse style
|
||||||
$styleArray = explode(';', str_replace(' ', '', $style));
|
$styleArray = explode(';', str_replace(' ', '', $style));
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,13 @@ class BaseDrawing implements IComparable
|
||||||
*/
|
*/
|
||||||
private $hyperlink;
|
private $hyperlink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image type.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new BaseDrawing.
|
* Create a new BaseDrawing.
|
||||||
*/
|
*/
|
||||||
|
|
@ -123,6 +130,7 @@ class BaseDrawing implements IComparable
|
||||||
$this->resizeProportional = true;
|
$this->resizeProportional = true;
|
||||||
$this->rotation = 0;
|
$this->rotation = 0;
|
||||||
$this->shadow = new Drawing\Shadow();
|
$this->shadow = new Drawing\Shadow();
|
||||||
|
$this->type = IMAGETYPE_UNKNOWN;
|
||||||
|
|
||||||
// Set image index
|
// Set image index
|
||||||
++self::$imageCounter;
|
++self::$imageCounter;
|
||||||
|
|
@ -526,4 +534,28 @@ class BaseDrawing implements IComparable
|
||||||
{
|
{
|
||||||
return $this->hyperlink;
|
return $this->hyperlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Fact Sizes and Type of Image.
|
||||||
|
*/
|
||||||
|
protected function setSizesAndType(string $path): void
|
||||||
|
{
|
||||||
|
if ($this->width == 0 && $this->height == 0 && $this->type == IMAGETYPE_UNKNOWN) {
|
||||||
|
$imageData = getimagesize($path);
|
||||||
|
|
||||||
|
if (is_array($imageData)) {
|
||||||
|
$this->width = $imageData[0];
|
||||||
|
$this->height = $imageData[1];
|
||||||
|
$this->type = $imageData[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Image Type.
|
||||||
|
*/
|
||||||
|
public function getType(): int
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,17 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
|
use ZipArchive;
|
||||||
|
|
||||||
class Drawing extends BaseDrawing
|
class Drawing extends BaseDrawing
|
||||||
{
|
{
|
||||||
|
const IMAGE_TYPES_CONVERTION_MAP = [
|
||||||
|
IMAGETYPE_GIF => IMAGETYPE_PNG,
|
||||||
|
IMAGETYPE_JPEG => IMAGETYPE_JPEG,
|
||||||
|
IMAGETYPE_PNG => IMAGETYPE_PNG,
|
||||||
|
IMAGETYPE_BMP => IMAGETYPE_PNG,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path.
|
* Path.
|
||||||
*
|
*
|
||||||
|
|
@ -63,6 +71,20 @@ class Drawing extends BaseDrawing
|
||||||
return $exploded[count($exploded) - 1];
|
return $exploded[count($exploded) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get full filepath to store drawing in zip archive.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMediaFilename()
|
||||||
|
{
|
||||||
|
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||||
|
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('image%d%s', $this->getImageIndex(), $this->getImageFileExtensionForSave());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Path.
|
* Get Path.
|
||||||
*
|
*
|
||||||
|
|
@ -78,10 +100,11 @@ class Drawing extends BaseDrawing
|
||||||
*
|
*
|
||||||
* @param string $path File path
|
* @param string $path File path
|
||||||
* @param bool $verifyFile Verify file
|
* @param bool $verifyFile Verify file
|
||||||
|
* @param ZipArchive $zip Zip archive instance
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setPath($path, $verifyFile = true)
|
public function setPath($path, $verifyFile = true, $zip = null)
|
||||||
{
|
{
|
||||||
if ($verifyFile) {
|
if ($verifyFile) {
|
||||||
// Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979
|
// Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979
|
||||||
|
|
@ -94,18 +117,18 @@ class Drawing extends BaseDrawing
|
||||||
if ($filePath) {
|
if ($filePath) {
|
||||||
file_put_contents($filePath, $imageContents);
|
file_put_contents($filePath, $imageContents);
|
||||||
if (file_exists($filePath)) {
|
if (file_exists($filePath)) {
|
||||||
if ($this->width == 0 && $this->height == 0) {
|
$this->setSizesAndType($filePath);
|
||||||
// Get width/height
|
|
||||||
[$this->width, $this->height] = getimagesize($filePath);
|
|
||||||
}
|
|
||||||
unlink($filePath);
|
unlink($filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif (file_exists($path)) {
|
} elseif (file_exists($path)) {
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
if ($this->width == 0 && $this->height == 0) {
|
$this->setSizesAndType($path);
|
||||||
// Get width/height
|
} elseif ($zip instanceof ZipArchive) {
|
||||||
[$this->width, $this->height] = getimagesize($path);
|
$zipPath = explode('#', $path)[1];
|
||||||
|
if ($zip->locateName($zipPath) !== false) {
|
||||||
|
$this->path = $path;
|
||||||
|
$this->setSizesAndType($path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new PhpSpreadsheetException("File $path not found!");
|
throw new PhpSpreadsheetException("File $path not found!");
|
||||||
|
|
@ -150,4 +173,42 @@ class Drawing extends BaseDrawing
|
||||||
__CLASS__
|
__CLASS__
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Image Type for Save.
|
||||||
|
*/
|
||||||
|
public function getImageTypeForSave(): int
|
||||||
|
{
|
||||||
|
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||||
|
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::IMAGE_TYPES_CONVERTION_MAP[$this->type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Image file extention for Save.
|
||||||
|
*/
|
||||||
|
public function getImageFileExtensionForSave(bool $includeDot = true): string
|
||||||
|
{
|
||||||
|
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||||
|
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = image_type_to_extension(self::IMAGE_TYPES_CONVERTION_MAP[$this->type], $includeDot);
|
||||||
|
|
||||||
|
return is_string($result) ? $result : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Image mime type.
|
||||||
|
*/
|
||||||
|
public function getImageMimeType(): string
|
||||||
|
{
|
||||||
|
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||||
|
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return image_type_to_mime_type(self::IMAGE_TYPES_CONVERTION_MAP[$this->type]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -440,11 +440,22 @@ class Xlsx extends BaseWriter
|
||||||
|
|
||||||
// Add comment relationship parts
|
// Add comment relationship parts
|
||||||
if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) {
|
if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) {
|
||||||
|
// VML Comments relationships
|
||||||
|
$zipContent['xl/drawings/_rels/vmlDrawing' . ($i + 1) . '.vml.rels'] = $this->getWriterPartRels()->writeVMLDrawingRelationships($this->spreadSheet->getSheet($i));
|
||||||
|
|
||||||
// VML Comments
|
// VML Comments
|
||||||
$zipContent['xl/drawings/vmlDrawing' . ($i + 1) . '.vml'] = $this->getWriterPartComments()->writeVMLComments($this->spreadSheet->getSheet($i));
|
$zipContent['xl/drawings/vmlDrawing' . ($i + 1) . '.vml'] = $this->getWriterPartComments()->writeVMLComments($this->spreadSheet->getSheet($i));
|
||||||
|
|
||||||
// Comments
|
// Comments
|
||||||
$zipContent['xl/comments' . ($i + 1) . '.xml'] = $this->getWriterPartComments()->writeComments($this->spreadSheet->getSheet($i));
|
$zipContent['xl/comments' . ($i + 1) . '.xml'] = $this->getWriterPartComments()->writeComments($this->spreadSheet->getSheet($i));
|
||||||
|
|
||||||
|
// Media
|
||||||
|
foreach ($this->spreadSheet->getSheet($i)->getComments() as $comment) {
|
||||||
|
if ($comment->hasBackgroundImage()) {
|
||||||
|
$image = $comment->getBackgroundImage();
|
||||||
|
$zipContent['xl/media/' . $image->getMediaFilename()] = $this->processDrawing($image);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add unparsed relationship parts
|
// Add unparsed relationship parts
|
||||||
|
|
@ -668,4 +679,52 @@ class Xlsx extends BaseWriter
|
||||||
$this->addZipFile($path, $content);
|
$this->addZipFile($path, $content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function processDrawing(WorksheetDrawing $drawing)
|
||||||
|
{
|
||||||
|
$data = null;
|
||||||
|
$filename = $drawing->getPath();
|
||||||
|
$imageData = getimagesize($filename);
|
||||||
|
|
||||||
|
if (is_array($imageData)) {
|
||||||
|
switch ($imageData[2]) {
|
||||||
|
case 1: // GIF, not supported by BIFF8, we convert to PNG
|
||||||
|
$image = imagecreatefromgif($filename);
|
||||||
|
if ($image !== false) {
|
||||||
|
ob_start();
|
||||||
|
imagepng($image);
|
||||||
|
$data = ob_get_contents();
|
||||||
|
ob_end_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // JPEG
|
||||||
|
$data = file_get_contents($filename);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // PNG
|
||||||
|
$data = file_get_contents($filename);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // Windows DIB (BMP), we convert to PNG
|
||||||
|
$image = imagecreatefrombmp($filename);
|
||||||
|
if ($image !== false) {
|
||||||
|
ob_start();
|
||||||
|
imagepng($image);
|
||||||
|
$data = ob_get_contents();
|
||||||
|
ob_end_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,12 @@ class Comments extends WriterPart
|
||||||
// v:fill
|
// v:fill
|
||||||
$objWriter->startElement('v:fill');
|
$objWriter->startElement('v:fill');
|
||||||
$objWriter->writeAttribute('color2', '#' . $comment->getFillColor()->getRGB());
|
$objWriter->writeAttribute('color2', '#' . $comment->getFillColor()->getRGB());
|
||||||
|
if ($comment->hasBackgroundImage()) {
|
||||||
|
$bgImage = $comment->getBackgroundImage();
|
||||||
|
$objWriter->writeAttribute('o:relid', 'rId' . $bgImage->getImageIndex());
|
||||||
|
$objWriter->writeAttribute('o:title', $bgImage->getName());
|
||||||
|
$objWriter->writeAttribute('type', 'frame');
|
||||||
|
}
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
||||||
// v:shadow
|
// v:shadow
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,23 @@ class ContentTypes extends WriterPart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($spreadsheet->getSheet($i)->getComments()) > 0) {
|
||||||
|
foreach ($spreadsheet->getSheet($i)->getComments() as $comment) {
|
||||||
|
if (!$comment->hasBackgroundImage()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bgImage = $comment->getBackgroundImage();
|
||||||
|
$bgImageExtentionKey = strtolower($bgImage->getImageFileExtensionForSave(false));
|
||||||
|
|
||||||
|
if (!isset($aMediaContentTypes[$bgImageExtentionKey])) {
|
||||||
|
$aMediaContentTypes[$bgImageExtentionKey] = $bgImage->getImageMimeType();
|
||||||
|
|
||||||
|
$this->writeDefaultContentType($objWriter, $bgImageExtentionKey, $aMediaContentTypes[$bgImageExtentionKey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unparsed defaults
|
// unparsed defaults
|
||||||
|
|
|
||||||
|
|
@ -396,6 +396,43 @@ class Rels extends WriterPart
|
||||||
return $objWriter->getData();
|
return $objWriter->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function writeVMLDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet): string
|
||||||
|
{
|
||||||
|
// Create XML writer
|
||||||
|
$objWriter = null;
|
||||||
|
if ($this->getParentWriter()->getUseDiskCaching()) {
|
||||||
|
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
|
||||||
|
} else {
|
||||||
|
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XML header
|
||||||
|
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
|
||||||
|
|
||||||
|
// Relationships
|
||||||
|
$objWriter->startElement('Relationships');
|
||||||
|
$objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
|
||||||
|
|
||||||
|
// Loop through images and write relationships
|
||||||
|
foreach ($worksheet->getComments() as $comment) {
|
||||||
|
if (!$comment->hasBackgroundImage()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bgImage = $comment->getBackgroundImage();
|
||||||
|
$this->writeRelationship(
|
||||||
|
$objWriter,
|
||||||
|
$bgImage->getImageIndex(),
|
||||||
|
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
|
||||||
|
'../media/' . $bgImage->getMediaFilename()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$objWriter->endElement();
|
||||||
|
|
||||||
|
return $objWriter->getData();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write Override content type.
|
* Write Override content type.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Comment;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||||
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||||
|
|
||||||
class DrawingsTest extends AbstractFunctional
|
class DrawingsTest extends AbstractFunctional
|
||||||
|
|
@ -56,4 +60,374 @@ class DrawingsTest extends AbstractFunctional
|
||||||
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
||||||
self::assertNotNull($reloadedSpreadsheet);
|
self::assertNotNull($reloadedSpreadsheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test save and load XLSX file with drawing in comment.
|
||||||
|
*/
|
||||||
|
public function testSaveLoadWithDrawingInComment(): void
|
||||||
|
{
|
||||||
|
// Read spreadsheet from file
|
||||||
|
$originalFileName = 'tests/data/Writer/XLSX/drawing_in_comment.xlsx';
|
||||||
|
|
||||||
|
$originalFile = file_get_contents($originalFileName);
|
||||||
|
|
||||||
|
$tempFileName = File::sysGetTempDir() . '/drawing_in_comment.xlsx';
|
||||||
|
|
||||||
|
file_put_contents($tempFileName, $originalFile);
|
||||||
|
|
||||||
|
// Load native xlsx file with drawing in comment background
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load($tempFileName);
|
||||||
|
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$comment = $sheet->getComment('A1');
|
||||||
|
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 178);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 140);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_JPEG);
|
||||||
|
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save($tempFileName);
|
||||||
|
|
||||||
|
$reloadedSpreadsheet = $reader->load($tempFileName);
|
||||||
|
unlink($tempFileName);
|
||||||
|
|
||||||
|
self::assertNotNull($reloadedSpreadsheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test save and load XLSX file with drawing in comment, image in BMP/GIF format saved as PNG.
|
||||||
|
*/
|
||||||
|
public function testDrawingInCommentImageFormatsConversions(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
// Add gif image to comment background
|
||||||
|
$sheet->setCellValue('A1', '.gif');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Green Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/green_square.gif');
|
||||||
|
self::assertEquals($drawing->getWidth(), 150);
|
||||||
|
self::assertEquals($drawing->getHeight(), 150);
|
||||||
|
$comment = $sheet->getComment('A1');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '112.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '112.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_GIF);
|
||||||
|
|
||||||
|
// Add bmp image to comment background
|
||||||
|
$sheet->setCellValue('A2', '.bmp 16 colors');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Yellow Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/yellow_square_16.bmp');
|
||||||
|
self::assertEquals($drawing->getWidth(), 70);
|
||||||
|
self::assertEquals($drawing->getHeight(), 70);
|
||||||
|
$comment = $sheet->getComment('A2');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_BMP);
|
||||||
|
|
||||||
|
// Write file
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$tempFileName = File::sysGetTempDir() . '/drawings_in_comments_conversions.xlsx';
|
||||||
|
$writer->save($tempFileName);
|
||||||
|
|
||||||
|
// Read new file
|
||||||
|
$reloadedSpreadsheet = $reader->load($tempFileName);
|
||||||
|
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
// Check first image in comment background
|
||||||
|
$comment = $sheet->getComment('A1');
|
||||||
|
self::assertEquals($comment->getWidth(), '112.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '112.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 150);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 150);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Check second image in comment background
|
||||||
|
$comment = $sheet->getComment('A2');
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
unlink($tempFileName);
|
||||||
|
self::assertNotNull($reloadedSpreadsheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test build and save XLSX with drawings in comments with comment size correction.
|
||||||
|
*/
|
||||||
|
public function testBuildWithDifferentImageFormats(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
// Add png image to comment background
|
||||||
|
$sheet->setCellValue('A1', '.png');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Blue Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/blue_square.png');
|
||||||
|
self::assertEquals($drawing->getWidth(), 100);
|
||||||
|
self::assertEquals($drawing->getHeight(), 100);
|
||||||
|
$comment = $sheet->getComment('A1');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '75pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '75pt');
|
||||||
|
|
||||||
|
$comment = $sheet->getComment('A1');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Add gif image to comment background
|
||||||
|
$sheet->setCellValue('A2', '.gif');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Green Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/green_square.gif');
|
||||||
|
self::assertEquals($drawing->getWidth(), 150);
|
||||||
|
self::assertEquals($drawing->getHeight(), 150);
|
||||||
|
$comment = $sheet->getComment('A2');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '112.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '112.5pt');
|
||||||
|
|
||||||
|
$comment = $sheet->getComment('A2');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_GIF);
|
||||||
|
|
||||||
|
// Add jpeg image to comment background
|
||||||
|
$sheet->setCellValue('A3', '.jpeg');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Red Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/red_square.jpeg');
|
||||||
|
self::assertEquals($drawing->getWidth(), 50);
|
||||||
|
self::assertEquals($drawing->getHeight(), 50);
|
||||||
|
$comment = $sheet->getComment('A3');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '37.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '37.5pt');
|
||||||
|
|
||||||
|
$comment = $sheet->getComment('A3');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_JPEG);
|
||||||
|
|
||||||
|
// Add bmp image to comment background
|
||||||
|
$sheet->setCellValue('A4', '.bmp 16 colors');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Yellow Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/yellow_square_16.bmp');
|
||||||
|
self::assertEquals($drawing->getWidth(), 70);
|
||||||
|
self::assertEquals($drawing->getHeight(), 70);
|
||||||
|
$comment = $sheet->getComment('A4');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
|
||||||
|
$comment = $sheet->getComment('A4');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_BMP);
|
||||||
|
|
||||||
|
// Add bmp image to comment background
|
||||||
|
$sheet->setCellValue('A5', '.bmp 256 colors');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Brown Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/brown_square_256.bmp');
|
||||||
|
self::assertEquals($drawing->getWidth(), 70);
|
||||||
|
self::assertEquals($drawing->getHeight(), 70);
|
||||||
|
$comment = $sheet->getComment('A5');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
|
||||||
|
$comment = $sheet->getComment('A5');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_BMP);
|
||||||
|
|
||||||
|
// Add bmp image to comment background
|
||||||
|
$sheet->setCellValue('A6', '.bmp 24 bit');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Orange Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/orange_square_24_bit.bmp');
|
||||||
|
self::assertEquals($drawing->getWidth(), 70);
|
||||||
|
self::assertEquals($drawing->getHeight(), 70);
|
||||||
|
$comment = $sheet->getComment('A6');
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
$comment->setSizeAsBackgroundImage();
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
|
||||||
|
$comment = $sheet->getComment('A6');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_BMP);
|
||||||
|
|
||||||
|
// Add unsupported tiff image to comment background
|
||||||
|
$sheet->setCellValue('A7', '.tiff');
|
||||||
|
$drawing = new Drawing();
|
||||||
|
$drawing->setName('Purple Square');
|
||||||
|
$drawing->setPath('tests/data/Writer/XLSX/purple_square.tiff');
|
||||||
|
$comment = $sheet->getComment('A7');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertFalse($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_UNKNOWN);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$comment->setBackgroundImage($drawing);
|
||||||
|
self::fail('Should throw exception when attempting to add tiff');
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
self::assertTrue($e instanceof PhpSpreadsheetException);
|
||||||
|
self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$drawing->getImageTypeForSave();
|
||||||
|
self::fail('Should throw exception when attempting to get image type for tiff');
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
self::assertTrue($e instanceof PhpSpreadsheetException);
|
||||||
|
self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$drawing->getImageFileExtensionForSave();
|
||||||
|
self::fail('Should throw exception when attempting to get image file extention for tiff');
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
self::assertTrue($e instanceof PhpSpreadsheetException);
|
||||||
|
self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$drawing->getImageMimeType();
|
||||||
|
self::fail('Should throw exception when attempting to get image mime type for tiff');
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
self::assertTrue($e instanceof PhpSpreadsheetException);
|
||||||
|
self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write file
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$tempFileName = File::sysGetTempDir() . '/drawings_in_comments.xlsx';
|
||||||
|
$writer->save($tempFileName);
|
||||||
|
|
||||||
|
// Read new file
|
||||||
|
$reloadedSpreadsheet = $reader->load($tempFileName);
|
||||||
|
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
// Check first image in comment background
|
||||||
|
$comment = $sheet->getComment('A1');
|
||||||
|
self::assertEquals($comment->getWidth(), '75pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '75pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 100);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 100);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Check second image in comment background
|
||||||
|
$comment = $sheet->getComment('A2');
|
||||||
|
self::assertEquals($comment->getWidth(), '112.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '112.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 150);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 150);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Check third image in comment background
|
||||||
|
$comment = $sheet->getComment('A3');
|
||||||
|
self::assertEquals($comment->getWidth(), '37.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '37.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 50);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 50);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_JPEG);
|
||||||
|
|
||||||
|
// Check fourth image in comment background
|
||||||
|
$comment = $sheet->getComment('A4');
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Check fifth image in comment background
|
||||||
|
$comment = $sheet->getComment('A5');
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Check sixth image in comment background
|
||||||
|
$comment = $sheet->getComment('A6');
|
||||||
|
self::assertEquals($comment->getWidth(), '52.5pt');
|
||||||
|
self::assertEquals($comment->getHeight(), '52.5pt');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertTrue($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 70);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||||
|
|
||||||
|
// Check seventh image in comment background
|
||||||
|
$comment = $sheet->getComment('A7');
|
||||||
|
self::assertTrue($comment instanceof Comment);
|
||||||
|
self::assertFalse($comment->hasBackgroundImage());
|
||||||
|
self::assertTrue($comment->getBackgroundImage() instanceof Drawing);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getWidth(), 0);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getHeight(), 0);
|
||||||
|
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_UNKNOWN);
|
||||||
|
|
||||||
|
unlink($tempFileName);
|
||||||
|
|
||||||
|
self::assertNotNull($reloadedSpreadsheet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 719 B |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |