Search code examples
ms-wordapache-poidirection

How to change table direction in Apache word poi (XWPF)?


I'm trying to use Apache poi word 3.8 to create word document in Persian/Arabic language.

My question is: how to change table direction in document? It means order of column in table(not text direction inside table cell).

For example:

rtl table vs lrt table direction

In MS word we could change table property using:

this option


Solution

  • If the whole table shall be bidirectional, then the org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr must contain bidiVisual set to ON.

    import java.io.FileOutputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
    
    import java.math.BigInteger;
    
    public class CreateWordRTLTable {
    
     public static void main(String[] args) throws Exception {
    
      XWPFDocument doc= new XWPFDocument();
    
      XWPFParagraph paragraph = doc.createParagraph();
      XWPFRun run = paragraph.createRun();
      run.setText("Paragraph 1 LTR");
    
      paragraph = doc.createParagraph();
    
      //create table:
      XWPFTable table = doc.createTable();
      //set the table itself to bidi visual
      if (table.getCTTbl().getTblPr() == null) {
       table.getCTTbl().addNewTblPr().addNewBidiVisual().setVal(STOnOff.ON);
      } else {
       table.getCTTbl().getTblPr().addNewBidiVisual().setVal(STOnOff.ON);
      }
      //create first row
      XWPFTableRow tableRow = table.getRow(0);
      tableRow.getCell(0).setText("first cell");
      tableRow.addNewTableCell().setText("السلام عليكم");
      tableRow.addNewTableCell().setText("third cell");
      //Each cell contains at least a paragraph. Those can be set to support bidi.
      for (int col = 0 ; col < 3; col++) {
       paragraph = tableRow.getCell(col).getParagraphs().get(0);
       CTP ctp = paragraph.getCTP();
       CTPPr ctppr = ctp.getPPr();
       if (ctppr == null) ctppr = ctp.addNewPPr();
       ctppr.addNewBidi().setVal(STOnOff.ON);
      }
    
      //create CTTblGrid for this table with widths of the 3 columns. 
      //necessary for Libreoffice/Openoffice to accept the column widths.
      //values are in unit twentieths of a point (1/1440 of an inch)
      table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*1440));
      for (int col = 1 ; col < 3; col++) {
       table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*1440));
      }
    
      //create and set column widths for all columns in all rows
      //most examples don't set the type of the CTTblWidth but this
      //is necessary for working in all office versions
      //values are in unit twentieths of a point (1/1440 of an inch)
      for (int col = 0; col < 3; col++) {
       CTTblWidth tblWidth = CTTblWidth.Factory.newInstance();
       tblWidth.setW(BigInteger.valueOf(2*1440));
       tblWidth.setType(STTblWidth.DXA);
       for (int row = 0; row < 1; row++) {
        CTTcPr cttcpr = table.getRow(row).getCell(col).getCTTc().getTcPr();
        if (cttcpr != null) {
         cttcpr.setTcW(tblWidth);
        } else {
         cttcpr = CTTcPr.Factory.newInstance();
         cttcpr.setTcW(tblWidth);
         table.getRow(row).getCell(col).getCTTc().setTcPr(cttcpr);
        }
       }
      }
    
      paragraph = doc.createParagraph();
    
      doc.write(new FileOutputStream("WordDocument.docx"));
    
     }
    }