En este post vamos a ver cómo trabajar con documentos de Word usando el lenguaje de programación PHP y la librería PHPWord, parte de la familia de PHPOffice.
Lo que veremos será cómo:
Este tutorial es la tercera parte de una serie de tutoriales sobre documentos de Word y PHP.
Recuerda ver la primera parte para ver cómo instalar la librería y su uso básico, así como la segunda parte para trabajar con listas, tablas e imágenes.
Agregar una marca de agua es tan sencillo como agregar una imagen; solo que la misma se agrega a un encabezado o header, no a una sección.
Para agregar un encabezado se crea una sección, y después se llama al método addHeader
.
Más tarde, se llama a $encabezado->addWatermark
para poner una marca de agua; con dos argumentos: la ruta de la imagen y un arreglo con el estilo de la misma.
<?php
/**
* Trabajar con documentos de Word y PHP usando PHPOffice
*
* Más tutoriales en: parzibyte.me/blog
*
* Ejemplo 7:
* Agregar marca de agua
* Nota: se utiliza la notación corta de arreglos [], que se pueden remplazar por array(),
* más información en https://parzibyte.me/blog/2018/10/11/sintaxis-corta-array-php/
*/require_once "vendor/autoload.php";
use PhpOffice\PhpWord\Style\Language;
$documento = new \PhpOffice\PhpWord\PhpWord();
$propiedades = $documento->getDocInfo();
$propiedades->setCreator("Luis Cabrera Benito");
$propiedades->setTitle("Marca de agua");
$seccion = $documento->addSection();
$encabezado = $seccion->addHeader();
$encabezado->addWatermark("conejo.jpg", [
"width" => 500,
]);
# Títulos. Solo modificando depth (el número)
$fuenteTitulo = [
"name" => "Verdana",
"size" => 20,
"color" => "000000",
];
$documento->addTitleStyle(1, $fuenteTitulo);
$seccion->addTitle("Gopher", 1);
$seccion->addText("Los geómidos son una familia de roedores castorimorfos conocidos vulgarmente como tuzas, taltuzas o ratas de abazones. Se encuentran en Canadá, Estados Unidos, México, América Central y Colombia. En México habitan seis especies que se encuentran en peligro de extinción. ");
$seccion->addTitle("Conejo", 1);
$seccion->addText("El conejo común o conejo europeo es una especie de mamífero lagomorfo de la familia Leporidae, y el único miembro actual del género Oryctolagus. Está incluido en la lista 100 de las especies exóticas invasoras más dañinas del mundo de la Unión Internacional para la Conservación de la Naturaleza.");
# Para que no diga que se abre en modo de compatibilidad
$documento->getCompatibility()->setOoxmlVersion(15);
# Idioma español de México
$documento->getSettings()->setThemeFontLang(new Language("ES-MX"));
# Guardarlo
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($documento, "Word2007");
$objWriter->save("7-marca-de-agua.docx");
Después de haber agregado la marca de agua se puede agregar todo tipo de contenido a la sección: títulos, texto, más imágenes, etcétera.
Nota: puedes ver el documento generado aquí.
Para agregar un TOC o tabla de contenido addTOC
de una sección.
Recuerda que existirá una tabla de contenido si hay títulos, así que debes separar el documento por título.
En el ejemplo le pasamos dos argumento a addTOC
: en primer lugar un arreglo con la fuente y en segundo lugar un arreglo de opciones, el cual solo lleva la forma en la que separa el título del número de páginas, y lo hace a través de guiones bajos.
<?php
/**
* Trabajar con documentos de Word y PHP usando PHPOffice
*
* Más tutoriales en: parzibyte.me/blog
*
* Ejemplo 8:
* Agregar contenido y un índice
* Nota: se utiliza la notación corta de arreglos [], que se pueden remplazar por array(),
* más información en https://parzibyte.me/blog/2018/10/11/sintaxis-corta-array-php/
*/require_once "vendor/autoload.php";
use PhpOffice\PhpWord\Style\Language;
use PhpOffice\PhpWord\Style\TOC;
$documento = new \PhpOffice\PhpWord\PhpWord();
$propiedades = $documento->getDocInfo();
$propiedades->setCreator("Luis Cabrera Benito");
$propiedades->setTitle("Tabla de contenidos");
/*
Todos los textos deben estar dentro de una sección
*/
$seccion = $documento->addSection();
# Registrar el estilo del título
$fuenteTitulo = [
"name" => "Verdana",
"size" => 20,
"color" => "000000",
];
$documento->addTitleStyle(1, $fuenteTitulo);
# Agregar el título del índice
$seccion->addTitle("Índice", 1);
# Aquí agregamos la tabla de contenidos
$fuenteTablaContenidos = [
"name" => "Arial",
"size" => 20,
"color" => "881111",
];
$estiloTablaDeContenidos = [
"tabLeader" => TOC::TABLEADER_UNDERSCORE,
];
$seccion->addTOC($fuenteTablaContenidos, $estiloTablaDeContenidos);
$seccion->addTitle("Lorem", 1);
# Texto bajo el título
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addTitle("Ipsum", 1);
# Texto bajo el título
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addTitle("Dolor", 1);
# Texto bajo el título
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
# Ahora un subtítulo con profundidad de 2
$fuenteSubtitulo = [
"name" => "Verdana",
"size" => 18,
"color" => "000000",
];
$documento->addTitleStyle(2, $fuenteSubtitulo);
$seccion->addTitle("Soy un subtítulo", 2);
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addTitle("Soy un subtítulo", 2);
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
$seccion->addTitle("Otro título", 1);
$seccion->addTitle("Otro subtítulo", 2);
# Texto bajo el título
$seccion->addText("Lorem ipsum dolor sit amet consectetur adipiscing elit, cursus facilisi id risus aliquet enim, varius ultricies dictum suspendisse mollis non.");
# Para que no diga que se abre en modo de compatibilidad
$documento->getCompatibility()->setOoxmlVersion(15);
# Idioma español de México
$documento->getSettings()->setThemeFontLang(new Language("ES-MX"));
# Guardarlo
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($documento, "Word2007");
$objWriter->save("8-tabla-de-contenidos.docx");
Estos separadores están definidos en la clase PhpOffice\PhpWord\Style\TOC.
Dentro del ejemplo se agrega un índice al inicio, y más adelante se agregan múltiples encabezados para que la tabla tenga contenido.
El resultado es el siguiente:
Puedes ver el documento completo en este enlace.
Gracias a PHPWord podemos agregar múltiples gráficas y datos de una manera sencilla. Vamos a ver cómo trabajar con gráficas de dona (o como se diga en español), gráficas de pastel, de área (o como se diga en español), de barras y de líneas.
Las gráficas se agregan a una sección a través del método addChart
, el cual recibe 3 argumentos:
Adicionalmente hay algunas gráficas que soportan multiseries o múltiples datos, para agregar más datos a la gráfica debemos guardar lo que regresa addChart
y luego llamar al método addSeries
, con dos argumentos: las etiquetas y los valores que se agregan.
<?php
/**
* Trabajar con documentos de Word y PHP usando PHPOffice
*
* Más tutoriales en: parzibyte.me/blog
*
* Ejemplo 9:
* Gráficas
* Nota: se utiliza la notación corta de arreglos [], que se pueden remplazar por array(),
* más información en https://parzibyte.me/blog/2018/10/11/sintaxis-corta-array-php/
*/require_once "vendor/autoload.php";
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\Style\Language;
$documento = new \PhpOffice\PhpWord\PhpWord();
$propiedades = $documento->getDocInfo();
$propiedades->setCreator("Luis Cabrera Benito");
$propiedades->setTitle("Gráficas");
$seccion = $documento->addSection();
# Títulos. Solo modificando depth (el número)
$fuenteTitulo = [
"name" => "Verdana",
"size" => 20,
"color" => "000000",
];
$documento->addTitleStyle(1, $fuenteTitulo);
$estilo = [
"width" => Converter::cmToEmu(17),
"height" => Converter::cmToEmu(10),
];
# Gráfica con una sola línea
$seccion->addTitle("Ventas del año actual", 1);
$etiquetas = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$series = [600, 700, 999, 1000, 2800, 3000, 5000, 3000, 6000, 6000, 5000, 7000];
# Gráfica con 3 líneas
$grafica = $seccion->addChart("line", $etiquetas, $series, $estilo);
$seccion->addTitle("Comparación de ventas", 1);
$etiquetas = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$series = [600, 700, 999, 1000, 2800, 3000, 5000, 3000, 6000, 6000, 5000, 7000];
$grafica = $seccion->addChart("line", $etiquetas, $series, $estilo);
# Agregar más datos...
$grafica->addSeries($etiquetas, [500, 132, 32, 432, 332, 456, 212, 5333, 4568, 123, 879, 4544]);
$grafica->addSeries($etiquetas, [999, 4848, 4544, 7833, 4549, 454, 212, 666, 121, 999, 454, 335]);
# La misma de arriba, pero no de tipo line, sino bar
$seccion->addTitle("Comparación de ventas", 1);
$etiquetas = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$series = [600, 700, 999, 1000, 2800, 3000, 5000, 3000, 6000, 6000, 5000, 7000];
$grafica = $seccion->addChart("bar", $etiquetas, $series, $estilo);
# Agregar más datos...
$grafica->addSeries($etiquetas, [500, 132, 32, 432, 332, 456, 212, 5333, 4568, 123, 879, 4544]);
$grafica->addSeries($etiquetas, [999, 4848, 4544, 7833, 4549, 454, 212, 666, 121, 999, 454, 335]);
# La misma de arriba, pero no de tipo bar, sino column
$seccion->addTitle("Comparación de ventas", 1);
$etiquetas = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$series = [600, 700, 999, 1000, 2800, 3000, 5000, 3000, 6000, 6000, 5000, 7000];
$grafica = $seccion->addChart("column", $etiquetas, $series, $estilo);
# Agregar más datos...
$grafica->addSeries($etiquetas, [500, 132, 32, 432, 332, 456, 212, 5333, 4568, 123, 879, 4544]);
$grafica->addSeries($etiquetas, [999, 4848, 4544, 7833, 4549, 454, 212, 666, 121, 999, 454, 335]);
# La misma de arriba, pero no de tipo column, sino area
$seccion->addTitle("Comparación de ventas", 1);
$etiquetas = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$series = [600, 700, 999, 1000, 2800, 3000, 5000, 3000, 6000, 6000, 5000, 7000];
$grafica = $seccion->addChart("area", $etiquetas, $series, $estilo);
# Agregar más datos...
$grafica->addSeries($etiquetas, [500, 132, 32, 432, 332, 456, 212, 5333, 4568, 123, 879, 4544]);
$grafica->addSeries($etiquetas, [999, 4848, 4544, 7833, 4549, 454, 212, 666, 121, 999, 454, 335]);
# Una de pastel
$seccion->addTitle("Gastos por categoría", 1);
$etiquetas = ["Comida", "Escuela", "Tecnología"];
$series = [123, 456, 789];
$grafica = $seccion->addChart("pie", $etiquetas, $series, $estilo);
# Una de dona
$seccion->addTitle("Gastos por categoría", 1);
$etiquetas = ["Comida", "Escuela", "Tecnología"];
$series = [123, 456, 789];
$grafica = $seccion->addChart("doughnut", $etiquetas, $series, $estilo);
# La primera, pero en 3d
$estilo = [
"width" => Converter::cmToEmu(17),
"height" => Converter::cmToEmu(10),
"3d" => true,
];
$seccion->addTitle("Ventas del año actual", 1);
$etiquetas = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
$series = [600, 700, 999, 1000, 2800, 3000, 5000, 3000, 6000, 6000, 5000, 7000];
$grafica = $seccion->addChart("line", $etiquetas, $series, $estilo);
# Para que no diga que se abre en modo de compatibilidad
$documento->getCompatibility()->setOoxmlVersion(15);
# Idioma español de México
$documento->getSettings()->setThemeFontLang(new Language("ES-MX"));
# Guardarlo
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($documento, "Word2007");
$objWriter->save("9-graficas.docx");
En el código usamos un conversor de medidas de la clase PhpOffice\PhpWord\Shared\Converter, llamando al método cmToEmu
, centímetros a Emu (una unidad de medida especialmente para los estándares de estos documentos)
Además de las gráficas podemos agregar títulos o texto como normalmente se hace.
Para indicar que una gráfica sea 3d ponemos la clave del arreglo “3d” en true.
Mira todas las gráficas y el documento en este enlace.
Así concluyo esta serie de posts sobre PHPWord para la creación de documentos de Word usando PHP.
Por el momento no hay métodos documentados para leer un documento de Word, es decir, hacer el proceso inverso (al menos con esta librería)
Supongo que la complejidad es que a diferencia de las hojas de cálculo, un documento de Word no tiene una estructura definida (no solo tiene celdas).
Tal vez tiene secciones y las secciones tienen muchas cosas, pero será un lío hacer una manera fácil de leer los datos.
En fin, tal vez en un futuro se agreguen estas características para leer un documento de Word, aunque no lo veo tan necesario; pero tal vez a un cliente se le ocurra, uno nunca sabe.
La parte 1 de este tutorial está aquí, y la parte 2 aquí. El código con los ejemplos y archivos generados en mi GitHub, la librería también en GitHub y la documentación en readthedocs.
En este post te quiero compartir mi experiencia tramitando un acta de nacimiento de México…
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
Esta web usa cookies.
Ver comentarios
Que tal, yo quisiera saber si se puede crear varios archivos de Word al mismo tiempo. Todos los comandos que se utilizan para crear el documentos estand dentro de un for o un foreach que debería de crear un nuevo documento recorriendo un arreglo con la información que necesito. Es decir, quiero crear un nuevo documento con una misma plantilla donde solo me cambie el nombre del documento y un dato de la información que contiene la plantilla dentro de esta..