Skip to content

Commit

Permalink
Add two cell anhor drawing.
Browse files Browse the repository at this point in the history
  • Loading branch information
naotake51 committed Jan 26, 2022
1 parent e7b0497 commit 10d5664
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 19 deletions.
9 changes: 7 additions & 2 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -7200,6 +7200,11 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Writer/Xlsx/DocProps.php

-
message: "#^Parameter \\#1 \\$coordinates of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:indexesFromString\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php

-
message: "#^Parameter \\#1 \\$index of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:getChartByIndex\\(\\) expects string, int given\\.$#"
count: 1
Expand All @@ -7212,12 +7217,12 @@ parameters:

-
message: "#^Parameter \\#2 \\$content of method XMLWriter\\:\\:writeElement\\(\\) expects string\\|null, int given\\.$#"
count: 12
count: 20
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php

-
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#"
count: 8
count: 10
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php

-
Expand Down
6 changes: 6 additions & 0 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,12 @@ public function load(string $filename, int $flags = 0): Spreadsheet

$objDrawing->setOffsetX(Drawing::EMUToPixels($twoCellAnchor->from->colOff));
$objDrawing->setOffsetY(Drawing::EMUToPixels($twoCellAnchor->from->rowOff));

$objDrawing->setCoordinates2(Coordinate::stringFromColumnIndex(((int) $twoCellAnchor->to->col) + 1) . ($twoCellAnchor->to->row + 1));

$objDrawing->setOffsetX2(Drawing::EMUToPixels($twoCellAnchor->to->colOff));
$objDrawing->setOffsetY2(Drawing::EMUToPixels($twoCellAnchor->to->rowOff));

$objDrawing->setResizeProportional(false);

if ($xfrm) {
Expand Down
99 changes: 99 additions & 0 deletions src/PhpSpreadsheet/Worksheet/BaseDrawing.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,27 @@ class BaseDrawing implements IComparable
*/
protected $offsetY;

/**
* Coordinates2.
*
* @var null|string
*/
protected $coordinates2;

/**
* Offset X2.
*
* @var int
*/
protected $offsetX2;

/**
* Offset Y2.
*
* @var int
*/
protected $offsetY2;

/**
* Width.
*
Expand Down Expand Up @@ -125,6 +146,9 @@ public function __construct()
$this->coordinates = 'A1';
$this->offsetX = 0;
$this->offsetY = 0;
$this->coordinates2 = null;
$this->offsetX2 = 0;
$this->offsetY2 = 0;
$this->width = 0;
$this->height = 0;
$this->resizeProportional = true;
Expand Down Expand Up @@ -301,6 +325,78 @@ public function getOffsetY()
return $this->offsetY;
}

/**
* Get Coordinates2.
*
* @return null|string
*/
public function getCoordinates2()
{
return $this->coordinates2;
}

/**
* Set Coordinates2.
*
* @param null|string $coordinates2 eg: 'A1'
*
* @return $this
*/
public function setCoordinates2($coordinates2)
{
$this->coordinates2 = $coordinates2;

return $this;
}

/**
* Get OffsetX2.
*
* @return int
*/
public function getOffsetX2()
{
return $this->offsetX2;
}

/**
* Set OffsetX2.
*
* @param int $offsetX2
*
* @return $this
*/
public function setOffsetX2($offsetX2)
{
$this->offsetX2 = $offsetX2;

return $this;
}

/**
* Get OffsetY2.
*
* @return int
*/
public function getOffsetY2()
{
return $this->offsetY2;
}

/**
* Set OffsetY2.
*
* @param int $offsetY2
*
* @return $this
*/
public function setOffsetY2($offsetY2)
{
$this->offsetY2 = $offsetY2;

return $this;
}

/**
* Set OffsetY.
*
Expand Down Expand Up @@ -497,6 +593,9 @@ public function getHashCode()
$this->coordinates .
$this->offsetX .
$this->offsetY .
$this->coordinates2 .
$this->offsetX2 .
$this->offsetY2 .
$this->width .
$this->height .
$this->rotation .
Expand Down
65 changes: 48 additions & 17 deletions src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,24 +153,49 @@ public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart
public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relationId = -1, $hlinkClickId = null): void
{
if ($relationId >= 0) {
// xdr:oneCellAnchor
$objWriter->startElement('xdr:oneCellAnchor');
// Image location
$aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());

// xdr:from
$objWriter->startElement('xdr:from');
$objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX()));
$objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY()));
$objWriter->endElement();
$isTwoCellAnchor = $drawing->getCoordinates2() !== null;
if ($isTwoCellAnchor) {
// xdr:twoCellAnchor
$objWriter->startElement('xdr:twoCellAnchor');
// Image location
$aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
$aCoordinates2 = Coordinate::indexesFromString($drawing->getCoordinates2());

// xdr:from
$objWriter->startElement('xdr:from');
$objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX()));
$objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY()));
$objWriter->endElement();

// xdr:ext
$objWriter->startElement('xdr:ext');
$objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getWidth()));
$objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getHeight()));
$objWriter->endElement();
// xdr:to
$objWriter->startElement('xdr:to');
$objWriter->writeElement('xdr:col', $aCoordinates2[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX2()));
$objWriter->writeElement('xdr:row', $aCoordinates2[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY2()));
$objWriter->endElement();
} else {
// xdr:oneCellAnchor
$objWriter->startElement('xdr:oneCellAnchor');
// Image location
$aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());

// xdr:from
$objWriter->startElement('xdr:from');
$objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX()));
$objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY()));
$objWriter->endElement();

// xdr:ext
$objWriter->startElement('xdr:ext');
$objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getWidth()));
$objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getHeight()));
$objWriter->endElement();
}

// xdr:pic
$objWriter->startElement('xdr:pic');
Expand Down Expand Up @@ -223,6 +248,12 @@ public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relati
// a:xfrm
$objWriter->startElement('a:xfrm');
$objWriter->writeAttribute('rot', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($drawing->getRotation()));
if ($isTwoCellAnchor) {
$objWriter->startElement('a:ext');
$objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getWidth()));
$objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getHeight()));
$objWriter->endElement();
}
$objWriter->endElement();

// a:prstGeom
Expand Down
52 changes: 52 additions & 0 deletions tests/PhpSpreadsheetTests/Writer/Xlsx/DrawingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,56 @@ public function testBuildWithDifferentImageFormats(): void

self::assertNotNull($reloadedSpreadsheet);
}

/**
* Test save and load XLSX file with drawing image that coordinate is two cell anchor.
*/
public function testTwoCellAnchorDrawing(): void
{
$reader = new Xlsx();
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();

// Add gif image that coordinates is two cell anchor.
$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);
$drawing->setCoordinates('A1');
$drawing->setOffsetX(30);
$drawing->setOffsetY(10);
$drawing->setCoordinates2('E8');
$drawing->setOffsetX2(-50);
$drawing->setOffsetY2(-20);
$drawing->setWorksheet($sheet);

// Write file
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$tempFileName = File::sysGetTempDir() . '/drawings_image_that_two_cell_anchor.xlsx';
$writer->save($tempFileName);

// Read new file
$reloadedSpreadsheet = $reader->load($tempFileName);
$sheet = $reloadedSpreadsheet->getActiveSheet();

// Check image coordinates.
$drawingCollection = $sheet->getDrawingCollection();
$drawing = $drawingCollection[0];
self::assertNotNull($drawing);

self::assertEquals($drawing->getWidth(), 150);
self::assertEquals($drawing->getHeight(), 150);
self::assertEquals($drawing->getCoordinates(), 'A1');
self::assertEquals($drawing->getOffsetX(), 30);
self::assertEquals($drawing->getOffsetY(), 10);
self::assertEquals($drawing->getCoordinates2(), 'E8');
self::assertEquals($drawing->getOffsetX2(), -50);
self::assertEquals($drawing->getOffsetY2(), -20);
self::assertEquals($drawing->getWorksheet(), $sheet);

unlink($tempFileName);

self::assertNotNull($reloadedSpreadsheet);
}
}

0 comments on commit 10d5664

Please sign in to comment.