sfTinyDocPlugin
1.0.3stable
for sf 1.2sf 1.1sf 1.0 MIT
The sfTinyDocPlugin allows to generate OpenOffice and Word 2007 documents with TinyButStrong template engine.
As in French we can said, "Un dessin vaut mieux qu'un long discours", here some examples for sfTinyDocPlugin
Developers
License
Copyright (c) 2005-2009 Olivier LOYNET
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
sfTinyDocPlugin
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
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 method mergeXmlField() in place of use globals vars
- Can't merge sub-block because TinyButStrong need global vars, see
headergrp syntax
Installation
Install sfTinyDocPlugin :
$ pear channel-discover pear.symfony-project.com
$ symfony plugin-install http://plugins.symfony-project.com/sfTinyDocPlugin
Or from the SVN repository
$ svn co http://svn.symfony-project.com/plugins/sfTinyDocPlugin/trunk/
Optionally add the following config to app.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 directory
Clear your cache :
$ ./symfony cc
Configure the method to zip/unzip office documents :
Method 1 : shell (by default)
To install Zip on Red Hat Enterprise Linux or CentOS
$ yum install zip
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 doc in your application
Create an action basic in doc/actions/actions.class.php
<?php
public 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.odt in template directory doc/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
<?php
$doc->createFrom();
By
<?php
$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.ods in template directory doc/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
<?php
$doc->createFrom();
$doc->loadXml('content.xml');
By
<?php
$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.docx in template directory doc/templates/
You can now test the Word2007 document in a browser the result : doc/basicWord
Tips
<?php
$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.xml
content.xml is the main file to merge in OpenOffice documents.
word/document.xml is the main file to merge in Word 2007 documents.
content.xml is the defaut file in loadXml() 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
<?php
$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 $options array 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 :
[php]
<?php
$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
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).
NOTES
Note #1 : Only one TBS field can be merge in a cell when the parameter type is set.
Note #2 : To fix the format the cell, use OpenOffice dialog box format for that. Don't use frm parameter.
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 bug #6436 : to a better support than escapeshellcmd PHP function used
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
Bugs / Features
add formula support in spreadsheet
<?php
<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.