Há algum tempo, recebi uma solicitação de um aplicativo da web para gerar automaticamente o Word. Agora compilei algumas etapas importantes para compartilhar.
Ideia: (Nota: Isto é apenas para a versão WORD2003, outras versões são semelhantes.)
Como os dados internos e o formato dos arquivos WORD são armazenados na forma de arquivos XML, os arquivos WORD podem ser facilmente convertidos do formato DOC para XML, e é muito mais conveniente operar arquivos XML, realizando assim a integração com várias operações independentes de plataforma gerar arquivos Word por meio de consulta de nó, substituição, exclusão, adição, etc. Portanto, a essência da geração de um arquivo WORD baseado em um modelo é o processo de substituir as tags especiais no arquivo XML pelos dados do usuário e salvá-los como um arquivo DOC.
Aqui estão algumas das principais etapas envolvidas (tomando uma carta de apresentação como exemplo)
Passo um: Faça um modelo WORD de acordo com suas necessidades
Crie um novo arquivo WORD no formato DOC, preencha o conteúdo do modelo conforme necessário e defina o formato do modelo, incluindo fontes, estilos, linhas em branco, etc. Use tags especiais (como: [※Nome da Unidade※]) para pré-ocupar o bit de dados que precisa ser preenchido e, em seguida, salvar o arquivo WORD recém-criado como um arquivo no formato XML. Desta forma, o template WORD está concluído, o código é o seguinte:
Adicione um novo arquivo de configuração denominado template-rule.xml, cada nó de modelo corresponde a um tipo de modelo. Há um nó de lista de tags em cada modelo. Todos os nós filhos contidos neste nó contêm informações sobre todos os nós que serão substituídos ou excluídos no modelo. As informações do nó incluem: valor do nó, nome em inglês do atributo do nó, descrição em chinês, tipo de campo. se pode ser excluído, etc. Ao definir este arquivo de configuração, você precisa observar que o valor do atributo desc deve ser consistente com o espaço reservado no modelo XML. Por exemplo: o item de entrada do ano [※Year※] definido no modelo XML precisa corresponder ao nome desc="Year" em template-rule.xml.
Copie o código do código da seguinte forma:
<!--?xml version="1.0" encoding="GB2312"?-->
<!-- Definição do modelo-->
<modelos>
<!-- Descrição: S-string; D-data; M-valor em letras maiúsculas;
<template name="RECOMMEND-LETTER" desc="Carta de apresentação" templatefile="template4.xml">
<taglist remark="Lista de tags de valor único">
<tag id="1" name="ToPartment" desc="Departamento de recebimento" type="S" ifemptydelete="T">#ToPartment</tag><!--Departamento de recebimento-->
<tag id="2" name="Nome do Proprietário" desc="Nome" type="S">#Nome do Proprietário</tag><!--Nome-->
<tag id="3" name="CountNum" desc="Número de pessoas" type="S">#CountNum</tag><!--Número de pessoas-->
<tag id="4" name="Negócios" desc="Content" type="S">#Negócios</tag><!--Content-->
<tag id="5" name="UsefulDays" desc="Período de validade" type="S">#UsefulDays</tag><!--Período de validade-->
<tag id="6" name="Ano" desc="ano" type="S">#Ano</tag><!--ano-->
<tag id="7" name="Mês" desc="mês" type="S">#Mês</tag><!--mês-->
<tag id="8" name="Dia" desc="日" type="S">#Dia</tag><!--Dia-->
</taglist>
</template>
</modelos>
Etapa 3: escrever código java
Copie o código do código da seguinte forma:
/**
* Parâmetros e regras
*/
classe pública RuleDTO {
/**
*nome da etiqueta
*/
private String parmName;
/**
* descrição da etiqueta
*/
string privada parmDesc;
/**
* etiquetar número de série
*/
string privada parmSeq;
/**
* tipo de valor de tag
*/
private String parmType;
/**
* nome do parâmetro da tag
*/
string privada parmRegular;
/**
* valor da etiqueta
*/
private String parmValue;
/**
*Se o valor da tag estiver vazio, exclua este atributo
*/
String privada ifEmptyDelete;
}
Copie o código do código da seguinte forma:
/**
* Descrição: informações do modelo do Word
*/
modelo de classe pública {
private String nome; // nome do modelo
private String desc;//descrição do modelo
private String templateFile; // arquivo de modelo
private Vector<ruledto> regras; // regras do modelo
}</ruledto>
Copie o código do código da seguinte forma:
classe pública WordBuilder {
/**
* Leia as regras de substituição com base no modelo
* @param templateName ID do modelo
*/
@SuppressWarnings("desmarcado")
modelo público loadRules(Map<string, string=""> regraValue) {
InputStream em = null;
Modelo modelo = novo modelo();
//Caminho do arquivo de configuração de regras
String regraFile = "template-rule.xml";
//Nome da regra do modelo
String templateRuleName = "";
tentar {
templateRuleName = regraValue.get("ruleName");
//Lê o arquivo de regras do modelo
in = this.getClass().getClassLoader().getResourceAsStream(ruleFile);
// Analisar regras do modelo
SAXBuilder sb = new SAXBuilder();
Documento doc = sb.build(in);
Elemento root = doc.getRootElement();
List<element> templateList = root.getChildren();//Todas as configurações do modelo
Elemento elemento = nulo;
Vector<ruledto> regras = null;
for (int i = 0; i < templateList.size(); i++) {// Percorrer todos os modelos
elemento = (Elemento) templateList.get(i);
String templateName = element.getAttributeValue("nome");
if (templateRuleName.equalsIgnoreCase(templateName)) {//Encontre a configuração do modelo fornecida
template.setName(templateName);
template.setDesc(element.getAttributeValue("desc"));
template.setTemplateFile(elemento
.getAttributeValue("templateFile"));
Lista<elemento> tagList = ((Elemento) element.getChildren()
.get(0)).getChildren(); // lista de tags
Tag do elemento = null;
RegraDTO regraDTO = null;
regras = new Vector<ruledto>();
for (int j = 0; j < tagList.size(); j++) {
tag = (Elemento) tagList.get(j);
regraDTO = nova regraDTO();
regraDTO.setParmName(tag.getAttributeValue("nome"));
regraDTO.setParmDesc("【※"
+ tag.getAttributeValue("desc") + "※】");
regraDTO.setParmSeq(tag.getAttributeValue("id"));
regraDTO.setParmType(tag.getAttributeValue("tipo"));
if ("T".equalsIgnoreCase(tag
.getAttributeValue("ifEmptyDelete"))) {// Se a marca pode ser excluída
regraDTO.setIfEmptyDelete("T");
} outro {
regraDTO.setIfEmptyDelete("F");
}
regraDTO.setParmRegular(tag.getText());
// valor
//Determina o tipo de parâmetro
Valor da string = (String) ((Mapa<string, string="">) regraValue)
.get(ruleDTO.getParmRegular().replaceAll("#",
""));
regraDTO.setParmValue(valor);
regras.add(ruleDTO);
}
template.setRules(regras);
quebrar;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finalmente {
tentar {
in.close();
} catch (Exceção e) {
e.printStackTrace();
}
}
modelo de devolução;
}
/**
* Encontre o nó pai
*/
Elemento público findElement(Elemento currNode, String parentNodeId) {
//O nó é marcado como vazio
if (currNode == null || parentNodeId == null) {
retornar nulo;
}
Elemento pNode = null;
fazer {
pNode = currNode.getParent();
currNode = pNode;
} while (parentNodeId.equalsIgnoreCase(pNode.getName()));
retornar pNode;
}
/**
* Gerar arquivo Word
*/
@SuppressWarnings("desmarcado")
construção de string pública (modelo de modelo) {
InputStream em = null;
OutputStream fo = null;
//O caminho para o arquivo gerado
Arquivo de string = "d://test//" + template.getDesc() + ".doc";
tentar {
//Lê o arquivo modelo
in = this.getClass().getClassLoader()
.getResourceAsStream(template.getTemplateFile());
SAXBuilder sb = new SAXBuilder();
Documento doc = sb.build(in);
Elemento root = doc.getRootElement(); // Obtém o elemento raiz
Namespace ns = root.getNamespace();// NameSpace
// O elemento <wx:sect> existe no modelo word 03
List<elemento> sectList = root.getChild("corpo", ns).getChildren();
Elemento sectElement = (Elemento) sectList.get(0);
// Coleção de tags em <w:p>
List<elemento> pTagList = sectElement.getChildren("p", ns);
// Coleção de tags em <w:tbl>
List<elemento> 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);
}
//grava arquivo
Saída XMLOutputter = new XMLOutputter(" ", true, "UTF-8");
fo = novo FileOutputStream(arquivo);
saída.output(doc, fo);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finalmente {
tentar {
in.close();
fo.fechar();
} catch (Exceção e) {
e.printStackTrace();
}
}
arquivo de retorno;
}
/**
* Para modelos WORD do nível <w:body><wx:sect><w:p>, encontre e substitua as tags em <w:p>.
* @param pTagList:<w:p>coleção
* @param regrasValue: coleção RuleDTO
* @param ns: objeto NameSpace
* @param trChildren: a coleção de nós filhos <w:tr> de <w:tbl>
*/
@SuppressWarnings("desmarcado")
private boolean changeValue4PTag(List<elemento> pTagList,
Vector<ruledto> regrasValue, Namespace ns, List<element> trChildren) {
Elemento p = nulo;
booleano delFlag = falso;
for (int i = 0; i <pTagList.size(); i++) {
boolean delCurrNode = false; //Exclui o nó atual
boolean delCurrNode4TabWR = false; // Exclui um único nó de linha na tabela
p = (Elemento) pTagList.get(i);
Lista<elemento> pChild = p.getChildren("r", ns);
for (int j = 0; pChild != null && j < pChild.size(); j++) {
Elemento pChildren = (Elemento) pChild.get(j);
Elemento t = pChildren.getChild("t", ns);
if (t! = nulo) {
String texto = t.getTextTrim();
if (text.indexOf("【※") != -1) {
for (int v = 0; v < regrasValue.size(); v++) {
RuleDTO dto = (RuleDTO) regrasValue.get(v);
if (text.indexOf(dto.getParmDesc().trim()) != -1) {
// Determina se o valor do atributo é anulável para exclusão
if ("T".equals(dto.getIfEmptyDelete())
&& StringUtils.isBlank(dto
.getParmValue())) {
//Exclui o nó superior deste nó
texto = "";
if (trChildren != null) {//Exclua esta linha para <w:tbl>
Elemento elemento = ((Elemento) p
.getParent()).getParent();
trCrianças.remove(elemento);
delCurrNode4TabWR = verdadeiro;
} else {//Excluir segmento de <w:r>
//pTagList.remove(p);
pTagList.remove(pCrianças);
delCurrNode = verdadeiro;
}
quebrar;
} outro {
texto = text.replaceAll(dto.getParmDesc()
.trim(), dto.getParmValue());
}
}
}
t.setText(texto);
}
if (delCurrNode4TabWR) {// <w:tbl>O nó da linha em TABLE foi excluído
delFlag = verdadeiro;
quebrar;
} else if (delCurrNode) {// O nó em <w:p> foi excluído
eu--;
delFlag = verdadeiro;
quebrar;
}
}
}
}
retornar delFlag;
}
/**
* Para modelos WORD contendo tabelas, localize e substitua as tags em <w:tbl>.
* @param tblTagList:<w:tbl> coleção
* @param regrasValue: coleção RuleDTO
* @param ns: objeto NameSpace
*/
@SuppressWarnings("desmarcado")
private void changeValue4TblTag(List<elemento> tblTagList,
Vector<ruledto> regrasValue, Namespace ns) {
Elemento p = nulo;
for (int i = 0; tblTagList != null && i < tblTagList.size(); i++) {
p = (Elemento) tblTagList.get(i);
List<elemento> trChildren = p.getChildren("tr", ns);
for (int j = 0; trChildren != null && j < trChildren.size(); j++) {// Loop<w:tr>
Elemento pChildren = (Elemento) trChildren.get(j);
List<elemento> tcTagList = pChildren.getChildren("tc", ns);
for (int c = 0; tcTagList != null && c < tcTagList.size(); c++) {// Loop <w:tc> para obter a coleção <w:p>
Elemento tcChildren = (Elemento) tcTagList.get(c);
List<elemento> pTagList = tcChildren.getChildren("p", ns);
boolean delFlag = changeValue4PTag(pTagList, regrasValue,
ns, trCrianças);
if (delFlag) {// Após excluir a linha, você precisa alterar a posição do ponteiro de trChildren
j--;
}
}
}
}
}
public static void main(String[] args) lança exceção {
Palavra do WordBuilder = new WordBuilder();
Mapa<string, string=""> mapa = new HashMap<string, string="">();
//preenche os parâmetros
map.put("ToPartment", "XXX Empresa");
map.put("NomeProprietário", "Zhang San");
map.put("ContNum", "5");
map.put("Negócios", "Verificação de Rotina");
map.put("DiasÚteis", "15");
map.put("Ano", "2014");
map.put("Mês", "5");
map.put("Dia", "13");
map.put("ruleName", "RECOMMEND-LETTER");
Modelo modelo = word.loadRules(mapa);
//Abre o arquivo diretamente
Runtime.getRuntime().exec("explorador " + 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,>
Etapa 4: Concluído
Alguns pontos resumidos e notas:
1. O nome do elemento definido deve ser consistente com o valor correspondente ao mesmo nome em template_rule.xml, caso contrário, uma regra de conversão precisará ser definida.
2. O texto no espaço reservado [※※] definido no modelo xml deve ser igual ao desc correspondente em template_rule.xml, caso contrário, uma regra de conversão precisará ser definida.
3. Após configurar o modelo XML, você precisa verificar se o nó filho sob o rótulo é um rótulo (relacionado à versão WORD, o rótulo deve ser adicionado).
4. Se você deseja excluir dinamicamente um nó de rótulo, o conteúdo desse nó precisa estar na mesma linha do modelo. Caso contrário, você pode ajustar manualmente o XML do modelo.
5. Se você precisar implementar a função de quebra automática de linha do WORD (ainda não há solução melhor para quebra de linha em modelos), primeiro você precisa calcular o número de palavras na linha correspondente do modelo e, em seguida, usar o preenchimento de espaço para alcançá-lo.