Search code examples
javaapache-poidocxbidirectionalfarsi

Disorganization of Persian-English sentence in word file (.docx) created by Apache POI


When I try to create a paragraph with English-Farsi words (first photo), and using Apache POI to create .docx file and save the paragraph or save to table, the sentence becomes messy and unreadable (second photo). How to solve this problem? You can see the simplified code below.

The correct sentence (its my JList):

first photo that show my sentence I get it from ArrayList and try to save in word document

The incorrect sentence (its from my .docx file):

The second photo shows what appears in the table in the word file

You can see the ctppr.addNewBidi().setVal(true); don't help.

    public void printToWord(){
    if (activites != null && !activites.isEmpty()) {
        try (XWPFDocument doc = new XWPFDocument()) {

            CTDocument1 ctDocument = doc.getDocument();
            CTBody ctBody = ctDocument.getBody();
            CTSectPr ctSectPr = (ctBody.isSetSectPr())? ctBody.getSectPr(): ctBody.addNewSectPr();
            CTPageSz ctPageSz = (ctSectPr.isSetPgSz()) ? ctSectPr.getPgSz() : ctSectPr.addNewPgSz();
            ctPageSz.setOrient(STPageOrientation.PORTRAIT);
            ctPageSz.setW(java.math.BigInteger.valueOf(Math.round(5.8 * 1440))); //5.8 inches
            ctPageSz.setH(java.math.BigInteger.valueOf(Math.round(8.3 * 1440))); //8.3 inches

            XWPFParagraph p1 = doc.createParagraph();
            p1.setAlignment(ParagraphAlignment.LEFT);
            XWPFRun r1 = p1.createRun();
            String lin1 = info.getModirmosyaghim();
            r1.setText(lin1);

            XWPFParagraph pBody = doc.createParagraph();
            pBody.setAlignment(ParagraphAlignment.LEFT);

            XWPFRun rBody = pBody.createRun();
            String body = "به استحضار می رساند گزارش فعالیت های اینجانب " + logeduser.getName() + "در تاریخ " + cb_date.getSelectedItem() +  " به صورت زیر می باشد";

            rBody.setText(body);
            rBody.addBreak();

            XWPFTable table = doc.createTable();
            //table.setTableAlignment(TableRowAlign.LEFT);
            //table.setWidth(600);

            //Creating first Row or tableHeader
            XWPFTableRow row1 = table.getRow(0);
            row1.getCell(0).setText("تاریخ");
            row1.addNewTableCell().setText("فعالیت");
            row1.addNewTableCell().setText("شماره");

            int num= 0;
            XWPFTableRow row2 = null;
            for (ActivitiesEntity ac : activites) {
                radif += 1;
                row2 = table.createRow();
                row2.getCell(0).setText(ac.getDate());
                row2.getCell(1).setText(ac.getActivity());
                row2.getCell(2).setText(String.valueOf(num));
            }

            XWPFParagraph p2 = doc.createParagraph();
            p2.setAlignment(ParagraphAlignment.RIGHT);
            XWPFRun r2 = p2.createRun();
            String end = info.getBatashakor();
            r2.setText(end);
            r2.setText(logeduser.getName());

            for (int i = 0; i<activites.size(); i++){
                for (int col = 0 ; col < 3; col++) {
                    XWPFParagraph paragraph = table.getRow(i).getCell(col).getParagraphs().get(0);
                    CTP ctp = paragraph.getCTP();
                    CTPPr ctppr = ctp.getPPr();
                    if (ctppr == null) ctppr = ctp.addNewPPr();
                    ctppr.addNewBidi().setVal(true);
                }
            }


            String DEST;
            DEST = "./Reports/" + "filename" +.docx";

            // save the docs

            try (FileOutputStream out = new FileOutputStream(DEST)) {
                doc.write(out);
                out.close();
                doc.close();
            }
            JOptionPane.showMessageDialog(null,"Report Created!");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }else {
        JOptionPane.showMessageDialog(null,"The list is empty");
    }

}

I tried to simplify the code and remove irrelevant codes to make it easier to understand:

    public void WordTest(){
        if (activites != null && !activites.isEmpty()) {
            try (XWPFDocument doc = new XWPFDocument()) {

                XWPFTable table = doc.createTable();

                XWPFTableRow row1 = table.getRow(0);
                row1.getCell(0).setText("تاریخ");
                row1.addNewTableCell().setText("فعالیت");
                row1.addNewTableCell().setText("شماره");

                XWPFTableRow row2 = null;
                row2 = table.createRow();
                String date = "1401-07-27";
                String activity = "ماشین های مختلف مانند" + "BMW" + "و پیکان";
                row2.getCell(0).setText(date);
                row2.getCell(1).setText(activity);
                row2.getCell(2).setText(String.valueOf(1));


                //cell or column width
                table.getRow(0).getCell(0).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1500));
                table.getRow(0).getCell(1).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(6000));
                table.getRow(0).getCell(2).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(500));

                //first row color
                table.getRow(0).getCell(0).getCTTc().addNewTcPr().addNewShd().setFill("cccccc");
                table.getRow(0).getCell(1).getCTTc().addNewTcPr().addNewShd().setFill("cccccc");
                table.getRow(0).getCell(2).getCTTc().addNewTcPr().addNewShd().setFill("cccccc");


                for (int i = 0; i<2; i++){
                    for (int col = 0 ; col < 3; col++) {
                        XWPFParagraph paragraph = table.getRow(i).getCell(col).getParagraphs().get(0);
                        CTP ctp = paragraph.getCTP();
                        CTPPr ctppr = ctp.getPPr();
                        if (ctppr == null) ctppr = ctp.addNewPPr();
                        ctppr.addNewBidi().setVal(true);
                    }
                }

                String DEST = "./Reports/" + "filename" + "(" + cb_date.getSelectedItem().toString() + "-" + logeduser.getName() + ")" + ".docx";
                // save the docs
                try (FileOutputStream out = new FileOutputStream(DEST)) {
                    doc.write(out);
                    out.close();
                    doc.close();
                }
                JOptionPane.showMessageDialog(null,"Report Created!");

            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            JOptionPane.showMessageDialog(null,"The list is empty");
        }

    }

I try to use run.setText("\u202E" + activity + "\u202C"); this part of code works but messy English words:

messy English words


Solution

  • It's worked for me: run.setText("\u202B" + activity + "\u202B");