Overview
The sfTinyDocPlugin allows to generate OpenOffice (OpenDocument) and Word 2007 documents with TinyButStrong template engine.
Prerequisite :
- PHP 5.2
- symfony framework 1.0, 1.1 and 1.2 (for the plugin)
History :
The previous class was named tbsOOo. I rewrite the class to have a clean code with new methods and add some new functionnality like :
- works with the last version of TinyButStrong
- better support of specials characters like carriage return, new line and tab
- can generate Word 2007 documents
- can add images (only OpenDocument)
- can merge data with native format in OpenOffice spreadsheet
- two methods to zip and unzip the office files (zip with command line and the pecl ZipArchive)
- and a plugin for symfony framework : sfTinyDocPlugin
The office formats supported :
- OpenOffice 1.0 or OpenDocument 1.0
- OpenOffice 2.0 or OpenDocument 1.1
- Word 2007
It's useful :
- To create word processing and spreadsheet documents.
- To create reports, bill, orders.
- To create mailing.
- To create multi pages documents.
- To use the power of the TinyButStrong template engine syntax :
- Merge fields
- Merge blocks (repetitive fields)
- and more...
It's not :
- To create an Office document from scratch.
- To convert a document from OpenOffice to Word or to PDF or else. See the project PyODConverter to do that.
Avantages :
- No installation of OpenOffice on the server side.
- Works on *nix, win and other systems.
- Templates can be created and modified easyly by designer.
- Templates layouts and styles are made with OpenOffice or Word2007 application.
- For the symfony framework
- Works with sf1.0, sf1.1 and sf1.2
- No dependance with ORM
- Template have the same location as the symfony templates.
- Template name have the same name as the symfony templates.
moduleName/templates/actionNameSuccess.odt - Get the config from app.yml.
Only for OpenDocument (OpenOffice) :
- Merge pictures dynamicaly with the new parameter named 'image'.
- Data in spreadsheet are converted to native OpenOffice format with the new parameter named 'type'.
- Useful to work with spreadsheet formulas
- Useful to work the spreadsheet formats
- Transform data to a linkable text with the new parameter named 'link'.
Limitations :
Can't merge collection of objects (iterator not supported in TinyButStrong, soon in next version), you have to transform to an array before.
- For Propel write your own method like
asArray()in the Jobeet tutorial, see day 16. - For Doctrine use the magic method :
$result->toArray (false | true)to transform the result to an array, see : doctrine api
- For Propel write your own method like
Can't change a style of the Office document by code, the styles are fix when you editing your Office document.
- Can't merge global vars
[var.xxx], use methodmergeXmlField()in place of use globals vars - Can't merge sub-block because TinyButStrong need global vars, see
headergrpsyntax
Installation
Install sfTinyDocPlugin :
$ pear channel-discover pear.symfony-project.com $ symfony plugin-install http://plugins.symfony-project.com/sfTinyDocPluginOr from the SVN repository
$ svn co http://svn.symfony-project.com/plugins/sfTinyDocPlugin/trunk/Optionally add the following config to
app.yml:[yml] all: sf_tiny_doc_plugin: zip_method: shell # the method to zip/unzip : shell | ziparchive zip_bin: zip # the binary to zip for 'shell' method unzip_bin: unzip # the binary to unzip for 'shell' method process_dir: %SF_WEB_DIR%/tmp # the process directoryClear your cache :
$ ./symfony ccConfigure the method to zip/unzip office documents :
Method 1 : shell (by default)
To install Zip on Red Hat Enterprise Linux or CentOS
$ yum install zipTo install Zip on Windows, download the zip binary and copy them onto your hard disk. It could be useful to modify your Windows global var
pathto use them without to specify the binary path.
Method 2 : ziparchive
To install Pecl ZipArchive on Red Hat Enterprise Linux or CentOS
$ yum install httpd-devel # if necessary $ pecl install zip
Create a directory where to process temporary files, by example on web root :
$ mkdir web/tmp $ chmod 777 web/tmp
My first OpenOffice text document in action (.odt)
Create a new module
docin your applicationCreate an action
basicindoc/actions/actions.class.phppublic function executeBasic(sfWebRequest $request)
{
// create the document
$doc = new sfTinyDoc();
$doc->createFrom();
$doc->loadXml('content.xml');
$doc->mergeXmlField('field1', 'variable');
$doc->mergeXmlField('field2', array('id' => 55, 'name' => 'bob'));
$doc->mergeXmlField('field3', $doc);
$doc->mergeXmlBlock('block1',
array(
array('firstname' => 'John' , 'lastname' => 'Doe'),
array('firstname' => 'Douglas', 'lastname' => 'Adams'),
array('firstname' => 'Roger' , 'lastname' => 'Waters'),
)
);
$doc->saveXml();
$doc->close();
// send and remove the document
$doc->sendResponse();
$doc->remove();
throw new sfStopException;
}Create an OpenOffice text document (.odt) and paste this.
$doc->mergeXmlField() with a string [field1] $doc->mergeXmlField() with an array [field2.id] [field2.name] $doc->mergeXmlField() with an object [field3.getZipMethod] [field3.getZipBinary] [field3.getUnzipBinary] $doc->mergeXmlBlock() with an array [block1;block=begin][block1.$] [block1.firstname] [block1.lastname] [block1;block=end] Num rows : [block1.#]Save the document as
basicSuccess.odtin template directorydoc/templates/You can now test my first doc in a browser the result : doc/basic
The result is something like this :
$doc->mergeXmlField() with a string variable $doc->mergeXmlField() with an array 55 bob $doc->mergeXmlField() with an object shell zip unzip $doc->mergeXmlBlock() with an array 0 John Doe 1 Douglas Adams 2 Roger Waters Num rows : 3
and for OpenOffice calc document (.ods)
Change in your action
$doc->createFrom();By
$doc->createFrom(array('extension' => 'ods'));Create an OpenOffice spreadsheed document (.ods) and paste the same as before.
$doc->mergeXmlField() with a string [field1] $doc->mergeXmlField() with an array [field2.id] [field2.name] $doc->mergeXmlField() with an object [field3.getZipMethod] [field3.getZipBinary] [field3.getUnzipBinary] $doc->mergeXmlBlock() with an array [block1;block=begin][block1.$] [block1.firstname] [block1.lastname] [block1;block=end] Num rows : [block1.#]Save the document as
basicSuccess.odsin template directorydoc/templates/You can now test my OpenOffice calc document in a browser the result : doc/basicCalc
and for Word2007 document (.docx)
Change in your action
$doc->createFrom();
$doc->loadXml('content.xml');By
$doc->createFrom(array('extension' => 'docx'));
$doc->loadXml('word/document.xml');Create an Word2007 document (.docx) and paste the same as before.
$doc->mergeXmlField() with a string [field1] $doc->mergeXmlField() with an array [field2.id] [field2.name] $doc->mergeXmlField() with an object [field3.getZipMethod] [field3.getZipBinary] [field3.getUnzipBinary] $doc->mergeXmlBlock() with an array [block1;block=begin][block1.$] [block1.firstname] [block1.lastname] [block1;block=end] Num rows : [block1.#]Save the document as
basicSuccess.docxin template directorydoc/templates/You can now test the Word2007 document in a browser the result : doc/basicWord
Tips
$doc->createFrom(); // the defaut extension is 'odt'
$doc->loadXml(); // the defaut XML filename is 'content.xml'
The basic structure of OpenDocument (OpenOffice) and Word 2007 files
The documents are a zip archive format with these main files :
OpenDocument Word2007 content content.xml word/document.xml meta meta.xml ? settings settings.xml word/settings.xml styles styles.xml word/styles.xml header styles.xml word/header1.xml footer styles.xml word/footer1.xmlcontent.xmlis the main file to merge in OpenOffice documents.word/document.xmlis the main file to merge in Word 2007 documents.content.xmlis the defaut file inloadXml()method.See more on :
The XML tags you have to know :
HTML tags OpenDocument XML tags Word2007 XML tags table <table> <table:table> <w:tbl> row <tr> <table:table-row> <w:tr> cell <td> <table:table-cell> <w:tc> paragraph <p> <text:p> <w:p>
The method to merge data
- Before merging data, you have to load the XML file with the
loadXml()method. After merging data, you have to save the result of merging in the XML file with the
saveXml()method.Each time you have to merge data with an another file you have to
$doc->loadXml('content.xml');
// ...
$doc->mergeXml(...);
$doc->mergeXmlField(...);
$doc->mergeXmlBlock(...);
$doc->mergeXml(...);
// ...
$doc->saveXml();
$doc->loadXml('styles.xml');
// ...
$doc->mergeXml(...);
$doc->mergeXmlField(...);
$doc->mergeXmlBlock(...);
$doc->mergeXml(...);
// ...
$doc->saveXml();There two different methods to merge data, field and block
method :
mergeXmlField($name, $data)MergeField it's for fields (one time)
method :
mergeXmlBlock($name, $data)MergeBlock it's for repetive fields to merge all items from an array.
TIPS
If you don't define the begin block and the end of the block, the fields are merged one time.
The two methods call the generic method :
mergeXml($options, $data)With this method, you can pass some parameters in the
$optionsarray like :- name: The tag name in the template ('block' by default)
- type: The tag type in the template ('field' | 'block' - 'block' by default)
- data_type: The data type - only for type = 'block' ('array' by default)
- charset: The data charset ('UTF-8' by default)
- is_escape: If data are escaped (true by default)
- callback: The callback to encode data ('=~encodeData' by default)
Example :
$doc->mergeXml(
array(
'name' => 'b1',
'type' => 'block',
'data_type' => 'array',
'charset' => 'UTF-8',
'is_escape' => true,
),
$data
);
TinyButStrong templates syntax (TBS tags)
For all parameters of TinyButStrong, have a look to the TinyButStrong manual
The TBS field parameters
- ifempty
- if expr1=expr2;then val1;else val2
- frm=format1|format2|format3|format4
- magnet
- mtype
- ope=action
The TBS block parameters
- block
- $
- #
- nodata
- bmagnet
- headergrp
- footergrp
- splittergrp
- parentgrp
- serial
- p1=val1 (for subquery, this param don't work inside a class, like for sfTinyDoc)
- when expr1=expr2
- default
- several
New parameters for OpenOffice
image : This parameter is to merge image automaticaly
- image or image=100% are equivalent
- image=[ratio] fix the ratio of the merged image
- image=fit the merged image is reduced or increased to fit on template's image size with the best ratio
image=max the merged image is limited to the maximum template's image size
Examples :
[field;image] [field.src;image] [block.src;image] [block.src;image=50%] [block.src;image=max] [block.src;image=fit]
NOTES
Note #1 : The TBS tag is set in the image name. Use OpenOffice dialog box image property to edit.
Note #2 : The file image is added into the document and you don't have to use the
addFile()method.Note #3 : If the image is empty or not found, the image is removed.
link : This parameter to transform to a linkable text
- link
- link=click here to render a different text, "click here" in this example
type : This parameter fixes the type of the cell, not the format (only for spreadsheet).
- type=currency or the shorten way type=c. Input data is float.
- type=date or type=d. Input data is string like 'Y-m-d' or 'Y-m-d H:i:s'.
- type=number or type=n. Input data is float or integer.
- type=percent or type=p. Input data is float.
type=time or type=t. Input data is string like 'H:i:s'.
Examples :
[field;type=number] [field;type=n] [field.data;type=date] [block.data;type=percentage] [block.data;type=time]
NOTES
Note #1 : Only one TBS field can be merge in a cell when the parameter
typeis set.Note #2 : To fix the format the cell, use OpenOffice dialog box format for that. Don't use
frmparameter.
Examples
As in French we can said, "Un dessin vaut mieux qu'un long discours", here some examples for sfTinyDocPlugin
Releases
Release 1.0.3
- ADDED : static method
self::escapeShellCommand()to replace the escapeshellcmd PHP function - FIXED ticket #6436 : to a better support than escapeshellcmd PHP function used
- ADDED : static method
Release 1.0.2
- ADDED : support differents units for picture (cm, mm, in, px)
- ADDED : the tinyDoc version in a constant,
tinyDoc::VERSION - FIXED : news parameters [link, image and type] can merge with data type var and array
Release 1.0.1
- ADDED : parameter [image] to merge pictures for OpenDocument
- ADDED : parameter [link] to merge linkable text for OpenDocument
Release 1.0.0
- Initial
Bugs / Features
add formula support in spreadsheet
<table:table-cell table:formula="of:=IF([.B2]>0;"true";"false")" office:value-type="string" office:string-value="true">
<text:p>true</text:p>
</table:table-cell>add optionals parameters in method
sendResponse()support native format (float, percentage, currency, date, time) in word processing tables (* not easy)
support merge images with a block in spreadsheet (* not easy)
next TinyButStrong version (3.5 ?) to support iterators and a new parameter to merge sub-block.
Todo
- More documentation
- More examples on specials TBS parameters
Support
Mailing-list : http://groups.google.fr/group/tinydoc
Please email to the mailing-list tinydoc@googlegroups.com for support (register only).
Bug tracker : http://trac.symfony-project.org/browser/plugins/sfTinyDocPlugin
The tbsOOo class is no longer supported, and I strongly discourage his use.
Contribution
If you have feature suggestions, bug reports, patches, usage examples for the documentation or want to become an active contributor, send me an email to: olivierloynet [at] gmail [dot] com
Any help is welcome!
Acknowledgements
Special thanks to Vincent who write TinyButStrong.
To Romain, Pierre and Cecile.

