1

I have a .docx document with some tables at the top. These contain text placeholders that need replaced, which works fine. However, one of these tables needs to be repeated and filled with different values. I am able to deep copy the table and add it to the end of the document, but I don't know how to insert it at the appropriate location. I tried adding the copy at the index of the template table, but that gives a "unknown graphics format" error in LibreOffice, even when I remove the original:

template.getMainDocumentPart().getContent().add(index, copy);
template.getMainDocumentPart().getContent().remove(table);

Any thoughts?

Edit:

I created an example project on a Windows box, but now I get a IndexOutOfBoundsException as the table is not present in the main document part content list (it is wrapped in a JAXBElement instead). See code below, this takes a document with three separate tables where the first one has a cell with the text "first" in it, etc.

package test;

import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Text;

import javax.xml.bind.JAXBElement;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Test {

    private WordprocessingMLPackage template;

    public void getTemplate(String name) {
        try {
            template = WordprocessingMLPackage.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(name));
        } catch (Exception e) {
        }
    }

    private List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
        List<Object> result = new ArrayList<Object>();
        if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();
        if (obj.getClass().equals(toSearch))
            result.add(obj);
        else if (obj instanceof ContentAccessor) {
            List<?> children = ((ContentAccessor) obj).getContent();
            for (Object child : children) {
                result.addAll(getAllElementFromObject(child, toSearch));
            }
        }
        return result;
    }

    public void duplicate() {
        List<Object> tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);
        for (Object table : tables) {
            List list = template.getMainDocumentPart().getContent();
        // Workaround for table being wrapped in JAXBElement
        // This simple code assumes table is present and top level
        int index = 0;
        for (Object o : list) {
            if (XmlUtils.unwrap(o)== table) {
                break;
            }
            index++;
        }
        List<Object> texts = getAllElementFromObject(table, Text.class);
        for (Object t : texts) {
            Text text = (Text) t;
            if (text.getValue().contains("second")) {
                Tbl copy = (Tbl) XmlUtils.deepCopy(table);
                template.getMainDocumentPart().getContent().add(index, copy);
                System.out.println(template.getMainDocumentPart().getXML());
                return;                    
            }
        }           }
    }

    public void save() {
        try {
            template.save(new File("out.docx"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.getTemplate("test.docx");
        test.duplicate();
        test.save();
    }

}

I'm not sure how to best deal with this.

JasonPlutext
  • 15,352
  • 4
  • 44
  • 84
user3170702
  • 1,971
  • 8
  • 25
  • 33

1 Answers1

0

Sounds like the table might have images in it? Are you copying it from another docx?

If you have only cloned content of the current main document part, and inserted as per your question, that would be fine and won't cause the error you report.

JasonPlutext
  • 15,352
  • 4
  • 44
  • 84
  • There are no images whatsoever. Right now I'm just trying to duplicate one of the tables, so there's no second document involved. I'll take a look at the generated xml. – user3170702 Mar 28 '14 at 07:47
  • 1
    Edited your code with a simple workaround for the IndexOutOfBoundsException; it works OK. Any "unknown graphics format" error in LibreOffice is either unrelated or misleading. – JasonPlutext Mar 28 '14 at 12:12