Files
oleibman cf709f3d3f Drawings for ODS
Fix #4809. This initial work for this PR was done by @xxltomcat-ux in PR #4812. That PR needed some work, and was accidentally closed in a manner that caused all its work to be lost. As compared with that version, this version corrects a write bug when Ods output is added to 27_Images_Xlsx, adds limited support for Read, and adds some tests (more are probably needed). What follows here is the original description from the closed PR.

# Summary

Currently, the ODS writer in PhpSpreadsheet does not support exporting images. Images (Drawing or MemoryDrawing objects) are completely ignored in ODS exports, though they work correctly for XLSX. This issue proposes and provides a full implementation to add support for image/drawing export in ODS, bringing feature parity with the XLSX writer.

# Problem

- ODS exports silently drop images and worksheet graphics
- This is a required feature for interoperability with LibreOffice/OpenOffice users

# Key Implementation:

- Update: Writer/Ods.php to collect/package images into the export ZIP
- Update: Writer/Ods/Content.php to integrate images into content.xml and table cells
- New: Writer/Ods/Drawing.php to manage extraction & XML for worksheet images (Drawing & MemoryDrawing)
- Update: Writer/Ods/MetaInf.php to list all Pictures/ images in the manifest
- Update: Reader/Ods.php to read drawing-related Xml and add those which meet certain criteria to spreadsheet.

# Features

- Exports all worksheet images (Drawing, MemoryDrawing)
- Embeds images in Pictures/ directory inside ODS
- Writes <draw:frame> and <draw:image> elements linked to cell positions
- Updates META-INF/manifest.xml with all images
- Handles cell/row mapping & coordinates
- Supports PNG, JPEG, GIF, BMP
2026-08-09 08:37:59 -07:00

64 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
class DrawingTest extends AbstractFunctional
{
public function testDrawing(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// Add a drawing to the worksheet
$drawing = new Drawing();
$drawing->setName('Letters B, M, and P');
$drawing->setDescription('Handwritten B, M, and P');
$drawing->setPath('samples/images/bmp.bmp');
$drawing->setWorksheet($sheet);
$drawing->setCoordinates('A1');
$drawing = new Drawing();
$drawing->setName('Letters G, I, and F');
$drawing->setDescription('Handwritten G, I, and F');
$drawing->setPath('samples/images/gif.gif');
$drawing->setWorksheet($sheet);
$drawing->setCoordinates('E5');
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Ods');
$spreadsheet->disconnectWorksheets();
$worksheet = $reloadedSpreadsheet->getActiveSheet();
$drawings = $worksheet->getDrawingCollection();
self::assertCount(2, $drawings);
$drawing = $drawings[0] ?? null;
self::assertInstanceOf(Drawing::class, $drawing);
// original width is 123, some loss of precision due to rounding
self::assertGreaterThanOrEqual(120, $drawing->getWidth());
self::assertLessThanOrEqual(126, $drawing->getWidth());
// original height is 81
self::assertGreaterThanOrEqual(78, $drawing->getHeight());
self::assertLessThanOrEqual(84, $drawing->getHeight());
self::assertSame('Letters B, M, and P', $drawing->getName());
self::assertSame('A1', $drawing->getCoordinates());
$drawing = $drawings[1] ?? null;
self::assertInstanceOf(Drawing::class, $drawing);
// original width is 163, some loss of precision due to rounding
self::assertGreaterThanOrEqual(160, $drawing->getWidth());
self::assertLessThanOrEqual(166, $drawing->getWidth());
// original height is 121
self::assertGreaterThanOrEqual(118, $drawing->getHeight());
self::assertLessThanOrEqual(124, $drawing->getHeight());
self::assertSame('Letters G, I, and F', $drawing->getName());
self::assertSame('E5', $drawing->getCoordinates());
$reloadedSpreadsheet->disconnectWorksheets();
}
}