docx-templates
docx-templates copied to clipboard
go to the next page with a specific condition (conditional page break)
HI
how to go to the next page (go to next docx page and keep going) with a specific condition like
+++IF condition +++ +++= page_break +++ +++END-IF+++
In python can use this //code from docxtpl import DocxTemplate, R, InlineImage page_break = R('\f') //docx template {% if condition %} {{r page_break }} {% endif %}
and how use index in FOR
and when try merge two docx file catch this error "For source /word/document.xml, cannot find part word/media/template_document.xml_img1.jpg from rel img1=media/template_document.xml_img1" i can not get this error with docxtpl before
Haven't tried this before, but what about adding a literal page break in between an IF-END-IF in the template? If not, you can look into using literal XML for this. I don't know the required XML magic, though. You may be able to find that here http://officeopenxml.com/anatomyofOOXML.php or here https://stackoverflow.com/questions/2795315/create-page-break-using-openxml
Would appreciate it if you could post in this thread what ended up working for you.
I have faced a similar situation and following is what I have used. In JS code,
createReport({
template,
data: {
...data,
pageBreak: '||<w:br w:type="page" />||',
},
cmdDelimiter: ['{{', '}}'],
});
In template
{{ IF condition }}
{{pageBreak}}
{{ END-IF }}
In a similar vein, I solved this with:
const report = await createReport({
...
additionalJsContext: {
pagebreak: (show) => (show || typeof show === 'undefined') ? '||<w:br w:type="page"/>||' : '',
}
})
which slims down the syntax a bit whilst allowing any given conditional or falsy value to prevent the break from showing, such as:
{{ pagebreak($idx < $component.issues.length-1) }}
{{ pagebreak($idx < 5) }}
{{ pagebreak($name === 'Alice') }}
{{ pagebreak($data) }}
pagebreak()
can also be called without an argument to always output a break (or used within other contexts such as IF
).
Thanks for this solution @davidjb !! 🥳
I encountered a problem with this method, since the <w:br w:type="page"/>
comes wrapped inside an
<w:t xml:space="preserve">
<w:br w:type="page" />
</w:t>
So I'd actually had to replace the text manually, here is the snippet if anyone wants it:
export function sanitizeDocumentXml(bin: Uint8Array) {
try {
writeFileSync('/tmp/template.docx', bin);
execSync('unzip -o /tmp/template.docx -d /tmp/template');
const documentXml = readFileSync('/tmp/template/word/document.xml', 'utf8');
const sanitizedDocumentXml = documentXml.replaceAll(
'<w:t xml:space="preserve"><w:br w:type="page" /></w:t>',
'<w:br w:type="page" />',
);
writeFileSync('/tmp/template/word/document.xml', sanitizedDocumentXml);
execSync('cd /tmp/template && zip -r /tmp/template.docx ./*');
return readFileSync('/tmp/template.docx');
} catch (error) {
console.log('[sanitizeDocumentXml]: error', error);
return bin;
}
}
I believe this is compatible with most operation systems, but I tested in linux
I have faced a similar situation and following is what I have used. In JS code,
createReport({ template, data: { ...data, pageBreak: '||<w:br w:type="page" />||', }, cmdDelimiter: ['{{', '}}'], });
In template
{{ IF condition }} {{pageBreak}} {{ END-IF }}
Hey @SuchiraD, for some reason this does not break my pages. Here is my template:
*FOR chartData IN chartsData*
*pageBreak*
*$chartData.question*
*IMAGE chart($chartData.imageSrc)*
*IF $chartData.table*
*IMAGE table($chartData.table)*
*END-IF*
*END-FOR chartData*
then, the code:
const buffer = await createReport({
cmdDelimiter: ['*', '*'],
template,
additionalJsContext: {
pageBreak: '||<w:br w:type="page" />||,
chartsData,
chart: (imageSrc) => {
...
},
table: (table) => {
...
}
}
})
and here is the result:
then, the code:
const buffer = await createReport({ cmdDelimiter: ['*', '*'], template, additionalJsContext: { pageBreak: '||<w:br w:type="page" />||, chartsData, chart: (imageSrc) => { ... }, table: (table) => { ... } } })
and here is the result:
@Vitomir2 , Sorry for very late late reply. Somehow I have missed this comment
I am not very clear on the second part of your comment. Were you able to do the pageBreak by adding it in additionalJsContext
?