Getting extra line in generated document

RangesGetText1.zip (54.5 KB)
Reco_Doc_64938_out.docx - FISCAL EFFECT: has two numbered bullets generated with poc program attached generated correctly.

tito test_75386.docx - same FISCAL EFFECT: is added but there is an extra line added between the two paragraphs. can you let me know what could be the reason.

Used the exact same logic in application to copy the nodes.

@wrushu2004,

Please also ZIP and attach your input Word document (Reco_Doc_64938.docx) here for further testing.

Reco_Doc_64938.zip (11.1 KB)

@wrushu2004,

Please check this output document (awjava-18.9.zip (10.5 KB)) that we produced on our end by using the following code:

Document docDest = new Document("D:\\temp\\RangesGetText1\\Reco_Doc_64938.docx");
Document docSrc = new Document("D:\\temp\\RangesGetText1\\SB168.docx");

final NodeCollection pChildNodes = docSrc.getChildNodes(NodeType.PARAGRAPH, true);

final List<Node> fiscalNodes = findMatch(pChildNodes, "FISCAL EFFECT:");
final List<Node> summaryNodes = findMatch(pChildNodes, "SUMMARY:");

final NodeCollection childNodes = docDest.getChildNodes(NodeType.PARAGRAPH, true);

DocumentBuilder builder = new DocumentBuilder(docDest);
Node labelNode = null;
for (Iterator<Node> iterator = childNodes.iterator(); iterator.hasNext();) {
    Node replaceNode = iterator.next();
    builder.moveTo(replaceNode);
    CompositeNode dstStory = replaceNode.getParentNode();
    NodeImporter importer = new NodeImporter(docSrc, replaceNode.getDocument(), ImportFormatMode.KEEP_SOURCE_FORMATTING);

    if (replaceNode.getText().startsWith("00000001_Summary_html_3")) {
        labelNode = replaceNode;
        for (Node summaryNode : summaryNodes) {
            final Node newNode = importer.importNode(summaryNode, true);
            dstStory.insertAfter(newNode, replaceNode);
            replaceNode = newNode;
        }
        labelNode.remove();
    } else if (replaceNode.getText().startsWith("00000001_Fiscal2_html_2")) {
        labelNode = replaceNode;
        for (Node fiscalNode : fiscalNodes) {
            final Node newNode = importer.importNode(fiscalNode, true);
            dstStory.insertAfter(newNode, replaceNode);
            replaceNode = newNode;
        }
        labelNode.remove();
    }
}

docDest.save("D:\\temp\\RangesGetText1\\awjava-18.9.docx");
//////////////////////////////////////////////////
private static List<Node> findMatch(NodeCollection pChildNodes, String match) {
    List<Node> nodes = null;
    int index = 0, startIndex = 0, endIndex = 0, pCount = 0;
    for (Iterator iterator = pChildNodes.iterator(); iterator.hasNext();) {
        Node next = (Node) iterator.next();
        if (startIndex == 0) {
            if (next.getText().startsWith(match)) {
                startIndex = index;
            } else {
                index++;
            }
            pCount = 1;
        } else {
            if (match.equals("FISCAL EFFECT:")) {
                if (next.getText().startsWith("COMMENTS:")
                        || next.getText().startsWith("Analysis Prepared by:")) {
                    break;
                }
            } else if (match.equals("SUMMARY:")) {
                if (next.getText().startsWith("FISCAL EFFECT:")) {
                    break;
                }
            }
            pCount++;
        }
    }
    System.out.println("startIndex:" + startIndex);
    System.out.println("pCount:" + pCount);
    if (pCount > 0) {
        nodes = new ArrayList();
        for (int i = 0; i < pCount; i++) {
            System.out.println(pChildNodes.get(startIndex + i).getText());
            nodes.add(pChildNodes.get(startIndex + i));
        }
    }
    return nodes;
}

Do you see any problem in this awjava-18.9.docx file? If yes, then please also provide a comparison screenshot highlighting the problematic areas in this Aspose.Words generated output Word document and attach them here for our reference.

tito test_75386.zip (13.7 KB)
I have highlighted the replaced nodes text.

  1. font from source is not retained.
  2. extra line between numbered list.

sample program works for me too, problem comes when I integrate in project.

below is my code:-

public void replaceMergeFields(Map<String, Map<String, String>> regularAttributeValues,
Map<String, Map<String, String>> customAttributeValues, ReportParamsBean paramBean, String fileName) {

    try {
        FindReplaceOptions findReplaceOptions = new FindReplaceOptions();
        findReplaceOptions.setReplacingCallback(new FindAndInsertHtml());
        findReplaceOptions.setPreserveMetaCharacters(true);

        UserBean userBean = paramBean.getUserBean();

        TemplateBean item = paramBean.getTemplateBean();
        final Map<String, String> customFields = remote.getCustomFields(userBean);
        final List<String> htmlFields = getHtmlFields(customFields);
        com.aspose.words.Document destDoc = new com.aspose.words.Document();
        DocumentBuilder builder = new DocumentBuilder(destDoc);
        builder.getCurrentParagraph().getParagraphFormat().setPageBreakBefore(true);
        final NodeCollection childNodes = destDoc.getChildNodes();
        childNodes.removeAt(0);
        CompositeNode destCompNode = childNodes.getContainer();
        com.aspose.words.Document tempDoc = null;

        Map<String, String> htmlPlaceHolders = new HashMap<>();
        int billCount = 0, index = 0, billCounter = 0, customAttrCounter = 1;
        for (Map.Entry<String, Map<String, String>> entrySet : regularAttributeValues.entrySet()) {
            try {
                billCounter++;
                customAttrCounter = 1;
                tempDoc = new com.aspose.words.Document(new ByteArrayInputStream(item.getTemplateDocument()));
                NodeImporter importer = new NodeImporter(tempDoc.getDocument(), destDoc.getDocument(), ImportFormatMode.KEEP_SOURCE_FORMATTING);
                String key = entrySet.getKey();
                Map<String, String> regularValues = entrySet.getValue();
                Map<String, String> customValues = customAttributeValues.get(key);
                List<String> fieldNames = new LinkedList<>();
                List<String> values = new LinkedList<>();
                if (regularValues != null) {
                    for (Map.Entry<String, String> regularEntrySet : regularValues.entrySet()) {
                        String key1 = regularEntrySet.getKey();
                        String value1 = regularEntrySet.getValue();

                        if (StringUtils.startsWith(key1, "bill_title") || StringUtils.startsWith(key1, "bill_digest")) {
                            htmlPlaceHolders.put(key1, transformBillXmlXsl(value1, key1));
                        } else {
                            fieldNames.add(key1);
                            values.add(value1);
                        }
                    }
                }
                if (customValues != null) {
                    for (Map.Entry<String, String> customEntrySet : customValues.entrySet()) {
                        String customKey = customEntrySet.getKey();                            
                        String customValue = customEntrySet.getValue();
                        if (htmlFields.contains(customKey)) {
                            htmlPlaceHolders.put(customKey + "_html", customValue);
                        } else {
                            fieldNames.add(customKey);
                            values.add(customValue);
                        }
                    }
                }

                if (htmlPlaceHolders.size() > 0) {
                    for (Map.Entry<String, String> htmlSet : htmlPlaceHolders.entrySet()) {
                        String placeHolder = htmlSet.getKey();
                        String replaceHtml = "";
                        if (StringUtils.isBlank(htmlSet.getValue())) {
                            replaceHtml = "<span></span>";
                        } else {
                            replaceHtml = htmlSet.getValue();
                            if (StringUtils.equals("bill_title_html", placeHolder) || StringUtils.equals("bill_digest_html", placeHolder)) {
                                replaceHtml = StringUtils.replace(replaceHtml, "<br>", "<br/>");
                            }
                        }
                        tempDoc.getRange().replace(Pattern.compile(placeHolder), replaceHtml, findReplaceOptions);
                    }
                }
                tempDoc.getMailMerge().setCleanupOptions(MailMergeCleanupOptions.REMOVE_UNUSED_FIELDS);
                tempDoc.getMailMerge().execute(fieldNames.toArray(new String[fieldNames.size()]),
                        values.toArray(new String[values.size()]));

                if (paramBean.isDocFieldsExists()) {
                    boolean summaryDone = true, fiscalDone = true;
                    String summaryDocFieldName = "", fiscalDocFieldName = "";
                    for (String docField : paramBean.getDocFields()) {
                        if (StringUtils.equalsIgnoreCase(docField, "summary_doc")) {
                            summaryDone = false;
                            summaryDocFieldName = docField;
                        } else if (StringUtils.equalsIgnoreCase(docField, "fiscal_doc")) {
                            fiscalDone = false;
                            fiscalDocFieldName = docField;
                        }
                    }
                    String analysisType = getAnalysisType(key);
                    final byte[] analysisFile = remote.getAnalysisFile(userBean, key, analysisType);
                    if (analysisFile != null) {
                        com.aspose.words.Document analysisDoc = new com.aspose.words.Document(new ByteArrayInputStream(analysisFile));
                        final NodeCollection aChildNodes = analysisDoc.getChildNodes(NodeType.PARAGRAPH, true);
                        final List<Node> fiscalNodes = findMatch(aChildNodes, "FISCAL EFFECT:");
                        final List<Node> summaryNodes = findMatch(aChildNodes, "SUMMARY:");
                        final DocumentBuilder tBuilder = new DocumentBuilder(tempDoc);
                        final NodeCollection tChildNodes = tempDoc.getChildNodes(NodeType.PARAGRAPH, true);
                        Node labelNode = null;                        

                        for (Iterator<Node> iterator = tChildNodes.iterator(); iterator.hasNext();) {
                            Node replaceNode = iterator.next();
                            final int nodeType = replaceNode.getNodeType();                                
                            tBuilder.moveTo(replaceNode);
                            CompositeNode destNode = replaceNode.getParentNode().getContainer();
                            NodeImporter analysisImporter = new NodeImporter(analysisDoc, replaceNode.getDocument(), ImportFormatMode.USE_DESTINATION_STYLES);
                            if (StringUtils.startsWith(replaceNode.getText(), summaryDocFieldName)) {
                                labelNode = replaceNode;
                                if (summaryNodes != null) {
                                    for (Node summaryNode : summaryNodes) {
                                        final Node newNode = analysisImporter.importNode(summaryNode, true);                                            
                                        destNode.insertAfter(newNode, replaceNode);
                                        replaceNode = newNode;
                                    }
                                    //labelNode.remove();
                                    summaryDone = true;
                                } else {
                                    tempDoc.getRange().replace(Pattern.compile(summaryDocFieldName), "", findReplaceOptions);                                        
                                    summaryDone = true;
                                }
                            } else if (StringUtils.startsWith(replaceNode.getText(), fiscalDocFieldName)) {
                                labelNode = replaceNode;
                                if (fiscalNodes != null) {
                                    for (Node fiscalNode : fiscalNodes) {
                                        final Node newNode = analysisImporter.importNode(fiscalNode, true);
                                        destNode.insertAfter(newNode, replaceNode);
                                        replaceNode = newNode;
                                    }
                                    //labelNode.remove();
                                    fiscalDone = true;
                                } else {
                                    tempDoc.getRange().replace(Pattern.compile(fiscalDocFieldName), "", findReplaceOptions);
                                    fiscalDone = true;
                                }
                            }
                            if (summaryDone && fiscalDone) {
                                break;
                            }
                        }
                    } else {
                        if(StringUtils.isNotEmpty(summaryDocFieldName)) {
                            tempDoc.getRange().replace(Pattern.compile(summaryDocFieldName), "", findReplaceOptions);
                        }
                        if(StringUtils.isNotEmpty(fiscalDocFieldName)) {
                            tempDoc.getRange().replace(Pattern.compile(fiscalDocFieldName), "", findReplaceOptions);
                        }
                    }
                }

                final NodeCollection tableNodes = tempDoc.getChildNodes(NodeType.TABLE, true);
                Node newNode = null;
                if (tableNodes.getCount() > 0) {
                    if (billCount++ > 0) {
                        for (Iterator<Node> iterator = tableNodes.iterator(); iterator.hasNext();) {
                            Table node = (Table) iterator.next();
                            final Node child = node.getChild(NodeType.ROW, 0, true);
                            node.removeChild(child);
                            break;
                        }
                        if (!paramBean.isBillOnNewPage()) {
                            final NodeCollection rowNodes = tempDoc.getChildNodes(NodeType.ROW, true);
                            final NodeCollection parentTableNodes = destDoc.getChildNodes(NodeType.TABLE, true);
                            if (parentTableNodes.getCount() > 0) {
                                final Table parentTable = (Table) parentTableNodes.get(0);
                                destCompNode = parentTable.getChildNodes().getContainer();
                                for (Iterator<Node> iterator = rowNodes.iterator(); iterator.hasNext();) {
                                    Node rowNode = (Node) iterator.next();
                                    newNode = importer.importNode(rowNode, true);
                                    destCompNode.appendChild(newNode);
                                }
                            }
                        } else {
                            final NodeCollection tempChildNodes = tempDoc.getChildNodes();
                            for (Iterator<Node> iterator = tempChildNodes.iterator(); iterator.hasNext();) {
                                Node childNode = iterator.next();
                                newNode = importer.importNode(childNode, true);
                                destCompNode.appendChild(newNode);
                            }
                        }
                    } else {
                        final NodeCollection tempChildNodes = tempDoc.getChildNodes();
                        for (Iterator<Node> iterator = tempChildNodes.iterator(); iterator.hasNext();) {
                            Node childNode = iterator.next();
                            newNode = importer.importNode(childNode, true);
                            destCompNode.appendChild(newNode);
                        }
                    }
                }
                if (paramBean.isBillOnNewPage() && billCounter != regularAttributeValues.size()) {
                    builder.moveToDocumentEnd();
                }

                if (index++ == 0) {
                    try {
                        mergeHeaderFooter(tempDoc, destDoc, HeaderFooterType.HEADER_PRIMARY);
                        mergeHeaderFooter(tempDoc, destDoc, HeaderFooterType.HEADER_FIRST);
                        mergeHeaderFooter(tempDoc, destDoc, HeaderFooterType.HEADER_EVEN);
                        mergeHeaderFooter(tempDoc, destDoc, HeaderFooterType.FOOTER_PRIMARY);
                        mergeHeaderFooter(tempDoc, destDoc, HeaderFooterType.FOOTER_FIRST);
                        mergeHeaderFooter(tempDoc, destDoc, HeaderFooterType.FOOTER_EVEN);
                    } catch (Exception ex) {
                        Logger.getLogger(Docx4jWriteHelper.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            } catch (Exception ex) {
                Logger.getLogger(Docx4jWriteHelper.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        destDoc.save(fileName);        
    } catch (Exception ex) {
        Logger.getLogger(Docx4jWriteHelper.class.getName()).log(Level.SEVERE, null, ex);
    }
}

I tried to save the tempDoc into a file and then saw that at that point it is correctly generated.

But then we copy tables from tempDoc and copy into destDoc and that’s where the formatting is lost and the extra line issue as well.

Do you suggest any steps to copy the styles and other settings from tempDoc to destDoc.

when I see the wml of both documents I see the difference only in styles.xml.

Used below code from some other thread but no improvement:-
StyleCollection sourceStyles = tempDoc.getStyles();
StyleCollection targetStyles = destDoc.getStyles();

                        System.out.println("SORGENTE = " + sourceStyles.getCount() + " stili");
                        System.out.println("DESTINAZIONE = " + targetStyles.getCount() + " stili");

                        for (Style style : sourceStyles) {
                            String name = style.getName();
                            if (name.endsWith("Carattere")) {
                                continue;
                            }

                            if (style.getType() == StyleType.PARAGRAPH
                                    || style.getType() == StyleType.TABLE) {
                                Style copied = targetStyles.addCopy(style);
                                copied.setBaseStyleName(style.getBaseStyleName());

                                if (style.getType() == StyleType.PARAGRAPH) {
                                    copied.setNextParagraphStyleName(style.getNextParagraphStyleName());
                                }
                                copied.setName(name);
                                System.out.println("COPIA STILE " + name + " -> " + copied.getName());
                            }
                        }

@wrushu2004,

To learn how to copy styles, please refer to the code examples mentioned in the following API reference guide:

public Style addCopy(Style style)

To make an exact copy (including Styles, Lists etc) of the whole Document, you can use the following method:

Document doc1 = new Document("D:\\temp\\RangesGetText1\\Reco_Doc_64938.docx");
Document exactCopy = (Document) doc1.deepClone(false);
exactCopy.removeAllChildren();
exactCopy.ensureMinimum();
exactCopy.save("D:\\temp\\exactCopy.docx");

Hope, this helps.

Above code worked in copying styles from source document to target document.
Thanks,

@wrushu2004,

It is great that you were able to resolve this issue on your end. Please let us know anytime you have any further queries.