Page 1 of 1

duplicating of table rows

PostPosted: Tue Feb 15, 2011 5:28 am
by Lars
Hi,

Situation:
I've got a document with a table and some rows in it. Due to some incoming data I want to duplicate a row and insert it again in the table. The row contains SdtBlocks in the cells.

The Problem is, if I'm doing something like this...
Code: Select all
Tr newRow = (Tr) XmlUtils.unwrap(mytbl.getEGContentRowContent() .get(1));
mytbl.getEGContentRowContent() .add(2, newRow);

...the new row has no more SdtBlocks in the cells and I have no idea why (content is ok). I also tested the same prcedure with renaming the tag of the SdtBlock (SdtPr.getTag.setVal) and with the CTSdtRow instead of normal Tr but nothing worked.

Could somebodyhelp me with this issue?

kind regards
Lars

Re: duplicating of table rows

PostPosted: Tue Feb 15, 2011 8:26 am
by jason
Lars wrote:...the new row has no more SdtBlocks in the cells and I have no idea why (content is ok).


Are they missing when you inspect the raw docx4j output, or only when/after you open the docx in Word?

I think the problem may be duplicate w:sdt/w:sdtPr/w:id. Where there is a duplicate w:id, I have observed that Word may remove the content control, leaving its content.

You can change the id with a call to:
Code: Select all
             sdtPr.setId();


or, if you want docx4j to do more of the work for you in repeating the table data, you can use its OpenDoPE implementation (which allows you to wrap a tr in a content control, specifying that that tr is to be repeated as many times as there is data to fill the rows). See the databinding sub-forum for further discussion.

Re: duplicating of table rows

PostPosted: Tue Feb 15, 2011 8:34 pm
by Lars
jason wrote:Are they missing when you inspect the raw docx4j output, or only when/after you open the docx in Word?


only after opening the docx file with word...

jason wrote:I think the problem may be duplicate w:sdt/w:sdtPr/w:id. Where there is a duplicate w:id, I have observed that Word may remove the content control, leaving its content.


updating the id was no solution cause the "newRow" was only a reference (no new object) of the old one in Java, so updating the Id of the new row means always updating the old one, too.

I created a new CTSdtRow object now and used:
- newRow.setSdtContent(oldRow.getSdtContent), to transfer the content of the old row
- then I created a new ID, Tag and SdtPr Object to use newRow.setSdtPr(newProps)
...and it finally worked.


Lars

Re: duplicating of table rows

PostPosted: Wed Feb 16, 2011 6:40 pm
by jason
Yes, that'd be right.

If you want to create a new object (as you need in this case), the clone method in XmlUtils is the easiest way to do it.

Anyway, I'm glad you worked it out for yourself :-)

Re: duplicating of table rows

PostPosted: Wed Mar 02, 2011 1:45 am
by Lars
Hi Jason,

jason wrote:If you want to create a new object (as you need in this case), the clone method in XmlUtils is the easiest way to do it.


Could you tell me a little bit more about this method?

After fixing the problem from above I tried to do something with the XmlUtils.deepCopy method but it just don't work and I've got the same problem. Is their a special way to use this method? Or does another "clone" method exists?

My goal is to find a method which is able to copy a SdtElement with all the content in it instead of writing a new method for the problem. That means tables, other SdtElements and CTCustomXMLElements for example.

kind regards
Lars

Re: duplicating of table rows

PostPosted: Wed Mar 02, 2011 8:20 am
by jason
Lars wrote: tried to do something with the XmlUtils.deepCopy method but it just don't work


Can you post an example of a structure it doesn't work on?

I use it pretty extensively.

cheers .. Jason

Re: duplicating of table rows

PostPosted: Wed Mar 02, 2011 6:47 pm
by Lars
Ok, small exsample:

Code: Select all
public class DeepCopy {

   /**
    * @param args
    * @throws Docx4JException
    */
   public static void main(String[] args) throws Docx4JException {
      
      File deepCopyFile       = new File("deepcopy_test.docx");
      File deepCopyFileOutput = new File("deepcopy_test_output.docx");
      WordprocessingMLPackage deepCopyDoc = WordprocessingMLPackage.load(deepCopyFile);
      
      SdtBlock table = (SdtBlock) XmlUtils.unwrap(deepCopyDoc.getMainDocumentPart().getJaxbElement().getBody().getEGBlockLevelElts().get(0));
      
      SdtBlock table2 = XmlUtils.deepCopy(table);
      
      deepCopyDoc.getMainDocumentPart().getJaxbElement().getBody().getEGBlockLevelElts().add(table2);
      
      deepCopyDoc.save(deepCopyFileOutput);
      
   
   }

}


The original docx file has only a SdtBlock at the beginning with a table in it and in the table cells there are again some SdtBlocks and some content.

It seems that deepCopy is not updating the IDs or something like this cause after proceeding the code and opening the docx File with word I have two tables. The first one without any SdtElement, the second one like the original table. So it looks like the problem from above.

kind regards
Lars

Re: duplicating of table rows

PostPosted: Wed Mar 02, 2011 10:28 pm
by jason
That's right, Word will strip a content control if it duplicates the ID of another content control.

It is your responsibility to change the ID (there's a method in the SdtPr class to help) - deepCopy just gives you an extact copy of whatever you pass it.

Re: duplicating of table rows

PostPosted: Thu Mar 03, 2011 6:37 pm
by Lars
Ok.

But what is the differnece between deepCopy and the example code in the first post? From my point of view deepCopy does the same or in other words it has the same result so there is no reason to use it.

regards

Re: duplicating of table rows

PostPosted: Thu Mar 03, 2011 7:42 pm
by jason
The difference is that it is a copy, not a reference to the same object.

So you can change the ID on the copy, and things will work.

Re: duplicating of table rows

PostPosted: Sat Mar 05, 2011 3:46 am
by Lars
ok. thanks.