Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用60+;使用ApachePOI的列_Java_Excel_Apache Poi - Fatal编程技术网

Java 用60+;使用ApachePOI的列

Java 用60+;使用ApachePOI的列,java,excel,apache-poi,Java,Excel,Apache Poi,我正在尝试使用从数据库获取的数据创建多个Excel工作表。每个Excel表格包含60多列和大约50k条记录(可能有所不同)。问题是系统花费了大量时间(5分钟以上),然后最终导致java.lang.OutOfMemoryError:GC开销限制超出了异常 我尝试将列的数量减少到只有6列,周转时间有了巨大的改进 下面是生成Excel工作表字节数组的代码: int rowIndex = 0; while (iterator.hasNext()) { List<CustomCell

我正在尝试使用从数据库获取的数据创建多个Excel工作表。每个Excel表格包含60多列和大约50k条记录(可能有所不同)。问题是系统花费了大量时间(5分钟以上),然后最终导致
java.lang.OutOfMemoryError:GC开销限制超出了
异常

我尝试将列的数量减少到只有6列,周转时间有了巨大的改进

下面是生成Excel工作表字节数组的代码:

int rowIndex = 0;
while (iterator.hasNext()) {
        List<CustomCellDataBean> cellData = iterator.next();

        // Insert generic data
        Row dataContentRow = sheet.createRow((short) rowIndex);

        for (int counter = 0; counter < cellData.size(); counter++) {
            CustomCellDataBean cd = cellData.get(counter);
            if (cd.getValue() != null) {
            // switch case based on the datatype of the cell
                switch (cd.getType()) {
                }
            }
        }
        rowIndex++;
}
// write to ByteArrayOutputStream and return the array of bytes
int行索引=0;
while(iterator.hasNext()){
List cellData=iterator.next();
//插入通用数据
行dataContentRow=sheet.createRow((短)行索引);
对于(int counter=0;counter

我已经提到了几个这样的问题,但无法找出任何有用的东西。我想知道,为了克服这个问题,我应该做些什么。

没有进一步的信息,我只能猜测你真正的问题是什么。但我可以告诉您,ApachePOI可以创建包含1000多列、20k多行、颜色、样式等内容的excel工作表(已经完成)

确保使用apache.poi的流式api

org.apache.poi.xssf.streaming

下面是apache的演示

更新

正如我链接到的演示中所述,您可能应该使用新的SXSSF用户模型(如果我记得正确的话,我就使用它),因为它为您处理所有流媒体内容;-)


这似乎有点落后,但我更喜欢在使用带有POI的大型数据集时手动构建工作表。下面是我用来帮助您入门的帮助器类:

public class Worksheet {
private static Logger logger = Logger.getLogger(Worksheet.class);

/**
 * XML data for building the worksheet.
 */
public StringBuilder data = new StringBuilder();

/**
 * The name of this worksheet's entry in the XLSX file.
 */
public String zipEntryName;

/**
 * Tracks the last row written to the spreadsheet.
 */
// xslx rows start at 1
// Changed lastRow to init at 0 after using startRow() for headers.
public int lastRow = 0;

/**
 * Tracks the last cell written to the spreadsheet.
 */
public int lastCell = 0;

/**
 * Stores any styles that have been generated using XSSF.
 */
public HashMap<String, XSSFCellStyle> styles = new HashMap<String, XSSFCellStyle>();

/**
 * Tracks any merged cells so that they can be appended to the worksheet XML.
 */
public List<String> merged = new ArrayList<String>();

private boolean inRow = false;

private XSSFSheet myWorksheet = null;

public void setPOIWorksheet(XSSFSheet sheet){
    myWorksheet = sheet;
    this.zipEntryName = sheet.getPackagePart().getPartName().getName().substring(1);
}
public XSSFSheet getPOIWorksheet(){
    return this.myWorksheet;
}

/**
 * Write the raw XML data of newSheets to the existing XLSX file in workbook.
 * @param workbook The current XSLX file to overwrite data in.
 * @param newSheets A Collection of Worksheet objects containing the XML data to insert into workbook.
 * @param newFile The OutputStream to write the new XLSX file to.
 */
public static void writeWorksheetsToWorkbook(InputStream workbook, Collection<Worksheet> newSheets, OutputStream newFile)
{
    ZipOutputStream zipStream = null;
    try{
        zipStream = new ZipOutputStream(newFile);
        ZipInputStream zip = new ZipInputStream(workbook);
        ZipEntry entry;
        // Copy unaffected entries.
        while((entry = zip.getNextEntry()) != null){
            boolean found = false;
            for(Worksheet ws : newSheets){
                if(entry.getName().equals(ws.zipEntryName)){
                    found = true;
                    break;
                }
            }
            if(!found){
                zipStream.putNextEntry(new ZipEntry(entry.getName()));
                byte[] buffer = new byte[1];
                while((zip.read(buffer, 0, 1)) > -1)
                    zipStream.write(buffer);
            }
        }
        // Insert XML for entries being replaced.
        for(Worksheet ws : newSheets){
            zipStream.putNextEntry(new ZipEntry(ws.zipEntryName));
            byte[] data = ws.data.toString().getBytes();
            zipStream.write(data, 0, data.length);
        }
    }catch(Exception e){
        logger.error("Error creating xlsx", e);
    }finally{
        if(zipStream != null) try{ zipStream.close(); }catch(Exception e){}
        if(newFile != null) try{ newFile.close(); }catch(Exception e){}
    }
}

/**
 * Write the raw XML data of newSheets to the existing XLSX file in workbook.
 * @param workbook The current XSLX file to overwrite data in.
 * @param newSheets A Collection of Worksheet objects containing the XML data to insert into workbook.
 * @param return A byte[] containing the new workbook.
 */
public static byte[] writeWorksheetsToWorkbook(InputStream workbook, Collection<Worksheet> newSheets){
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    writeWorksheetsToWorkbook(workbook, newSheets, bout);
    return bout.toByteArray();
}

public Worksheet setWorksheetName(XSSFSheet xssfWS){
    zipEntryName = xssfWS.getPackagePart().getPartName().getName().substring(1);

    return this;
}

/**
 * Write all of the XML used for starting the worksheet.
 */
public Worksheet startWorksheet(){
    data.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
    data.append("<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ");
    data.append("xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" ");
    data.append("xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" >\n");
    data.append("<sheetData>\n");

    return this;
}

/**
 * Write the XML for closing the worksheet, including merged cell data.
 */
public Worksheet closeWorksheet(){
    data.append("</sheetData>\n");

    if(merged.size() > 0){
        data.append("<mergeCells count=\"");
        data.append(merged.size());
        data.append("\">");
        for(String cells : merged){
            data.append("<mergeCell ref=\"");
            data.append(cells);
            data.append("\"/>");
        }
        data.append("</mergeCells>\n");
    }       
    data.append("</worksheet>\n");

    return this;
}

/**
 * Method for adding a new row to an Excel file.  This was added as part of Period Compliance Report because
 * we're not iterating over data like previous reports.
 * 
 * This will automatically close the previous row if left open.
 */
public Worksheet startRow(){
    lastCell = 0;
    if(inRow)
        endRow();

    lastRow++;
    data.append("<row r=\""+lastRow+"\">");
    inRow = true;

    return this;
}

/**
 * Method for closing a row in an Excel file.
 */
public Worksheet endRow(){
    data.append("</row>\n");
    inRow = false;

    return this;
}

/**
 * Method for adding Date data to an Excel file cell.
 * @param value The data to be added to the cell.
 */
public Worksheet addDateCell(String value){
    return addTextCell(value, null);
}
/**
 * Method for adding Date data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting to be used.
 */
public Worksheet addDateCell(String value, String formatting){
    return addTextCell(value, formatting);
}

/**
 * Method for adding String data to an Excel file cell. This was added as part of Period Compliance Report because
 * we're not iterating over data like previous reports.
 * @param value The data to be added to the cell.
 */
public Worksheet addTextCell(String value){
    return addTextCell(value, null);
}
/**
 * Method for adding String data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting used on the cell.
 */
public Worksheet addTextCell(String value, String formatting){
    return addCell(StringEscapeUtils.escapeXml(value), formatting, false, 0);
}
/**
 * Method for adding String data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting used on the cell.
 * @param mergeRight The number of cells to the right of this one that should be merged.
 */
public Worksheet addMergedTextCell(String value, String formatting, int mergeRight){
    return addCell(StringEscapeUtils.escapeXml(value), formatting, false, mergeRight);
}


/**
 * Method for adding numerical data to an Excel file cell.
 * @param value The data to be added to the cell.
 */
public Worksheet addNumberCell(String value){
    return addNumberCell(value,  null);
}
/**
 * Method for adding numerical data to an Excel file cell.
 * @param value The data to be added to the cell.
 */
public Worksheet addNumberCell(Number value){
    return addNumberCell(value.toString(), null);
}
/**
 * Method for adding numerical data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting used on the cell.
 */
public Worksheet addNumberCell(String value, String formatting){
    return addCell(value, formatting, true, 0);
}
/**
 * Method for adding numerical data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting used on the cell.
 */
public Worksheet addNumberCell(Number value, String formatting){
    return addCell(value.toString(), formatting, true, 0);
}
/**
 * Method for adding numerical data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting used on the cell.
 * @param mergeRight The number of cells to the right of this one that should be merged.
 */
public Worksheet addMergedNumberCell(String value, String formatting, int mergeRight){
    return addCell(value, formatting, true, mergeRight);
}
/**
 * Method for adding numerical data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param formatting Any style formatting used on the cell.
 * @param mergeRight The number of cells to the right of this one that should be merged.
 */
public Worksheet addMergedNumberCell(Number value, String formatting, int mergeRight){
    return addCell(value.toString(), formatting, true, mergeRight);
}

/**
 * Method for adding data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param element The cell location on the table row.
 * @param formatting The formatting style to use.
 * @param mergeRight The number of cells that should be merged to the right.
 * @return This Worksheet.
 */
private Worksheet addCell(String value, String formatting, boolean number, int mergeRight){
    String ref = addCell(value, formatting, number);

    if(mergeRight > 0){
        String right = null;
        for(int i = 1; i <= mergeRight; i++)
            right = addCell("", formatting, false);
        merged.add(ref+":"+right);
    }

    return this;
}
/**
 * Method for adding data to an Excel file cell.
 * @param value The data to be added to the cell.
 * @param element The cell location on the table row.
 * @param formatting The formatting style to use.
 * @return A String with the new cell's location.
 */
private String addCell(String value, String formatting, boolean number){
    String ref = new CellReference(lastRow-1,lastCell).formatAsString();
    data.append("<c ");
    if(formatting != null && styles.containsKey(formatting)){
        XSSFCellStyle style = styles.get(formatting);
        data.append("s=\"");
        data.append(style.getIndex());
        data.append("\" ");
    }else if(formatting != null)
        logger.debug("could not find style "+formatting);
    data.append("r=\"");
    data.append(ref);
    data.append((number) ? "\">" : "\" t=\"inlineStr\">");
    /*if(formatting == null) data.append((number) ? "\">" : "\" t=\"inlineStr\">");
    else{
        data.append("\" t=\"");
        data.append(formatting);
        data.append("\">");
    }*/
    data.append((number) ? "<v>" : "<is><t>");
    data.append(value);
    data.append((number) ? "</v>" : "</t></is>");
    data.append("</c>");
    lastCell++;

    return ref;
}

/**
 * Adds a bunch of cells to a row quickly.
 * @param fields The fields to be added.
 */
public Worksheet quickAdd(String... fields){
    if(!inRow)
        startRow();
    for(int i = 0; i < fields.length; i++)
        addTextCell(fields[i]);

    return this;
}
}
公共类工作表{
私有静态记录器=Logger.getLogger(Worksheet.class);
/**
*用于构建工作表的XML数据。
*/
公共StringBuilder数据=新StringBuilder();
/**
*XLSX文件中此工作表条目的名称。
*/
公共字符串zipEntryName;
/**
*跟踪写入电子表格的最后一行。
*/
//xslx行从1开始
//在对标头使用startRow()后,将lastRow更改为0处的init。
公共int lastRow=0;
/**
*跟踪写入电子表格的最后一个单元格。
*/
public int lastCell=0;
/**
*存储使用XSSF生成的所有样式。
*/
public HashMap styles=new HashMap();
/**
*跟踪任何合并的单元格,以便将其追加到工作表XML中。
*/
public List merged=new ArrayList();
私有布尔inRow=false;
私有XSSFSheet myWorksheet=null;
公共无效设置点工作表(XSSFSheet){
我的工作表=工作表;
this.zipEntryName=sheet.getPackagePart().getPartName().getName().substring(1);
}
公共XSSFSheet getPOIWorksheet(){
返回此.myWorksheet;
}
/**
*将新闻单的原始XML数据写入工作簿中现有的XLSX文件。
*@param工作簿当前要覆盖其中数据的XSLX文件。
*@param newSheets包含要插入工作簿的XML数据的工作表对象集合。
*@param newFile要将新XLSX文件写入的输出流。
*/
公共静态无效writeWorksheetsToWorkbook(InputStream工作簿、集合新闻表、OutputStream新文件)
{
ZipOutStream zipStream=null;
试一试{
zipStream=新ZipOutStream(新文件);
ZipInputStream zip=新的ZipInputStream(工作簿);
ZipEntry入口;
//复制未受影响的条目。
而((entry=zip.getnextery())!=null){
布尔值=false;
用于(工作表ws:newSheets){
if(entry.getName().equals(ws.zipEntryName)){
发现=真;
打破
}
}
如果(!找到){
putNextEntry(新的ZipEntry(entry.getName());
字节[]缓冲区=新字节[1];
而((zip.read(缓冲区,0,1))>-1)
zipStream.write(缓冲区);
}
}
//为要替换的条目插入XML。
用于(工作表ws:newSheets){
zipStream.putNextEntry(新Zippentry(ws.ZippentryName));
byte[]data=ws.data.toString().getBytes();
zipStream.write(数据,0,数据长度);
}
}捕获(例外e){
logger.error(“创建xlsx时出错”,e);
}最后{
如果(zipStream!=null),请尝试{zipStream.close();}捕获(异常e){}
如果(newFile!=null),请尝试{newFile.close();}捕获(异常e){}
}
}
/**
*将新闻单的原始XML数据写入工作簿中现有的XLSX文件。
*@param工作簿当前要覆盖其中数据的XSLX文件。
*@param newSheets包含要插入工作簿的XML数据的工作表对象集合。
*@param返回包含新工作簿的字节[]。
*/
公共静态字节[]writeWorksheetsToWorkbook(InputStream工作簿、集合新闻表){
ByteArrayOutputStream bout=新建ByteArrayOutputStream();
将工作表写入工作手册(工作簿、新闻表、布特);
返回bout.toByteArray();
}
公共工作表集合工作表名称(XSSFSheet xssfWS){
zipEntryName=xssfWS.getPackagePart().getPartName().getName().substring(1);
归还这个;
}
/**
*编写用于启动工作表的所有XML。
*/
公共工作表startWorksheet(){
数据。追加(“\n”);
数据。追加(“\n”);
数据。追加(“\n”);
归还这个;
}
/**
*编写用于关闭工作表的XML,包括合并的单元格数据。
*/
公共工作表关闭工作表(){
数据。追加(“\n”);
如果(合并的.size()>0){
数据。追加(“”);
对于(Str