Skip to content
Closed
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
6 changes: 6 additions & 0 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,12 @@ public function load($pFilename)
$objDrawing->setCoordinates(Coordinate::stringFromColumnIndex(((string) $twoCellAnchor->from->col) + 1) . ($twoCellAnchor->from->row + 1));
$objDrawing->setOffsetX(Drawing::EMUToPixels($twoCellAnchor->from->colOff));
$objDrawing->setOffsetY(Drawing::EMUToPixels($twoCellAnchor->from->rowOff));

$objDrawing->setBottomRightCell(Coordinate::stringFromColumnIndex(((string) $twoCellAnchor->to->col) + 1) . ($twoCellAnchor->to->row + 1));
$objDrawing->setBottomRightOffset(Drawing::EMUToPixels($twoCellAnchor->to->colOff), Drawing::EMUToPixels($twoCellAnchor->to->rowOff));
$editAs = (string) self::getArrayItem($twoCellAnchor->attributes(), 'editAs');
$objDrawing->editAs($editAs);

$objDrawing->setResizeProportional(false);

if ($xfrm) {
Expand Down
155 changes: 148 additions & 7 deletions src/PhpSpreadsheet/Worksheet/BaseDrawing.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php
<?php /** @noinspection ReturnTypeCanBeDeclaredInspection */

namespace PhpOffice\PhpSpreadsheet\Worksheet;

Expand All @@ -8,6 +8,9 @@

class BaseDrawing implements IComparable
{
const TWO_CELL = 'twoCell';
const ONE_CELL = 'oneCell';
const ABSOLUTE = 'absolute';
/**
* Image counter.
*
Expand Down Expand Up @@ -50,12 +53,12 @@ class BaseDrawing implements IComparable
*/
protected $coordinates;

/**
* Offset X.
*
* @var int
*/
protected $offsetX;
/**
* Offset X.
*
* @var int
*/
protected $offsetX;

/**
* Offset Y.
Expand All @@ -64,6 +67,27 @@ class BaseDrawing implements IComparable
*/
protected $offsetY;


/**
* Bottom-Right Cell Position.
*
* @var string
*/
private $bottomRightCellRef;

/**
* Bottom-Right X-Offset.
*
* @var int
*/
private $bottomRightXOffset;

/**
* Bottom-Right Y-Offset.
*
* @var int
*/
private $bottomRightYOffset;
/**
* Width.
*
Expand All @@ -85,6 +109,24 @@ class BaseDrawing implements IComparable
*/
protected $resizeProportional;

/**
* Specifies how the object should be moved/resized when the rows and columns between the start and end
* anchors are resized, or when additional rows or columns are added
*
* values are: absolute, oneCell, twoCell
*
* @var string
* */
protected $editAs = self::ABSOLUTE;

/**
* Determine which kind of anchoring should be used for the drawing
*
* @var string
* */
protected $anchorMode = 'oneCell';


/**
* Rotation.
*
Expand Down Expand Up @@ -124,6 +166,9 @@ public function __construct()
$this->rotation = 0;
$this->shadow = new Drawing\Shadow();

$this->anchorMode = 'oneCell';
$this->editAs = 'oneCell';

// Set image index
++self::$imageCounter;
$this->imageIndex = self::$imageCounter;
Expand Down Expand Up @@ -534,4 +579,100 @@ public function getHyperlink()
{
return $this->hyperlink;
}

/**
* @return string
*/
public function getBottomRightCell()
{
return $this->bottomRightCellRef;
}

/**
* @param string $bottomRightCellRef
* @return BaseDrawing
*/
public function setBottomRightCell(string $bottomRightCellRef)
{
$this->bottomRightCellRef = $bottomRightCellRef;
$this->anchorMode = 'twoCell';
return $this;
}

/**
* @param string $editAs
* @return BaseDrawing
*/
public function editAs($editAs)
{
if($editAs === self::ABSOLUTE || $editAs === self::ONE_CELL || $editAs === self::TWO_CELL){
$this->editAs = $editAs;
}
return $this;
}


public function getEditAs()
{
return $this->editAs;
}

/**
* @return string
*/
public function getAnchorMode()
{
return $this->anchorMode;
}

/**
* @return int
*/
public function getBottomRightXOffset()
{
return $this->bottomRightXOffset;
}

/**
* @param int $bottomRightXOffset
* @return BaseDrawing
*/
public function setBottomRightXOffset(int $bottomRightXOffset)
{
$this->bottomRightXOffset = $bottomRightXOffset;
return $this;
}

/**
* @return int
*/
public function getBottomRightYOffset()
{
return $this->bottomRightYOffset;
}

/**
* @param int $bottomRightYOffset
* @return BaseDrawing
*/
public function setBottomRightYOffset(int $bottomRightYOffset)
{
$this->bottomRightYOffset = $bottomRightYOffset;

return $this;
}

public function setBottomRightOffset($xOffset, $yOffset)
{
if ($xOffset !== null) {
$this->setBottomRightXOffset($xOffset);
}

if ($yOffset !== null) {
$this->setBottomRightYOffset($yOffset);
}

return $this;
}

}
19 changes: 19 additions & 0 deletions src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,14 @@ public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart
public function writeDrawing(XMLWriter $objWriter, BaseDrawing $pDrawing, $pRelationId = -1, $hlinkClickId = null)
{
if ($pRelationId >= 0) {
if($pDrawing->getAnchorMode() === 'twoCell'){
// xdr:twoCellAnchor
$objWriter->startElement('xdr:twoCellAnchor');
$objWriter->writeAttribute('editAs', $pDrawing->getEditAs());
} else {
// xdr:oneCellAnchor
$objWriter->startElement('xdr:oneCellAnchor');
}
// Image location
$aCoordinates = Coordinate::coordinateFromString($pDrawing->getCoordinates());
$aCoordinates[0] = Coordinate::columnIndexFromString($aCoordinates[0]);
Expand All @@ -176,11 +182,24 @@ public function writeDrawing(XMLWriter $objWriter, BaseDrawing $pDrawing, $pRela
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetY()));
$objWriter->endElement();

if ($pDrawing->getAnchorMode() === 'twoCell'){
$aBottomRightCoordinates = Coordinate::coordinateFromString($pDrawing->getBottomRightCell());
$aBottomRightCoordinates[0] = Coordinate::columnIndexFromString($aBottomRightCoordinates[0]);
// xdr:to
$objWriter->startElement('xdr:to');
$objWriter->writeElement('xdr:col', $aBottomRightCoordinates[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getBottomRightXOffset()));
$objWriter->writeElement('xdr:row', $aBottomRightCoordinates[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getBottomRightYOffset()));
$objWriter->endElement();
} else {
// xdr:ext
$objWriter->startElement('xdr:ext');
$objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getWidth()));
$objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getHeight()));
$objWriter->endElement();
}


// xdr:pic
$objWriter->startElement('xdr:pic');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php


namespace PhpOffice\PhpSpreadsheetTests\Functional;


use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;

class DrawingImageTwoCellAnchorTest extends AbstractFunctional
{

public function testDrawingImageTwoCellAnchor()
{
$spreadsheet = new Spreadsheet();

$aSheet = $spreadsheet->getActiveSheet();

$gdImage = @imagecreatetruecolor(120, 20);
$textColor = imagecolorallocate($gdImage, 255, 255, 255);
imagestring($gdImage, 1, 5, 5, 'Created with PhpSpreadsheet', $textColor);


$listOfModes = [
BaseDrawing::TWO_CELL,
BaseDrawing::ABSOLUTE,
BaseDrawing::ONE_CELL
];

foreach ($listOfModes as $i => $mode) {
$drawing = new MemoryDrawing();
$drawing->setName('In-Memory image ' . $i);
$drawing->setDescription('In-Memory image ' . $i);

$drawing->setCoordinates('A' . ((4 * $i) + 1));
$drawing->setBottomRightCell('D' . ((4 * $i) + 4));
$drawing->editAs($mode);

$drawing->setImageResource($gdImage);
$drawing->setRenderingFunction(
MemoryDrawing::RENDERING_JPEG
);

$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT);

$drawing->setWorksheet($aSheet);
}
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');

foreach ($reloadedSpreadsheet->getActiveSheet()->getDrawingCollection() as $index => $pDrawing) {
self::assertEquals($listOfModes[$index], $pDrawing->getEditAs(), 'functional test drawing twoCellAnchor');
}
}
}
Binary file added tests/seb.xlsx
Binary file not shown.