当前位置: 首页 > 知识库问答 >
问题:

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

越嘉树
2023-03-14

我有包含多个工作表的大型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());
        }
    }
}
}

文件很大,我只想使用事件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个答案

易镜
2023-03-14

我不认为POI中提供了任何开箱即用的东西,允许这样做。

因此,最好解压XLSX/XLSM文件(它们实际上是一个zip中的一堆XML文件),并将XML文件作为文本文件或使用普通XML解析器读取,这样您就可以轻松地再次写出更改后的文件,从而再次生成XLSX/XLSM文件。

 类似资料:
  • 我阅读了一些在线教程,并使用宏记录来学习如何设置格式。但是我想知道有没有一种方法可以不使用.select来完成以下操作?或者程序员更喜欢的方式是什么? 简单宏的要求: 循环所有工作表(仅可见) 将粗体格式设置为顶部行,并将背景设置为灰色 将所选内容重置到A1位置 ()

  • 我尝试了各种方式添加Excel电子表格。但问题总是相同的。 我尝试了这里提出的代码, 将工作表添加到现有excel文件 使用Apache POI for Java在现有Excel工作簿中创建新工作表 问题是:

  • 我正在尝试编写一个Java程序,该程序将每天运行(使用任务调度器),并在每次运行时向Excel电子表格中添加一列。我遇到的问题是,它只是重新写入文件,而不是附加到文件中。我正在使用Apache POI,以下是相关代码:

  • 问题内容: 我想向现有的Excel文件中添加工作表。我怎样才能做到这一点?我正在研究一个selenium项目,我想将所有自动化结果表添加到单个excel文件中。现在,我能够为每个工作表创建新的Excel文件。 问题答案: 如果从Java 使用: 分别打开现有工作表或创建新工作表: 要检查工作表是否存在以创建唯一的工作表名称,可以使用如下所示的内容: 然后您可以通过调用添加工作表: 在这种情况下,工

  • 我试图将列表数据写入一个工作簿中的多个excel表格。与第一个列表一样,代码将创建新工作簿并为列表[1]创建新工作表,对于第二个列表,它将在现有工作簿中创建新工作表,依此类推。所以我写了下面的代码。但是它不起作用,我只能看到列表[1]的第一页。有人能帮我提供任何替代解决方案吗? 下面我写的代码 谢谢,Priyank Shah

  • 我试图使用apache POI、使用primefaces和java在现有的excel工作簿中创建一个新的工作表,但是到目前为止还没有成功。谁能告诉我这是怎么做的吗?我可以做单张 下面的代码是我为在一个xls文件中创建多个工作表而编写的,我给出的条件是它没有大于65535的of行创建新工作表并迭代它,但它显示错误 警告:允许范围(0..65535)之外的无效行号(65536)java.lang.Il