excel - 读取 XLSX 文件并将数据存储在 Grails 中的有效方法

标签 excel grails groovy apache-poi sax

我需要读取一个 XLSX 文件,该文件包含 5 张纸中的约 50K 行,在 Grails 中大小约为 7MB。

我需要逐页读取文件,并将每一行存储到数据库表中。

但是我得到

Java heap space. Stacktrace follows:
Message: Executing action [abx] of controller [abc.xyz.controller]  caused exception: Runtime error executing action
        Line | Method
    ->>  198 | doFilter                 in grails.plugin.cache.web.filter.PageFragmentCachingFilter

我尝试通过将“GRAILS_OPTS”设置为来增加堆空间

GRAILS_OPTS=-XX:MaxPermSize=128m -XX:PermSize=128m -Xms1024m -Xmx1024m -XX:-UseGCOverheadLimit

但根本不起作用。

我遇到了这个问题

How to read XLSX file of size >40MB但这里没有正确的实现。

我尝试使用 SAX 从 XLSX 文件中读取 XML,方法如下:如何使用文档

http://poi.apache.org/spreadsheet/how-to.html

Grails Controller :

//      
//
        OPCPackage pkg = OPCPackage.open(filename);
        XSSFReader r = new XSSFReader( pkg );
        SharedStringsTable sst = r.getSharedStringsTable();

        XMLReader parser1 =
                XMLReaderFactory.createXMLReader(
                        "org.apache.xerces.parsers.SAXParser"
                );
        ContentHandler handler = new SheetHandler(sst);

 //
//

类SheetHandler.java

class SheetHandler extends DefaultHandler {
    private SharedStringsTable sst;
    private String lastContents;
    private boolean nextIsString;
    private List<String> rowData


    private SheetHandler(SharedStringsTable sst) {
        rowData = []
        this.sst = sst;
    }

    public void startElement(String uri, String localName, String name,
                             Attributes attributes) throws SAXException {

        // c => cell
        if(name.equals("c")) {
            // Print the cell reference
            //System.out.print(attributes.getValue("r") + " - ");
            // Figure out if the value is an index in the SST
            String cellType = attributes.getValue("t");
            if(cellType != null && cellType.equals("s")) {
                nextIsString = true;
            } else {
                nextIsString = false;
            }
        }
        // Clear contents cache
        lastContents = "";
    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {
        if(name  == "row"){
            println rowData
            rowData = []
        }
        // Process the last contents as required.
        // Do now, as characters() may be called more than once
        if(nextIsString) {
            int idx = Integer.parseInt(lastContents);
            lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            nextIsString = false;
        }

        // v => contents of a cell
        // Output after we've seen the string contents
        if(name.equals("v")) {
            rowData << lastContents
            System.out.println(lastContents);
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        lastContents += new String(ch, start, length);
    }
}

通过实现上述内容,我无法区分“标签”和“xlsx 文件行”。而且我也无法获取列的空值。

我无法正确使用 XSSFReader,请帮助我解决问题。

最佳答案

Shashank 您可以使用相同的解决方案。要跳过空单元格,您所要做的就是检查它正在解析的标签。 此代码将 xlsx 转换为带有标签的 xml

 <r> for row 
 <c> for cell
 <v> for value

和格式

 <r><c t="s" r="A32" s="50"><v>value in the cell</v></c></r> if there is a value in the cell
 <r><c t="s" r="A32" s="50"></c></r> if there is no value in the cell.

因此,如果有一行 8 列,并且第 3 列和第 5 列没有值,那么它将读取 xml 的顺序为(只需在 startElement 和 endElement 方法中打印变量名称)

r cvvc cvvc cc cvvc cc cvvc cvvc cvvc r

其中 cvvc 表示

<c><v></v></c>

因此,只需检查 startElement 方法和 endElement 方法中是否有连续的 c 作为名称,这意味着它有一个空值,然后在 rowData 中插入一个空格

  rowData << ""

您还可以通过将偏移参数传递给方法并跳过第一个偏移行数来跳过标签行。

希望有帮助。

关于excel - 读取 XLSX 文件并将数据存储在 Grails 中的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27890813/

相关文章:

excel - 如何在在线 Google Excel 中对数据进行中间处理?

excel - vba添加形状,等待3秒然后删除

java - 拦截groovy中所有元类的所有方法调用

excel - 我可以让这个宏更快吗?

vba - 打开多个工作簿和 SUM COUNTIFS

grails - View 中的grails数字( double )格式

eclipse - 在 MAC 中找到 ggts.ini

mongodb - Grails 4中mongo域类中的Autowire问题

java - 如何使用Groovy脚本查找文件中是否存在特定字符串?

java - 在 Activity 中使用变量