如何读写Excel文件

199

我想要使用Java读取和写入一个具有3列和N行的Excel文件,并将每个单元格中的一个字符串打印出来。是否可以给我提供简单的代码片段?我需要使用任何外部库还是Java内置支持它?

我想要做以下事情:

for(i=0; i <rows; i++)
     //read [i,col1] ,[i,col2], [i,col3]

for(i=0; i<rows; i++)
    //write [i,col1], [i,col2], [i,col3]

使用GemBox.Spreadsheet for Java,这很简单,只需在工作表中迭代行和行中分配的单元格,并在每个单元格上调用ExcelCell.getValue()。例如,请参阅此读取示例,对于写入,您可以查看示例。 - bellpatricia
23个回答

160
尝试使用Apache POI HSSF来处理Excel文件。以下是读取Excel文件的示例代码:
try {
    POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(file));
    HSSFWorkbook wb = new HSSFWorkbook(fs);
    HSSFSheet sheet = wb.getSheetAt(0);
    HSSFRow row;
    HSSFCell cell;

    int rows; // No of rows
    rows = sheet.getPhysicalNumberOfRows();

    int cols = 0; // No of columns
    int tmp = 0;

    // This trick ensures that we get the data properly even if it doesn't start from first few rows
    for(int i = 0; i < 10 || i < rows; i++) {
        row = sheet.getRow(i);
        if(row != null) {
            tmp = sheet.getRow(i).getPhysicalNumberOfCells();
            if(tmp > cols) cols = tmp;
        }
    }

    for(int r = 0; r < rows; r++) {
        row = sheet.getRow(r);
        if(row != null) {
            for(int c = 0; c < cols; c++) {
                cell = row.getCell((short)c);
                if(cell != null) {
                    // Your code here
                }
            }
        }
    }
} catch(Exception ioe) {
    ioe.printStackTrace();
}

在文档页面上,您还可以找到如何编写Excel文件的示例。

15
row.getCell((short)c); 已经不推荐使用,我认为应该使用 int 替代。 - DavidVdd
4
实际上,只需删除(short)转换:https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFRow.html#getCell%28short%29 - nicolallias
1
在尝试使用此代码时,我发现HSSFSheetgetPhysicalNumberOfRows()方法似乎返回非空行数(对于我来说,“物理”是什么意思并不明显)。因此,如果您的Excel文件有很多空行(即出于格式化原因),您可能会更幸运地使用rows = sheet.getLastRowNum();。这也应该意味着您可以从第一个循环中删除技巧(请参见注释):for(int i = 0; i <= rows; i++) {(请注意从<更改为<=)。 - pearcemerritt
文件编码在哪里指定? - Ring
1
尝试使用Workbook而不是HSSFWorkbook。它支持HSSF(.xls)和XSSF(.xlsx)两种格式。 - Jerin D Joy
显示剩余2条评论

59

Apache POI可以帮你实现这个功能。具体来说,使用HSSF模块。最有用的是快速指南。以下是如何完成您想要的操作-特别是创建一个工作表并将其写出。

Workbook wb = new HSSFWorkbook();
//Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");

// Create a row and put some cells in it. Rows are 0 based.
Row row = sheet.createRow((short)0);
// Create a cell and put a value in it.
Cell cell = row.createCell(0);
cell.setCellValue(1);

// Or do it on one line.
row.createCell(1).setCellValue(1.2);
row.createCell(2).setCellValue(
createHelper.createRichTextString("This is a string"));
row.createCell(3).setCellValue(true);

// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();

我们能否在不借助任何框架的情况下,使用纯Java/Spring来完成它? - Brooklyn99
1
如果你正在使用Spring,那么它不是纯Java。我认为,如果你想读取这些文件,那么POI是前进的方向。 - Brian Agnew

40

首先将以下jar文件添加到您的项目类路径中:

  1. poi-scratchpad-3.7-20101029
  2. poi-3.2-FINAL-20081019
  3. poi-3.7-20101029
  4. poi-examples-3.7-20101029
  5. poi-ooxml-3.7-20101029
  6. poi-ooxml-schemas-3.7-20101029
  7. xmlbeans-2.3.0
  8. dom4j-1.6.1

用于在Excel文件中写入代码:

public static void main(String[] args) {
    //Blank workbook
    XSSFWorkbook workbook = new XSSFWorkbook();

    //Create a blank sheet
    XSSFSheet sheet = workbook.createSheet("Employee Data");

    //This data needs to be written (Object[])
    Map<String, Object[]> data = new TreeMap<String, Object[]>();
    data.put("1", new Object[]{"ID", "NAME", "LASTNAME"});
    data.put("2", new Object[]{1, "Amit", "Shukla"});
    data.put("3", new Object[]{2, "Lokesh", "Gupta"});
    data.put("4", new Object[]{3, "John", "Adwards"});
    data.put("5", new Object[]{4, "Brian", "Schultz"});

    //Iterate over data and write to sheet
    Set<String> keyset = data.keySet();

    int rownum = 0;
    for (String key : keyset) 
    {
        //create a row of excelsheet
        Row row = sheet.createRow(rownum++);

        //get object array of prerticuler key
        Object[] objArr = data.get(key);

        int cellnum = 0;

        for (Object obj : objArr) 
        {
            Cell cell = row.createCell(cellnum++);
            if (obj instanceof String) 
            {
                cell.setCellValue((String) obj);
            }
            else if (obj instanceof Integer) 
            {
                cell.setCellValue((Integer) obj);
            }
        }
    }
    try 
    {
        //Write the workbook in file system
        FileOutputStream out = new FileOutputStream(new File("C:\\Documents and Settings\\admin\\Desktop\\imp data\\howtodoinjava_demo.xlsx"));
        workbook.write(out);
        out.close();
        System.out.println("howtodoinjava_demo.xlsx written successfully on disk.");
    } 
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

读取Excel文件的代码

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

public static void main(String[] args) {
    try {
        FileInputStream file = new FileInputStream(new File("C:\\Documents and Settings\\admin\\Desktop\\imp data\\howtodoinjava_demo.xlsx"));

        //Create Workbook instance holding reference to .xlsx file
        XSSFWorkbook workbook = new XSSFWorkbook(file);

        //Get first/desired sheet from the workbook
        XSSFSheet sheet = workbook.getSheetAt(0);

        //Iterate through each rows one by one
        Iterator<Row> rowIterator = sheet.iterator();
        while (rowIterator.hasNext())
        {
            Row row = rowIterator.next();
            //For each row, iterate through all the columns
            Iterator<Cell> cellIterator = row.cellIterator();

            while (cellIterator.hasNext()) 
            {
                Cell cell = cellIterator.next();
                //Check the cell type and format accordingly
                switch (cell.getCellType()) 
                {
                    case Cell.CELL_TYPE_NUMERIC:
                        System.out.print(cell.getNumericCellValue() + "\t");
                        break;
                    case Cell.CELL_TYPE_STRING:
                        System.out.print(cell.getStringCellValue() + "\t");
                        break;
                }
            }
            System.out.println("");
        }
        file.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

15

有一个新的易用而且非常酷的工具(感谢 Kfir):xcelite

写入:

public class User { 

  @Column (name="Firstname")
  private String firstName;

  @Column (name="Lastname")
  private String lastName;

  @Column
  private long id; 

  @Column
  private Date birthDate; 
}

Xcelite xcelite = new Xcelite();    
XceliteSheet sheet = xcelite.createSheet("users");
SheetWriter<User> writer = sheet.getBeanWriter(User.class);
List<User> users = new ArrayList<User>();
// ...fill up users
writer.write(users); 
xcelite.write(new File("users_doc.xlsx"));

阅读:

Xcelite xcelite = new Xcelite(new File("users_doc.xlsx"));
XceliteSheet sheet = xcelite.getSheet("users");
SheetReader<User> reader = sheet.getBeanReader(User.class);
Collection<User> users = reader.read();

15

您也可以考虑使用JExcelApi。我认为它比POI设计得更好。这里有一个教程点击这里


3
我尝试访问教程页面,但似乎已被移除。 - Vikram
5
JExcelApi适用于旧版(Excel 2003以前)二进制的.xls文件。 Apache POI-HSSF处理相同的旧版.xls文件,而 Apache POI-XSSF用于新版(Excel 2007及以上)的.xlsx文件。 - MGM
缺点是它仅支持处理 .xls(1997-2003)格式的 Excel 文件。 - zappee

11

我们可以使用 Apache POI 库来读取 xlsx 文件。 尝试这样做:

public static void readXLSXFile() throws IOException
    {
        InputStream ExcelFileToRead = new FileInputStream("C:/Test.xlsx");
        XSSFWorkbook  wb = new XSSFWorkbook(ExcelFileToRead);

        XSSFWorkbook test = new XSSFWorkbook(); 

        XSSFSheet sheet = wb.getSheetAt(0);
        XSSFRow row; 
        XSSFCell cell;

        Iterator rows = sheet.rowIterator();

        while (rows.hasNext())
        {
            row=(XSSFRow) rows.next();
            Iterator cells = row.cellIterator();
            while (cells.hasNext())
            {
                cell=(XSSFCell) cells.next();

                if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING)
                {
                    System.out.print(cell.getStringCellValue()+" ");
                }
                else if(cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC)
                {
                    System.out.print(cell.getNumericCellValue()+" ");
                }
                else
                {
                    //U Can Handel Boolean, Formula, Errors
                }
            }
            System.out.println();
        }

    }

9

.csv或POI肯定可以做到,但你应该知道Andy Khan的JExcel。我认为这是迄今为止最好的用于处理Excel的Java库。


而且它是商业的! - Michal - wereda-net
原始答案已经有12年了。或者说开源于2009年。 - duffymo

6
一个简单的CSV文件就足够了。

2
请注意,您将不得不在写入CSV的字符串中转义逗号。 - Brian Agnew
2
我不确定CSV是否足够,因为问题明确要求“读取”和“写入”Excel文件。他也许可以用CSV,但那不是他所问的。 - Brian Agnew
一些国际版本的Excel使用分号而不是逗号作为分隔符。这也增加了复杂性。 - Roalt
如果输出包含日期,CSV 可能过于简单。 - Thorbjørn Ravn Andersen
当你告诉普通用户将他们的Excel导出为CSV时,会出现很多问题 - 分号与逗号、逗号作为小数点、长数字(如ISBN / EAN)在CSV中显示为123E + 12、标签具有可能破坏CSV结构的换行符... 告诉用户上传他们的.xlsx文件并自己解析它要容易得多。 - Guntram Blohm
显示剩余3条评论

6
String path="C:\\Book2.xlsx";
try {

        File f = new File( path );
        Workbook wb = WorkbookFactory.create(f);
        Sheet mySheet = wb.getSheetAt(0);
        Iterator<Row> rowIter = mySheet.rowIterator();
        for ( Iterator<Row> rowIterator = mySheet.rowIterator() ;rowIterator.hasNext(); )
        {
            for (  Iterator<Cell> cellIterator = ((Row)rowIterator.next()).cellIterator() ; cellIterator.hasNext() ;  ) 
            {
                System.out.println ( ( (Cell)cellIterator.next() ).toString() );
            }
            System.out.println( " **************************************************************** ");
        }
    } catch ( Exception e )
    {
        System.out.println( "exception" );
        e.printStackTrace();
    }

请确保已将JAR文件 poi 和 poi-ooxml (org.apache.poi) 添加到您的项目中。


3

当然,您会发现下面的代码非常有用且易于阅读和编写。这是一个util类,您可以在主方法中使用它,然后就可以使用下面的所有方法了。

     public class ExcelUtils {
     private static XSSFSheet ExcelWSheet;
     private static XSSFWorkbook ExcelWBook;
     private static XSSFCell Cell;
     private static XSSFRow Row;
     File fileName = new File("C:\\Users\\satekuma\\Pro\\Fund.xlsx");
     public void setExcelFile(File Path, String SheetName) throws Exception                

    try {
        FileInputStream ExcelFile = new FileInputStream(Path);
        ExcelWBook = new XSSFWorkbook(ExcelFile);
        ExcelWSheet = ExcelWBook.getSheet(SheetName);
    } catch (Exception e) {
        throw (e);
    }

}


      public static String getCellData(int RowNum, int ColNum) throws Exception {

    try {
        Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
        String CellData = Cell.getStringCellValue();
        return CellData;
    } catch (Exception e) {

        return "";

    }

}
public static void setCellData(String Result, int RowNum, int ColNum, File Path) throws Exception {

    try {
        Row = ExcelWSheet.createRow(RowNum - 1);
        Cell = Row.createCell(ColNum - 1);
        Cell.setCellValue(Result);
        FileOutputStream fileOut = new FileOutputStream(Path);
        ExcelWBook.write(fileOut);
        fileOut.flush();
        fileOut.close();
    } catch (Exception e) {

        throw (e);

    }

}

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接