原文标题:Adding layout to your Docx4j-generated word documents, part 2
原文链接:http://blog.iprofs.nl/2012/11/19/adding-layout-to-your-docx4j-generated-word-documents-part-2/
原文作者:lvdpal
发表日期:2012年11月19日
注:我没有再试着翻译代码中的注释,因为我觉得我水平实在有限,翻译过来的注释还不如看英文来地明白...
在前面发表的两篇博客中,我写了一些关于在docx文档中创建表格和添加图像和布局的内容。本篇博客中我将继续介绍一些文档布局相关的示例:
更改默认样式
几乎所有的客户都想要他们自己的风格。Word提供了一些默认的样式但它们不够好(注意一下我没有更改两个图像之间的文本,因此图像中的文本并不反映实际的风格):
大多数客户会想改变这些风格,在应用了我们在本例中创建的风格之后,上面的word文档看起来会像这样:
- public class ChangingTheStyleSheet {
- private static WordprocessingMLPackage wordMLPackage;
- /**
- * First we create the package, then we alter the style sheet and add some
- * styled paragraphs. Finally we save the package.
- */
- public static void main (String[] args) throws Docx4JException {
- wordMLPackage = WordprocessingMLPackage.createPackage();
- alterStyleSheet();
- wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title",
- "Hello World! This title is now in Arial.");
- wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Subtitle",
- "Subtitle, this subtitle is now Arial too");
- wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Heading1",
- "As is Heading1");
- wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Heading2",
- "Heading2 is now Arial, no longer bold and has an underline " +
- "and fontsize 12");
- wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Heading3",
- "Heading3 is now Arial");
- wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Normal",
- "And normal text has changed to Arial and fontsize 10");
- wordMLPackage.save(new java.io.File("src/main/files/HelloWord12.docx") );
- }
- /**
- * This method alters the default style sheet that is part of each document.
- *
- * To do this, we first retrieve the style sheet from the package and then
- * get the Styles object from it. From this object, we get the list of actual
- * styles and iterate over them.
- * We check against all styles we want to alter and apply the alterations if
- * applicable.
- *
- * @param wordMLPackage
- */
- public static void alterStyleSheet() {
- StyleDefinitionsPart styleDefinitionsPart =
- wordMLPackage.getMainDocumentPart().getStyleDefinitionsPart();
- Styles styles = styleDefinitionsPart.getJaxbElement();
- List<Style> stylesList = styles.getStyle();
- for (Style style : stylesList) {
- if (style.getStyleId().equals("Normal")) {
- alterNormalStyle(style);
- } else if (style.getStyleId().equals("Heading2")) {
- alterHeading2Style(style);
- } else if (style.getStyleId().equals("Heading1") ||
- style.getStyleId().equals("Heading3") ||
- style.getStyleId().equals("Title") ||
- style.getStyleId().equals("Subtitle")) {
- getRunPropertiesAndRemoveThemeInfo(style);
- }
- }
- }
- /**
- * First we create a run properties object as we want to remove nearly all of
- * the existing styling. Then we change the font and font size and set the
- * run properties on the given style. As in previous examples, the font size
- * is defined to be in half-point size.
- */
- private static void alterNormalStyle(Style style) {
- // we want to change (or remove) almost all the run properties of the
- // normal style, so we create a new one.
- RPr rpr = new RPr();
- changeFontToArial(rpr);
- changeFontSize(rpr, 20);
- style.setRPr(rpr);
- }
- /**
- * For this style, we get the existing run properties from the style and
- * remove the theme font information from them. Then we also remove the bold
- * styling, change the font size (half-points) and add an underline.
- */
- private static void alterHeading2Style(Style style) {
- RPr rpr = getRunPropertiesAndRemoveThemeInfo(style);
- removeBoldStyle(rpr);
- changeFontSize(rpr, 24);
- addUnderline(rpr);
- }
- private static RPr getRunPropertiesAndRemoveThemeInfo(Style style) {
- // We only want to change some settings, so we get the existing run
- // properties from the style.
- RPr rpr = style.getRPr();
- removeThemeFontInformation(rpr);
- return rpr;
- }
- /**
- * Change the font of the given run properties to Arial.
- *
- * A run font specifies the fonts which shall be used to display the contents
- * of the run. Of the four possible types of content, we change the styling of
- * two of them: ASCII and High ANSI.
- * Finally we add the run font to the run properties.
- *
- * @param runProperties
- */
- private static void changeFontToArial(RPr runProperties) {
- RFonts runFont = new RFonts();
- runFont.setAscii("Arial");
- runFont.setHAnsi("Arial");
- runProperties.setRFonts(runFont);
- }
- /**
- * Change the font size of the given run properties to the given value.
- *
- * @param runProperties
- * @param fontSize Twice the size needed, as it is specified as half-point value
- */
- private static void changeFontSize(RPr runProperties, int fontSize) {
- HpsMeasure size = new HpsMeasure();
- size.setVal(BigInteger.valueOf(fontSize));
- runProperties.setSz(size);
- }
- /**
- * Removes the theme font information from the run properties.
- * If this is not removed then the styles based on the normal style won't
- * inherit the Arial font from the normal style.
- *
- * @param runProperties
- */
- private static void removeThemeFontInformation(RPr runProperties) {
- runProperties.getRFonts().setAsciiTheme(null);
- runProperties.getRFonts().setHAnsiTheme(null);
- }
- /**
- * Removes the Bold styling from the run properties.
- *
- * @param runProperties
- */
- private static void removeBoldStyle(RPr runProperties) {
- runProperties.getB().setVal(false);
- }
- /**
- * Adds a single underline to the run properties.
- *
- * @param runProperties
- */
- private static void addUnderline(RPr runProperties) {
- U underline = new U();
- underline.setVal(UnderlineEnumeration.SINGLE);
- runProperties.setU(underline );
- }
- }
添加页脚或页眉
添加页脚或页眉(或二者兼具)是一个很多客户都想要的特性。幸运的是,做这个并不是很难。这个例子是docx4j示例的一部分,但是我删掉了添加图像的部分只展示最基本的添加页脚部分。添加页眉,你需要做的仅仅是用header来替换footer(或者hdr替换ftr)。
- public class AddingAFooter {
- private static WordprocessingMLPackage wordMLPackage;
- private static ObjectFactory factory;
- /**
- * First we create the package and the factory. Then we create the footer part,
- * which returns a relationship. This relationship is then used to create
- * a reference. Finally we add some text to the document and save it.
- */
- public static void main (String[] args) throws Docx4JException {
- wordMLPackage = WordprocessingMLPackage.createPackage();
- factory = Context.getWmlObjectFactory();
- Relationship relationship = createFooterPart();
- createFooterReference(relationship);
- wordMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!");
- wordMLPackage.save(new File("src/main/files/HelloWord14.docx") );
- }
- /**
- * This method creates a footer part and set the package on it. Then we add some
- * text and add the footer part to the package. Finally we return the
- * corresponding relationship.
- *
- * @return
- * @throws InvalidFormatException
- */
- private static Relationship createFooterPart() throws InvalidFormatException {
- FooterPart footerPart = new FooterPart();
- footerPart.setPackage(wordMLPackage);
- footerPart.setJaxbElement(createFooter("Text"));
- return wordMLPackage.getMainDocumentPart().addTargetPart(footerPart);
- }
- /**
- * First we create a footer, a paragraph, a run and a text. We add the given
- * given content to the text and add that to the run. The run is then added to
- * the paragraph, which is in turn added to the footer. Finally we return the
- * footer.
- *
- * @param content
- * @return
- */
- private static Ftr createFooter(String content) {
- Ftr footer = factory.createFtr();
- P paragraph = factory.createP();
- R run = factory.createR();
- Text text = new Text();
- text.setValue(content);
- run.getContent().add(text);
- paragraph.getContent().add(run);
- footer.getContent().add(paragraph);
- return footer;
- }
- /**
- * First we retrieve the document sections from the package. As we want to add
- * a footer, we get the last section and take the section properties from it.
- * The section is always present, but it might not have properties, so we check
- * if they exist to see if we should create them. If they need to be created,
- * we do and add them to the main document part and the section.
- * Then we create a reference to the footer, give it the id of the relationship,
- * set the type to header/footer reference and add it to the collection of
- * references to headers and footers in the section properties.
- *
- * @param relationship
- */
- private static void createFooterReference(Relationship relationship) {
- List<SectionWrapper> sections =
- wordMLPackage.getDocumentModel().getSections();
- SectPr sectionProperties = sections.get(sections.size() - 1).getSectPr();
- // There is always a section wrapper, but it might not contain a sectPr
- if (sectionProperties==null ) {
- sectionProperties = factory.createSectPr();
- wordMLPackage.getMainDocumentPart().addObject(sectionProperties);
- sections.get(sections.size() - 1).setSectPr(sectionProperties);
- }
- FooterReference footerReference = factory.createFooterReference();
- footerReference.setId(relationship.getId());
- footerReference.setType(HdrFtrRef.DEFAULT);
- sectionProperties.getEGHdrFtrReferences().add(footerReference);
- }
- }
在页脚添加页码
我在本博客要讨论的最后一个特性是怎样在我们刚创建的页脚处添加页码。你可能已经知道,在Word中页码是一个域,因此本例或多或少是前面的两个例子的结合:目录表和页脚。
- public class AddingPageNrToFooter {
- private static WordprocessingMLPackage wordMLPackage;
- private static ObjectFactory factory;
- /**
- * First we create the package and the factory. Then we create the footer.
- * Finally we add two pages with text to the document and save it.
- */
- public static void main (String[] args) throws Exception {
- wordMLPackage = WordprocessingMLPackage.createPackage();
- factory = Context.getWmlObjectFactory();
- Relationship relationship = createFooterPart();
- createFooterReference(relationship);
- MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
- documentPart.addParagraphOfText("Hello World!");
- addPageBreak(documentPart);
- documentPart.addParagraphOfText("This is page 2!");
- wordMLPackage.save(new File("src/main/files/HelloWord15.docx") );
- }
- /**
- * As in the previous example, this method creates a footer part and adds it to
- * the main document and then returns the corresponding relationship.
- *
- * @return
- * @throws InvalidFormatException
- */
- private static Relationship createFooterPart() throws InvalidFormatException {
- FooterPart footerPart = new FooterPart();
- footerPart.setPackage(wordMLPackage);
- footerPart.setJaxbElement(createFooterWithPageNr());
- return wordMLPackage.getMainDocumentPart().addTargetPart(footerPart);
- }
- /**
- * As in the previous example, we create a footer and a paragraph object. But
- * this time, instead of adding text to a run, we add a field. And just as with
- * the table of content, we have to add a begin and end character around the
- * actual field with the page number. Finally we add the paragraph to the
- * content of the footer and then return it.
- *
- * @return
- */
- public static Ftr createFooterWithPageNr() {
- Ftr ftr = factory.createFtr();
- P paragraph = factory.createP();
- addFieldBegin(paragraph);
- addPageNumberField(paragraph);
- addFieldEnd(paragraph);
- ftr.getContent().add(paragraph);
- return ftr;
- }
- /**
- * Creating the page number field is nearly the same as creating the field in
- * the TOC example. The only difference is in the value. We use the PAGE
- * command, which prints the number of the current page, together with the
- * MERGEFORMAT switch, which indicates that the current formatting should be
- * preserved when the field is updated.
- *
- * @param paragraph
- */
- private static void addPageNumberField(P paragraph) {
- R run = factory.createR();
- Text txt = new Text();
- txt.setSpace("preserve");
- txt.setValue(" PAGE \\* MERGEFORMAT ");
- run.getContent().add(factory.createRInstrText(txt));
- paragraph.getContent().add(run);
- }
- /**
- * Every fields needs to be delimited by complex field characters. This method
- * adds the delimiter that precedes the actual field to the given paragraph.
- * @param paragraph
- */
- private static void addFieldBegin(P paragraph) {
- R run = factory.createR();
- FldChar fldchar = factory.createFldChar();
- fldchar.setFldCharType(STFldCharType.BEGIN);
- run.getContent().add(fldchar);
- paragraph.getContent().add(run);
- }
- /**
- * Every fields needs to be delimited by complex field characters. This method
- * adds the delimiter that follows the actual field to the given paragraph.
- * @param paragraph
- */
- private static void addFieldEnd(P paragraph) {
- FldChar fldcharend = factory.createFldChar();
- fldcharend.setFldCharType(STFldCharType.END);
- R run3 = factory.createR();
- run3.getContent().add(fldcharend);
- paragraph.getContent().add(run3);
- }
- /**
- * This method fetches the document final section properties, and adds a newly
- * created footer reference to them.
- *
- * @param relationship
- */
- public static void createFooterReference(Relationship relationship){
- List<SectionWrapper> sections =
- wordMLPackage.getDocumentModel().getSections();
- SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
- // There is always a section wrapper, but it might not contain a sectPr
- if (sectPr==null ) {
- sectPr = factory.createSectPr();
- wordMLPackage.getMainDocumentPart().addObject(sectPr);
- sections.get(sections.size() - 1).setSectPr(sectPr);
- }
- FooterReference footerReference = factory.createFooterReference();
- footerReference.setId(relationship.getId());
- footerReference.setType(HdrFtrRef.DEFAULT);
- sectPr.getEGHdrFtrReferences().add(footerReference);
- }
- /**
- * Adds a page break to the document.
- *
- * @param documentPart
- */
- private static void addPageBreak(MainDocumentPart documentPart) {
- Br breakObj = new Br();
- breakObj.setType(STBrType.PAGE);
- P paragraph = factory.createP();
- paragraph.getContent().add(breakObj);
- documentPart.getJaxbElement().getBody().getContent().add(paragraph);
- }
- }
总结
在三篇博客中,我展示了怎样创建一个word文档以及一些很常用的特性。这些示例全都是我的客户要求我需要创建的word文档。而且我觉得它们足以让你知道如何去做更多其它的事情,如果不是,用你所需要的特性创建一个文档并去查看内部的XML,如果一切仍然不能奏效,你可以到Docx4j论坛进行提问,docx4j的作者会定期尝试回答所有的问题。
在以后的博客中我会展示一些关于xlsx文档的示例。
向Docx4j生成的word文档中添加布局--第二部分的更多相关文章
-
向Docx4j生成的word文档添加图片和布局--第一部分
原文标题:Adding images and layout to your Docx4j-generated word documents, part 1 原文链接:http://blog.iprof ...
-
如何在word文档中添加mathtype加载项
MathType是强大的数学公式编辑器,通常与office一起使用,mathtype安装完成后,正常情况下会在word文档中的菜单中自动添加mathtype加载项,但有时也会出现小意外,mathtyp ...
-
在word文档中添加上角标和下角标
方法一 摘录:https://jingyan.baidu.com/article/02027811b4d2da1bcc9ce5f7.html 方法二 利用MathType数学公式编辑器 exe下载:h ...
-
C# 在Word文档中生成条形码
C# 在Word文档中生成条形码 简介 条形码是由多个不同的空白和黑条按照一定的顺序组成,用于表示各种信息如产品名称.制造商.类别.价格等.目前,条形码在我们的日常生活中有着很广泛的应用,不管是在图书 ...
-
C# 在word文档中复制表格并粘帖到下一页中
C# 在word文档中复制表格并粘帖到下一页中 object oMissing = System.Reflection.Missing.Value; Microsoft.Offi ...
-
C# Word文档中插入、提取图片,文字替换图片
Download Files:ImageOperationsInWord.zip 简介 在这篇文章中我们可以学到在C#程序中使用一个Word文档对图像的各种操作.图像会比阅读文字更有吸引力,而且图像是 ...
-
Android开发——使用Jword生成本地word文档
本文主要介绍如何使用Jword生成本地word文档,这里涉及到Jword的使用技巧,本文给出相应的代码,需要的朋友可以参考下. 为什么使用Jword呢?因为IText .Freemark在安卓平台上压 ...
-
java生成复杂word文档
在Web应用中,有时需要按照固定的模板将数据导出到Word,如流程审批单,在流程处理完成后将处理过程按照流程单的要求导出,有时程序中需要实现生成 标准Word文档,要求能够打印,并且保持页面样式不变, ...
-
利用POI操作不同版本号word文档中的图片以及创建word文档
我们都知道要想利用java对office操作最经常使用的技术就应该是POI了,在这里本人就不多说到底POI是什么和怎么用了. 先说本人遇到的问题,不同于利用POI去向word文档以及excel文档去写 ...
随机推荐
-
ios app的版本号
ios其实有3个版本号 version 就是ios的版本号 (只能分3段,并且都是数字) build 是ios构建内部版本时的版本号 (可以分4段) 而提交到appstore时, 还是要创建一个sku ...
-
(翻译)《Hands-on Node.js》—— Introduction
今天开始会和大熊君{{bb}}一起着手翻译node的系列外文书籍,大熊负责翻译<Node.js IN ACTION>一书,而我暂时负责翻译这本<Hands-on Node.js> ...
-
C++混合编程之idlcpp教程Python篇(3)
上一篇 C++混合编程之idlcpp教程Python篇(2) 是一个 hello world 的例子,仅仅涉及了静态函数的调用.这一篇会有新的内容. 与PythonTutorial0相似,工程Pyth ...
-
***CI中的数据库操作(insert_id新增后返回记录ID)
在system/application/config 文件夹和里面的config文件里已经配置了参数 $active_group = "default";$db['default' ...
-
夺命雷公狗ThinkPHP项目之----企业网站6之栏目的添加(主要用模型来验证字段)
我们刚才的控制器已经写好了,那么我们现在就来完成我们的模型, 首先我们在Model目录下创建一个CategoryModel.class.php 代码如下: <?php namespace Adm ...
-
leetcode:Integer to Roman(整数转化为罗马数字)
Question: Given an integer, convert it to a roman numeral. Input is guaranteed to be within the rang ...
-
win32 sdk树形控件的项拖拽实现
本课中,我们将学习如何使用树型视图控件.另外还要学习如何在树型视图中完成拖-拉动作,以及如何使用图象列表. 理论: 树型视图是一种特别的窗口,我们可以使用它一目了然地表示某种层次关系.譬如象在资源管理 ...
-
Python之CVXOPT模块
Python中支持Convex Optimization(凸规划)的模块为CVXOPT,其安装方式为: 卸载原Pyhon中的Numpy 安装CVXOPT的whl文件,链接为:https://www ...
-
测试系统工程师TSE的职责与培养
测试系统工程师TSE的职责与培养 研发资深顾问 杨学明 如今,国内所有的研发型的公司都有测试部门,无论测试团队大小,都有测试组长,测试经理,测试工程师等头衔,但随着产品和业务的质量要求越来越高,产品的 ...
-
1、git基础介绍及远程/本地仓库、分支
1. Git基础介绍 基于Git进行开发时,首先需要将远程仓库代码clone到本地,即为本地仓库.后续大部分时间都是基于本地仓库上的分支进行编码,最后将本地仓库的代码合入远程仓库. 1.1. 远程仓库 ...