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
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.
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:
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.
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
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
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.