Aprende a crear un archivo de Word que admita Microsoft Office Open XML (OOXML u OpenXML), OASIS Open Document Format para aplicaciones de Office (OpenDocument u ODF), Rich Text Format (RTF).

Cómo crear un archivo de Word con PHP en Symfony 3

Muchas aplicaciones PHP requieren exportar documentos en formatos de Microsoft Word, esta tarea se puede lograr fácilmente usando PHPWord. PHPWord es una biblioteca escrita en PHP puro que proporciona un conjunto de clases para escribir y leer desde diferentes formatos de archivos de documentos. La versión actual de PHPWord es compatible con Microsoft Office Open XML (OOXML u OpenXML), OASIS Open Document Format para aplicaciones de Office (OpenDocument u ODF), Rich Text Format (RTF), HTML y PDF. PHPWord es un proyecto de código abierto con licencia según los términos de la versión 3 de LGPL . PHPWord tiene como objetivo ser un producto de software de alta calidad incorporando integración continua y pruebas unitarias. Puede obtener más información sobre PHPWord leyendo la documentación para desarrolladores y la documentación de la API .

Con PHPWord puede crear hermosos documentos Word y PDF desde cero. Cree plantillas y edite solo algunas variables para facilitar la creación de documentos de Word. En este artículo, aprenderá a implementar PHPWord en un proyecto Symfony 3.

Requisitos

Para crear archivos de Word con PHP, como se mencionó anteriormente, vamos a depender de la biblioteca PHPWord . Para instalar esta biblioteca como una dependencia en su proyecto Symfony, ejecute el siguiente comando en una terminal:

composer install phpoffice/phpword

O modifique el composer.jsonarchivo de su proyecto y agregue la biblioteca manualmente y luego ejecute composer install:

{
    "require": {
       "phpoffice/phpword": "v0.13.*"
    }
}

Después de la descarga, su proyecto debería tener PhpWord disponible para su uso. Si desea obtener más información sobre esta biblioteca, visite el repositorio oficial de Github .

Ejemplos

En este artículo, vamos a cubrir las 4 características más utilizadas por los desarrolladores cuando trabajan con PHPWord. Si necesita más ejemplos, le recomendamos que consulte todos los ejemplos de PHPWord aquí (aunque no están basados ​​en Symfony, estoy seguro de que comprenderá cómo usarlos).

Nota

En los ejemplos estamos usando el programa de escritura Word2007 (archivo OOXML) para aumentar la compatibilidad de nuestro documento. Además, como una buena práctica en Symfony, es posible que desee mantener su controlador lo más delgado posible, por lo que le recomendamos que cree servicios 

1. Transmisión de un archivo generado dinámicamente

Lamentablemente, el escritor de Phpword no proporciona ningún método para transmitir un documento, además, si existiera, no sería útil ya que estamos trabajando con Symfony. Para devolver un archivo generado como respuesta, deberá crearlo y luego enviarlo usando la clase BinaryFileResponse, sin embargo, no nos encargaremos de crear un archivo en algún lugar de su servidor y luego eliminarlo. Para que sea más fácil, puede crear un archivo temporal en el sistema usando  tempnam(sys_get_temp_dir(), "filename.extension").

El siguiente controlador crea un archivo de Word y se devuelve inmediatamente como un archivo adjunto:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

// Incluya BinaryFileResponse y ResponseHeaderBag
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

// Incluya las clases obligatorias de Phpword
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // Crea un nuevo documento de Word
        $phpWord = new PhpWord();

        /* Nota: cualquier elemento que agregue a un documento debe residir dentro de una sección. */

        // Agregar una sección vacía al documento ...
        $section = $phpWord->addSection();
        // Añadiendo un elemento de texto a la sección con estilo de fuente por defecto ...
        $section->addText(
            '"Learn from yesterday, live for today, hope for tomorrow. '
            . 'The important thing is not to stop questioning." '
            . '(Albert Einstein)'
        );

        // Guardando el documento como archivo OOXML ...
        $objWriter = IOFactory::createWriter($phpWord, 'Word2007');

        // Crea un archivo temporal en el sistema
        $fileName = 'hello_world_download_file.docx';
        $temp_file = tempnam(sys_get_temp_dir(), $fileName);

        // Escribir en la ruta del archivo temporal
        $objWriter->save($temp_file);

        // Envíe el archivo temporal como respuesta (como adjunto)
        $response = new BinaryFileResponse($temp_file);
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $fileName
        );

        return $response;
    }
}

2. Guarde el archivo en el servidor.

De forma predeterminada, puede escribir un archivo de Word generado en una ruta local utilizando el savemétodo de un escritor y proporcionando la ruta de destino con el nombre del archivo como primer argumento:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

// El objeto de respuesta
use Symfony\Component\HttpFoundation\Response;

// Incluya las clases obligatorias de Phpword
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // Crea un nuevo documento de Word
        $phpWord = new PhpWord();

        /* Nota: cualquier elemento que agregue a un documento debe residir dentro de una sección. */

        // Agregar una sección vacía al documento ...
        $section = $phpWord->addSection();
        // Añadiendo un elemento de texto a la sección con estilo de fuente por defecto ...
        $section->addText(
            '"Learn from yesterday, live for today, hope for tomorrow. '
            . 'The important thing is not to stop questioning." '
            . '(Albert Einstein)'
        );

        // Guardando el documento como archivo OOXML ...
        $objWriter = IOFactory::createWriter($phpWord, 'Word2007');

        $filePath = 'hello_world_serverfile.docx';
        // Escribir archivo en la ruta
        $objWriter->save($filePath);

        return new Response("Archivo escrito correctamente en $filePath");
    }
}

3. Insertar una imagen en un documento de Word

Para agregar una imagen, puede usar el addImagemétodo disponible en la clase PhpWord:

Nota

En el ejemplo, estamos usando la siguiente imagen de demostración (earth.jpg)  disponible en el repositorio oficial para fines de prueba .

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

// Devolver una respuesta de texto
use Symfony\Component\HttpFoundation\Response;


// Incluya las clases obligatorias de Phpword
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\Style\Image;
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\SimpleType\Jc;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {

        $phpWord = new PhpWord();

        // Obtener la ruta de la carpeta de imágenes en Symfony
        $imagesFolder = $this->get('kernel')->getRootDir() . '/../web/images/';
        $_local_image_path = $imagesFolder.'earth.jpg';

        // Código de inicio
        $section = $phpWord->addSection();
        $section->addText('Local image without any styles:');
        $section->addImage($_local_image_path);
        $section->addTextBreak(2);
        $section->addText('Local image with styles:');
        $section->addImage($_local_image_path, array('width' => 210, 'height' => 210, 'alignment' => Jc::CENTER));
        $section->addTextBreak(2);

        // 1) Agregar una imagen remota
        $source = 'http://php.net/images/logos/php-med-trans-light.gif';
        $section->addText("Remote image from: {$source}");
        $section->addImage($source);

        // Estilo de envoltura
        $text = str_repeat('Hello World! ', 15);
        $wrappingStyles = array('inline', 'behind', 'infront', 'square', 'tight');
        foreach ($wrappingStyles as $wrappingStyle) {
            $section->addTextBreak(5);
            $section->addText("Wrapping style {$wrappingStyle}");
            $section->addImage(
                $_local_image_path,
                array(
                    'positioning'   => 'relative',
                    'marginTop'     => -1,
                    'marginLeft'    => 1,
                    'width'         => 80,
                    'height'        => 80,
                    'wrappingStyle' => $wrappingStyle,
                )
            );
            $section->addText($text);
        }

        // Posicionamiento absoluto
        $section->addTextBreak(3);
        $section->addText('Absolute positioning: see top right corner of page');
        $section->addImage(
            $_local_image_path,
            array(
                'width'            => Converter::cmToPixel(3),
                'height'           => Converter::cmToPixel(3),
                'positioning'      => Image::POSITION_ABSOLUTE,
                'posHorizontal'    => Image::POSITION_HORIZONTAL_RIGHT,
                'posHorizontalRel' => Image::POSITION_RELATIVE_TO_PAGE,
                'posVerticalRel'   => Image::POSITION_RELATIVE_TO_PAGE,
                'marginLeft'       => Converter::cmToPixel(15.5),
                'marginTop'        => Converter::cmToPixel(1.55),
            )
        );

        // Posicionamiento relativo
        $section->addTextBreak(3);
        $section->addText('Relative positioning: Horizontal position center relative to column,');
        $section->addText('Vertical position top relative to line');
        $section->addImage(
            $_local_image_path,
            array(
                'width'            => Converter::cmToPixel(3),
                'height'           => Converter::cmToPixel(3),
                'positioning'      => Image::POSITION_RELATIVE,
                'posHorizontal'    => Image::POSITION_HORIZONTAL_CENTER,
                'posHorizontalRel' => Image::POSITION_RELATIVE_TO_COLUMN,
                'posVertical'      => Image::POSITION_VERTICAL_TOP,
                'posVerticalRel'   => Image::POSITION_RELATIVE_TO_LINE,
            )
        );

        // Guardando el documento como archivo OOXML ...
        $objWriter = IOFactory::createWriter($phpWord, 'Word2007');

        $filePath = 'hello_world_images.docx';
        // Escribir archivo en la ruta
        $objWriter->save($filePath);

        return new Response("Archivo escrito correctamente en $filePath");
    }
}

4. Insertar gráficos en un archivo de Word

En Word, los gráficos son ideales para presentar información gráficamente y también es bastante fácil agregarlos con PHPWord (las EMU se utilizan para coordenadas en dibujos basados ​​en vectores e imágenes incrustadas):

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

// Devolver una respuesta de texto
use Symfony\Component\HttpFoundation\Response;


// Incluya las clases obligatorias de Phpword
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\Shared\Converter;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {

        $phpWord = new PhpWord();

        // Definir estilos
        $phpWord->addTitleStyle(1, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240));
        $phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240));


        // Gráficos 2D
        $section = $phpWord->addSection();
        $section->addTitle('2D charts', 1);
        $section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous'));
        $chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar');
        $twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar');
        $threeSeries = array('bar', 'line');
        $categories = array('A', 'B', 'C', 'D', 'E');
        $series1 = array(1, 3, 2, 5, 4);
        $series2 = array(3, 1, 7, 2, 6);
        $series3 = array(8, 3, 2, 5, 4);

        foreach ($chartTypes as $chartType) {
            $section->addTitle(ucfirst($chartType), 2);
            $chart = $section->addChart($chartType, $categories, $series1);
            $chart->getStyle()->setWidth(Converter::inchToEmu(2.5))->setHeight(Converter::inchToEmu(2));
            if (in_array($chartType, $twoSeries)) {
                $chart->addSeries($categories, $series2);
            }
            if (in_array($chartType, $threeSeries)) {
                $chart->addSeries($categories, $series3);
            }
            $section->addTextBreak();
        }

        // Gráficos 3D
        $section = $phpWord->addSection(array('breakType' => 'continuous'));
        $section->addTitle('3D charts', 1);
        $section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous'));
        $chartTypes = array('pie', 'bar', 'column', 'line', 'area');
        $multiSeries = array('bar', 'column', 'line', 'area');
        $style = array('width' => Converter::cmToEmu(5), 'height' => Converter::cmToEmu(4), '3d' => true);

        foreach ($chartTypes as $chartType) {

            $section->addTitle(ucfirst($chartType), 2);

            $chart = $section->addChart($chartType, $categories, $series1, $style);

            if (in_array($chartType, $multiSeries)) {
                $chart->addSeries($categories, $series2);
                $chart->addSeries($categories, $series3);
            }

            $section->addTextBreak();
        }


        // Guardando el documento como archivo OOXML ...
        $objWriter = IOFactory::createWriter($phpWord, 'Word2007');

        $filePath = 'hello_world_charts.docx';
        // Escribir archivo en la ruta
        $objWriter->save($filePath);

        return new Response("Archivo escrito correctamente en $filePath");
    }
}

Te recomendamos que leas la documentación para ver todas las cosas increíbles que puedes hacer con PHPWord.

Que te diviertas ❤️!


Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores