如何使用java + poi在excel中设置单元格背景颜色

时间:2017-09-13 12:13:28

标签: java spring-mvc apache-poi

到目前为止,我使用Spring MVC进行了编码。

重要 - 我没有在这里使用HSSFWorkbook

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

我的要求是假设单元格数据格式不正确,例如“错误的数据格式”,所以我想更改特定的单元格背景颜色。

但如果我正在使用它能够做到这一点

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

但是当我使用这段代码时,我无法加载大量文件。

在上面的代码中,我只需要更改以添加样式。

2 个答案:

答案 0 :(得分:0)

以下是可能对您有所帮助的部分解决方案:

  1. 我已将rowCacheSize设置为1000(使用更高的值,花费的时间太长)

  2. 我自己创建了cellStyle并在其上使用了setCellStyle。

  3. 我有 - 但是到目前为止还没能找到保存方法,所以我无法测试它。

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

答案 1 :(得分:0)

Excel Streaming Reader名为读者,因为它仅供阅读使用。有一个StreamingWorkbook实现了Workbook,但大部分方法尚未实现。所以这是一个草案,直到现在。

如果涉及巨大的Excel文件,那么我们必须考虑一种完全不同的方法,而不是从这些大文件中创建HSSFWorkbookXSSFWorkbook

Workbook只能作为一个整体创建。但是我们当然可以将Excel文件的单个部分(如工作表部分(包含行和单元格))或样式部分(包含单元格样式,字体,填充,边框等)或共享字符串部分(包含单元格的文本内容)并解析它们。这导致较少的资源消耗,因为单个部分不如整个文件大。但它还需要更多关于文件内部结构的知识。最简单的任务是读取和解析单个部分,但如果涉及到变化,那么需要将它们写入部分流,那么它会变得很复杂,因为我们还需要了解并考虑部分关系

幸运的是XSSF*.xlsx)部分是XML,因此要解析(读取)并使用StAX进行写入。

以下代码使用此方法。它获取样式表部分,sheet1部分形成*.xlsx文件的ZIP包,然后在此文件的Sheet1的每第5行的每个单元格中设置红色背景颜色。此外,如果文件可能很大,那么代码应该以尽可能少的资源量运行。

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