简体   繁体   English

如何使用Java + Poi在Excel中设置单元格背景色

[英]How to set cell background color in excel using java + poi

So far I did bellow coding using Spring MVC. 到目前为止,我已经使用Spring MVC进行了风箱编码。

Important- I am not using here HSSFWorkbook 重要提示-我不在这里使用HSSFWorkbook

So what is the equivalent of the POI method setCellStyle in StreamingReader 那么StreamingReader中的POI方法setCellStyle等效于什么

InputStream is = new FileInputStream(new File("file path"));
    StreamingReader  reader = StreamingReader.builder()
            .rowCacheSize(90000000)   
            .bufferSize(4096)  
            .sheetIndex(0)
            .read(is);            
    for (Row r : reader) {
       Test_huge_excel_data data = new Test_huge_excel_data();
       data.setCol1(r.getCell(0).getStringCellValue());
       data.setCol2(r.getCell(1).getStringCellValue());

       drtamminaService.saveExcelData(data);
    }

My requirement is suppose if a cell data is not formatted well example "wrong data format" so I want to change that particular cell background color. 我的要求是假设单元格数据的格式不正确,例如“错误的数据格式”,因此我想更改该特定单元格的背景色。

But if I am using this am able to do it 但是如果我正在使用它就可以做到

XSSFWorkbook myWorkBook = new XSSFWorkbook (fileInputStream);
XSSFCellStyle style = myWorkBook.createCellStyle();
style.setFillForegroundColor(IndexedColors.RED.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
row.getCell(30).setCellStyle(style);

But when I am using this code I am not able to load a huge amount of file. 但是,当我使用此代码时,我无法加载大量文件。

In my above code only I need changes to add style. 在我上面的代码中,仅需更改即可添加样式。

Here's a partial solution that might help you: 以下是部分解决方案可能会为您提供帮助:

  1. I have set rowCacheSize to 1000 (with your higher value, it took way too long) 我已将rowCacheSize设置为1000(使用更高的值,花费了太长时间)

  2. I have created the cellStyle myself and used setCellStyle on it. 我自己创建了cellStyle,并在其上使用了setCellStyle。

I have - however - not been able to find a save method so far, so I could not test it. 但是,到目前为止,我还无法找到保存方法,因此无法对其进行测试。

    StreamingReader reader = StreamingReader
            .builder()
            .rowCacheSize(1000)
            .bufferSize(4096)
            .sheetIndex(0)
            .read(is);

    XSSFCellStyle style = new XSSFCellStyle(new StylesTable());
    style.setFillForegroundColor(IndexedColors.RED.getIndex());
    style.setFillPattern(FillPatternType.SOLID_FOREGROUND);


    for (Row row : reader) {
        System.out.println(row.getRowNum());
        row.getCell(3).setCellStyle(style);
    }

The Excel Streaming Reader is named Reader because it is for reading only. Excel Streaming Reader被命名为Reader,因为它仅用于读取。 There is a StreamingWorkbook which implements Workbook but most of it's methods are not implemented yet. 有一个StreamingWorkbook可以实现Workbook,但大多数方法尚未实现。 So it is a draft until now. 因此,这是迄今为止的草案。

If it comes to huge Excel files then we must consider a totally different approach than creating HSSFWorkbook or XSSFWorkbook from those huge files. 如果涉及到巨大的Excel文件,那么我们必须考虑一种完全不同于从这些巨大文件创建HSSFWorkbookXSSFWorkbook方法。

A Workbook can only be created as a whole. 只能创建一个整体的Workbook But of course we could take single parts of the Excel files like the sheets part (containing rows and cells) or the styles part (containing the styles of the cells, the fonts, fills, borders etc.) or the shared strings part (containing text contents of the cells) and parse those. 但是当然,我们可以将Excel文件的单个部分,如工作表部分(包含行和单元格)或样式部分(包含单元格的样式,字体,填充,边框等)或共享字符串部分(包含单元格的文本内容)并进行解析。 This leads to less resource consuming since the single parts are less huge than the whole file. 由于单个部分的大小小于整个文件的大小,因此减少了资源消耗。 But it also needs more knowledge about the internal structure of the file. 但它也需要有关文件内部结构的更多知识。 And the easiest task is reading and parsing the single parts but if it comes to changings and so to the need writing those into the part streams, then it gets quickly complicated because then we need also to know about and to take into account the part relationships. 最简单的任务是读取和解析单个零件,但是如果涉及更改,因此需要将这些零件写入零件流中,那么它将很快变得很复杂,因为我们还需要了解并考虑零件关系。

Fortunately the XSSF ( *.xlsx ) parts are XML and as such to parse (read) and also to write using StAX . 幸运的是, XSSF*.xlsx )部分是XML ,因此可以解析(读取)并使用StAX进行写入。

The following code uses this approach. 以下代码使用此方法。 It gets the styles table part and the sheet1 part form the ZIP package of an *.xlsx file and then sets red background color in each cell of every 5th row from Sheet1 of this file. 它从*.xlsx文件的ZIP包中获取样式表部分和sheet1部分,然后在该文件的Sheet1的第5行的每个单元格中设置红色背景色。 Also if the file maybe huge, the code should nevertheless running with as less possible resource amount. 另外,如果文件可能很大,则代码仍应以尽可能少的资源量运行。

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;

import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;

import javax.xml.namespace.QName;

import java.io.File;
import java.io.OutputStream;

import java.util.regex.Pattern;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

class StaxReadAndWriteTestRowBGColor {

 public static void main(String[] args) {
  try {

   File file = new File("file.xlsx");
   OPCPackage opcpackage = OPCPackage.open(file);

   //get the styles table
   PackagePart stylestabletablepart = opcpackage.getPartsByName(Pattern.compile("/xl/styles.xml")).get(0);
   StylesTable stylestable = new StylesTable(stylestabletablepart);

   //get the sheet1 package part
   PackagePart sheetpart = opcpackage.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0);

   //create reader and writer for the sheet1 package part            
   XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(sheetpart.getInputStream());
   XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(sheetpart.getOutputStream());

   //create a factory for producing XML elements and attributes
   XMLEventFactory eventFactory = XMLEventFactory.newInstance();

   int rowsCount = 0;

   Map<Integer, Integer> styleIdxMap = new HashMap<>(); //a Map for mapping old styleIdx to new styleIdx

   while(reader.hasNext()){ //loop over all XML in sheet1.xml
    XMLEvent event = (XMLEvent)reader.next();

    if(event.isStartElement()){
     StartElement startElement = (StartElement)event;
     QName startElementName = startElement.getName();
     if(startElementName.getLocalPart().equalsIgnoreCase("row")) { //start element of row
      rowsCount++;
     } else if (startElementName.getLocalPart().equalsIgnoreCase("c")) { //start element of cell
      if (rowsCount % 5 == 0) { // every 5th row
       Attribute attribute;

       Iterator attributeIterator = startElement.getAttributes(); //get cell's attributes
       List<Attribute> attributeList = new ArrayList<>();
       int styleIdx = 0;
       while (attributeIterator.hasNext()) {
        attribute = (Attribute)attributeIterator.next();
        if ("s".equals(attribute.getName().getLocalPart())) { //cell has style attribute already
         styleIdx = Integer.valueOf(attribute.getValue()); //so get the styleIdx 
                                                           //but don't put in the attributeList since we wants creating it new
        } else {
         attributeList.add(attribute);
        }
       }

       XSSFCellStyle cellstyle;
       cellstyle = stylestable.getStyleAt(styleIdx);

       if (cellstyle.getFillForegroundColor() != IndexedColors.RED.getIndex() 
           && cellstyle.getFillPatternEnum() != FillPatternType.SOLID_FOREGR‌​OUND) {
        if (styleIdxMap.get(styleIdx) == null) { //old cell style is not mapped until now
         cellstyle = (XSSFCellStyle)cellstyle.clone(); //so clone style
         styleIdxMap.put(styleIdx, (int)cellstyle.getIndex()); //and put in the map
        } else {
         cellstyle = stylestable.getStyleAt(styleIdxMap.get(styleIdx)); //else get from already mapped style
        }
        cellstyle.setFillForegroundColor(IndexedColors.RED.getIndex());
        cellstyle.setFillPattern(FillPatternType.SOLID_FOREGR‌​OUND);
       }

       styleIdx = (int)cellstyle.getIndex(); //get final styleIdx
       attribute = eventFactory.createAttribute("s", Integer.toString(styleIdx)); //create new style attribute
       attributeList.add(attribute); //add it to the attributeList now
       StartElement newstartElement = eventFactory.createStartElement(startElementName, 
                                                                      attributeList.iterator(), 
                                                                      startElement.getNamespaces());

       event = newstartElement; //create a new event for the writer using the new cell StartElement
      }
     }
    }
    writer.add(event); //by default write each read event
   }
   writer.flush();

   //write out the styles table
   OutputStream out = stylestabletablepart.getOutputStream();
   stylestable.writeTo(out);
   out.close();

   opcpackage.close();

  } catch (Exception ex) {
     ex.printStackTrace();
  }
 }
}

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

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