Search code examples
javaapache-poims-office

POI word files generator, generates file full of wrong Proofing Warning


I have some program That I have developed on Java with poi package, which is taking some content from one word file and inject it into new file.

The new file is generated from exist file template and the content injected into the table.

Most of the content is in Hebrew.

The problem is that all of the content that is generated is coming up with proofing warning (see image), although it's correct spelled.

problem

Copy to another file doesn't solve it (but if I type manually new words the file correcting well), and it's very annoying problem.

I want that the proofing check will be working well.

I have some googled it and didn't find a solution.

Does someone has a clue?

This is the method which inject the content into the tables.

public boolean fillInTable() throws IOException {
    System.out.println("fillInTable -current data = " + data);
    XWPFTable table = document.getTables().get(0);
    boolean moreResults = false;
    ListIterator<MichrazOutputLine> lines = data.listIterator();
    while(lines.hasNext()) {
        XWPFTableRow row4 = table.getRow(table.getRows().size() - 1);
        XWPFTableRow tableRow = table.createRow();
        MichrazOutputLine currLine = lines.next();
        tableRow.getCell(0).setText((rowIndex++) + ".");
        for(int i = 0; i < parameters.size(); i++) {
            SearchParameter<?> curr = parameters.get(i);
            if(curr.isOutput()) {
                String value = "";
                switch(curr.getAppCriteria()){
                case CUSTOMER_NAME:
                    value = currLine.getCustomerName();
                    break;
                case DATE:
                    value = currLine.getYear();
                    break;
                case EMPLOYEES_NUMBER:
                    value = currLine.getEmployeeNum();
                    break;
                case PROJECT_DESCRIPTION:
                    value = currLine.getProjectDescription();
                    break;
                case WORK_HOURS:
                    value = currLine.getWorkHoursSum();
                    break;
                case BUDGET:
                    value = currLine.getBudget();
                    break;
                case RECOMMENDER:
                    value = currLine.getRecommender();
                    break;
                case FILE_PATH:
                    value = currLine.getFilePath();
                    break;
                }           
                tableRow.getCell(curr.getOutputCellIndex()).setText(value);
            }
        }
        lines.remove();
        if(table.getRows().size()-1> maxResult-1) {
            dataFull = true;
            System.out.println("fillInTable -data finished  = " + data);
            return true;
        }   
    }
    System.out.println("fillInTable -data finished  = " + data);
    return moreResults;//true - continue the process
}

Solution

  • According to the screenshot your Word application seems not be able to detect the language correctly. Is it Hebrew? If not able to detect the language correctly, proofing (spell checking) uses default proofing language. That also seems not to be Hebrew in your Word application.

    You can help the Word application to detect the language correctly by setting the language tag associated with the text run. See XWPFRun.setLang.

    Complete example:

    import java.io.FileOutputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    public class CreateWordForeignLanguages {
    
     public static void main(String[] args) throws Exception {
         
      XWPFDocument document = new XWPFDocument();
    
      XWPFParagraph paragraph;
      XWPFRun run;
    
      paragraph = document.createParagraph();
      run = paragraph.createRun();
      run.setText("Paragraph containing English text");
      run.setLang("en-US");
      
      paragraph = document.createParagraph();
      run = paragraph.createRun();
      run.setText("Absatz mit deutschsprachigem Text");
      run.setLang("de-DE");
      
      paragraph = document.createParagraph();
      run = paragraph.createRun();
      run.setText("Абзац с текстом на русском языке");
      run.setLang("ru-RU");
     
      paragraph = document.createParagraph();
      run = paragraph.createRun();
      run.setText("פסקה עם טקסט בעברית");
      run.setLang("he-IL");
     
      paragraph = document.createParagraph();
    
      FileOutputStream out = new FileOutputStream("./CreateWordForeignLanguages.docx");
      document.write(out);
      out.close();
      document.close();
    
     }
    }
    

    This should result in an document without red wavy lines.


    Using tables and especially using XWPFTableCell.setText increases the complexity. XWPFTableCell.setText internally creates XWPFParagraph and XWPFRuns and the language settings must be set for those XWPFRuns. But accessing the XWPFRuns is not as easy as it should be. One needs to iterate over all XWPFParagraphs and XWPFRuns in the XWPFTableCells to get the single text runs.

    Complete example again:

    import java.io.FileOutputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    public class CreateWordForeignLanguagesInTable {
    
     public static void main(String[] args) throws Exception {
         
      XWPFDocument document = new XWPFDocument();
      
      XWPFTable table;
      XWPFTableRow tableRow;
      XWPFTableCell tableCell;
        
      XWPFParagraph paragraph = document.createParagraph();
      
      table = document.createTable(1, 3);
      
      paragraph = document.createParagraph();
      
      tableRow = table.getRow(0);
      tableRow.getCell(0).setText("German");
      tableRow.getCell(1).setText("Russian");
      tableRow.getCell(2).setText("Hebrew");
      for (XWPFTableCell tC : tableRow.getTableCells()) {
       for (XWPFParagraph p : tC.getParagraphs()) {
        for (XWPFRun r : p.getRuns()) {
         r.setLang("en-US");
        }
       }       
      }
      
      tableRow = table.createRow();
      
      tableCell = tableRow.getCell(0);
      tableCell.setText("Absatz mit deutschsprachigem Text");
      for (XWPFParagraph p : tableCell.getParagraphs()) {
       for (XWPFRun r : p.getRuns()) {
        r.setLang("de-DE");
       }
      }    
      
      tableCell = tableRow.getCell(1);
      tableCell.setText("Абзац с текстом на русском языке");
      for (XWPFParagraph p : tableCell.getParagraphs()) {
       for (XWPFRun r : p.getRuns()) {
        r.setLang("ru-RU");
       }
      }    
      
      tableCell = tableRow.getCell(2);
      tableCell.setText("פסקה עם טקסט בעברית");
      for (XWPFParagraph p : tableCell.getParagraphs()) {
       for (XWPFRun r : p.getRuns()) {
        r.setLang("he-IL");
       }
      }    
    
      FileOutputStream out = new FileOutputStream("./CreateWordForeignLanguagesInTable.docx");
      document.write(out);
      out.close();
      document.close();
    
     }
    }
    

    Note: This example ignores bidirectional (Bidi) settings so as not to add further complexity.