A small JAVA project Web application automatically generates Word
- 2020-04-01 03:23:05
- OfStack
Some time ago, I received a request from a Web application to automatically generate Word. Now I have compiled the following key steps to share with you.
Idea: note: this is for WORD2003 only, other versions are similar.
Because WORD and data within the file format is through the form of an XML file, such as storage, so the WORD file can easily realize transformation from DOC to XML format, and manipulate XML documents is much more convenient, thus realize the has nothing to do with the platform of various operations, through the node, delete, query, substitution of new generation such as WORD file. So, generating a WORD file from a template is the process of replacing a special label in an XML file with user data and saving it as a DOC file.
Here are some of the key steps involved (take a letter of introduction)
Step 1: make WORD templates according to your requirements
Create a new WORD file in DOC format, fill in the template contents as required, set the template format, including font, style, blank line, etc., use special labels (such as: [ does unit name does ]) to fill in the data in advance, and then save the new WORD file as an XML file. In this way, the WORD template is finished. The code is as follows:
< img border = 0 id = theimg onclick = window. The open this. (SRC) SRC = "/ / files.jb51.net/file_images/article/201405/2014515120200242.jpg? 201441512216 "> Step 2: configure the template information in the configuration file
Add a configuration file named template-rule. XML, with each template node corresponding to a template type. There is a taglist node in each template, and all the child nodes contained by this node contain all the node information to be replaced or deleted in the template. The node information includes: node value, node attribute English name, Chinese description, field type, whether to delete or not. When setting up this configuration file, it is important to note that the value of the desc attribute must be the same as the placeholder in the template XML. For example, the entry item [ does year does ] set in the template XML should correspond to the name of desc=" year "in template-rule. The code is as follows:
<!--?xml version="1.0" encoding="GB2312"?-->
<!-- The template definition -->
<templates>
<!-- instructions : S- string ; D- The date of ; E- The amount of ; M- Amount in words ; ifEmptyDelete: T- The value is null to delete the parent node , The default is F -->
<template name="RECOMMEND-LETTER" desc=" Letter of introduction " templatefile="template4.xml">
<taglist remark=" List of single value labels ">
<tag id="1" name="ToPartment" desc=" Receiving department " type="S" ifemptydelete="T">#ToPartment</tag><!-- Receiving department -->
<tag id="2" name="OwnerName" desc=" The name " type="S">#OwnerName</tag><!-- The name -->
<tag id="3" name="CountNum" desc=" The number of " type="S">#CountNum</tag><!-- The number of -->
<tag id="4" name="Business" desc=" content " type="S">#Business</tag><!-- content -->
<tag id="5" name="UsefulDays" desc=" The period of validity " type="S">#UsefulDays</tag><!-- The period of validity -->
<tag id="6" name="Year" desc=" years " type="S">#Year</tag><!-- years -->
<tag id="7" name="Month" desc=" month " type="S">#Month</tag><!-- month -->
<tag id="8" name="Day" desc=" day " type="S">#Day</tag><!-- day -->
</taglist>
</template>
</templates>
Step 3: write Java code
public class RuleDTO {
private String parmName;
private String parmDesc;
private String parmSeq;
private String parmType;
private String parmRegular;
private String parmValue;
private String ifEmptyDelete;
}
public class Template {
private String name;//The template name
private String desc;//Template description
private String templateFile;//Template file
private Vector<ruledto> rules;//Template rule
}</ruledto>
public class WordBuilder {
@SuppressWarnings("unchecked")
public Template loadRules(Map<string, string=""> ruleValue) {
InputStream in = null;
Template template = new Template();
//Rule profile path
String ruleFile = "template-rule.xml";
//Template rule name
String templateRuleName = "";
try {
templateRuleName = ruleValue.get("ruleName");
//Read the template rule file
in = this.getClass().getClassLoader().getResourceAsStream(ruleFile);
//Parse template rule
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(in);
Element root = doc.getRootElement(); //Get the root element
List<element> templateList = root.getChildren();//All template configurations
Element element = null;
Vector<ruledto> rules = null;
for (int i = 0; i < templateList.size(); i++) {//Iterate through all templates
element = (Element) templateList.get(i);
String templateName = element.getAttributeValue("name");
if (templateRuleName.equalsIgnoreCase(templateName)) {//Finds the given template configuration
template.setName(templateName);
template.setDesc(element.getAttributeValue("desc"));
template.setTemplateFile(element
.getAttributeValue("templateFile"));
List<element> tagList = ((Element) element.getChildren()
.get(0)).getChildren();//The tag list
Element tag = null;
RuleDTO ruleDTO = null;
rules = new Vector<ruledto>();
for (int j = 0; j < tagList.size(); j++) {
tag = (Element) tagList.get(j);
ruleDTO = new RuleDTO();
ruleDTO.setParmName(tag.getAttributeValue("name"));
ruleDTO.setParmDesc(" 【 does "
+ tag.getAttributeValue("desc") + " Does. ");
ruleDTO.setParmSeq(tag.getAttributeValue("id"));
ruleDTO.setParmType(tag.getAttributeValue("type"));
if ("T".equalsIgnoreCase(tag
.getAttributeValue("ifEmptyDelete"))) {//Whether the tag can be deleted
ruleDTO.setIfEmptyDelete("T");
} else {
ruleDTO.setIfEmptyDelete("F");
}
ruleDTO.setParmRegular(tag.getText());
//value
//Type of judgment parameter
String value = (String) ((Map<string, string="">) ruleValue)
.get(ruleDTO.getParmRegular().replaceAll("#",
""));
ruleDTO.setParmValue(value);
rules.add(ruleDTO);
}
template.setRules(rules);
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return template;
}
public Element findElement(Element currNode, String parentNodeId) {
//The node is marked as empty
if (currNode == null || parentNodeId == null) {
return null;
}
Element pNode = null;
do {
pNode = currNode.getParent();
currNode = pNode;
} while (parentNodeId.equalsIgnoreCase(pNode.getName()));
return pNode;
}
@SuppressWarnings("unchecked")
public String build(Template template) {
InputStream in = null;
OutputStream fo = null;
//The path to the generated file
String file = "d:\test\" + template.getDesc() + ".doc";
try {
//Read template file
in = this.getClass().getClassLoader()
.getResourceAsStream(template.getTemplateFile());
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(in);
Element root = doc.getRootElement(); //Get the root element
Namespace ns = root.getNamespace();// NameSpace
//Word 03 template exists <Wx: sect> The element
List<element> sectList = root.getChild("body", ns).getChildren();
Element sectElement = (Element) sectList.get(0);
//<W: p> The collection of tags under
List<element> pTagList = sectElement.getChildren("p", ns);
//<W: tbl> The collection of tags under
List<element> tblTagList = sectElement.getChildren("tbl", ns);
if (pTagList != null && pTagList.size() > 0) {
changeValue4PTag(pTagList, template.getRules(), ns, null);
}
if (tblTagList != null && tblTagList.size() > 0) {
changeValue4TblTag(tblTagList, template.getRules(), ns);
}
//Write files
XMLOutputter outp = new XMLOutputter(" ", true, "UTF-8");
fo = new FileOutputStream(file);
outp.output(doc, fo);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
fo.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return file;
}
@SuppressWarnings("unchecked")
private boolean changeValue4PTag(List<element> pTagList,
Vector<ruledto> rulesValue, Namespace ns, List<element> trChildren) {
Element p = null;
boolean delFlag = false;
for (int i = 0; i < pTagList.size(); i++) {
boolean delCurrNode = false;//Delete the current node
boolean delCurrNode4TabWR = false;//Delete the single row node in the table
p = (Element) pTagList.get(i);
List<element> pChild = p.getChildren("r", ns);
for (int j = 0; pChild != null && j < pChild.size(); j++) {
Element pChildren = (Element) pChild.get(j);
Element t = pChildren.getChild("t", ns);
if (t != null) {
String text = t.getTextTrim();
if (text.indexOf(" 【 does ") != -1) {
for (int v = 0; v < rulesValue.size(); v++) {
RuleDTO dto = (RuleDTO) rulesValue.get(v);
if (text.indexOf(dto.getParmDesc().trim()) != -1) {
//Determines whether the property value is nullable
if ("T".equals(dto.getIfEmptyDelete())
&& StringUtils.isBlank(dto
.getParmValue())) {
//Deletes the node's top-level node
text = "";
if (trChildren != null) {//In view of the <W: tbl> Delete the
Element element = ((Element) p
.getParent()).getParent();
trChildren.remove(element);
delCurrNode4TabWR = true;
} else {//In view of the <W: r> Delete the paragraph
// pTagList.remove(p);
pTagList.remove(pChildren);
delCurrNode = true;
}
break;
} else {
text = text.replaceAll(dto.getParmDesc()
.trim(), dto.getParmValue());
}
}
}
t.setText(text);
}
if (delCurrNode4TabWR) {//<W: tbl> The row nodes under the TABLE have been deleted
delFlag = true;
break;
} else if (delCurrNode) {//<W: p> The node under has been deleted
i--;
delFlag = true;
break;
}
}
}
}
return delFlag;
}
@SuppressWarnings("unchecked")
private void changeValue4TblTag(List<element> tblTagList,
Vector<ruledto> rulesValue, Namespace ns) {
Element p = null;
for (int i = 0; tblTagList != null && i < tblTagList.size(); i++) {
p = (Element) tblTagList.get(i);
List<element> trChildren = p.getChildren("tr", ns);
for (int j = 0; trChildren != null && j < trChildren.size(); j++) {//Cycle <W: tr>
Element pChildren = (Element) trChildren.get(j);
List<element> tcTagList = pChildren.getChildren("tc", ns);
for (int c = 0; tcTagList != null && c < tcTagList.size(); c++) {//Cycle <W: tc> Take <W: p> A collection of
Element tcChildren = (Element) tcTagList.get(c);
List<element> pTagList = tcChildren.getChildren("p", ns);
boolean delFlag = changeValue4PTag(pTagList, rulesValue,
ns, trChildren);
if (delFlag) {//The pointer position of trChildren needs to be changed after the row is deleted
j--;
}
}
}
}
}
public static void main(String[] args) throws Exception {
WordBuilder word = new WordBuilder();
Map<string, string=""> map = new HashMap<string, string="">();
//Filling parameters
map.put("ToPartment", "XXX The company ");
map.put("OwnerName", " Zhang SAN ");
map.put("CountNum", "5");
map.put("Business", " Routine inspection ");
map.put("UsefulDays", "15");
map.put("Year", "2014");
map.put("Month", "5");
map.put("Day", "13");
map.put("ruleName", "RECOMMEND-LETTER");
Template template = word.loadRules(map);
//Open the file directly
Runtime.getRuntime().exec("explorer " + word.build(template));
}
}</string,></string,></element></w:p></w:tc></element></w:tr></element></ruledto></element></w:tbl></w:tbl></w:p></w:tbl></w:r></w:tbl></element></element></ruledto></element></w:tr></w:tbl></w:p></w:p></w:p></wx:sect></w:body></element></w:tbl></element></w:p></element></wx:sect></string,></ruledto></element></ruledto></element></string,>
Step 4: done
Several summaries and matters needing attention:
1. The element name defined must be the same as the value corresponding to the same name in the template_rule.xml, otherwise the conversion rules need to be set.
2. The text in the placeholder [ Does does ] defined in the template XML must be the same as the corresponding desc in the template_rule.
3. After the template XML has been configured, you need to check whether the child node under the tag is a tag (related to the WORD version), if not, you must add the tag.
4. If you want to delete a tag node dynamically, the content of that node needs to be on the same line in the template. If not, you can manually adjust the template XML.
5. If you need to realize WORD WORD wrap function (no better WORD wrap scheme in the template has been thought of), you need to first calculate the WORD count of the line of the corresponding template, and then use space to fill.