少し前に、Word を自動的に生成する Web アプリケーションのリクエストを受け取りましたので、いくつかの重要な手順をまとめました。
アイデア: (注: これは WORD2003 バージョンのみに関するもので、他のバージョンも同様です。)
WORD ファイルの内部データと形式は XML ファイルの形式で保存されているため、WORD ファイルは DOC から XML 形式に簡単に変換でき、XML ファイルの操作がより便利になり、プラットフォームに依存しないさまざまな操作との統合が実現します。ノードのクエリ、置換、削除、追加などを通じて Word ファイルを生成します。したがって、テンプレートに基づいて WORD ファイルを生成する本質は、XML ファイル内の特別なタグをユーザー データに置き換えて DOC ファイルとして保存するプロセスです。
ここでは、関連する重要な手順をいくつか示します (紹介状を例として取り上げます)。
ステップ 1: ニーズに応じて WORD テンプレートを作成する
新しい WORD ファイルを DOC 形式で作成し、必要に応じてテンプレートの内容を入力し、フォント、スタイル、空白行などのテンプレートの形式を設定します。特殊なタグ ([※ユニット名※] など) を使用して、埋める必要のあるデータビットを事前に占有してから、新しく作成した WORD ファイルを XML 形式のファイルとして保存します。こうしてWORDテンプレートが完成します。コードは以下のようになります。
template-rule.xml という名前の新しい構成ファイルを追加します。各テンプレート ノードはテンプレート タイプに対応します。各テンプレートにはタグリスト ノードがあり、このノードに含まれるすべての子ノードには、テンプレート内で置換または削除されるすべてのノードに関する情報が含まれます。ノード情報には、ノード値、ノード属性の英語名、中国語の説明、フィールド タイプ、削除できるかどうかなど。この構成ファイルを設定するときは、desc 属性の値がテンプレート XML 内のプレースホルダーと一致している必要があることに注意する必要があります。例: テンプレート XML に設定されている年の入力項目 [※年※] は、template-rule.xml の desc="年" 名に対応している必要があります。 コードは次のとおりです。
次のようにコードをコピーします。
<!--?xml バージョン="1.0" エンコーディング="GB2312"?-->
<!-- テンプレート定義 -->
<テンプレート>
<!-- 説明: S-文字列; E-金額; M-大文字の金額; ifEmptyDelete: 親ノードを削除する場合は T 値が空です、デフォルトは F -->
<template name="RECOMMEND-LETTER" desc="紹介状" templatefile="template4.xml">
<taglist 備考="単一値タグリスト">
<tag id="1" name="ToPartment" desc="受信部門" type="S" ifemptydelete="T">#ToPartment</tag><!--受信部門-->
<tag id="2" name="OwnerName" desc="Name" type="S">#OwnerName</tag><!--Name-->
<tag id="3" name="CountNum" desc="人数" type="S">#CountNum</tag><!--人数-->
<tag id="4" name="ビジネス" desc="Content" type="S">#ビジネス</tag><!--コンテンツ-->
<tag id="5" name="UsefulDays" desc="有効期間" type="S">#UsefulDays</tag><!--有効期間-->
<tag id="6" name="年" desc="year" type="S">#年</tag><!--年-->
<tag id="7" name="月" desc="month" type="S">#月</tag><!--month-->
<tag id="8" name="日" desc="日" type="S">#日</tag><!--日-->
</タグリスト>
</テンプレート>
</テンプレート>
ステップ 3: Java コードを作成する
次のようにコードをコピーします。
/**
* パラメータとルール
*/
パブリック クラス RuleDTO {
/**
* タグ名
*/
プライベート文字列parmName;
/**
* タグの説明
*/
プライベート文字列parmDesc;
/**
* タグのシリアル番号
*/
プライベート文字列parmSeq;
/**
* タグ値の型
*/
プライベート文字列parmType;
/**
* タグパラメータ名
*/
プライベート文字列parmREGULAR;
/**
* タグ値
*/
プライベート文字列parmValue;
/**
* タグ値が空の場合、この属性を削除します
*/
プライベート文字列 ifEmptyDelete;
}
次のようにコードをコピーします。
/**
* 説明: Word テンプレートの情報
*/
パブリック クラス テンプレート {
private String 名;//テンプレート名
private String desc;//テンプレートの説明
private String templateFile;//テンプレート ファイル
private Vector<ruledto> ルール;//テンプレート ルール
}</ruledto>
次のようにコードをコピーします。
パブリック クラス WordBuilder {
/**
* テンプレートに基づいて置換ルールを読み取る
* @param templateName テンプレート ID
*/
@SuppressWarnings("未チェック")
public Template loadRules(Map<string, string=""> rulesValue) {
入力ストリーム = null;
テンプレート template = new Template();
// ルール設定ファイルのパス
文字列ルールファイル = "テンプレートルール.xml";
// テンプレートルール名
文字列 templateRuleName = "";
試す {
templateRuleName = rulesValue.get("ruleName");
//テンプレートルールファイルを読み込む
in = this.getClass().getClassLoader().getResourceAsStream(ruleFile);
// テンプレートルールを解析する
SAXBuilder sb = 新しい SAXBuilder();
ドキュメント doc = sb.build(in);
Element root = doc.getRootElement() // ルート要素を取得します。
List<element> templateList = root.getChildren();//すべてのテンプレート設定
要素要素 = null;
Vector<ruledto> ルール = null;
for (int i = 0; i < templateList.size(); i++) {// すべてのテンプレートを走査します
element = (要素) templateList.get(i);
String templateName = element.getAttributeValue("name");
if (templateRuleName.equalsIgnoreCase(templateName)) {//指定されたテンプレート構成を検索します
template.setName(テンプレート名);
template.setDesc(element.getAttributeValue("desc"));
template.setTemplateFile(要素
.getAttributeValue("テンプレートファイル"));
List<要素> tagList = ((要素) element.getChildren()
.get(0)).getChildren(); // タグリスト
要素タグ = null;
RuleDTO ルールDTO = null;
rules = new Vector<ruledto>();
for (int j = 0; j < tagList.size(); j++) {
tag = (要素) tagList.get(j);
ルールDTO = 新しいルールDTO();
rulesDTO.setParmName(tag.getAttributeValue("name"));
rulesDTO.setParmDesc("【※"
+ tag.getAttributeValue("desc") + "※】");
rulesDTO.setParmSeq(tag.getAttributeValue("id"));
rulesDTO.setParmType(tag.getAttributeValue("type"));
if ("T".equalsIgnoreCase(タグ
.getAttributeValue("ifEmptyDelete"))) {// マークを削除できるかどうか
rulesDTO.setIfEmptyDelete("T");
} それ以外 {
rulesDTO.setIfEmptyDelete("F");
}
rulesDTO.setParm Regular(tag.getText());
// 価値
// パラメータの型を決定する
文字列値 = (文字列) ((Map<string, string="">) ルール値)
.get(ruleDTO.getParm Regular().replaceAll("#",
""));
rulesDTO.setParmValue(値);
rules.add(ruleDTO);
}
template.setRules(ルール);
壊す;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} キャッチ (JDOMException e) {
e.printStackTrace();
} キャッチ (IOException e) {
e.printStackTrace();
} ついに {
試す {
in.close();
} catch (例外 e) {
e.printStackTrace();
}
}
テンプレートを返す;
}
/**
* 親ノードを見つける
*/
public Element findElement(Element currNode, StringparentNodeId) {
// ノードは空としてマークされます
if (currNode == null ||parentNodeId == null) {
null を返します。
}
要素 pNode = null;
する {
pNode = currNode.getParent();
currNode = pNode;
while (parentNodeId.equalsIgnoreCase(pNode.getName()));
pNode を返します。
}
/**
* Wordファイルを生成
*/
@SuppressWarnings("未チェック")
public String build(テンプレートテンプレート) {
入力ストリーム = null;
出力ストリーム fo = null;
// 生成されたファイルへのパス
文字列ファイル = "d://test//" + template.getDesc() + ".doc";
試す {
//テンプレートファイルを読み込む
in = this.getClass().getClassLoader()
.getResourceAsStream(template.getTemplateFile());
SAXBuilder sb = 新しい SAXBuilder();
ドキュメント doc = sb.build(in);
Element root = doc.getRootElement() // ルート要素を取得します。
名前空間 ns = root.getNamespace();// 名前空間
// <wx:sect> 要素は Word 03 テンプレートに存在します
List<要素> sectList = root.getChild("body", ns).getChildren();
要素sectElement = (要素)sectList.get(0);
// <w:p> の下のタグのコレクション
List<要素> pTagList = sectElement.getChildren("p", ns);
// <w:tbl> の下のタグのコレクション
List<要素> 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);
}
// ファイルを書き込む
XMLOutputter outp = new XMLOutputter(" ", true, "UTF-8");
fo = 新しい FileOutputStream(ファイル);
outp.output(doc, fo);
} catch (FileNotFoundException e) {
e.printStackTrace();
} キャッチ (JDOMException e) {
e.printStackTrace();
} キャッチ (IOException e) {
e.printStackTrace();
} ついに {
試す {
in.close();
fo.close();
} catch (例外 e) {
e.printStackTrace();
}
}
ファイルを返す;
}
/**
* <w:body><wx:sect><w:p> レベルの WORD テンプレートの場合、<w:p> の下のタグを検索して置換します。
* @param pTagList:<w:p>コレクション
* @param rulesValue: RuleDTO コレクション
* @param ns: NameSpace オブジェクト
* @param trChildren: <w:tbl> の子ノード <w:tr> のコレクション
*/
@SuppressWarnings("未チェック")
private booleanchangeValue4PTag(List<要素> pTagList,
Vector<ruledto> rulesValue, Namespace ns, List<element> trChildren) {
要素 p = null;
ブール値 delFlag = false;
for (int i = 0; i < pTagList.size(); i++) {
boolean delCurrNode = false;//現在のノードを削除します
boolean delCurrNode4TabWR = false;//テーブル内の単一行ノードを削除します
p = (要素) pTagList.get(i);
List<要素> pChild = p.getChildren("r", ns);
for (int j = 0; pChild != null && j < pChild.size(); j++) {
要素 pChildren = (要素) pChild.get(j);
要素 t = pChildren.getChild("t", ns);
if (t != null) {
文字列テキスト = 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) {
// 属性値が削除のために NULL 可能かどうかを判断します
if ("T".equals(dto.getIfEmptyDelete())
&& StringUtils.isBlank(dto
.getParmValue())) {
// このノードの最上位ノードを削除します
テキスト = "";
if (trChildren != null) {//<w:tbl> のこの行を削除します
要素要素 = ((要素) p
.getParent()).getParent();
trChildren.remove(要素);
delCurrNode4TabWR = true;
} else {//<w:r> のセグメントを削除します
// pTagList.remove(p);
pTagList.remove(pChildren);
delCurrNode = true;
}
壊す;
} それ以外 {
text = text.replaceAll(dto.getParmDesc()
.trim()、dto.getParmValue());
}
}
}
t.setText(テキスト);
}
if (delCurrNode4TabWR) {// <w:tbl>TABLE の下の行ノードが削除されました
delFlag = true;
壊す;
} else if (delCurrNode) {// <w:p> 下のノードが削除されました
私 - ;
delFlag = true;
壊す;
}
}
}
}
delFlag を返します。
}
/**
* 表を含む WORD テンプレートの場合は、<w:tbl> の下のタグを検索して置換します。
* @param tblTagList:<w:tbl> コレクション
* @param rulesValue: RuleDTO コレクション
* @param ns: NameSpace オブジェクト
*/
@SuppressWarnings("未チェック")
private void changeValue4TblTag(List<要素> tblTagList,
Vector<ruledto> rulesValue、名前空間 ns) {
要素 p = null;
for (int i = 0; tblTagList != null && i < tblTagList.size(); i++) {
p = (要素) tblTagList.get(i);
List<要素> trChildren = p.getChildren("tr", ns);
for (int j = 0; trChildren != null && j < trChildren.size(); j++) {// Loop<w:tr>
要素 pChildren = (要素) trChildren.get(j);
List<要素> tcTagList = pChildren.getChildren("tc", ns);
for (int c = 0; tcTagList != null && c < tcTagList.size(); c++) {// <w:tc> をループして <w:p> コレクションを取得します
要素 tcChildren = (要素) tcTagList.get(c);
List<要素> pTagList = tcChildren.getChildren("p", ns);
boolean delFlag =changeValue4PTag(pTagList, rulesValue,
ns、trChildren);
if (delFlag) {// 行を削除した後、trChildren のポインタの位置を変更する必要があります
j--;
}
}
}
}
}
public static void main(String[] args) throws Exception {
WordBuilder word = new WordBuilder();
Map<string, string=""> map = new HashMap<string, string="">();
//パラメータを入力します
map.put("ToPartment", "XXX Company");
map.put("オーナー名", "張三");
map.put("カウント数", "5");
map.put("ビジネス", "定期チェック");
map.put("UsefulDays", "15");
map.put("年", "2014");
map.put("月", "5");
map.put("日", "13");
map.put("ルール名", "推奨レター");
テンプレート template = word.loadRules(map);
// ファイルを直接開く
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,>
ステップ 4: 完了
いくつかの要約ポイントとメモ:
1. 定義された要素名は、template_rule.xml 内の同じ名前に対応する値と一致している必要があります。そうでない場合は、変換ルールを設定する必要があります。
2. テンプレート XML で定義されたプレースホルダー [※※] 内のテキストは、template_rule.xml の対応する記述と同じである必要があります。そうでない場合は、変換ルールを設定する必要があります。
3. テンプレート XML を構成した後、ラベルの下の子ノードがラベルであるかどうかを確認する必要があります (WORD バージョンに関連します)。そうでない場合は、ラベルを追加する必要があります。
4. ラベル ノードを動的に削除する場合は、このノードのコンテンツがテンプレート内の同じ行にある必要があります。そうでない場合は、テンプレート XML を手動で調整できます。
5. WORD の自動行折り返し機能を実装する必要がある場合 (テンプレートでの行折り返しについてこれより良い解決策はまだありません)、まずテンプレートの対応する行の単語数を計算してから、スペース充填を使用する必要があります。それを達成するために。