将 Jtable 转换为 excel,更新文件错误

Converting Jtable to excel,updated file error

我写了一个代码来创建 jTable 并导出到 Excel.I works.But 当我打开 Excel 文件时文件没有完全恢复。 它显示了以下问题:

已修复部分:/xl/worksheets/sheet2.xml 部分有 XML 错误。加载错误。第 2 行,第 0 列。 已修复部分:/xl/worksheets/sheet7.xml 部分有 XML 错误。加载错误。第 2 行,第 0 列。 删除的记录:/xl/workbook.xml 部分的命名范围(工作簿) 删除的记录:Table 来自 /xl/tables/table1.xml 部分 (Table)

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.awt.event.ActionEvent;

public class GUI {
    private static JTextField textField;
    private static JTextField textField_1;

public static void main(String args[]) throws IOException {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Object rowData[][] = null ;
    Object columnNames[] = { "Column One", "Column Two"};
    DefaultTableModel model = new    DefaultTableModel(rowData,columnNames);
    frame.getContentPane().setLayout(null);
    JTable table = new JTable(model);
    table.setModel(model);
    JScrollPane scrollPane = new JScrollPane(table);
    scrollPane.setBounds(76, 106, 300, 200);
    scrollPane.setVisible(true);
    frame.getContentPane().add(scrollPane);

    textField = new JTextField();
    textField.setBounds(76, 21, 86, 20);
    frame.getContentPane().add(textField);
    textField.setColumns(10);

    textField_1 = new JTextField();
    textField_1.setBounds(76, 61, 86, 20);
    frame.getContentPane().add(textField_1);
    textField_1.setColumns(10);

    JLabel lblNewLabel = new JLabel("Name");
    lblNewLabel.setBounds(20, 24, 46, 14);
    frame.getContentPane().add(lblNewLabel);

    JLabel lblAge = new JLabel("Age");
    lblAge.setBounds(20, 64, 46, 14);
    frame.getContentPane().add(lblAge);



    JButton btnNewButton = new JButton("Get Data");
    btnNewButton.setBounds(235, 40, 89, 23);
    btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
            String name = textField.getText().toString();
            int age = Integer.parseInt(textField_1.getText());
            model.addRow(new Object[] {name,age});
            Object obj1 = GetData(table, 0,0 );
            System.out.println("Cell value of 1 column and 1 row :" + obj1);
            Object obj2 = GetData(table, 0,1 );
            System.out.println("Cell value of 2 column and 1 row :" + obj2);

        }
    });



    frame.getContentPane().add(btnNewButton);

    JButton btnNewButton_1 = new JButton("Excel");
    btnNewButton_1.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            try {
                writeToExcel(table);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
    btnNewButton_1.setBounds(340, 40, 89, 23);
    frame.getContentPane().add(btnNewButton_1);
    frame.setSize(455, 356);
    frame.setVisible(true);
  }



protected static void writeToExcel(JTable table) throws Exception {

    try {
        File file = new File("IET.xlsx");
        FileInputStream inputStream = new FileInputStream(file);
        XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(inputStream);
        XSSFSheet sh = workbook.getSheet("UserInputs");
        TableModel model = table.getModel();
        String value1 = model.getValueAt(0, 0).toString();
        String value2 = model.getValueAt(0, 1).toString();

        workbook.getSheet("UserInputs").getRow(8).getCell(1).setCellValue(value2);


    FileOutputStream fileOut = new FileOutputStream(file);
    workbook.write(fileOut);
    fileOut.close();
    workbook.close();
    System.out.println("File written successfully");
    }
    catch(Exception e){
    System.out.print(e);}
    }



private static Object GetData(JTable table, int x, int y) {

    return table.getValueAt(x, y).toString();
}
  }

代码有问题吗?

您的代码仅覆盖 sheet UserInputs 中的一个单元格 B9。如果这导致问题:

"Repaired Part: /xl/worksheets/sheet2.xml part with XML error. Load error. Line 2, column 0. Repaired Part: /xl/worksheets/sheet7.xml part with XML error. Load error. Line 2, column 0. Removed Records: Named range from /xl/workbook.xml part (Workbook) Removed Records: Table from /xl/tables/table1.xml part (Table)"

打开 Excel 中的工作簿时,sheet 中的单元格 B9 sheet UserInputs 是 header 中的单元格之一一个 Excel table object。此外,至少在 sheet2 和 sheet7 中使用了结构化 table 引用,例如 =Tablename[Columnname],用于公式中,并且还使用了此类结构化 table 引用在命名范围内。

所以如果 B9 in sheet sheet UserInputs 是 Excel table 的 header 单元格之一object 并且现在已更改,然后一开始 table 本身已损坏,因为其中一个列名称已更改而没有更新 table。但是所有结构化的 table 引用,例如 =Tablename[Columnname],都是损坏的,因为 Columnname 已经更改而没有更新所有这些公式。

更新 table header 可以使用 XSSFTable.updateHeaders。但是更新所有 sheet 甚至所有命名范围中所有公式中的所有结构化 table 引用将非常昂贵,甚至几乎不可能。所以我建议 而不是 更改 Excel table object 的 header 单元格。让 header 单元格保持原样,仅更改 table.

的内容范围

示例:

让我们有以下 IET.xlsx 文件:

如您所见,sheet UserInput 中有一个名为 Table1 的 table,header 位于第 9 行。

现在我们可以用 JTable 中的内容覆盖内容范围 B10:F[10+n],如下所示:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.*;
import org.apache.poi.ss.util.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;

import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

class ReadAndWriteExcelHavingTableObject {

 static void writeToExcel(XSSFTable exceltable, JTable table) throws Exception {

  int exceltableStartRow = exceltable.getStartRowIndex();
  int exceltableStartCol = exceltable.getStartColIndex();

  XSSFSheet sheet = (XSSFSheet)exceltable.getParent();

  TableModel model = table.getModel();

  int exceltableEndRow = exceltableStartRow + model.getRowCount(); //as much rows as are in the model
  int exceltableEndCol = exceltable.getEndColIndex();

  //write the content
  for (int r = 0; r < model.getRowCount(); r++) {
   for (int c = 0; c < exceltableEndCol - exceltableStartCol + 1; c++) {
    XSSFRow row = sheet.getRow(exceltableStartRow + 1 + r);
    if (row == null) row = sheet.createRow(exceltableStartRow + 1 + r);
    XSSFCell cell = row.getCell(exceltableStartCol + c);
    if (cell == null) cell = row.createCell(exceltableStartCol + c);

    if (c < model.getColumnCount() && model.getValueAt(r, c) instanceof String) {
     String str = (String)model.getValueAt(r, c);
     cell.setCellValue(str);
    } else if (c < model.getColumnCount() && model.getValueAt(r, c) instanceof Double) {
     Double value = (Double)model.getValueAt(r, c);
     cell.setCellValue(value);
    } else if (c >= model.getColumnCount()) { //formula cells
     XSSFCell firstCell = sheet.getRow(exceltableStartRow + 1).getCell(exceltableStartCol + c);
     if (firstCell.getCellTypeEnum() == CellType.FORMULA) { 
      cell.setCellFormula(firstCell.getCellFormula());
     }
    }
   }
  }

  //update the size of exceltable
  exceltable.setCellReferences(new AreaReference(
    new CellReference(exceltableStartRow, exceltableStartCol),
    new CellReference(exceltableEndRow, exceltableEndCol),
    SpreadsheetVersion.EXCEL2007));

 }


 public static void main(String[] args) throws Exception {

  Object rowData[][] = {
          {"Bob", 12.0, 3.0},
          {"Alice", 34.0, 2.5},
          {"Jack", 56.0, 2.0},
          {"John", 78.0, 1.5}
          };
  Object columnNames[] = {"Name", "Amount", "Factor"};
  DefaultTableModel model = new DefaultTableModel(rowData, columnNames);
  JTable table = new JTable(model);
  table.setModel(model);

  File file = new File("IET.xlsx");
  FileInputStream inputStream = new FileInputStream(file);
  XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(inputStream);

  XSSFTable exceltable = workbook.getTable("Table1");

  writeToExcel(exceltable, table);

  workbook.setForceFormulaRecalculation(true);

  FileOutputStream fileOut = new FileOutputStream(file);
  workbook.write(fileOut);
  fileOut.close();
  workbook.close();

 }
}

结果将是:

并且由于没有更改 header,table 本身和所有结构化引用在此之后都不会损坏。