简体   繁体   English

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

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

BACKGROUND : I am trying to read an Excel file into a Java Program. 背景 :我正在尝试将Excel文件读入Java程序。 My Excel file is meant to represent a grid or raster map, so I made the height and width of each cell one inch. 我的Excel文件用于表示网格或栅格地图,因此我将每个像元的高度和宽度都设置为1英寸。 The idea is that I can "draw" a map or image by shading in each cell with a color. 我的想法是,我可以通过在每个单元格中加阴影来“绘制”地图或图像。 Then, I can read the Excel file to a Java program I created myself with a "Pixel" object and create a more literal image. 然后,我可以将Excel文件读取到使用“ Pixel”对象创建的Java程序中,并创建一个更直观的图像。 I am an undergraduate in Computer Science, and I've only had four computer science classes at this point. 我是计算机科学专业的本科生,目前我只有四门计算机科学课程。 I understand OOP and can program in Java. 我了解OOP,并且可以使用Java编程。 This is not for a class; 这不是上课; this is a side project. 这是一个附带项目。 I am using XSSF (Microsoft 2007 and after). 我正在使用XSSF(Microsoft 2007及更高版本)。

RESEARCH : I have discovered that the solution to this is to use Apache POI. 研究 :我发现解决此问题的方法是使用Apache POI。 I have already downloaded the required Apache POI jar files and configured the BuildPath in Eclipse to read them. 我已经下载了必需的Apache POI jar文件,并在Eclipse中配置了BuildPath来读取它们。 I have discovered that using an Iterator hasNext() method will skip over blank cells, so the solution is to use the more direct getCell() method. 我发现使用Iterator hasNext()方法将跳过空白单元格,因此解决方案是使用更直接的getCell()方法。 I have discovered that there are two getCell() methods -- one with only the index as an input, and one that uses both the index input and MissingCellPolicy. 我发现有两种getCell()方法-一种仅将索引作为输入,另一种同时使用索引输入和MissingCellPolicy。 However, when I tried using the MissingCellPolicy method by placing a RETURN_NULL_AND_BLANK as the input, it made the cell blank, but made the color null in the process. 但是,当我尝试通过将RETURN_NULL_AND_BLANK用作输入来使用MissingCellPolicy方法时,它使单元格为空白,但在此过程中使颜色为空。 The MissingCellPolicy CREATE_NULL_AS_BLANK has the same problem. MissingCellPolicy CREATE_NULL_AS_BLANK具有相同的问题。

AN INEFFICIENT SOLUTION : When I put text in a cell, it correctly reads the color. 一种无效的解决方案 :当我将文本放在单元格中时,它会正确读取颜色。 Even the iterator method can correctly read cells that have text in them. 即使是迭代器方法也可以正确读取其中包含文本的单元格。 This is because once I put text in them, the cell is initialized. 这是因为一旦将文本放入其中,单元格就会被初始化。 However, the grid I am trying to make is too large for me to put text in every cell. 但是,我尝试制作的网格太大,无法在每个单元格中放置文本。 There is probably a way to set every cell on the sheet to have the same text, but I can't do this either because I already have many cells with specific text throughout my grid, and they can't be erased. 可能有一种方法可以将工作表上的每个单元格设置为具有相同的文本,但是我也不能这样做,因为我在网格中已经有很多具有特定文本的单元格,并且无法删除它们。 That would also probably make all of the cells the same color, which I also can't do at this point. 这也可能会使所有单元格具有相同的颜色,这也是我目前无法做到的。 Besides, I would prefer it if I could have cells with no text. 此外,如果我可以有没有文本的单元格,我会更喜欢。

TL;DR : I need to read the color of a cell in Excel into Java by using Apache POI without writing text into the cell. TL; DR :我需要通过使用Apache POI将Excel中的单元格颜色读取到Java中,而无需将文本写入单元格中。 From my understanding, the method getCell() with a MissingCellPolicy does not work because the Policy creates a new blank cell, overwriting the existing color. 据我了解,带有MissingCellPolicy的方法getCell()不起作用,因为该策略创建了一个新的空白单元格,覆盖了现有颜色。 I have seen a lot of questions regarding reading blank cells in Apache POI, but I did not see one about accessing color. 我已经看到了很多有关读取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 Constructor Code: 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: The above code correctly reads the color of a cell if it has text in it and creates an RGBColor object from the color. RESULT:上面的代码正确读取单元格的颜色(如果其中包含文本),并从该颜色创建RGBColor对象。 The above code can also read text from a cell. 上面的代码还可以从单元格中读取文本。 However, as soon as it reaches a cell without text, it causes a NullPointerException at the ExtendedColor line (So the cell is null). 但是,一旦到达没有文本的单元格,它就会在ExtendedColor行引起NullPointerException (因此该单元格为null)。 When the MissingCellPolicy CREATE_NULL_AS_BLANK is used instead, it causes a NullPointerException at the byte[] line (So the color is null). 当改用MissingCellPolicy CREATE_NULL_AS_BLANK时,它将在byte[]行处引起NullPointerException (因此颜色为null)。 Any help is appreciated, even if it isn't exactly what I ask for, because I am new to Apache POI ! 感谢任何帮助,即使它不是我真正想要的,因为我对Apache POI

Ultimately what's happening is you're trying to deal with null or blank cells and not handling them when you encounter them. 最终发生的事情是您尝试处理空单元格或空白单元格,并且在遇到它们时不进行处理。 What you want to do is something like this after calling getCell(): 调用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
}

A single colored cell can never be null. 单个彩色单元永远不能为空。 It must exists. 它必须存在。 So we can loop over existing cells only. 因此,我们只能遍历现有单元。 CellStyle is not-null per definition. 每个定义的CellStyle都不为空。 But CellStyle.getFillForegroundColorColor can return null if there is not a color. 但是,如果没有颜色, CellStyle.getFillForegroundColorColor可以返回null。 So we need to check. 所以我们需要检查。

Supposing the following sheet: 假设以下工作表:

在此处输入图片说明

Code: 码:

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);
   }
  }
 }
}

Will print: 将打印:

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]

But in Excel whole columns and whole rows also may have styles. 但是在Excel整个列和整个行也可能具有样式。 If so, not the cells will have the color but the columns and/or rows. 如果是这样,则单元格不是颜色,而是列和/或行。 So if the need is also to get not existing cells, such which current are not stored and so be null, and also take into account that there may be column styles (whole columns) and row styles (whole rows), then consider the following: 因此,如果还需要获取不存在的单元格(这样的单元格将不存储因此为空),并且还考虑到可能存在列样式(整个列)和行样式(整个行),请考虑以下内容:

Sheet: 片:

在此处输入图片说明

All cells (all columns) have white background, row 8 has light blue background, column E has light green background. 所有单元格(所有列)具有白色背景,第8行具有浅蓝色背景,列E具有浅绿色背景。 Some cells have their own cell background. 一些细胞具有自己的细胞背景。

Code: 码:

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);
   }
  }
 }
}

Now all possible styles should be taken into account. 现在应该考虑所有可能的样式。

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

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