与POI相关的代码块运行缓慢

时间:2013-09-24 14:45:20

标签: java apache-poi

我在下面的代码块中包含循环:

Row row = null;
Cell cell = null;
String dataVal = null;
String[] temp = null;

for (int j = 0; j < this.myDataValues.size(); j++) {
  row = sheet.createRow(rownum++);
  temp = this.finalRowValues.get(j);

   for (int i = 0; i < 4; i++) {
       cell = row.createCell(i);

       dataVal = temp[i];

            if (NumberUtils.isNumber(dataVal)) {
                double d = Double.valueOf(dataVal);
                cell.setCellValue(d);
                cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                cell.setCellStyle(styles.get("currency"));
            } else if (isValidDate(dataVal)) {
                cell.setCellValue(dataVal);
                cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                cell.setCellStyle(styles.get("date"));
            } else {
                cell.setCellValue(temp[i]);
                cell.setCellType(Cell.CELL_TYPE_STRING);
                cell.setCellStyle(styles.get("data"));
            }
            sheet.autoSizeColumn(i);
        }
    }

其中myDataValuesList String[],每个String[]对象包含4个值。

我在Rational Application Developer版本8和Apache POI 3.8中运行它。

myDataValues中有大约5500个元素,我认为这个元素值很小。

但是,此代码块需要花费一个多小时才能运行。

我觉得这有点不对劲。每个包含4个元素的5500个元素应该运行得非常快,应该是几分钟的问题。可能的原因是什么?有没有办法让这个块运行得更快?

机器的可用内存或任何其他此类问题没有任何问题。一切都按预期工作,我已经验证了。问题仅出在此块中。

3 个答案:

答案 0 :(得分:6)

您的处理速度很慢,因为您为每一行调用autoSizeColumn。来自Javadocs for the autoSizeColumn method

  

这个过程在大型纸张上可能相对较慢,因此应该这样做   通常每列只调用一次,在你的结尾   处理

将调用放置在创建行的循环之外的autoSizeColumn,仅在列上的for循环中。这将最大限度地减少对此方法的调用并提高您的性能。

答案 1 :(得分:1)

仅供参考...

就我而言,我有超过一百万,并且AutoSizeColumn仍然很慢(甚至最后)。

因此,我想提高性能,只存储列值和每个值的内容长度(在Dictionary中)(当它大于上次存储时)。

在所有过程结束时,只需“遍历”列表,并使用sheet.SetColumnWidth设置列的宽度。

  • 使用自动调整大小:永无止境;
  • witdh:3秒。

伪代码

if(!dictionary.Any(a => a.Key == columnIndex))
                {
                    dictionary.Add(columnIndex, columnContent.Length);
                }
                else if(dictionary.Any(a => a.Key == columnIndex && a.Value < columnContent.Length))
                {
                    dictionary[columnIndex] = columnContent.Length;
                }

最后

foreach (KeyValuePair<int, int> column in dictionary)
        {
            sheet.SetColumnWidth(column.Key, column.Value*300);
        }

答案 2 :(得分:0)

试试这个......

for (int j = 0; j < this.myDataValues.size(); j++) {
  row = sheet.createRow(rownum++);
  temp = this.finalRowValues.get(j);

   for (int i = 0; i < 4; i++) {
       cell = row.createCell(i);

       dataVal = temp[i];

            if (NumberUtils.isNumber(dataVal)) {
                double d = Double.valueOf(dataVal);
                cell.setCellValue(d);
                cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                cell.setCellStyle(styles.get("currency"));
            } else if (isValidDate(dataVal)) {
                cell.setCellValue(dataVal);
                cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                cell.setCellStyle(styles.get("date"));
            } else {
                cell.setCellValue(temp[i]);
                cell.setCellType(Cell.CELL_TYPE_STRING);
                cell.setCellStyle(styles.get("data"));
            }
        }
    }
    for (int i = 0; i < 4; i++) {
      sheet.autoSizeColumn(i);
    }