Page 1 of 1

Setting Column Width of a Table and fix this

PostPosted: Fri Mar 07, 2014 7:57 am
by MrFogg
Hello,

I want to set the column width in a table and fix this column width, so that the text automatically breaks.

My document contains several tables. And I want to set the column-width / fixing for every table.

How can I FIX the table width to a certain value and the column widths of this table?

For example:
Table1 (width =14cm fixed)

Column1=5cm (fixed); Column2=4cm (fixed); Column3=3cm (fixed); Column4=2cm (fixed)

Table2 (width=20cm fixed)
Column1=2cm (not fixed); Column2=4cm (not fixed); Column3=6cm (not fixed); Column4=8cm (not fixed)

etc.

I tried:

Code: Select all
             TblPr tableProps = new TblPr();
             CTTblLayoutType tblLayoutType = new CTTblLayoutType();
             STTblLayoutType stTblLayoutType = STTblLayoutType.FIXED;
             tblLayoutType.setType(stTblLayoutType);
             tableProps.setTblLayout(tblLayoutType);
             table.setTblPr(tableProps);


It fixes as I want, but then I can't change the column width. I tried

Code: Select all
    private static void addTableCellWithWidth(Tr row, String content, int width){
        Tc tableCell = factory.createTc();
        tableCell.getContent().add(
                wordMLPackageTemplate.getMainDocumentPart().createParagraphOfText(
                        content));

        if (width > 0) {
            setCellWidth(tableCell, width);
        }
        row.getContent().add(tableCell);
    }



Code: Select all
    private static void setCellWidth(Tc tableCell, int width) {
        TcPr tableCellProperties = new TcPr();
        TblWidth tableWidth = new TblWidth();
        tableWidth.setW(BigInteger.valueOf(width));
        tableCellProperties.setTcW(tableWidth);
        tableCell.setTcPr(tableCellProperties);
    }



but the column width doesn't change.

Re: Setting Column Width of a Table and fix this

PostPosted: Thu Mar 13, 2014 8:44 pm
by jason
I don't think you can fix the width of a table, but allow the width of the individual columns to resize to fit their contents.

In Word, as soon as you say "autofit contents", then the table width is not fixed. I might be wrong .. you could ask in a forum which specialises in Word. Then if it is possible in Word (let us know!), you'll be able to do it in docx4j.

Re: Setting Column Width of a Table and fix this

PostPosted: Thu Mar 13, 2014 11:18 pm
by MrFogg
Hello,
the columns shouldn't autofit, because it doesn't look very nice.

I tried to use a template word document with a template table and diverse table properties (column width, break text lines at end of column width etc.)

But if I want to copy the template table and replace it's content, the properties are not copied.

Code: Select all
            List<Object> tables1 = getAllElementFromObject(wordMLPackageTemplate.getMainDocumentPart(), Tbl.class);

            Tbl tempTable = getTemplateTable(tables1,"Dummy3");

            List<Object> rows = getAllElementFromObject(tempTable, Tr.class);

            Tbl copy = factory.createTbl();

            for (Object obj : rows){
                copy.getContent().add(obj);
            }

            replaceTable(content,copy);

            addBorders(copy);
            wordMLPackageTemplate.getMainDocumentPart().addObject(copy);


Do you know, how to copy the table properties, too?

Thanks

Re: Setting Column Width of a Table and fix this

PostPosted: Fri Mar 14, 2014 8:00 am
by jason
MrFogg wrote:Do you know, how to copy the table properties, too?


I guess you mean copy the table style definition?

Generally it is easier to talk about this stuff if you paste the XML into your post.

Anyway, you get the style from the style definitions part. Assuming that style isn't already defined in your target docx, you won't need to worry about name collisions. A style may be "basedOn" another, so you might need that one as well... and so on.

Or you can upload your sample template to the webapp (linked above), and generate code for the style, so that instead of copying whatever it happens to be, you are programmatically generating from scratch...

Re: Setting Column Width of a Table and fix this

PostPosted: Fri Mar 14, 2014 7:48 pm
by MrFogg
Hello,

I attached the document xml-part of my docx-template.

The table with Header1, Header2, Header3 and Header4 is the table, which I want to copy including its style (column width, line break, etc.). Then I replace the content of the row Dummy1, Dummy2, Dummy3,Dummy4 and add more rows to it.

But after replacing and adding the rows, the style information is lost. The columns width is adjusted to the text.

Re: Setting Column Width of a Table and fix this

PostPosted: Fri Mar 14, 2014 8:13 pm
by jason
OK, so:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
    <w:tbl>
      <w:tblPr>
        <w:tblStyle w:val="Tabellengitternetz"/>
        <w:tblpPr w:leftFromText="142" w:rightFromText="142" w:vertAnchor="text" w:horzAnchor="margin" w:tblpY="642"/>
        <w:tblW w:w="0" w:type="auto"/>
        <w:tblLayout w:type="fixed"/>
        <w:tblLook w:val="04A0"/>
      </w:tblPr>
      <w:tblGrid>
        <w:gridCol w:w="5920"/>
        <w:gridCol w:w="4536"/>
        <w:gridCol w:w="1427"/>
        <w:gridCol w:w="1485"/>
      </w:tblGrid>
      <w:tr w:rsidR="005E4987" w:rsidRPr="00206C3E" w:rsidTr="0093489D">
        <w:trPr>
          <w:trHeight w:val="300"/>
          <w:tblHeader/>
        </w:trPr>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="5920" w:type="dxa"/>
            <w:shd w:val="clear" w:color="auto" w:fill="C6D9F1" w:themeFill="text2" w:themeFillTint="33"/>
            <w:noWrap/>
            <w:hideMark/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="00206C3E" w:rsidRDefault="00556979" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
              <w:lastRenderedPageBreak/>
              <w:t>Header1</w:t>
            </w:r>
          </w:p>
        </w:tc>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="4536" w:type="dxa"/>
            <w:shd w:val="clear" w:color="auto" w:fill="C6D9F1" w:themeFill="text2" w:themeFillTint="33"/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="00206C3E" w:rsidRDefault="00556979" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
              <w:t>Header2</w:t>
            </w:r>
          </w:p>
        </w:tc>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="1427" w:type="dxa"/>
            <w:shd w:val="clear" w:color="auto" w:fill="C6D9F1" w:themeFill="text2" w:themeFillTint="33"/>
            <w:hideMark/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="00206C3E" w:rsidRDefault="00556979" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
              <w:t>Header3</w:t>
            </w:r>
          </w:p>
        </w:tc>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="1485" w:type="dxa"/>
            <w:shd w:val="clear" w:color="auto" w:fill="C6D9F1" w:themeFill="text2" w:themeFillTint="33"/>
            <w:hideMark/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="00206C3E" w:rsidRDefault="00556979" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:b/>
                <w:sz w:val="20"/>
                <w:szCs w:val="20"/>
              </w:rPr>
              <w:t>Header4</w:t>
            </w:r>
          </w:p>
        </w:tc>
      </w:tr>
      <w:tr w:rsidR="005E4987" w:rsidRPr="005E2E48" w:rsidTr="0093489D">
        <w:trPr>
          <w:trHeight w:val="300"/>
        </w:trPr>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="5920" w:type="dxa"/>
            <w:noWrap/>
            <w:hideMark/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="005E2E48" w:rsidRDefault="005E4987" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
              <w:t>Dummy1</w:t>
            </w:r>
          </w:p>
        </w:tc>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="4536" w:type="dxa"/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="005E2E48" w:rsidRDefault="005E4987" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
              <w:t>Dummy2</w:t>
            </w:r>
          </w:p>
        </w:tc>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="1427" w:type="dxa"/>
            <w:hideMark/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="005E2E48" w:rsidRDefault="005E4987" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
              <w:t>Dummy3</w:t>
            </w:r>
          </w:p>
        </w:tc>
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="1485" w:type="dxa"/>
            <w:hideMark/>
          </w:tcPr>
          <w:p w:rsidR="005E4987" w:rsidRPr="005E2E48" w:rsidRDefault="005E4987" w:rsidP="0093489D">
            <w:pPr>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
            </w:pPr>
            <w:r>
              <w:rPr>
                <w:sz w:val="18"/>
                <w:szCs w:val="18"/>
              </w:rPr>
              <w:t>Dummy4</w:t>
            </w:r>
          </w:p>
        </w:tc>
      </w:tr>
    </w:tbl>
 
Parsed in 0.017 seconds, using GeSHi 1.0.8.4


What I was saying is that if you copy this table to a new docx, and want it to look the same, you'll need to ensure style "Tabellengitternetz" is present.

MrFogg wrote:But after replacing and adding the rows, the style information is lost. The columns width is adjusted to the text.


You can see from the above that each w:tc has a w:tcPr which defines the preferred cell width (w:tcW). You'll need to copy that.

Similarly, certain properties are defined at the tr level (eg row height).

Re: Setting Column Width of a Table and fix this

PostPosted: Fri Mar 14, 2014 11:58 pm
by MrFogg
Hello,

this is my quick and dirty attempt to copy table, row and cell properties from the template table.

Code: Select all
   
            List<Object> tables1 = getAllElementFromObject(wordMLPackageTemplate.getMainDocumentPart(), Tbl.class);
            // 1. find the table
            Tbl tempTable = getTemplateTable(tables1,"Dummy1");

       
            List<Object> tr = tempTable.getEGContentRowContent();


            Tbl copy = factory.createTbl();

            copy.setTblPr(tempTable.getTblPr());
            copy.setTblGrid(tempTable.getTblGrid());

            Tr tempRow0 = (Tr) tr.get(0);
            Tr copyTempRow0 = tempRow0;
            copyTempRow0.setTrPr(tempRow0.getTrPr());

            Tr tempRow1 = (Tr) tempTable.getContent().get(1);
            Tr copyTempRow1 = tempRow1;
            copyTempRow1.setTrPr(tempRow1.getTrPr());

            List<Object> tcs0 = tempRow0.getEGContentCellContent();

            Tc tempCell00 = (Tc) XmlUtils.unwrap(tcs0.get(0));
            Tc copyTempCell00 = tempCell00;
            copyTempCell00.setTcPr(tempCell00.getTcPr());

            Tc tempCell01 = (Tc) XmlUtils.unwrap(tcs0.get(1));
            Tc copyTempCell01 = tempCell01;
            copyTempCell01.setTcPr(tempCell01.getTcPr());

            Tc tempCell02 = (Tc) XmlUtils.unwrap(tcs0.get(2));
            Tc copyTempCell02 = tempCell02;
            copyTempCell02.setTcPr(tempCell02.getTcPr());

            Tc tempCell03 = (Tc) XmlUtils.unwrap(tcs0.get(3));
            Tc copyTempCell03 = tempCell03;
            copyTempCell03.setTcPr(tempCell03.getTcPr());

            List<Object> tcs1 = tempRow1.getEGContentCellContent();

            Tc tempCell10 = (Tc) XmlUtils.unwrap(tcs1.get(0));
            Tc copyTempCell10 = tempCell10;
            copyTempCell10.setTcPr(tempCell10.getTcPr());

            Tc tempCell11 = (Tc) XmlUtils.unwrap(tcs1.get(1));
            Tc copyTempCell11 = tempCell11;
            copyTempCell11.setTcPr(tempCell11.getTcPr());

            Tc tempCell12 = (Tc) XmlUtils.unwrap(tcs1.get(2));
            Tc copyTempCell12 = tempCell12;
            copyTempCell12.setTcPr(tempCell12.getTcPr());

            Tc tempCell13 = (Tc) XmlUtils.unwrap(tcs1.get(3));
            Tc copyTempCell13 = tempCell13;
            copyTempCell13.setTcPr(tempCell13.getTcPr());

            copyTempRow0.getContent().add(copyTempCell00);
            copyTempRow0.getContent().add(copyTempCell01);
            copyTempRow0.getContent().add(copyTempCell02);
            copyTempRow0.getContent().add(copyTempCell03);

            copyTempRow1.getContent().add(copyTempCell10);
            copyTempRow1.getContent().add(copyTempCell11);
            copyTempRow1.getContent().add(copyTempCell12);
            copyTempRow1.getContent().add(copyTempCell13);

            copy.getContent().add(copyTempRow0);
            copy.getContent().add(copyTempRow1);


but it doesn't work.

No Error or Exception, but the table looks terrible in word, much too small column width. Not the settings of the template table!

Re: Setting Column Width of a Table and fix this

PostPosted: Sat Mar 15, 2014 8:48 am
by jason
Compare the XML you have generated with the original XML to see what is different.

Re: Setting Column Width of a Table and fix this

PostPosted: Mon Mar 17, 2014 7:43 pm
by MrFogg
the xml of the template table with the correct properties is

Code: Select all
         <w:tblPr>
            <w:tblStyle w:val="Tabellengitternetz"/>
            <w:tblpPr w:tblpY="642" w:horzAnchor="margin" w:vertAnchor="text" w:rightFromText="142" w:leftFromText="142"/>
            <w:tblW w:type="auto" w:w="0"/>
            <w:tblLayout w:type="fixed"/>
            <w:tblLook w:val="04A0"/>
         </w:tblPr>


my program creates the following table properties

Code: Select all
         <w:tblPr>
            <w:tblBorders>
               <w:top w:space="0" w:sz="4" w:color="auto" w:val="single"/>
               <w:left w:space="0" w:sz="4" w:color="auto" w:val="single"/>
               <w:bottom w:space="0" w:sz="4" w:color="auto" w:val="single"/>
               <w:right w:space="0" w:sz="4" w:color="auto" w:val="single"/>
               <w:insideH w:space="0" w:sz="4" w:color="auto" w:val="single"/>
               <w:insideV w:space="0" w:sz="4" w:color="auto" w:val="single"/>
            </w:tblBorders>
         </w:tblPr>


I think the main difference lies in <w:tblLayout w:type="fixed"/>
This doesn't appear in the table, my program creates, so it is set to "auto" by default.

Do you know how to set the Layout Type to fixed?

Re: Setting Column Width of a Table and fix this

PostPosted: Mon Mar 17, 2014 8:14 pm
by jason
Upload your docx to the webapp, and click through to the relevant table; click on it to generate code.

Re: Setting Column Width of a Table and fix this

PostPosted: Mon Mar 17, 2014 9:01 pm
by MrFogg
I uploaded the docx to the webapp, followed the instructions and tried

Code: Select all
   TblPr tableProps = new TblPr();
            CTTblLayoutType tbllayouttype = createIt();

            tableProps.setTblLayout(tbllayouttype);
            copy.setTblPr(tableProps);

            Tr tempRow0 = (Tr) tr.get(0);
            Tr tempRow1 = (Tr) tr.get(1);
            copy.getContent().add(tempRow0);
            copy.getContent().add(tempRow1);


with the method
Code: Select all
    protected CTTblLayoutType createIt() {

        org.docx4j.wml.ObjectFactory wmlObjectFactory = new org.docx4j.wml.ObjectFactory();

        CTTblLayoutType tbllayouttype = wmlObjectFactory.createCTTblLayoutType();
        tbllayouttype.setType(org.docx4j.wml.STTblLayoutType.FIXED);

        return tbllayouttype;
    }


but it didn't help. The Layout Type is not changed in my generated table.

with

Code: Select all
   
            String openXML = "<w:tblLayout w:type=\"fixed\"/ xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">";
            CTTblLayoutType tbllayouttype = (CTTblLayoutType)XmlUtils.unmarshalString(openXML);

            TblPr tableProps = new TblPr();
            tableProps.setTblLayout(tbllayouttype);
            copy.setTblPr(tableProps);

            Tr tempRow0 = (Tr) tr.get(0);
            Tr tempRow1 = (Tr) tr.get(1);


the program throws [org.xml.sax.SAXParseException: Element type "w:tblLayout" must be followed by either attribute specifications, ">" or "/>".] and doesn't continue.

Re: Setting Column Width of a Table and fix this

PostPosted: Mon Mar 17, 2014 9:50 pm
by jason
Your first piece of code looks OK. Do System.out.println(XmlUtils.marshalToString(copy)) to verify the results.

MrFogg wrote:the program throws [org.xml.sax.SAXParseException: Element type "w:tblLayout" must be followed by either attribute specifications, ">" or "/>".] and doesn't continue.


As per the error message, it looks like you need to make w:tblLayout a self-closing tab ie "/>"

String openXML = "<w:tblLayout w:type=\"fixed\"/ xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" />";

By the way another approach to all of this would be just to get the w:tblPr object from your source table, and put it in your target table. No need to clone it unless you are changing it. But if you did want to clone it, you can use XmlUtils.deepCopy.

Re: Setting Column Width of a Table and fix this

PostPosted: Mon Mar 17, 2014 10:44 pm
by MrFogg
Thank you very much. I found the solution.

My first attempt with the method " protected CTTblLayoutType createIt() ..." is correct.

The error was in the order of creating new table property instances. After setting the tbl Layout to fixed, my program additionally adds borders. These borders were created in a new table property instance and the last was overwritten. I fixed it by adding the borders to the same table properties object, which was instantiated before for the laout type.

:D :D :D :D

Thanky You!