Documents reporting sample in docx, odt, pdf, xhtml and pptx formats extending XDocReport project and using Spring Framework.
Supported template formats: .docx, .odt and .pptx
More about XDocReport: https://code.google.com/p/xdocreport/wiki/Overview
- For the first, we need any template in supported format to processing (see example), corresponding Java model (see example) and choose template engine (Velocity or Freemarker)
Template and Java model creating tutorial:
-
Then add in your pom.xml repository:
<repository> <id>DocsReporter-mvn-repo</id> <url>https://raw.github.com/creepid/DocsReporter/mvn-repo/</url> <snapshots> <enabled>true</enabled> <updatePolicy>always</updatePolicy> </snapshots> </repository>
and dependency:
<dependency> <groupId>by.creepid</groupId> <artifactId>docsreporter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
-
Then add in app-context.xml of your Spring application:
<import resource="classpath*:META-INF/spring/docsreporter-context.xml" />
and define our reportTemplate bean:
<bean id="reportTemplate" parent="reportTemplateBase">
<property name="templatePath">
<value>/pathto/template/DocxProjectWithVelocity.docx</value>
</property>
<property name="modelClass">
<value>by.creepid.docsreporter.model.Project</value>
</property>
<property name="modelName" value="project"/>
</bean>
So, as you guess,
templatePath is path to our template (remember only .docx, .odt, .pptx supported)
modelClass - defines our trunk model class (maybe with deep hierarchy)
modelName - name of root class in template
Then in code autowire reportTemplate in any bean of your application (ReportTemplate is thread safe):
@Autowire
private ReportTemplate reportTemplate;
Create and process project instance:
Project project = new Project();
...//fill the object
//If we have any dynamic images in our template define ImageExtractObserver instance:
ImageExtractObserver observer = new ImageExtractObserver() {
public void getImage(byte[] content, String path) {
//process image extraction event, maybe saving it in some folder
}
};
//choose output document format (.docx, .odt, .pptx, .pdf, .xhtml available)
DocFormat outFormat = DocFormat.PDF;
//receive processed document and saving it to file or to response wrapper etc.
OutputStream out = reportTemplate.generateReport(outFormat, project, observer);
That's it!
If we want to tell that given class field is image (essentially in byte array) and it links to temp image in template with called "logo" bookmark, just to add annotation: @Image(bookmarks = {"logo"}) or @Image(bookmarks = {"logo1", "logo2"}) if we have several bookmarks(more about template dynamic image)
Adding **@Image** annotation:
Given template with marked temp image:
And after have:
Other opportunities of @Image annotation:
-
**useTemplateSize()** default true - set size of template image in your document
-
**useRatioSize()** default true - define is need to save aspect ratio of image
-
**width()** - forced set image width
-
**height()** - forced set image height
Note: DocsReporter allows use even images in CMYK color style and improves images quality after resizing by using special filters
If we have null value of some field in model class to map we can configure the value that will replace this value in emptyField property of contextProcessor bean:
<bean id="contextProcessor" class="by.creepid.docsreporter.context.DocContextProcessor"
scope="prototype" lazy-init="true" depends-on="imageConverter">
<property name="emptyField">
<value>_________</value>
</property>
</bean>
The other way: add @NullValue annotation to this field:
So, we have: if mail field of developer in list will be null, we'll see "Enter your mail, please" instead and "_________" in other cases.
Now we want to apply text styling in name field of developer in HTML way, see more about TextStyling, and then set developer.setName("<b>Victor</b>")
We'll see name in bold type in doc:
#Add field formatters
We can add our own field formatter by implementing the interface:
public interface DocTypesFormatter<F,T> {
public T format(F f);
public Class<T> getToClass();
public Class<F> getFromClass();
}
And define this class as @Component
.
So, when the context meets the field with given type, it's searching for corresponding formatter, modifies the value and then maps it in target document