Hace algún tiempo, recibí una solicitud para una aplicación web que generara Word automáticamente. Ahora he recopilado algunos pasos clave para compartir.
Idea: (Nota: esto es sólo para la versión WORD2003, otras versiones son similares).
Debido a que los datos internos y el formato de los archivos WORD se almacenan en forma de archivos XML, los archivos WORD se pueden convertir fácilmente del formato DOC al formato XML, y es mucho más conveniente operar archivos XML, logrando así la integración con varias operaciones independientes de la plataforma. generar archivos de Word mediante consulta de nodos, reemplazo, eliminación, adición, etc. Por lo tanto, la esencia de generar un archivo WORD basado en una plantilla es el proceso de reemplazar las etiquetas especiales en el archivo XML con datos del usuario y luego guardarlo como un archivo DOC.
Estos son algunos de los pasos clave involucrados (tomando una carta de presentación como ejemplo)
Paso uno: Haz una plantilla de WORD según tus necesidades
Cree un nuevo archivo WORD en formato DOC, complete el contenido de la plantilla según sea necesario y establezca el formato de la plantilla, incluidas fuentes, estilos, líneas en blanco, etc. Utilice etiquetas especiales (como: [※Nombre de la unidad※]) para ocupe previamente los datos que deben completarse y luego guarde el archivo WORD recién creado como un archivo de formato XML. De esta forma se completa la plantilla WORD, el código es el siguiente:
Agregue un nuevo archivo de configuración llamado template-rule.xml, cada nodo de plantilla corresponde a un tipo de plantilla. Hay un nodo de lista de etiquetas en cada plantilla. Todos los nodos secundarios contenidos en este nodo contienen información sobre todos los nodos que serán reemplazados o eliminados en la plantilla. La información del nodo incluye: valor del nodo, nombre en inglés del atributo del nodo, descripción en chino, tipo de campo. si se puede eliminar, etc. Al configurar este archivo de configuración, debe tener en cuenta que el valor del atributo desc debe ser coherente con el marcador de posición en la plantilla XML. Por ejemplo: el elemento de entrada del año [※Year※] establecido en la plantilla XML debe corresponder al nombre desc="Year" en template-rule.xml. El código es el siguiente:
Copie el código de código de la siguiente manera:
<!--?xml versión="1.0" codificación="GB2312"?-->
<!-- Definición de plantilla-->
<plantillas>
<!-- Descripción: cadena S; fecha D; cantidad E; cantidad M en mayúscula; ifEmptyDelete: el valor T está vacío para eliminar el nodo principal, el valor predeterminado es F -->
<template name="RECOMMEND-LETTER" desc="Carta de presentación" templatefile="template4.xml">
<taglist comment="Lista de etiquetas de valor único">
<tag id="1" name="ToPartment" desc="Departamento de recepción" type="S" ifemptydelete="T">#ToPartment</tag><!--Departamento de recepción-->
<tag id="2" nombre="NombrePropietario" desc="Nombre" tipo="S">#NombrePropietario</tag><!--Nombre-->
<tag id="3" name="CountNum" desc="Número de personas" type="S">#CountNum</tag><!--Número de personas-->
<tag id="4" name="Negocio" desc="Contenido" tipo="S">#Negocio</tag><!--Contenido-->
<tag id="5" name="Días Útiles" desc="Período de validez" type="S">#DíasÚtiles</tag><!--Período de validez-->
<tag id="6" name="Año" desc="año" type="S">#Año</tag><!--año-->
<tag id="7" name="Mes" desc="mes" type="S">#Mes</tag><!--mes-->
<tag id="8" name="Día" desc="日" type="S">#Día</tag><!--Día-->
</etiqueta>
</plantilla>
</plantillas>
Paso 3: escribir código java
Copie el código de código de la siguiente manera:
/**
* Parámetros y reglas.
*/
regla de clase públicaDTO {
/**
* nombre de la etiqueta
*/
nombre del parámetro de cadena privada;
/**
* descripción de la etiqueta
*/
cadena privada parmDesc;
/**
* número de serie de la etiqueta
*/
cadena privada parmSeq;
/**
* tipo de valor de etiqueta
*/
parmType de cadena privada;
/**
* nombre del parámetro de etiqueta
*/
parmRegular de cadena privada;
/**
* valor de etiqueta
*/
cadena privada parmValue;
/**
* Si el valor de la etiqueta está vacío, elimine este atributo
*/
Cadena privada ifEmptyDelete;
}
Copie el código de código de la siguiente manera:
/**
* Descripción: información de la plantilla de Word
*/
Plantilla de clase pública {
nombre de cadena privada;//nombre de plantilla
cadena privada desc;//descripción de la plantilla
plantilla de cadena privadaFile;//archivo de plantilla
reglas privadas de Vector<ruledto>;//reglas de plantilla
}</ruledto>
Copie el código de código de la siguiente manera:
constructor de palabras de clase pública {
/**
* Leer reglas de reemplazo basadas en plantilla
* @param templateName ID de plantilla
*/
@SuppressWarnings("sin marcar")
Plantilla pública loadRules(Map<string, string=""> ruleValue) {
InputStream en = nulo;
Plantilla plantilla = nueva Plantilla();
// Ruta del archivo de configuración de reglas
String ruleFile = "template-rule.xml";
// Nombre de la regla de la plantilla
Cadena templateRuleName = "";
intentar {
templateRuleName = ruleValue.get("reglaName");
//Leer el archivo de reglas de plantilla
en = this.getClass().getClassLoader().getResourceAsStream(ruleFile);
// Analizar reglas de plantilla
SAXBuilder sb = nuevo SAXBuilder();
Documento doc = sb.build(in);
Elemento raíz = doc.getRootElement() // Obtener el elemento raíz
List<element> templateList = root.getChildren();//Todas las configuraciones de plantilla
Elemento elemento = nulo;
Vector<ruledto> reglas = null;
for (int i = 0; i < templateList.size(); i++) {// Recorrer todas las plantillas
elemento = (Elemento) templateList.get(i);
String templateName = element.getAttributeValue("nombre");
if (templateRuleName.equalsIgnoreCase(templateName)) {//Encuentre la configuración de plantilla proporcionada
plantilla.setName(nombredeplantilla);
template.setDesc(element.getAttributeValue("desc"));
plantilla.setTemplateFile(elemento
.getAttributeValue("templateFile"));
Lista<elemento> lista de etiquetas = ((Elemento) elemento.getChildren()
.get(0)).getChildren(); // lista de etiquetas
Etiqueta de elemento = nulo;
ReglaDTO reglaDTO = nulo;
reglas = nuevo Vector<ruledto>();
for (int j = 0; j < tagList.size(); j++) {
etiqueta = (Elemento) tagList.get(j);
reglaDTO = nueva ReglaDTO();
ruleDTO.setParmName(tag.getAttributeValue("nombre"));
ruleDTO.setParmDesc("【※"
+ tag.getAttributeValue("desc") + "※】");
ruleDTO.setParmSeq(tag.getAttributeValue("id"));
ruleDTO.setParmType(tag.getAttributeValue("tipo"));
si ("T".equalsIgnoreCase(etiqueta
.getAttributeValue("ifEmptyDelete"))) {// Si la marca se puede eliminar
reglaDTO.setIfEmptyDelete("T");
} demás {
reglaDTO.setIfEmptyDelete("F");
}
reglaDTO.setParmRegular(tag.getText());
// valor
// Determinar el tipo de parámetro
Valor de cadena = (Cadena) ((Map<string, string="">) ruleValue)
.get(ruleDTO.getParmRegular().replaceAll("#",
""));
reglaDTO.setParmValue(valor);
reglas.add(reglaDTO);
}
plantilla.setRules(reglas);
romper;
}
}
} captura (FileNotFoundException e) {
e.printStackTrace();
} captura (JDOMException e) {
e.printStackTrace();
} captura (IOException e) {
e.printStackTrace();
} finalmente {
intentar {
cercar();
} captura (Excepción e) {
e.printStackTrace();
}
}
plantilla de devolución;
}
/**
* Encuentra el nodo padre
*/
Elemento público findElement (Elemento currNode, String parentNodeId) {
//El nodo está marcado como vacío
if (currNode == nulo || parentNodeId == nulo) {
devolver nulo;
}
Elemento pNodo = nulo;
hacer {
pNodo = currNode.getParent();
nodocurr = nodop;
} mientras (parentNodeId.equalsIgnoreCase(pNode.getName()));
devolver pNodo;
}
/**
* Generar archivo de Word
*/
@SuppressWarnings("sin marcar")
compilación de cadena pública (plantilla de plantilla) {
InputStream en = nulo;
Flujo de salida fo = nulo;
//La ruta al archivo generado
Archivo de cadena = "d://test//" + template.getDesc() + ".doc";
intentar {
//Leer archivo de plantilla
en = this.getClass().getClassLoader()
.getResourceAsStream(template.getTemplateFile());
SAXBuilder sb = nuevo SAXBuilder();
Documento doc = sb.build(in);
Elemento raíz = doc.getRootElement() // Obtener el elemento raíz
Espacio de nombres ns = root.getNamespace();// Espacio de nombres
// El elemento <wx:sect> existe en la plantilla de palabra 03
Lista<elemento> sectList = root.getChild("body", ns).getChildren();
Elemento sectElement = (Elemento) sectList.get(0);
// Colección de etiquetas bajo <w:p>
Lista<elemento> pTagList = sectElement.getChildren("p", ns);
// Colección de etiquetas bajo <w:tbl>
Lista<elemento> tblTagList = sectElement.getChildren("tbl", ns);
si (pTagList! = nulo && pTagList.size() > 0) {
changeValue4PTag(pTagList, template.getRules(), ns, null);
}
si (tblTagList! = nulo && tblTagList.size() > 0) {
changeValue4TblTag(tblTagList, template.getRules(), ns);
}
//escribir archivo
Salida XMLOutputter = nueva XMLOutputter(" ", verdadero, "UTF-8");
fo = nuevo FileOutputStream(archivo);
salida.salida(doc, fo);
} captura (FileNotFoundException e) {
e.printStackTrace();
} captura (JDOMException e) {
e.printStackTrace();
} captura (IOException e) {
e.printStackTrace();
} finalmente {
intentar {
cercar();
fo.cerrar();
} captura (Excepción e) {
e.printStackTrace();
}
}
archivo de devolución;
}
/**
* Para plantillas WORD del nivel <w:body><wx:sect><w:p>, busque y reemplace etiquetas en <w:p>.
* @param pTagList:<w:p>colección
* @param reglasValue: colección RuleDTO
* @param ns: objeto NameSpace
* @param trChildren: la colección de nodos secundarios <w:tr> de <w:tbl>
*/
@SuppressWarnings("sin marcar")
cambio booleano privadoValue4PTag(Lista<elemento> pTagList,
Vector<ruledto> reglasValor, Espacio de nombres ns, Lista<elemento> trChildren) {
Elemento p = nulo;
booleano delFlag = falso;
para (int i = 0; i < pTagList.size(); i++) {
boolean delCurrNode = false;//Eliminar el nodo actual
boolean delCurrNode4TabWR = false;//Eliminar un nodo de una sola fila en la tabla
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);
si (t! = nulo) {
Texto de cadena = t.getTextTrim();
si (texto.indexOf("【※") != -1) {
for (int v = 0; v < reglasValue.size(); v++) {
RuleDTO dto = (RuleDTO) reglasValue.get(v);
si (text.indexOf(dto.getParmDesc().trim()) != -1) {
// Determinar si el valor del atributo se puede anular para su eliminación
si ("T".equals(dto.getIfEmptyDelete())
&& StringUtils.isBlank(dto
.getParmValue())) {
//Eliminar el nodo superior de este nodo
texto = "";
if (trChildren != null) {//Eliminar esta fila para <w:tbl>
Elemento elemento = ((Elemento) p
.getParent()).getParent();
trChildren.remove(elemento);
delCurrNode4TabWR = verdadero;
} else {//Eliminar segmento para <w:r>
// pTagList.remove(p);
pTagList.remove(pChildren);
delCurrNode = verdadero;
}
romper;
} demás {
texto = texto.replaceAll(dto.getParmDesc()
.trim(), dto.getParmValue());
}
}
}
t.setText(texto);
}
if (delCurrNode4TabWR) {// <w:tbl>El nodo de fila en TABLA ha sido eliminado
delFlag = verdadero;
romper;
} else if (delCurrNode) {// El nodo bajo <w:p> ha sido eliminado
i--;
delFlag = verdadero;
romper;
}
}
}
}
devolver delFlag;
}
/**
* Para plantillas de WORD que contienen tablas, busque y reemplace etiquetas en <w:tbl>.
* @param tblTagList:<w:tbl> colección
* @param reglasValue: colección RuleDTO
* @param ns: objeto NameSpace
*/
@SuppressWarnings("sin marcar")
cambio vacío privadoValue4TblTag(Lista<elemento> tblTagList,
Vector<ruledto> reglasValor, Espacio de nombres ns) {
Elemento p = nulo;
for (int i = 0; tblTagList! = nulo && i < tblTagList.size(); i++) {
p = (Elemento) tblTagList.get(i);
Lista<elemento> trChildren = p.getChildren("tr", ns);
for (int j = 0; trChildren != null && j < trChildren.size(); j++) {// Bucle<w:tr>
Elemento pChildren = (Elemento) trChildren.get(j);
Lista<elemento> tcTagList = pChildren.getChildren("tc", ns);
for (int c = 0; tcTagList != null && c < tcTagList.size(); c++) {// Bucle <w:tc> para obtener la colección <w:p>
Elemento tcChildren = (Elemento) tcTagList.get(c);
Lista<elemento> pTagList = tcChildren.getChildren("p", ns);
booleano delFlag = changeValue4PTag(pTagList, reglasValue,
ns, trNiños);
if (delFlag) {// Después de eliminar la fila, debe cambiar la posición del puntero de trChildren
j--;
}
}
}
}
}
public static void main (String [] args) lanza una excepción {
palabra de WordBuilder = nuevo WordBuilder();
Mapa<cadena, cadena=""> mapa = nuevo HashMap<cadena, cadena="">();
//completar parámetros
map.put("ToPartment", "XXX Empresa");
map.put("Nombre del propietario", "Zhang San");
map.put("CountNum", "5");
map.put("Negocios", "Comprobación de rutina");
map.put("Días Útiles", "15");
map.put("Año", "2014");
map.put("Mes", "5");
map.put("Día", "13");
map.put("NombreRegla", "LETRA RECOMENDADA");
Plantilla plantilla = word.loadRules(mapa);
//Abre el archivo directamente
Runtime.getRuntime().exec("explorador" + word.build(plantilla));
}
}</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,>
Paso 4: hecho
Algunos puntos y notas resumidas:
1. El nombre del elemento definido debe ser coherente con el valor correspondiente al mismo nombre en template_rule.xml; de lo contrario, se debe establecer una regla de conversión.
2. El texto en el marcador de posición [※※] definido en la plantilla xml debe ser el mismo que el desc correspondiente en template_rule.xml; de lo contrario, se debe establecer una regla de conversión.
3. Después de configurar la plantilla XML, debe verificar si el nodo secundario debajo de la etiqueta es una etiqueta (relacionada con la versión WORD, de lo contrario, se debe agregar la etiqueta).
4. Si desea eliminar dinámicamente un nodo de etiqueta, el contenido de este nodo debe estar en la misma línea en la plantilla. De lo contrario, puede ajustar manualmente el XML de la plantilla.
5. Si necesita implementar la función de ajuste de línea automático de WORD (aún no existe una mejor solución para el ajuste de línea en las plantillas), primero debe calcular la cantidad de palabras en la línea correspondiente de la plantilla y luego usar el relleno de espacios. para lograrlo.