Generar documentos de Word RTF con php

15 de febrero de 2005
Valoración del artículo:
Crear archivos RTF combinando un documento con datos almacenados en la Intranet/Extranet.
En muchos desarrollos web surge la necesidad de crear documentos que proceden de la combinación de un documento origen con los datos almacenados en la Intranet/Extranet de la empresa, algo parecido a lo que se consigue con la combinación de correspondencia de Word.

Ejemplos prácticos pueden ser los siguientes:

Generación de etiquetas a partir de una base de datos de clientes o artículos
Certificados o diplomas para los alumnos de un curso
Listados de participantes en un evento.
El control de la impresión desde un documento HTML es algo bastante complejo, por lo que generar un documento DOC, o mejor dicho RTF, nos permitirá resolver nuestro problema de una manera muy efectiva.

En este artículo desarrollaremos un ejemplo práctico, el de obtener un certificado de asistencia para cada uno de los alumnos que asisten a un curso.

La estrategia:
Nuestra estrategia se fundamenta en los siguientes pasos:

Partimos del documento en formato de Word que queremos obtener.
Convertimos el formato .DOC en .RTF. (Los archivos .RTF son de texto legible)
Introducimos en el documento .RTF unos códigos manuales que serán sustituidos por los datos procedentes de la base de datos.
Creamos una aplicación en PHP que lea el archivo .RTF y sustituya los códigos introducidos por los datos buscados.

Primer paso, Preparar la plantilla:

Para nuestro ejemplo partimos de un documento .DOC que certifica que un alumno ha realizado un curso. En la siguiente imagen vemos un certificado tipo.


Será preciso crear un certificado para cada uno de los alumnos que ha realizado un curso, los datos que varía son los del alumno y los del curso realizado.

Una vez abierto el documento con Word, lo guardamos en formato RTF y sustituimos cada dato variable por unos códigos fácilmente reconocibles. Ojo, el formato RTF es muy puñetero, por lo que será preciso escribir los códigos sin confundirse para que no se introduzcan caracteres raros.


En el caso del ejemplo utilizamos la # y el * de tal manera que por ejemplo, sustituimos el nombre del alumno por #*NOMBRE*#

Guardaremos el documento con el nombre de plantilla.rtf

Segundo paso, El programa PHP:

Crearemos dos funciones auxiliares, la primera se llama leef().


Esta función como se puede ver, recibe como argumento el nombre del fichero RTF, lo abre y almacena el contenido en la variable de texto $todo. Esta función por tanto devuelve el contenido de un fichero.

La siguiente función, rtf(), es la que crea un RTF a partir de una plantilla y sustituyendo los códigos por los datos de la Intranet.



Esta función recibe cuatro argumentos:

$sql: la sentencia sql que devuelve los datos que se necesitan
$plantilla: la plantilla RTF con los códigos
$fsalida: el nombre del fichero resultado
$matequivalencias: una matriz con las equivalencias entre los datos procedentes de la sentencia sql y los campos del certificado.
Vamos a comentar línea por línea el programa:

Las líneas 13 y 14 determinan el nombre y la ruta del fichero de salida, utilizamos la función time() para asegurarnos de que no se producirán dos ficheros con el mismo nombre.

En la línea 17 se almacena el contenido de la plantilla en la variable $txtplantilla

En las líneas de la 19 a la 24 se extrae el cuerpo del documento RTF, el cuerpo del documento es lo que se repite, para extraerlo primero obtenemos la cabecera del documento, la cabecera queda determinada por la etiqueta rtf sectd. Un documento rtf termina siempre en }, con esa información extraemos el cuerpo.

En el paso 3, a partir de la línea 26 vamos escribiendo el archivo resultado.

En la línea 27 escribimos la cabecera del documento

En la línea 28 ejecutamos la consulta y en la 29 entramos un un bucle, en cada ciclo obtendremos los datos de un alumno y crearemos un certificado.

En la línea 30 creamos una copia del cuerpo del documento llamada $despues, sobre esa copia realizaremos los cambios.

En la línea 31 entramos en un bucle que recorre la matriz de equivalencias, la línea 32 obtiene de la base de datos el dato, la línea 34 obtiene de la matriz el código a sustituir en la plantilla y la línea 35 sustituye el dato por el código.

Una vez sustituidos todos los campos la línea 37 escribe el certificado del alumno y las líneas 38 y 39 generan un salto de página para volver a escribir el siguiente certificado.

Una vez que hemos salido del While que va extrayendo los datos, la línea 41 cierra el documento rtf y la 42 la escritura del fichero.

Tercer paso, Llamada a la función RTF:
Una vez hemos creado estas dos funciones ya podemos llamar a la función rtf() y generar el documento.



Comentamos las líneas:

En la línea 48 especificamos cual es la plantilla.

En la línea 49 establecemos la sentencia SQL que extrae los datos, en el caso del ejemplo es un poco compleja pues extrae los datos de varias tablas.

En las líneas desde la 50 a la 71 creamos la matriz de equivalencias, se trata de una matriz de dos dimensiones que relaciona el código que se encontrará en el archivo RTF con el campo de la sentencia SQL.

La línea 72 llama a la función rtf()

Y por fin las líneas 73 y 74 generan un enlace al archivo resultado.

Mejoras y comentarios.
Todo en esta vida es susceptible de ser mejorado, en este caso me queda pendiente el generar el archivo de salida directamente al navegador, con el objeto de no tenerlo que escribir en el disco duro.

Además tenemos desarrollados ejemplos de listados y de etiquetas que podemos documentar en posteriores artículos.

Un aspecto importante para seguir progresando en este tema es conocer la sintaxis de los documentos rtf, se trata de un trabajo un poco durillo que también podemos abordar en posteriores artículos.

Comentarios
Fueron enviados 35 comentarios al artículo
28 comentarios no revisados
7 comentarios revisados:
Por: Toni Martorell
18/2/2005
He probado este artículo pero me da un errar en la linea 74. he cambiado la secuencia sql para que atacara a una base de datos de mi servidor pero supongo que no lo hago bien, me gustaria saber si al alguien le a ido bien y si es así como lo ha conseguido.
p.d. podriais hacer un ejemplo más sencillo con la secuencia sql, de antemano muchas gracias por vuestros consejos y clases
Por: Matyx
15/5/2005
No probé la función... pero se podría optimizar mucho la carga del archivo a una variable de texto utilizando:

a)
$var = file_get_contents($nombre_archivo);

b) //Si usamos una version anterior a la 4.3...
$var = implode("", file($nombre_archivo));

Salu2!
Por: German Infante
07/7/2005
el artículo es intresante, le hacen falta algunas líneas de código para realizar bien la conexión a mysql desde PHP. Ya lo probé y funciona perfectamente y como lo dice su autor la plantilla en formato rtf es bastante sensible con caracteres extraños. Edite la plantilla con un editor de php como el maguma y elimine los caracteres extraños y todo funciono OK.
Bucaramanga-Colombia
Por: Fabi
18/8/2005
linea 6 del codigo (función leef())cambiar:
$tamleef - sizeof($texto);
por
$tamleef = sizeof($texto);




juan_fe...
Problemas con tablas
30/7/2010
Tengo problemas al querer remplazar los datos de una tabla, todo me funciona pero con tablas imposible.

ericksu...
NO JALA ARCHIVOS DE MI WeB
20/11/2011
BUEN DIA QUISE CONECTAR A UNA BASE DE DATOS PERO PARESE QUE ALGO ESTA MAL NO ME JALA UN ARCHIVO, SI PUDIERAS ME PODRIAS ESCRIBIR LA SENTENCIA DETALLADAMENTE,

GRACIAS
DUDAS CON EL CODIGO
Por: Carlos Sanchez
16/10/2012
EL CODIGO ME FUNCIONO PERFECTO CUADNO LO PROBE LOCAL PERO AHORA ME DA PROBLEMAS CUANDO LO MONTE AL SERVIDOR YA QUE ME LO GUARDA EN OTRA UBICACION Y EN BLANCO QUIEN ME PODRIA AYUDAR<br />
, LA CONEXION SE RELAIZO CON POSTGRES, SALUDOS Y GRACIAS<br />
<br />
&lt;?php<br />
function leef($fichero)<br />
{<br />
$texto= file($fichero);<br />
$tamleef = sizeof($texto);<br />
for ($n=0; $n&lt;$tamleef;$n++)<br />
{ $todo = $todo.$texto[$n];}<br />
return $todo;<br />
}<br />
<br />
function rtf($sql, $plantilla, $fsalida, $matequivalencias)<br />
{<br />
$pre=time();<br />
$fsalida=$_SERVER[&#039;DOCUMENT_ROOT&#039;].&quot;SIMCEDMod_Historialplanilla_Generadas&quot;.$pre.$fsalida;<br />
//$fsalida=&quot;C:varwwwlogicasa_desaSIMCEDMod_Historialplanilla_Generadas&quot;.$pre.$fsalida;<br />
$user = &#039;postgres&#039;;<br />
$passwd = &#039;postgres&#039;;<br />
$db = &#039;SIMCED&#039;;<br />
$port = 5432;<br />
$host = &#039;127.0.0.1&#039;;<br />
$strCnx = &quot;host=$host port=$port dbname=$db user=$user password=$passwd&quot;;<br />
$link=pg_connect($strCnx);<br />
<br />
$txtplantilla=leef($plantilla);<br />
<br />
$matriz=explode(&quot;sectd&quot;,$txtplantilla);<br />
$cabecera=$matriz[0].&quot;sectd&quot;;<br />
$inicio=strlen($cabecera);<br />
$final=strrpos($txtplantilla,&quot;}&quot;);<br />
$largo=$final-$inicio;<br />
$cuerpo=substr($txtplantilla,$inicio,$largo);<br />
<br />
$punt = fopen($fsalida ,&quot;w&quot;);<br />
fputs($punt,$cabecera);<br />
//mssql_select_db(&quot;SGRH1&quot;,$link);<br />
$result=pg_query($sql);<br />
while($row=pg_fetch_array($result)){<br />
$despues=$cuerpo;<br />
foreach($matequivalencias as $dato){<br />
$datosql=$row[$dato[1]];<br />
$datosql=stripslashes($datosql);<br />
$datortf=$dato[0];<br />
$despues=str_replace($datortf,$datosql,$despues);<br />
}<br />
fputs($punt,$despues);<br />
//$saltopag=&quot;par page par&quot;;<br />
fputs($punt,$saltopag);<br />
}<br />
fputs($punt,&quot;}&quot;);<br />
fclose($punt);<br />
return $fsalida;<br />
}<br />
<br />
<br />
function GenerarDoc($idModificador) {<br />
$idModificador;<br />
<br />
$plantilla=&quot;plantilla.rtf&quot;;<br />
//Incluimos libreria<br />
include_once(&quot;class_historial/class_Historial.php&quot;);<br />
$objectDocument= new operacionHistorial();<br />
$fecha_actual = date(&quot;d/m/Y&quot;);<br />
$sql = $objectDocument-&gt;selectDocumentoG($idModificador,$fecha_actual);<br />
<br />
$equivalencia[0][0]=&quot;#*Solicitante*#&quot;;<br />
$equivalencia[0][1]=&quot;nombre_doc&quot;; <br />
$equivalencia[1][0]=&quot;#*Dia*#&quot;;<br />
$equivalencia[1][1]=&quot;dia&quot;; <br />
$equivalencia[2][0]=&quot;#*Mes*#&quot;;<br />
$equivalencia[2][1]=&quot;mes&quot;; <br />
$equivalencia[3][0]=&quot;#*Anio*#&quot;;<br />
$equivalencia[3][1]=&quot;anio&quot;; <br />
$equivalencia[4][0]=&quot;#*cant_personas*#&quot;;<br />
$equivalencia[4][1]=&quot;id_doc_aso&quot;; <br />
$equivalencia[5][0]=&quot;#*Especialidad*#&quot;;<br />
$equivalencia[5][1]=&quot;descripcion&quot;; <br />
$equivalencia[6][0]=&quot;#*tiempo*#&quot;;<br />
$equivalencia[6][1]=&quot;per_dest&quot;;<br />
$equivalencia[7][0]=&quot;#*gerencia*#&quot;;<br />
$equivalencia[7][1]=&quot;cargo_dest&quot;;<br />
$equivalencia[8][0]=&quot;#*cant_personas*#&quot;;<br />
$equivalencia[8][1]=&quot;NUMERO_PLAZAS&quot;;<br />
$equivalencia[9][0]=&quot;#*Especialidad*#&quot;;<br />
$equivalencia[9][1]=&quot;ESPECIALIDAD&quot;;<br />
$equivalencia[10][0]=&quot;#*tiempo*#&quot;;<br />
$equivalencia[10][1]=&quot;TIPO_CONTRATO&quot;;<br />
$equivalencia[11][0]=&quot;#*gerencia*#&quot;;<br />
$equivalencia[11][1]=&quot;AREA&quot;;<br />
$equivalencia[12][0]=&quot;#*Funciones*#&quot;;<br />
$equivalencia[12][1]=&quot;FUNCIONES&quot;;<br />
$equivalencia[13][0]=&quot;#*Beneficios*#&quot;;<br />
$equivalencia[13][1]=&quot;BENEFICIOS&quot;;<br />
$equivalencia[14][0]=&quot;#*Observaciones*#&quot;;<br />
$equivalencia[14][1]=&quot;OBSERVACIONES&quot;;<br />
$equivalencia[15][0]=&quot;#*Aprobado*#&quot;;<br />
$equivalencia[15][1]=&quot;APROBACION&quot;;<br />
<br />
<br />
<br />
$salida=rtf($sql,$plantilla,&quot;certificado.rtf&quot;,$equivalencia);<br />
/*$salida=&quot;&lt;a href=&#039;$salida&#039;&gt;Obtener&lt;/a&gt;&quot;;*/<br />
/*echo (&quot;&lt;p&gt;$salida&lt;/p&gt;&quot;);*/<br />
return $salida;<br />
<br />
}<br />
?&gt;

Manuales relacionados
Categorias relacionadas
El autor
Alfredo Anaya
Director Técnico de ADR Formacion
http://www.adrformacion.com


Últimas noticias
Donaciones
Si piensas que te hemos ayudado y merecemos tu apoyo económico...