Apache POI事件API更新现有Excel工作表

时间:2016-02-08 21:29:23

标签: java excel apache-poi

我有大量的excel文件,里面有几个工作表 我想在文件中处理一个工作表...从两列读取值并更新两列。

使用此代码,我可以从sheet中读取数据。但是无法弄清楚如何保存输出。

public class ExcelFunctions {

private class ExcelData implements SheetContentsHandler {       
    private Record rec ;


    public void startRow(int rowNum) {
        rec = new Record();
        output.put("R"+rowNum, rec);            
    }

    public void endRow(int rowNum) {
    }

    public void cell(String cellReference, String formattedValue,
            XSSFComment comment) {

        int thisCol = (new CellReference(cellReference)).getCol();
        if(thisCol==7){
            try {
                rec.setK1(formattedValue);
            } catch (Exception e) {
            }
        }
        if(thisCol==8){
            try {
                rec.setK2(formattedValue);
            } catch (Exception e) {
            }
        }
        if(thisCol == 27){
            String key = rec.full_key();
            System.out.println(key);
            ///////Process Matched Key...get Data
            //////Set value to column 27
        }
        if(thisCol == 28){
            String key = rec.full_key();
            System.out.println(key);
            ///////Process Matched Key...get Data
            //////Set value to column 28
        }

    }

    public void headerFooter(String text, boolean isHeader, String tagName) {
    }
}


///////////////////////////////////////

private final OPCPackage xlsxPackage;


private final Map<String, Record> output;

public ExcelFunctions(OPCPackage pkg, Map<String, Record> output) {
    this.xlsxPackage = pkg;
    this.output = output;
}

public void processSheet(
        StylesTable styles,
        ReadOnlySharedStringsTable strings,
        SheetContentsHandler sheetHandler, 
        InputStream sheetInputStream)
        throws IOException, ParserConfigurationException, SAXException {
    DataFormatter formatter = new DataFormatter();
    InputSource sheetSource = new InputSource(sheetInputStream);
    try {
        XMLReader sheetParser = SAXHelper.newXMLReader();
        ContentHandler handler = new XSSFSheetXMLHandler(
              styles, null, strings, sheetHandler, formatter, false);
        sheetParser.setContentHandler(handler);
        sheetParser.parse(sheetSource);
     } catch(ParserConfigurationException e) {
        throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
     }
}

public void process()
        throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
    ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
    XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
    StylesTable styles = xssfReader.getStylesTable();
    XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
    boolean found = false;
    while (iter.hasNext() &&  !found) {
        InputStream stream = iter.next();
        String sheetName = iter.getSheetName();
        if(sheetName.equals("All Notes") ){
            processSheet(styles, strings, new ExcelData(), stream);
            found = true;
        }
        stream.close();
    }
}

@SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
    File xlsxFile = new File("C:\\Users\\admin\\Downloads\\Unique Name Macro\\big.xlsm");
    if (!xlsxFile.exists()) {
        System.err.println("Not found or not a file: " + xlsxFile.getPath());
        return;
    }

    // The package open is instantaneous, as it should be.
    OPCPackage p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ_WRITE);
    Map<String, Record> output = new HashMap<String, Record>();
    ExcelFunctions xlFunctions = new ExcelFunctions(p, output);
    xlFunctions.process();
    p.close();

    if (output != null){
        for(Record rec : output.values()){
            System.out.println(rec.full_key());
        }
    }
}
}

文件非常大,我只想使用Event API 我已成功测试使用此代码。
但是这会将整个文件加载到内存中(导致应用程序崩溃)...虽然我只需要编辑一张表。

    public static void saveToExcel(String ofn, Map<String, Record> data) {
    FileInputStream infile;
    try {
        infile = new FileInputStream(new File("C:\\Users\\admin\\Downloads\\Unique Name Macro\\big.xlsm"));
        XSSFWorkbook workbook = new XSSFWorkbook (infile);
        XSSFSheet sheet = workbook.getSheet("All Notes");

        for(Record rec : output.values()){
            Row dataRow = rec.getRow(rev.getRownum-1);
            setCellValue(dataRow, 26, "SomeValue");
            setCellValue(dataRow, 27, "SomeValue");
        }

        FileOutputStream out =  new FileOutputStream(new File(ofn));
        workbook.write(out);
        infile.close();
        out.close();
        workbook.close();
    }
    catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
private static void setCellValue(Row row,int col, String value){
    Cell c0 = row.getCell(col);
    if (c0 == null){
        c0 = row.createCell(col);
    }
    c0.setCellValue(value);
}

1 个答案:

答案 0 :(得分:1)

我认为POI开箱即可提供任何可以执行此操作的内容。

因此,通过解压缩XLSX / XLSM文件(它们实际上是zip中的一堆xml文件)并将xml文件作为文本文件或使用普通的XML Parser读取,这样做可能会更好您可以轻松地再次写出更改的文件以再次生成XLSX / XLSM文件。