Creating Powerpoint files with PHP

If you’re looking to create Powerpoint files using PHP there’s a good chance you’ll end up using the PHPPowerPoint library. Having just spent a few days converting a complex PDF report to PPTX format using this library, I learned a few things that I thought I should share with the world.

Getting Started

Once you’ve downloaded and unpacked the zip file, you will probably might need to:

  1. Rename the PHPPowerpoint folder to PHPPowerPoint
  2. Rename the PHPPowerpoint.php file to PHPPowerPoint.php

If you are running on a machine that has a case-insensitive file system and you don’t rename the above files, you will have trouble with the require_once() statements.

[EDIT 24/Oct/2013] I was just comparing the "latest" version of the library that is in CodePlex with the copy I had and the version online already had these corrections made. This is strange, because I’m 99.9% sure that I downloaded my version from CodePlex in 2012 and according to CodePlex (and the notes in Github), the code hasn’t been changed since 2010. Strange.

Positioning System

After some experimentation I figured out that PHPPowerPoint creates slides in Powerpoint’s default size, which is “4:3 Screen Layout”. The actual positioning system is as follows:

  1. 0,0 is top left corner
  2. 959, 719 is bottom right corner
  3. Total size is 960 x 720

Interestingly, I did find some slight alignment issues when adding images that went all the way from one edge to the other. Depending on the image, sometimes they would appear slightly too wide or slightly too narrow. Other images would end up perfectly aligned. Weird.

Functionality

With PHPPowerPoint you can do the following things:

  1. Create a new PHPPowerPoint object (which, by default, will already contain one slide)
  2. Add and delete slides
  3. Add shapes to slides
  4. Save the whole lot as a PPTX file

Unfortunately you cannot read in an existing PPTX file and modify it.

Shapes

Although the Powerpoint application supports a large range of shapes, PHPPowerPoint supports only two (but they are two pretty important ones!):

  1. Drawing Shapes - You can create drawing shapes in memory using GD library and add them to a slide or you can add an image from disk.
  2. Text Shapes - You can set the font name, size, colour and the horizontal/vertical alignment when writing text. You can also set the size of the box that the text is being placed in, which makes it easy, for example, to write text in the center of the page.

You can obviously control the size and placement of both kinds of shapes and you can add a shadow effect as well. The test scripts included with the library are very helpful and provide examples of everything that can be done with the library.

Order of Operations Gotcha

[EDIT 24/Oct/2013] See earlier comment about versions. I just tested with the version from Github, which is apparently an identical copy of the version on CodePlex (the latter being the "master" copy), and the problem I describe below does NOT occur.

I’m not sure why this happens, but if you add any drawing objects to a slide after you’ve added text objects, the resulting PPTX file will not open in Powerpoint. I tested this by swapping the order in which the text and drawing objects are added to the slide in the 01simple.php example script and the resulting file failed to open on Powerpoint 2003 and 2007 for Windows and Powerpoint 2008 for Mac.

Depending on your situation, this constraint may or may not be an issue. In my case, I was planning to write a wrapper around PHPPowerPoint and pass the resulting object into an class that expects a generic “renderer” object. However, the object using the renderer was obviously not written with this constraint in mind and assumed it could add any kind of shape in any order, so this constraint was a huge limitation for me. Thankfully, it wasn’t too hard to fix. Although there may have been a more “correct” way to resolve this issue, in the interest of getting something working quickly, I came up with a very low impact change that fixed it.

Each instance of the Slide class uses an ArrayObject called _slideCollection to store the objects that have been added to the slide. When the save() method is called, each Slide object iterates through its _shapeCollection from start to finish, writing the appropriate XML to the output file. So to solve the problem I needed to ensure that each _shapeCollection was sorted such that all drawing objects came before all text objects. Rather than doing the sort at the time save() was called, I opted to sort the shapes as they were added.

In order to achieve this, I added the following code to the top of the Slide.php:

class CustomArrayObject extends ArrayObject
{
    private $images = 0;
    private $others = 1000;

    public function append( $thing )
    {
        if ( $thing instanceof PHPPowerPoint_Shape_Drawing ||
         $thing instanceof PHPPowerPoint_Shape_MemoryDrawing )
        {
            $this->offsetSet( $this->images++, $thing );
        }
        else
        {
            $this->offsetSet( $this->others++, $thing );
        }

        $this->ksort();
    }
}

Then I simply changed the following line in the Slide constructor:

From this:

    	$this->_shapeCollection = new ArrayObject();

To this:

    	$this->_shapeCollection = new CustomArrayObject();

And voila! Shapes can now be added to a slide in any order and the resulting PPTX file will still open successfully.

Yes, it’s a hack. But as I mentioned earlier, it was the fastest (to code), least intrusive solution that I could come up with quickly. If you have any other hints to using PHPPowerPoint, feel free to pop a comment below.

Yet Another Programming Blog

Where James Gordon rambles about PHP, Laravel and web development in general.

Find me on Google Plus Find me on Twitter Find me on Stack Exchange Find me on Github Subscribe