Search code examples
javadocx4j

VariableReplacing is not working sometimes


I am taking the docx file as a template, and when writing variables(${}) with Microsoft Word, not seeing some variables

But when I am changing it on LibreOffice, it is working(java seeing variable), but I can't do it everytime with LibreOffice!

File doc = new File("nameOfMyFile.docx");

WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(doc);

MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();

HashMap mappings = new HashMap();

VariablePrepare.prepare(wordMLPackage); 

mappings.put("lessonsEachWeek", contract.getHoursInWeek());

wordMLPackage.getMainDocumentPart().variableReplace(mappings);
Docx4J.save(wordMLPackage, new File("someName.docx"));

XML of Docx file:

<w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/>
                                <w:color w:val="000000"/>
                                <w:lang w:eastAsia="ru-RU"/>
                            </w:rPr>
                            <w:t xml:space="preserve">1.2 some text ${</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/>
                                <w:color w:val="000000"/>
                                <w:lang w:val="en-US" w:eastAsia="ru-RU"/>
                            </w:rPr>
                            <w:t>lessonsEachWeek</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/>
                                <w:color w:val="000000"/>
                                <w:lang w:eastAsia="ru-RU"/>
                            </w:rPr>
                            <w:t xml:space="preserve">} some text</w:t>
                        </w:r>
                    </w:p>

As you see brackets goes other runs, but when with LibreOffice:

<w:r>
                         <w:rPr>
                                <w:rFonts w:eastAsia="Times New Roman" w:cs="Calibri"/>
                                <w:b/>
                                <w:bCs/>
                                <w:color w:val="000000"/>
                                <w:lang w:eastAsia="ru-RU"/>
                            </w:rPr>
                            <w:t>${lessonsEachWeek}</w:t>
                        </w:r>

And the Error:

2019-07-17 15:00:57.097  WARN 10717 --- [nio-8080-exec-5] org.docx4j.XmlUtils                      : Invalid key '</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/><w:color w:val="000000"/><w:lang w:val="en-US" w:eastAsia="ru-RU"/></w:rPr><w:t>lessonsEachWeek</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/><w:color w:val="000000"/><w:lang w:eastAsia="ru-RU"/></w:rPr><w:t xml:space="preserve">' or key not mapped to a value
2019-07-17 15:00:57.097  WARN 10717 --- [nio-8080-exec-5] org.docx4j.XmlUtils                      : Invalid key '</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/><w:color w:val="000000"/><w:lang w:val="en-US" w:eastAsia="ru-RU"/></w:rPr><w:t>lessonsEachWeek</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:eastAsia="Times New Roman" w:cs="Times New Roman"/><w:color w:val="000000"/><w:lang w:eastAsia="ru-RU"/></w:rPr><w:t xml:space="preserve">' or key not mapped to a value
2019-07-17 15:00:57.135  INFO 10717 --- [nio-8080-exec-5] o.d.o.parts.WordprocessingML.BinaryPart  : .. closed.

Solution

  • Root cause

    Word's text proofing feature have wrapped lessonsEachWeek text into some tags splitting it out from ${ and } tokens. Given such document docx4j tries to find substitution for key </w:t></w:r><w:r><w:rPr>...lessonsEachWeek...</w:rPr><w:t xml:space="preserve"> while there is no such key, of course.

    Solution

    For existing document i was unable to find automated and graceful way to remove these wrapping tags, unfortunately. Disabling spell check in Word, rechecking and saving document doesn't work for some reason. I have done some "manual surgery": opened docx file in 7z as zip file, located \word\document.xml in it, F4 (edit) and removed these wrapping tags. 7z repacked zip file, Word still opens it without a problem while my Java / Kotlin application can now substitute keys that were fixed! Any similar archiver and editor should also do the trick.

    How to avoid this problem in new documents

    Disable text proofing in Word when creating such templates.

    "File" -> "Options" -> "Proofing", uncheck all checkboxes in "When correcting spelling and grammar in Word" section.