Vor einiger Zeit erhielt ich eine Anfrage für eine Webanwendung zur automatischen Generierung von Word. Jetzt habe ich einige wichtige Schritte zum Teilen zusammengestellt.
Idee: (Hinweis: Dies gilt nur für die WORD2003-Version, andere Versionen sind ähnlich.)
Da die internen Daten und das Format von WORD-Dateien in Form von XML-Dateien gespeichert werden, können WORD-Dateien problemlos vom DOC- in das XML-Format konvertiert werden. Außerdem ist es viel bequemer, XML-Dateien zu bedienen und so die Integration mit verschiedenen plattformunabhängigen Vorgängen zu realisieren Generieren Sie Word-Dateien durch Knotenabfrage, Ersetzen, Löschen, Hinzufügen usw. Daher besteht der Kern der Generierung einer WORD-Datei auf Basis einer Vorlage darin, die speziellen Tags in der XML-Datei durch Benutzerdaten zu ersetzen und sie dann als DOC-Datei zu speichern.
Hier sind einige der wichtigsten Schritte (am Beispiel eines Einführungsschreibens):
Schritt eins: Erstellen Sie eine WORD-Vorlage entsprechend Ihren Anforderungen
Erstellen Sie eine neue WORD-Datei im DOC-Format, füllen Sie den Vorlageninhalt nach Bedarf aus und legen Sie das Format der Vorlage fest, einschließlich Schriftarten, Stile, Leerzeilen usw. Verwenden Sie spezielle Tags (z. B. [※Einheitenname※]), um Belegen Sie vorab die zu füllenden Daten und speichern Sie dann die neu erstellte WORD-Datei als XML-Formatdatei. Auf diese Weise ist die WORD-Vorlage fertig. Der Code lautet wie folgt:
Fügen Sie eine neue Konfigurationsdatei mit dem Namen template-rule.xml hinzu. Jeder Vorlagenknoten entspricht einem Vorlagentyp. In jeder Vorlage gibt es einen Taglist-Knoten. Alle in diesem Knoten enthaltenen untergeordneten Knoten enthalten Informationen zu allen Knoten, die in der Vorlage ersetzt oder gelöscht werden. Die Knoteninformationen umfassen: Knotenwert, englischer Name des Knotenattributs, chinesische Beschreibung, Feldtyp. ob es gelöscht werden kann usw. Beim Festlegen dieser Konfigurationsdatei müssen Sie beachten, dass der Wert des desc-Attributs mit dem Platzhalter in der XML-Vorlage übereinstimmen muss. Beispiel: Das in der XML-Vorlage festgelegte Jahreseingabeelement [※Year※] muss dem Namen desc="Year" in template-rule.xml entsprechen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
<!--?xml version="1.0"kodierung="GB2312"?-->
<!-- Vorlagendefinition-->
<Vorlagen>
<!-- Beschreibung: S-String;
<template name="RECOMMEND-LETTER" desc="Einführungsschreiben" templatefile="template4.xml">
<taglist comment="Einzelwert-Tag-Liste">
<tag id="1" name="ToPartment" desc="Receiving Department" type="S" ifemptydelete="T">#ToPartment</tag><!--Receiving Department-->
<tag id="2" name="OwnerName" desc="Name" type="S">#OwnerName</tag><!--Name-->
<tag id="3" name="CountNum" desc="Anzahl der Personen" type="S">#CountNum</tag><!--Anzahl der Personen-->
<tag id="4" name="Business" desc="Content" type="S">#Business</tag><!--Content-->
<tag id="5" name="UsefulDays" desc="Validity period" type="S">#UsefulDays</tag><!--Validity period-->
<tag id="6" name="Year" desc="year" type="S">#Year</tag><!--year-->
<tag id="7" name="Month" desc="month" type="S">#Month</tag><!--month-->
<tag id="8" name="Day" desc="日" type="S">#Day</tag><!--Day-->
</taglist>
</template>
</templates>
Schritt 3: Schreiben Sie Java-Code
Kopieren Sie den Codecode wie folgt:
/**
* Parameter und Regeln
*/
öffentliche Klasse RuleDTO {
/**
* Tag-Name
*/
privater String parmName;
/**
* Tag-Beschreibung
*/
privater String parmDesc;
/**
* Tag-Seriennummer
*/
private String parmSeq;
/**
* Tag-Werttyp
*/
privater String parmType;
/**
* Tag-Parametername
*/
privater String parmRegular;
/**
* Tag-Wert
*/
privater String parmValue;
/**
* Wenn der Tag-Wert leer ist, löschen Sie dieses Attribut
*/
privater String ifEmptyDelete;
}
Kopieren Sie den Codecode wie folgt:
/**
* Beschreibung: Informationen zur Word-Vorlage
*/
Vorlage für öffentliche Klassen {
privater String-Name;//Vorlagenname
privater String desc;//Vorlagenbeschreibung
private String templateFile;//template file
private Vector<ruledto> Rules;//Vorlagenregeln
</ruledto>
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse WordBuilder {
/**
* Lesen Sie die Ersetzungsregeln basierend auf der Vorlage
* @param templateName Vorlagen-ID
*/
@SuppressWarnings("ungeprüft")
öffentliche Vorlage LoadRules(Map<string, string=""> RuleValue) {
InputStream in = null;
Vorlage template = new Template();
// Pfad der Regelkonfigurationsdatei
String RuleFile = "template-rule.xml";
// Name der Vorlagenregel
String templateRuleName = "";
versuchen {
templateRuleName = RuleValue.get("ruleName");
//Vorlagenregeldatei lesen
in = this.getClass().getClassLoader().getResourceAsStream(ruleFile);
// Vorlagenregeln analysieren
SAXBuilder sb = new SAXBuilder();
Dokument doc = sb.build(in);
Element root = doc.getRootElement(); // Holen Sie sich das Root-Element
List<element> templateList = root.getChildren();//Alle Vorlagenkonfigurationen
Element element = null;
Vector<ruledto> Rules = null;
for (int i = 0; i < templateList.size(); i++) {// Alle Vorlagen durchlaufen
element = (Element) templateList.get(i);
String templateName = element.getAttributeValue("name");
if (templateRuleName.equalsIgnoreCase(templateName)) {//Suchen Sie die angegebene Vorlagenkonfiguration
template.setName(templateName);
template.setDesc(element.getAttributeValue("desc"));
template.setTemplateFile(element
.getAttributeValue("templateFile"));
List<element> tagList = ((Element) element.getChildren()
.get(0)).getChildren(); // Tag-Liste
Element-Tag = null;
RuleDTO RuleDTO = null;
Regeln = neuer Vektor<ruledto>();
for (int j = 0; j < tagList.size(); j++) {
tag = (Element) tagList.get(j);
RuleDTO = neues RuleDTO();
RuleDTO.setParmName(tag.getAttributeValue("name"));
RuleDTO.setParmDesc("【※"
+ tag.getAttributeValue("desc") + "※】");
RuleDTO.setParmSeq(tag.getAttributeValue("id"));
RuleDTO.setParmType(tag.getAttributeValue("type"));
if ("T".equalsIgnoreCase(tag
.getAttributeValue("ifEmptyDelete"))) {// Ob die Markierung gelöscht werden kann
RuleDTO.setIfEmptyDelete("T");
} anders {
RuleDTO.setIfEmptyDelete("F");
}
RuleDTO.setParmRegular(tag.getText());
// Wert
// Parametertyp bestimmen
String-Wert = (String) ((Map<string, string="">) RuleValue)
.get(ruleDTO.getParmRegular().replaceAll("#",
""));
RuleDTO.setParmValue(value);
Regeln.add(ruleDTO);
}
template.setRules(rules);
brechen;
}
}
} Catch (FileNotFoundException e) {
e.printStackTrace();
} Catch (JDOMException e) {
e.printStackTrace();
} Catch (IOException e) {
e.printStackTrace();
} Endlich {
versuchen {
in.close();
} Catch (Ausnahme e) {
e.printStackTrace();
}
}
Rücksendevorlage;
}
/**
* Finden Sie den übergeordneten Knoten
*/
öffentliches Element findElement(Element currNode, String parentNodeId) {
//Der Knoten wird als leer markiert
if (currNode == null || parentNodeId == null) {
null zurückgeben;
}
Element pNode = null;
Tun {
pNode = currNode.getParent();
currNode = pNode;
} while (parentNodeId.equalsIgnoreCase(pNode.getName()));
pNode zurückgeben;
}
/**
* Word-Datei erstellen
*/
@SuppressWarnings("ungeprüft")
public String build(Vorlagenvorlage) {
InputStream in = null;
OutputStream fo = null;
//Der Pfad zur generierten Datei
String file = "d://test//" + template.getDesc() + ".doc";
versuchen {
//Vorlagendatei lesen
in = this.getClass().getClassLoader()
.getResourceAsStream(template.getTemplateFile());
SAXBuilder sb = new SAXBuilder();
Dokument doc = sb.build(in);
Element root = doc.getRootElement(); // Holen Sie sich das Root-Element
Namespace ns = root.getNamespace();// NameSpace
// Das Element <wx:sect> ist in der Word-03-Vorlage vorhanden
List<element> sectList = root.getChild("body", ns).getChildren();
Element sectElement = (Element) sectList.get(0);
// Sammlung von Tags unter <w:p>
List<element> pTagList = sectElement.getChildren("p", ns);
// Sammlung von Tags unter <w:tbl>
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);
}
// Datei schreiben
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();
} Endlich {
versuchen {
in.close();
fo.close();
} Catch (Ausnahme e) {
e.printStackTrace();
}
}
Rückgabedatei;
}
/**
* Bei WORD-Vorlagen der Ebene <w:body><wx:sect><w:p> suchen und ersetzen Sie Tags unter <w:p>.
* @param pTagList:<w:p>collection
* @param RulesValue: RuleDTO-Sammlung
* @param ns: NameSpace-Objekt
* @param trChildren: die Sammlung der untergeordneten Knoten <w:tr> von <w:tbl>
*/
@SuppressWarnings("ungeprüft")
privater boolescher Wert 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;//Löschen Sie den aktuellen Knoten
boolean delCurrNode4TabWR = false;//Einen einzelnen Zeilenknoten in der Tabelle löschen
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("【※") != -1) {
for (int v = 0; v < RulesValue.size(); v++) {
RuleDTO dto = (RuleDTO) RulesValue.get(v);
if (text.indexOf(dto.getParmDesc().trim()) != -1) {
// Bestimmen Sie, ob der Attributwert zum Löschen nullfähig ist
if ("T".equals(dto.getIfEmptyDelete())
&& StringUtils.isBlank(dto
.getParmValue())) {
//Löschen Sie den obersten Knoten dieses Knotens
text = "";
if (trChildren != null) {//Löschen Sie diese Zeile für <w:tbl>
Element element = ((Element) p
.getParent()).getParent();
trChildren.remove(element);
delCurrNode4TabWR = true;
} else {//Segment für <w:r> löschen
// pTagList.remove(p);
pTagList.remove(pChildren);
delCurrNode = true;
}
brechen;
} anders {
text = text.replaceAll(dto.getParmDesc()
.trim(), dto.getParmValue());
}
}
}
t.setText(text);
}
if (delCurrNode4TabWR) {// <w:tbl>Der Zeilenknoten unter TABLE wurde gelöscht
delFlag = true;
brechen;
} else if (delCurrNode) {// Der Knoten unter <w:p> wurde gelöscht
ich--;
delFlag = true;
brechen;
}
}
}
}
return delFlag;
}
/**
* Suchen und ersetzen Sie bei WORD-Vorlagen mit Tabellen die Tags unter <w:tbl>.
* @param tblTagList:<w:tbl>-Sammlung
* @param RulesValue: RuleDTO-Sammlung
* @param ns: NameSpace-Objekt
*/
@SuppressWarnings("ungeprüft")
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++) {// Loop<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++) {// Schleife <w:tc>, um die <w:p>-Sammlung zu erhalten
Element tcChildren = (Element) tcTagList.get(c);
List<element> pTagList = tcChildren.getChildren("p", ns);
boolean delFlag = changeValue4PTag(pTagList, RulesValue,
ns, trKinder);
if (delFlag) {// Nach dem Löschen der Zeile müssen Sie die Zeigerposition von trChildren ändern
J--;
}
}
}
}
}
public static void main(String[] args) löst eine Ausnahme aus {
WordBuilder word = new WordBuilder();
Map<string, string=""> map = new HashMap<string, string="">();
//Parameter füllen
map.put("ToPartment", "XXX Company");
map.put("OwnerName", "Zhang San");
map.put("CountNum", "5");
map.put("Business", "Routine Check");
map.put("UsefulDays", "15");
map.put("Jahr", "2014");
map.put("Monat", "5");
map.put("Tag", "13");
map.put("ruleName", "RECOMMEND-LETTER");
Vorlage template = word.loadRules(map);
//Öffne die Datei direkt
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></ele ment></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,>
Schritt 4: Fertig
Einige zusammenfassende Punkte und Anmerkungen:
1. Der definierte Elementname muss mit dem gleichnamigen Wert in template_rule.xml übereinstimmen, andernfalls muss eine Konvertierungsregel festgelegt werden.
2. Der Text im Platzhalter [※※], der in der Vorlagen-XML definiert ist, muss mit dem entsprechenden Desc in template_rule.xml identisch sein, andernfalls muss eine Konvertierungsregel festgelegt werden.
3. Nach der Konfiguration der XML-Vorlage müssen Sie prüfen, ob der untergeordnete Knoten unter der Bezeichnung eine Bezeichnung ist (bezogen auf die WORD-Version). Wenn nicht, muss die Bezeichnung hinzugefügt werden.
4. Wenn Sie einen Label-Knoten dynamisch löschen möchten, muss sich der Inhalt dieses Knotens in derselben Zeile in der Vorlage befinden. Andernfalls können Sie die XML-Vorlage manuell anpassen.
5. Wenn Sie die automatische Zeilenumbruchfunktion von WORD implementieren müssen (es gibt noch keine bessere Lösung für den Zeilenumbruch in Vorlagen), müssen Sie zunächst die Anzahl der Wörter in der entsprechenden Zeile der Vorlage berechnen und dann die Leerzeichenfüllung verwenden um es zu erreichen.