Export Zen Cart orders to OpenOffice in 1 click

You are welcome to extract excerpt of this article, but do not copy it entirely on your blog/web site.
You are only allowed to use this post content in an printed article or a newsletter by clearly exposing the source URL of this article.

Synopsis

In this article, I'm going to explain you how integrate the OpenOffice with Zen Cart, to generate ODT files on the fly from your web server.

This article only gives you directions on how to achieve this. Every Zen cart is specific, and too many payment plugins make it just too much to have something portable for everything.
But if someone wants to realize it, (s)he is welcome...

For this, you will need:

The problem

So, let say you operate an Zen Cart shop. If you do this as I do, you probably run it in your free time, next to a regular day job.
If you ship "hard" merchandises, you certainly want to include an order invoice with your command. I sure do, even if it's just for me, to double check the order...
Now, if the official layout suites you, perfect, but in my case, I wanted something more precise, and to be able to have something more personalized without messing the cart file.

I always had used the web interface, and made a bunch of copy/paste to OpenOffice until now, but the increasing number of orders just make this not viable any more.
Spending 10 minutes to create the invoice and print it was just too much. I had to find another way.
Sure, there are contributions out there that allows you to customize those orders, but they all have their weak spots, and none contented me.

The idea

And one day I thought: "OpenOffice uses XML to store it's files, so it should be fairly easy to generate an OpenOffice file..."
And yes, it IS easy, as long as a bit of work don't frightens you...

For starter, let talk about the OpenOffice writer file format: ODT, for Open Document Text.
An ODT file is nothing more than an XML (content.xml) file, accompanied by several files and a snapshot of a document, zipped in 1 file.
As you may not know, XML is a way of describing datas in a logic way, based on parent/child relations.
HTML is a subset of XML, so if you read this, you should at least have an idea.

A bit of explaination about XML

Alongside with XML, there is a real nifty technology called XSLT, for eXtended StyLesheet Transformations.
In short, it allows you to merge XML datas into a style sheet, and get another file at the end of the chain.
The outputted file could be HTML, XML again (but in another format), PDF, XLS....

We are going to leverage this process via PHP XSLT engine to generate our ODT file.
That way, all we need is a XML representation of our order, the XSL style sheet to transform it, and the PHP XSL engine.

And now, we get dirty

So, to summarize, we need 2 files:

  1. An XML representation of our order.
  2. An XSL style sheet to transform this XML into an ODT file.

Now let's proceed to the first point....

We generate our order's XML

If you never generated XML before, it may look scary, but really it's not.
As XML is just a text file formatted in a specific way, all we are going to do is create a string.

First, we need to fetch the datas of our order. No need to re-design the wheel, the file located in admin/order.php does already that.

To avoid our XML generating file to be overwritten in an update, we are going to copy it to odt.php.
I had no time digging into the file structure. Zen cart (and OsCommerce) have a code that is just so unreadable that I didn't even wanted to.
What I've done was simply to located the beginning of HTML in the file, and replace it by the XML output of the order.

There is just 1 catch; the character "&" needs to be escaped in XML, because it represents the start of an entity, just like in html. Others characters that may need to be checked are accentuated characters. You may want to convert them back to their literal values.

Just a side note here: I may not have replicated every parts of an order. Especially when it comes to the delivery/payment plugins. As I just use paypal and pay on delivery, I totally neglected the other payment methods

You can see here an example of the XML outputted by odt.php.

We now create our XSL style sheet...

Our style sheet will be an ODT document, with some specific command inserted into it to retrieve datas from the XML.
To create it, simply open OpenOffice Writer, and create an empty invoice the way you want it to be. I recommend you to place self descriptive enough catch words at the places you want to place datas from the XML, as we will need to do a bit of search and replace there.
Once it's done, save it and quit OpenOffice.

Now, unzip your odt file into a directory with 7Zip in a safe place and locate content.xml. This is the file that we need to edit. Now, the file has no indentation, and may be hard to read. If you don't have a « pretty print » option in your text editor, open this file with firefox or Internet Explorer, and copy/paste from the browser window. They will re-indent the file correctly.
Keep this directory at hand, we will need it again..

So, that's it. We now have our file, and we are ready to place XSL command in it to replace our catch phrases by the XML datas. If you are not used to XSL syntax, I recommend you to take a look at the zvon XSLT tutorial and reference. It's a good start point.
I've uploaded my XSL style sheet, so you can look at it too, and inspire yourself from it.

You can test your XSL style sheet without using your web site. There are numerous tools that exists for that, but I'll recommend you the cooktop XML editor.
A small free editor that allows you to edit and format XML and XSL, and to apply the transformation on the fly.

We have the XML and the XSL, now we transform it

Ok, so you now have your XML, and your XSL files.

First, you need to locate the directory where you unzipped your order template. Copy it, as we are going to replace the content.xml file with the generated XML.

Apply the transformation between the XML file and your XL style sheet, and save it into the content.xml. Cooktop use the key F5 to do apply the transformation.

After replacing content.xml, re-zip the directory, giving the new archive a .odt extension.
Now, simply try to open it with OpenOffice, and if everything went well, you should have your order into your ODT file.

Tweak your order template, re-apply the XSL command in it and re-zip the content.xml to test subsequent modifications.
Once you are satisfied with your result, we are going to install it into your web site.

Going live

For this part, you need to upload the odt.php and your XSL style sheet into the admin directory of your shop.
Use any FTP software you use usually for that task.

The PHP code below is the one I used in my odt.php to apply the transformation. It's just an excerpt of the final file. To see all of it, take a look on odt.phps.

//We initialize the XSLT engine
$xsl = new XSLTProcessor();
//And create a DOM document element.
$doc = new DOMDocument();
//I load the XSL style sheet into the DOM document
$doc->load('order.xsl');
//And indicate the XSLT engine to use this DOM representation of my file.
$xsl->importStyleSheet($doc);
//$xml contains my order XML. I import it as a DOM document
$doc->loadXML($xml);
//And we transform it via the XSL engine
$xml=$xsl->transformToXML($doc);
//The resulting XML is saved into a unzipped ODT content.xml
file_put_contents("odt/content.xml", $xml);
//If there is a file named “order.odt”, it is deleted
@unlink('order.odt');
//And we re-zip the odt file as order.odt
$createOdt="cd odt;zip -r ../order.odt *";
$out=shell_exec($createOdt);
//Redirect the browser to the generated ODT,
//to trigger the download/opening of the file
header("location:order.odt");
die();

The process is really simple. Now, all that we need is to define a way to call this odt.php script from our regular order.
For that, I've simply edited the regular orders.php, and added a link just under the "go back" button, that will point to the odt.php page.

he back button can be located if you look for this text:
zen_image_button('button_back.gif', IMAGE_BACK);

This is the code I placed into order.php, right after the previously located line:
<br/>
<?php
echo "<a href=\"odt.php?{$_SERVER['QUERY_STRING']}\">Generate OpenOffice order</a>";
php>

Now, save orders.php, and display an order like usually. You should now have a "generate OpenOffice order" link on the top left of the order area.
The generate OpenOffice link

Try to click on it, and if everything goes like it should, your browser should offer you to open or download an file named "order.odt"
The opening file dialog in Firefox

Conclusion

Here we are... Now, you created your very own OpenOffice layout, and you can import your order in it with just 1 click. Print it, generate a PDF out of it, do what you want, but no more need to re-format your document after a copy paste.

Goal reached !

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically each day to your feed reader.

Trackbacks & Pingbacks

No trackbacks/pingbacks yet.

Comments

I strongly recommend you to lose that screenshot plugin because it creates lotsa PHP errors. More, it’s damn annoying.

PHP errors ?
I haven’t seen anyone. I’ve seen a javascript error in internet explorer, but that is related to wordpress, not this snapshot service

Beside, I must say it’s a service I run myself (http://www.web-screenshots.com), and I think it adds something.
And really, it’s effective only on links, and it’s not THAT intrusive.

In your odt.php file, you could delete these 2 lines:
require(DIR_WS_CLASSES . 'currencies.php');
$currencies = new currencies();

and then delete the large block of code after this line:
include(DIR_WS_CLASSES . 'order.php');

… up until your section that begins like this:
/**
* Handle XML output
*
*/

All you really need to do to accomplish the same end result is to load application_top and the order class. Your code does all the rest.
You might want to build in some error checking to be sure that it has a valid order ID in the $_GET parameters just for safe-keeping as an enhancement.

Thanks DrByte,
I’ll make those modifications later.
What I explain here is really a quick hack that I put together in 3 hours, an evening I could not find sleep, so it’s sure up for improvement.

I just thought it could/would be interesting to other zen-cart users.

Tripy.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(required)

(required)