Reading and Writing Spreadsheets with PHP

      16 Comments on Reading and Writing Spreadsheets with PHP

Breaking The Language Barrier

When it comes to playing nice with data in different formats, PHP’s pedigree is hard to beat. Not only does the language make it a breeze to deal with SQL resultsets and XML files, but it comes with extensions to deal with formats as diverse as Ogg/Vorbis audio files, ZIP archives and EXIF headers. So it should come as no surprise that PHP can also read and write Microsoft Excel spreadsheets, albeit with a little help from PEAR.

In this article, I’ll introduce you to two packages that make it surprisingly easy to hook your PHP scripts up to a Microsoft Excel spreadsheet and extract the data contained therein. I’ll also show you how to dynamically create a new spreadsheet from scratch, complete with formulae and formatting, and import data from a spreadsheet into a database. So come on it, and let’s get started!

Putting The Pieces Together

There isn’t currently a unified reader/writer package for Excel spreadsheets in PEAR, so this tutorial will make use of two separate packages:

For the latter package, you’ll also need to download and install the PEAR OLE package, from

You can install these packages manually, or using the PEAR installer, as below:

I should mention at this point certain changes you might need to make to your development environment in order to get the PHP-ExcelReader package working. As noted above, this package is currently not maintained and so, simply include()-ing the main class file, ‘reader.php’, in your script, as suggested in the package documentation, is insufficient and generates a ‘missing file’ error.

To get things working, extract the file ‘’ from the distribution archive and save it to a location in your PHP include path using the directory structure ‘Spreadsheet/Excel/Reader/OLERead.php’. Once you do this, the error should disappear and things should begin working normally. There’s a caveat, though: this procedure works with the version of PHP-ExcelReader dated Jul 5 2007 (the most current version at the time of writing) but may not work with other versions.

The Number Game

Now that you have all the pieces installed, let’s see them in action. Assume for a moment that you have the following Excel spreadsheet:

Now, let’s put together a simple PHP script that reads this spreadsheet and displays the number of worksheets, rows and columns in it:

Here’s the output:

How did this happen? It’s actually not very difficult, because PHP-ExcelReader does most of the heavy lifting for you. The first step is to include the package file and instantiate a new Spreadsheet_Excel_Reader object. This object exposes a read() method, which accepts the name and path to the source Excel spreadsheet as input argument and then goes to work reading the spreadsheet data and converting it into PHP-readable data structures.

Every Excel spreadsheet file contains one or more worksheets; these worksheets are now represented in the Spreadsheet_Excel_Reader’s ‘sheets’ property, as array elements indexed from 0. As a result, worksheet 1 may be accessed using the notation $obj->sheets[0], worksheet 2 as $obj->sheets[1], and so on.

For each worksheet, PHP-ExcelReader also creates some special array keys with sheet-level information – for example, the ‘numRows’ key holds the number of rows in the worksheet, while the ‘numCols’ holds the number of columns. The script above merely uses this information to iterate over the array of worksheets and print the number of rows and columns in each.

Off The Grid

Now, while this is interesting, it’s not really all that useful – after all, what you’re really after is the data within the spreadsheet. PHP-ExcelReader has you covered there too: the cells of each worksheet are nested inside the corresponding worksheet array, and are accessible via the ‘cells’ array key. An individual cell is accessed using its row and column coordinates – for example, the cell at row 5 and column C would be accessed using the notation $obj->sheets[0][‘cells’][5][3]. Row and column indexing starts from 1.

With this in mind, consider the next PHP script, which uses the PHP-ExcelReader to represent the example spreadsheet as an HTML table:

It’s now a simple task to represent the data from a worksheet as an HTML table. All that’s needed are two loops, one iterating over the rows and the other iterating over the columns in each row, and a little bit of PHP code to access the value of the cell at their point of intersection. That’s precisely what the script above does, together with some CSS code to render the table neatly.

Here’s what the output looks like:

Interestingly, if your spreadsheet cells contain formulae, PHP-ExcelReader will return the final result of the formulae as the corresponding cell value (instead of the raw formula string). However, when it comes to cell formatting, PHP-ExcelReader returns the raw value of each cell, rather than the formatted cell value. To illustrate both these facts, let’s revise the spreadsheet so it contains both formulae and formatting:

And now, when you re-run the previous script, you should see something like this:

Turning The Tables

With the power of PHP-ExcelReader at your command, it’s also quite easy to transfer data from a spreadsheet into a database, so that you can run queries on it. Consider the following script, which illustrates the process by bringing together PHP-ExcelReader, PDO and prepared statements to read data from a spreadsheet and INSERT it into a MySQL table:

Given the following spreadsheet,

the script above will read the data in the spreadsheet and save each spreadsheet row as a record in the named MySQL table. It begins by reading the spreadsheet into a Spreadsheet_Excel_Reader object, and then opening a PDO connection to the MySQL database. It then prepares an INSERT statement with $pdo->prepare() and then iterates over the spreadsheet rows (skipping the first row, which is the table header row), binding the values in each row to the prepared statement before executing it. This process continues until all the rows in the spreadsheet are processed.

At the end of the process, you should see the data safely transferred to your MySQL table:

There’s one key thing to remember when performing this kind of spreadsheet-to-database conversion: your spreadsheet data must be correctly and consistently structured, with all the values lining up neatly, or else your table fields will end up with missing or incorrect values. So it’s a good idea to visually check the source spreadsheet for consistency once before reading it into an SQL database.

Back To Class

So that takes care of reading Excel spreadsheets. Now, how about writing them?

Well, with PEAR’s Spreadsheet_Excel_Writer package, this is actually a piece of cake. Consider the following script, which illustrates the process:

There’s a fairly standard sequence of actions to follow when creating a new Excel spreadsheet. First, include the class file and initialize an object of the Spreadsheet_Excel_Writer class, passing the name and path of the output spreadsheet file to the object constructor. Once you’ve got your empty spreadsheet initialized, add a new, empty worksheet to it with the object’s addWorksheet() method; pass the worksheet name to the method as an additional argument.

At this point, your spreadsheet is ready for some data. Inserting data is a task for the write() method, which accepts three arguments: the row number, the column number and the value to be inserted. Row and column indexing starts from 0. So, for example, to write the value ‘Hello’ to the cell at row 4 and column F, you’d call $obj->write(3,5,’Hello’).

In the previous example, a loop iterates over the array of source data, using write() to add each element to the spreadsheet as a cell. Once you’ve finished writing data to the spreadsheet, the close() method wraps things up and saves the output file to disk. You can now read this spreadsheet in Microsoft Excel – open it up, and you’ll see something like this:

If, instead of writing the output file to disk, you’d prefer to have it sent directly to the user’s browser, Spreadsheet_Excel_Writer has you covered there too! To do this, call the Spreadsheet_Excel_Writer’s send() method with the output file name instead of passing it to the object constructor, as in the following revision of the previous example:

The send() method sends the client browser headers that identify the data that follows as a spreadsheet. The browser should then offer the user a choice to view the spreadsheet directly in Microsoft Excel, or save the file to disk.

The Secret Formula

Why stop with just values? It’s easy to create cells containing formulae as well – simply call the writeFormula() method with the row and column coordinates of the target cell and the formula to be inserted into that cell. As per normal Excel operation, formulae must be preceded with an equality symbol (=). Consider the following revision of the previous example, which averages the grades of each student across the three subjects:

Here, Excel’s AVERAGE() formula is used to calculate the average grade of each student, by dynamically generating the formula string and placing it at the end of each row of grades. Notice the script’s use of the rowcolToCell() static method, which accepts a row and column number and returns an Excel-compliant alphanumeric grid identifier corresponding to that cell.

Here’s what the output looks like:

In addition to the writeFormula() method, the Spreadsheet_Excel_Writer also comes with writeNote() and writeUrl() methods, which come in handy to attach notes or hyperlinks to a cell. The following example illustrates both these in action:

Looking Pretty

Spreadsheet_Excel_Writer also offers a large number of methods to format your spreadsheet cells and make them look pretty. There are two steps to using formats: first, define a new format with the addFormat() method and then, apply the format to a cell by specifying it as an additional argument to the write() method.

The following example illustrates the process:

This example defines five different formats: $firstRow, which has red text and a bottom border; $firstCol, which has blue text and a right border; $firstRowCol, which has both a right and bottom border; $num, which formats numbers as integer values; and $avg, which formats numbers as decimal values. Each of these formats is created by calling the Spreadsheet_Excel_Writer’s addFormat() method to create a new Format object, and then calling methods of this Format object to set various formatting attributes such as color, size and weight.

So, for example, the Format object’s setColor() method sets the text color for the format, while the setBorderColor() method sets the border color. Similarly, there’s a setSize() method to set text size, a setAlign() method to set the text alignment, a setTextWrap() method to define text wrapping, and a setNumFormat() method to define how numeric values are formatted. Some of these methods are used in the previous example.

Once the various Format objects are defined, all that’s left is to apply them to the relevant cells. This is accomplished by using the relevant object when invoking the write() method. Thus, in the script above, all subject names (the first row) are formatted using $firstRow, all student names (the first column) are formatted using $firstCol, and all grades (the table content) are formatted using $num.

Here’s what the output looks like:

It should be noted that the Format object exposes many more formatting methods than the few shown in the previous example. To obtain a complete list, look in the documentation for the Spreadsheet_Excel_Writer package, at; there’s also an excellent tutorial on formatting there that you’ll undoubtedly find useful!

Around The World In 80 Rows

Earlier on in this article, I showed you how to read data from an Excel spreadsheet and transfer it to an SQL database. Now it’s time to do the reverse: transform an SQL result set into an Excel spreadsheet. In the following example, I’ll use the MySQL example ‘world’ database, and turn all the records from the ‘country’ table into rows of an Excel spreadsheet. Take a look at the code:

If you’ve been following along, there shouldn’t be any major surprises here. The script begins by initializing a new spreadsheet and attaching a blank worksheet to it. It then opens a PDO connection to the ‘world’ database and executes a SELECT query to return all the records from the ‘country’ table.

Having obtained a result set, the script then begins building the spreadsheet. First, it creates the header row by retrieving a list of all the fields in the result set, obtaining each field’s name, and writing this to the spreadsheet as the first row. Then, it iterates over the result set, writing the contents of each record to the spreadsheet as a new row. This continues until the entire result set is processed, at which time the spreadsheet file is closed and sent to the user’s browser.

If you look inside the resulting output file, here’s a snippet of what you should see:

And that’s about it for this article. Over the last few pages, I showed you how to read spreadsheet data and insert it into an SQL database, dynamically create a new spreadsheet, attach formulae, formatting, notes and hyperlinks to spreadsheet cells, and re-render SQL records in spreadsheet format. You probably wouldn’t have thought all of this possible using just PHP code…but it is, and it isn’t even very difficult.

I hope you enjoyed this tutorial, and that it will save you some time the next time you sit down to work with spreadsheet data and PHP. Happy coding!

Copyright Melonfire 2008. All rights reserved.