向Docx4j生成的word文档中添加布局--第二部分
原文标题: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 ...
- Java 在Word文档中添加艺术字
艺术字是以普通文字为基础,经过专业的字体设计师艺术加工的变形字体.字体特点符合文字含义.具有美观有趣.易认易识.醒目张扬等特性,是一种有图案意味或装饰意味的字体变形,常用来创建旗帜鲜明的标志或标题. ...
- 在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文档,要求能够打印,并且保持页面样式不变, ...
随机推荐
- WaitForSingleObject()
参见:http://blog.csdn.net/xiaobai1593/article/details/6672193 1. 格式 DWORD WaitForSingleObject( HANDLE ...
- CentOS简单命令学习:date cal bc
简单的shell指令: 1.日期的格式化显示: 2.日历的显示: 3.bc计算器: 使用Tab指令自动补全:
- 使用 JMeter 完成常用的压力测试 [转]
讲到测试,人们脑海中首先浮现的就是针对软件正确性的测试,即常说的功能测试.但是软件仅仅只是功能正确是不够的.在实际开发中,还有其它的非功能因素也起着决定性的因素,例如软件的响应速度.影响软件响应速度的 ...
- Unity的加载路径
1.Resources 路径 只读 不能动态的修改 存放内容 预制体(prefabs) - 不容易变化的预制体 prefabs打包的时候 会自动过滤不需要的资源 有利于减小资源大小 主线程加载 Res ...
- 如何将ppt转换为高清图片?
PPT2010版本直接提供了“另存为”图片的功能,但另存为后的图片清晰度不够,这是因为office提供的默认点每英寸点数 (dpi)为96dpi,也就是说图片的尺寸为960x720像素,通过注册表可以 ...
- mysqldump进行数据库的全备时,备份数据库的顺序是什么,就是先备份哪个库,然后再备份哪个库
需求描述: 今天在用mysqldump工具进行数据库的备份的时候,突然想了一个问题,比如我有10个库要进行备份 那么是先备份哪个,然后再备份哪个呢,所以,做了实验,验证下. 操作过程: 1.使用--a ...
- Visual Studio使用技巧,创建自己的代码片段
1.代码片段的使用示例 在编写代码中常会使用代码片段来提高我们的编写代码的效率,如:在Visual Studio中编写一个 for(int i = 0; i < length;i++) { } ...
- HTTP 错误 404.3 解决
问题 由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. 解决 在开始菜单中找到 Visual Studio 命令提示工具.然后用管理员 ...
- Android移动网络如何抓取数据包
1)下载tcpdump工具 tcpdump(dump the traffic on a network)是Linux中强大的网络数据采集分析工具之一,可以将网络中传送的数据包头完全截获下来提供分析.它 ...
- 说说GPIO.H(NUC131)
/**************************************************************************//** * @file GPIO.h * @ve ...