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

Xlsx image background in comments #1547 #2422

Merged
merged 11 commits into from
Dec 17, 2021
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- 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

Expand Down
22 changes: 20 additions & 2 deletions docs/references/features-cross-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,7 @@
<td></td>
</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: green;">✔</td>
<td style="text-align: center; color: red;">✖</td>
Expand All @@ -1273,7 +1273,7 @@
<td></td>
</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;">✖</td>
<td style="text-align: center; color: red;">✖</td>
Expand All @@ -1290,6 +1290,24 @@
<td></td>
<td></td>
</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>
<td><strong>Cell Validation</strong></td>
<td style="text-align: center; color: green;">✔</td>
Expand Down
Binary file added docs/topics/images/08-cell-comment-with-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 18 additions & 1 deletion docs/topics/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -957,9 +957,26 @@ $spreadsheet->getActiveSheet()
->getComment('E11')
->getText()->createTextRun('Total amount on the current invoice, excluding VAT.');
```

![08-cell-comment.png](./images/08-cell-comment.png)

## 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();
```
![08-cell-comment-with-image.png](./images/08-cell-comment-with-image.png)

## Apply autofilter to a range of cells

To apply an autofilter to a range of cells, use the following code:
Expand Down
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6045,11 +6045,6 @@ parameters:
count: 1
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\\.$#"
count: 1
Expand Down
60 changes: 60 additions & 0 deletions src/PhpSpreadsheet/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace PhpOffice\PhpSpreadsheet;

use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
use PhpOffice\PhpSpreadsheet\Helper\Size;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

class Comment implements IComparable
{
Expand Down Expand Up @@ -72,6 +75,13 @@ class Comment implements IComparable
*/
private $alignment;

/**
* Background image in comment.
*
* @var Drawing
*/
private $backgroundImage;

/**
* Create a new Comment.
*/
Expand All @@ -82,6 +92,7 @@ public function __construct()
$this->text = new RichText();
$this->fillColor = new Color('FFFFFFE1');
$this->alignment = Alignment::HORIZONTAL_GENERAL;
$this->backgroundImage = new Drawing();
}

/**
Expand Down Expand Up @@ -273,6 +284,7 @@ public function getHashCode(): string
($this->visible ? 1 : 0) .
$this->fillColor->getHashCode() .
$this->alignment .
($this->hasBackgroundImage() ? $this->backgroundImage->getHashCode() : '') .
__CLASS__
);
}
Expand All @@ -299,4 +311,52 @@ public function __toString(): string
{
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;
}
}
44 changes: 44 additions & 0 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,19 @@ public function load(string $filename, int $flags = 0): Spreadsheet
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');
foreach ($shapes as $shape) {
$shape->registerXPathNamespace('v', Namespaces::URN_VML);
Expand All @@ -993,6 +1006,8 @@ public function load(string $filename, int $flags = 0): Spreadsheet
$fillColor = strtoupper(substr((string) $shape['fillcolor'], 1));
$column = null;
$row = null;
$fillImageRelId = null;
$fillImageTitle = '';

$clientData = $shape->xpath('.//x:ClientData');
if (is_array($clientData) && !empty($clientData)) {
Expand All @@ -1011,10 +1026,39 @@ public function load(string $filename, int $flags = 0): Spreadsheet
}
}

$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)) {
// Set comment properties
$comment = $docSheet->getCommentByColumnAndRow($column + 1, $row + 1);
$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
$styleArray = explode(';', str_replace(' ', '', $style));
Expand Down
32 changes: 32 additions & 0 deletions src/PhpSpreadsheet/Worksheet/BaseDrawing.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ class BaseDrawing implements IComparable
*/
private $hyperlink;

/**
* Image type.
*
* @var int
*/
protected $type;

/**
* Create a new BaseDrawing.
*/
Expand All @@ -123,6 +130,7 @@ public function __construct()
$this->resizeProportional = true;
$this->rotation = 0;
$this->shadow = new Drawing\Shadow();
$this->type = IMAGETYPE_UNKNOWN;

// Set image index
++self::$imageCounter;
Expand Down Expand Up @@ -526,4 +534,28 @@ public function getHyperlink()
{
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;
}
}
Loading