svvparakala
svvparakala

Reputation: 3

Apache POI Word Table Cell not updating color (XWPFTableCell)

I have the following code where I am trying to edit the background color of a specific TableCell. Currently it is gray and I want to make it red.

String rgb = "FF0000";

for(XWPFTable table : moddedFile.getTables()) {
    for (XWPFTableRow row : table.getRows()) {
        for (XWPFTableCell cell : row.getTableCells()) {
            for (XWPFParagraph paragraph : cell.getParagraphs()) {
                if (paragraph == p) {
                    System.out.println(cell.getText());
                    System.out.println(cell.getColor());
                    cell.setColor(rgb);
                    System.out.println(cell.getColor());
                }
            }
        }
    }
}

However after saving the file, the table cell color is still gray. The print statements confirm that I am working with the right cell, and shows that the color is changing from "F2F2F2" to "FF0000". But when I open the document I don't see a change. Any idea on why this could be happening?

Upvotes: 0

Views: 1134

Answers (1)

Axel Richter
Axel Richter

Reputation: 61852

Maybe the gray background of the cells was set using theme fill and theme fill shade. Theme fill settings and explicit fill settings can both be set. But theme fill settings are privileged. So if theme fill settings are present, then explicit fill settigs will be ignored.

XWPFTableCell.setColor(String rgbStr) only sets explicit fill settings but does not take theme fill setting into account. It should be patched like so:

public void setColor(String rgbStr) {
    CTTcPr tcpr = getTcPr();
    CTShd ctshd = tcpr.isSetShd() ? tcpr.getShd() : tcpr.addNewShd();
    ctshd.setColor("auto");
    ctshd.setVal(STShd.CLEAR);
    ctshd.setFill(rgbStr);

    if (ctshd.isSetThemeFill()) ctshd.unsetThemeFill();
    if (ctshd.isSetThemeFillShade()) ctshd.unsetThemeFillShade();
    if (ctshd.isSetThemeFillTint()) ctshd.unsetThemeFillTint();
}

Without patching one could use an own setColor method:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

public class WordChangeTableCellColor{

 static void setColor(XWPFTableCell cell, String rgbStr) {
  CTTc ctTc = cell.getCTTc();
  CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr();
  CTShd ctshd = tcpr.isSetShd() ? tcpr.getShd() : tcpr.addNewShd();
  ctshd.setColor("auto");
  ctshd.setVal(STShd.CLEAR);
  ctshd.setFill(rgbStr);

  if (ctshd.isSetThemeFill()) ctshd.unsetThemeFill();
  if (ctshd.isSetThemeFillShade()) ctshd.unsetThemeFillShade();
  if (ctshd.isSetThemeFillTint()) ctshd.unsetThemeFillTint();
 }

 public static void main(String[] args) throws Exception {
  XWPFDocument moddedFile = new XWPFDocument(new FileInputStream("./WordDocument.docx"));

  //Not clear where the XWPFParagraph p comes from in question's code.
  //But if WordDocument.docx contains at least one table having at least one row having at least three cells, then this should work.
  XWPFParagraph p = null;
  try {
   p = moddedFile.getTables().get(0).getRows().get(0).getTableCells().get(2).getParagraphs().get(0);
  } catch (Exception ex) {
   ex.printStackTrace();
  }

  String rgb = "FF0000";

  for(XWPFTable table : moddedFile.getTables()) {
   for (XWPFTableRow row : table.getRows()) {
    for (XWPFTableCell cell : row.getTableCells()) {
     for (XWPFParagraph paragraph : cell.getParagraphs()) {
      if (paragraph == p) {
       System.out.println(cell.getText());
       System.out.println(cell.getColor());
       //cell.setColor(rgb);
       setColor(cell, rgb);
       System.out.println(cell.getColor());
      }
     }
    }
   }
  }

  FileOutputStream out = new FileOutputStream("./WordDocumentNew.docx");
  moddedFile.write(out);
  out.close();
  moddedFile.close();
 }
}

Upvotes: 1

Related Questions