Forum


Replies: 6   Views: 2706
Reemplazar bookmark
Topic closed:
Please note this is an old forum thread. Information in this post may be out-to-date and/or erroneous.
Every phpdocx version includes new features and improvements. Previously unsupported features may have been added to newer releases, or past issues may have been corrected.
We encourage you to download the current phpdocx version and check the Documentation available.

Posted by j660971@mvrht.com  · 18-01-2017 - 15:54

Deleted by j660971@mvrht.com · 18-01-2017 - 15:58

Posted by Samuel  · 18-01-2017 - 15:59

Hola,

Disculpa, escribí antes con una cuenta incorrecta. No hay licencia asociada a esta cuenta ya que la licencia la tiene el cliente para el que trabajamos.

En un paso, generamos un docx con bookmarks, conteniendo éstos graficas y texto, del siguiente modo:

$docx->addBookmark(array(
    'type' => 'start',
    'name' => "chapter_module_$chapter[id]"
));

$docx->add...

[...]

$docx->addBookmark(array(
    'type' => 'end',
    'name' => "chapter_module_$chapter[id]"
));

Y generamos el docx. Una vez abierto con MS Word, podemos ver los bookmarks, al seleccionar uno se selecciona todo su contenido, etc.

En otro paso, el usuario sube el docx y queremos reemplazar el contenido del bookmark por otro, mediante:

$docx->replaceWordContent($wordfragment, $reference_node)

Pero no logro hacerlo funcionar. Veo que replaceWordContent() no permite que type sea 'bookmark', en la documentación se indica "paragraph (also for bookmarks, links and lists)", así que he probado de la siguiente manera:

$reference_node = array(
    'type' => 'paragraph',
    'attributes' => array(
        'name' => "chapter_module_$chapter[id]"
    )
);
$docx->replaceWordContent($content, $reference_node);

Pero no funciona.

De hecho, a pesar de que en word aparecen los bookmarks, getDOCXPathQueryInfo creo que no los encuentra:

$reference_node = array(
    'type' => 'bookmark',
);

$query_result = $docx->getDOCXPathQueryInfo($reference_node);
var_dump($query_result);

Devuelve:

array(size=2)
  'length' => int 0
  'query' => string '//w:body/w:bookmarkStart[1=1]'

¿Hay alguna forma de reemplazar un bookmark de principio a fin con un WordFragment? ¿O alguna otra forma de agrupar distinto contenido en un .docx de modo que, trabajando con ese fichero como plantilla, se pueda reemplazar? Teniendo en cuenta que habrá varios bloques distintos y tienen que tener algún nombre o clave que los diferencie entre sí, es decir, puede haber varios de estos bloques y que sólo se tenga que reemplazar uno en concreto que puede estar en cualquier posición...

Estamos usando la versión advanced con namespaces.

Gracias

Posted by admin  · 18-01-2017 - 16:54

Hola,

Para hacer lo que necesitaís es necesario trabajar con siblings. El equipo de desarrollo va a hacer un pequeño ejemplo para mostraros cómo; actualizaremos este mismo topic.

Saludos.

Posted by admin  · 19-01-2017 - 08:03

Hola,

Aunque efectivamente se puede hacer directamente con siblings con DOCXPath, el desarrollador encargado de hacer tu ejemplo, propone una solución que es más sencilla: combinar DOCXPath y los bloques de phpdocx.

Este es un ejemplo práctico:

<?php

require_once 'classes/CreateDocx.inc';

$docx = new CreateDocx();

$docx->addText('$BLOCK_CONTENT_1$');
$docx->addText('Text in a block.');
$docx->addText('$BLOCK_CONTENT_1$');

$docx->addText('Other text.');

$docx->createDocx('output_block');

$docxTemplate = new CreateDocxFromTemplate('output_block.docx');

$content = new WordFragment($docxTemplate, 'document');
$content->addText('New text.', array('fontSize' => 20, 'color' => '#0000ff'));

$referenceNode = array(
    'type' => 'paragraph',
    'ocurrence' => 2,
    'contains' => '$BLOCK_CONTENT_1$',
);
$docxTemplate->insertWordFragment($content, $referenceNode, 'after');

$docxTemplate->deleteTemplateBlock('CONTENT_1');

$docxTemplate->createDocx('output_result');

Aunque este ejemplo añade los bloques de manera dinámica, también funciona perfectamente trabajando directamente con templates.

Los pasos generales son:

  1. Rodeas de placeholders de tipo bloque cada contenido a reemplazar (puede ser uno, dos o más contenidos).
  2. Con insertWordFragment de DOCXPath añades el nuevo wordFragment tras el segundo placeholder del bloque a reemplazar.
  3. Con deleteTemplateBlock eliminas el bloque deseado.

Estos mismos pasos los puedes seguir para todos los bloques y te da la misma flexibilidad que con DOCXPath pero de manera más flexible gracias a utilizar bloques.

También comentarte que al utilizar atributos en DOCXPath es necesario indicar el namespace del atributo en caso de usarlo. Por ejemplo:

'attributes' => array(
    'w:name' => "chapter_module_$chapter[id]"
)

Saludos.

Posted by Samuel  · 19-01-2017 - 08:44

Hola, gracias por vuestras respuestas.

Entiendo la solución que proponéis, el problema es que el docx del que partiríamos no puede incluír placeholders.

El usuario descarga un docx generado mediante phpdocx, un docx que puede usar tal cual, o puede modificar para subirlo a la web y que se actualice. Por eso habíamos probado con los bookmarks, ya que son "transparentes" al usuario, no se ven en el documento y, además, tienen un "name" con el que identificarlos.

En cuanto a los siblings, no he encontrado nada en la documentación y no sé a qué se refiere.

Pruebo la solución propuesta, quizá poniendo esos placeholders en color blanco y en un tamaño mínimo les sirve.

Un saludo y muchas gracias

Posted by Samuel  · 20-01-2017 - 07:49

Hola,

Con el método de los bloques funciona a la perfección, y poniéndolos en blanco y a tamaño 1 prácticamente no se ven.

Al cliente parece que le sirve, aunque estaría bien ver cómo sería el método de los siblings, si fuera posible.

Un saludo

Posted by admin  · 20-01-2017 - 08:23

Hola,

Estamos escribiendo un artículo para el cookbook que los detalle de manera genérica para que sea de utilidad al máximo número de personas.

De manera muy resumida se basa en utilizar DOCXPath con una customQuery mediante siblings de XPath para poder seleccionar conjuntos de nodos hermanos y poder realizar acciones sobre ellos. Para los bookmarks serían necesarios, ya que los bookmarks no rodean contenidos mediante XML, sino que tienen un inicio y un fin pero delimitan mediante nodos hermanos (no hijos).

Saludos.