繁体   English   中英

使用Apache POI从Excel中的空白单元格读取颜色到Java

[英]Read a Color from a Blank Cell in Excel to Java using Apache POI

背景 :我正在尝试将Excel文件读入Java程序。 我的Excel文件用于表示网格或栅格地图,因此我将每个像元的高度和宽度都设置为1英寸。 我的想法是,我可以通过在每个单元格中加阴影来“绘制”地图或图像。 然后,我可以将Excel文件读取到使用“ Pixel”对象创建的Java程序中,并创建一个更直观的图像。 我是计算机科学专业的本科生,目前我只有四门计算机科学课程。 我了解OOP,并且可以使用Java编程。 这不是上课; 这是一个附带项目。 我正在使用XSSF(Microsoft 2007及更高版本)。

研究 :我发现解决此问题的方法是使用Apache POI。 我已经下载了必需的Apache POI jar文件,并在Eclipse中配置了BuildPath来读取它们。 我发现使用Iterator hasNext()方法将跳过空白单元格,因此解决方案是使用更直接的getCell()方法。 我发现有两种getCell()方法-一种仅将索引作为输入,另一种同时使用索引输入和MissingCellPolicy。 但是,当我尝试通过将RETURN_NULL_AND_BLANK用作输入来使用MissingCellPolicy方法时,它使单元格为空白,但在此过程中使颜色为空。 MissingCellPolicy CREATE_NULL_AS_BLANK具有相同的问题。

一种无效的解决方案 :当我将文本放在单元格中时,它会正确读取颜色。 即使是迭代器方法也可以正确读取其中包含文本的单元格。 这是因为一旦将文本放入其中,单元格就会被初始化。 但是,我尝试制作的网格太大,无法在每个单元格中放置文本。 可能有一种方法可以将工作表上的每个单元格设置为具有相同的文本,但是我也不能这样做,因为我在网格中已经有很多具有特定文本的单元格,并且无法删除它们。 这也可能会使所有单元格具有相同的颜色,这也是我目前无法做到的。 此外,如果我可以有没有文本的单元格,我会更喜欢。

TL; DR :我需要通过使用Apache POI将Excel中的单元格颜色读取到Java中,而无需将文本写入单元格中。 据我了解,带有MissingCellPolicy的方法getCell()不起作用,因为该策略创建了一个新的空白单元格,覆盖了现有颜色。 我已经看到了很多有关读取Apache POI中的空白单元格的问题,但是我没有看到有关访问颜色的问题。

MAIN CODE:

    try {
        FileInputStream file = new FileInputStream(new File("My FilePath"));
        XSSFWorkbook workbook = new XSSFWorkbook(file);
        XSSFSheet sheet = workbook.getSheetAt(0);
        for(int i=0; i<5040; i++) {
            Row row = sheet.getRow(i);
        for(int j=0; j<10080; j++) {
            Cell cell = row.getCell(j, Row.MissingCellPolicy.RETURN_NULL_AND_BLANK);
            ExtendedColor color = (ExtendedColor) cell.getCellStyle().getFillForegroundColorColor(); 
            //NOTE: getFillBackgroundColorColor did not work! It only returns the color black.
            byte[] bytes = color.getRGB();
            RGBColor rgb = new RGBColor(bytes);
            String text = cell.getStringCellValue();
            Coordinate coordinate = new Coordinate(j, i);
            Tile tile = new Tile(rgb, text);
            map[j][i] = tile;
            // Coordinate and Tile are other objects I made myself. 
            // The map is a two-dimensional array of Tiles, declared previously. 
            // I left this code here because it works.
        }
    }
    workbook.close();
    file.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

RGBColor构造函数代码:

    public RGBColor(byte[] bytes) {
        if(bytes != null) {
        this.red = (int) bytes[0];
        this.green = (int) bytes[1];
        this.blue = (int) bytes[2];
        if(red<0) {red = red+256;}
        if(green<0) {green = green+256;}
        if(blue<0) {blue = blue+256;}
    }

RESULT:上面的代码正确读取单元格的颜色(如果其中包含文本),并从该颜色创建RGBColor对象。 上面的代码还可以从单元格中读取文本。 但是,一旦到达没有文本的单元格,它就会在ExtendedColor行引起NullPointerException (因此该单元格为null)。 当改用MissingCellPolicy CREATE_NULL_AS_BLANK时,它将在byte[]行处引起NullPointerException (因此颜色为null)。 感谢任何帮助,即使它不是我真正想要的,因为我对Apache POI

最终发生的事情是您尝试处理空单元格或空白单元格,并且在遇到它们时不进行处理。 调用getCell()之后,您要做的是这样的事情:

if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
    // assign whatever color you want for a blank cell to rgb
} else {
    // do your logic to get the ExtendedColor and turn it into an RGBColor
}

单个彩色单元永远不能为空。 它必须存在。 因此,我们只能遍历现有单元。 每个定义的CellStyle都不为空。 但是,如果没有颜色, CellStyle.getFillForegroundColorColor可以返回null。 所以我们需要检查。

假设以下工作表:

在此处输入图片说明

码:

import org.apache.poi.ss.usermodel.*;
import java.io.*;

import java.util.Arrays;

class ReadColorsFromExcel {

 public static void main(String[] args) throws Exception{

  InputStream inp = new FileInputStream("MyFile.xlsx");
  Workbook workbook = WorkbookFactory.create(inp);
  Sheet sheet = workbook.getSheetAt(0);
  for (Row row : sheet) {
   for (Cell cell : row) { // cell will always be not-null only existing cells are in loop
    CellStyle cellStyle = cell.getCellStyle(); // cellStyle is always not-null
    ExtendedColor extendedColor = (ExtendedColor)cellStyle.getFillForegroundColorColor(); // extendedColor may be null
    String color = "none";
    if (extendedColor != null) {
     byte[] bytes = extendedColor.getRGB();
     color = Arrays.toString(bytes);
    }
    System.out.println("Cell " + cell.getAddress() + " of type " + cell.getCellType() + " has color " + color);
   }
  }
 }
}

将打印:

Cell A1 of type 1 has color none
Cell B1 of type 0 has color [-1, -1, 0]
Cell C1 of type 2 has color none
Cell B3 of type 0 has color none
Cell C3 of type 3 has color [-110, -48, 80]
Cell D4 of type 1 has color none
Cell B6 of type 3 has color [0, 112, -64]
Cell D7 of type 3 has color [-1, 0, 0]
Cell A9 of type 3 has color [-1, -64, 0]
Cell F12 of type 3 has color [0, -80, 80]

但是在Excel整个列和整个行也可能具有样式。 如果是这样,则单元格不是颜色,而是列和/或行。 因此,如果还需要获取不存在的单元格(这样的单元格将不存储因此为空),并且还考虑到可能存在列样式(整个列)和行样式(整个行),请考虑以下内容:

片:

在此处输入图片说明

所有单元格(所有列)具有白色背景,第8行具有浅蓝色背景,列E具有浅绿色背景。 一些细胞具有自己的细胞背景。

码:

import org.apache.poi.ss.usermodel.*;
import java.io.*;

import java.util.Arrays;

class ReadColorsFromExcel {

 public static void main(String[] args) throws Exception{

  InputStream inp = new FileInputStream("MyFile.xlsx");
  Workbook workbook = WorkbookFactory.create(inp);
  Sheet sheet = workbook.getSheetAt(0);

  int lastRow = 12;
  int lastCol = 6;

  for (int rowNum = 0; rowNum < lastRow; rowNum++) {
   Row row = sheet.getRow(rowNum);
   if (row == null) {
    row = sheet.createRow(rowNum);
   }
   CellStyle rowStyle = row.getRowStyle(); // if the whole row has a style
   for (int colNum = 0; colNum < lastCol; colNum++) {
    CellStyle colStyle = sheet.getColumnStyle(colNum); // if the whole column has a style
    Cell cell = row.getCell(colNum, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
    CellStyle cellStyle = cell.getCellStyle(); // cellStyle is always not-null
    String color = "none";
    ExtendedColor extendedColor = (ExtendedColor)cellStyle.getFillForegroundColorColor(); // first we try cellStyle
    if (extendedColor == null && rowStyle != null) extendedColor = (ExtendedColor)rowStyle.getFillForegroundColorColor(); // now we try rowStyle
    if (extendedColor == null && colStyle != null) extendedColor = (ExtendedColor)colStyle.getFillForegroundColorColor(); // at last we try colStyle
    if (extendedColor != null) {
     byte[] bytes = extendedColor.getRGB();
     color = Arrays.toString(bytes);
    }
    System.out.println("Cell " + cell.getAddress() + " of type " + cell.getCellType() + " has color " + color);
   }
  }
 }
}

现在应该考虑所有可能的样式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM