1. 程式人生 > >Java 讀寫 excel 實戰完全解析

Java 讀寫 excel 實戰完全解析

本文微信公眾號「AndroidTraveler」首發。

背景

時值畢業季,很多畢業生初入職場。

因此,這邊也寫了一些新手相關的 Android 技術點。

比如上一篇的 Android 開發你需要了解的那些事 就是列舉了一些小點,避免新手 Android 開發者踩坑。

同時,也是恰逢暑假,因此大學生處於放假階段。

這一篇主要是來自一位大學生的提問。

因此這邊分享一下我個人的解題思路和方法,希望能夠對他有所啟發。

歡迎大家交流分享。

題目

使用語言:JAVA

需求:讀取一個Excel表格裡面的資料(例如:姓名+分數),對其進行重新排序(按分數高低),然後輸出在另一個Excel表格。

分析

一般對需求我們都採取拆分思維。

將大問題拆成小問題,小問題解決了,整個大問題也就解決了。

這個需求很明確,需要解決三個問題:

  1. 讀取 Excel 表格資料
  2. 對資料排序
  3. 將資料寫入另一個 Excel 表格

我們這裡要求使用 Java 語言,而 Java 語言一個很重要的點就是面向物件。

因此首先我們要考慮一下,這個題目裡面有哪些類需要我們建立。

大概可以想象需要下面這些類:

讀取資料類:ExcelReader
寫入資料類:ExcelWriter
資料排序類:由於 Java API 自帶,所以不需要重複造輪子
資料模型類:StudentScore
啟動類:ParserStart,帶有 main 方法

大概的 UML 圖如下:

此時我們可以寫出 v0.1 程式碼:
ExcelReader.java:

import java.util.List;
public class ExcelReader {
    public List<StudentScore> read(String fileName) {
        //TODO
        return null;
    }
}

ExcelWriter.java:

import java.util.List;
public class ExcelWriter {
    public void write(String fileName, List<StudentScore> list) {
        //TODO
    }
}

StudentScore.java:

public class StudentScore {
    private String name;
    private int score;
    
    public StudentScore(String name, int score) {
        super();
        this.name = name;
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
}

ParserStart.java:

import java.util.List;

public class ParserStart {
    public static void main(String[] args) {
        // 第一步:讀取資料
        List<StudentScore> dataList = new ExcelReader().read("input.xls");
        // 第二步:排序
        //TODO
        // 第三部:寫入資料
        new ExcelWriter().write("output.xls", dataList);
    }
}

好了,基本框架搭好了。接下來就一步一步來實現我們的方法。

v0.2 程式碼:完善 ExcelReader 的 read 方法

Excel 的讀取方法有第三方的庫可以使用,因此我們不需要自己寫。
我們這裡使用的是第三方的 Apache 提供的 POI 庫。
下載連結地址:https://poi.apache.org/download.html
寫這篇文章時使用到的版本是 4.1.0
解壓然後將 jar 包引入 Eclipse 專案即可。

接下來就是實際編寫程式碼了,詳情見註釋。

我們要讀取的檔案示例如下:

ExcelReader.java:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class ExcelReader {
    public List<StudentScore> read(String fileName) throws EncryptedDocumentException, IOException {
        if (fileName == null) return null;
        
        File xlsFile = new File(fileName);
        if (!xlsFile.exists()) return null;
        
        // 工作表
        Workbook workbook = WorkbookFactory.create(xlsFile);
        // 表個數
        int numberOfSheets = workbook.getNumberOfSheets();
//      System.out.println(numberOfSheets);
        if (numberOfSheets <= 0) return null;
        
        List<StudentScore> list = new ArrayList<>();
        //我們的需求只需要處理一個表,因此不需要遍歷
        Sheet sheet = workbook.getSheetAt(0);
        // 行數
        int rowNumbers = sheet.getLastRowNum() + 1;
//      System.out.println(rowNumbers);
        StudentScore score;
        // 讀資料,第二行開始讀取
        for (int row = 1; row < rowNumbers; row++) {
            Row r = sheet.getRow(row);
//          System.out.println(r.getPhysicalNumberOfCells());
            //我們只需要前兩列
            if (r.getPhysicalNumberOfCells() >= 2) {
                score = new StudentScore(r.getCell(0).toString(), (int) Double.parseDouble(r.getCell(1).toString()));
                list.add(score);
            } 
        }
        return list;
    }
}

v0.3 程式碼:對讀取後的資料做排序處理

在 v0.2 版本中,我們成功讀取了資料,但是我們讀取的資料是按照 Excel 裡面的順序的,因此我們需要做排序處理。Java 函式庫有對集合進行排序的方法。不過我們需要對 Model 進行額外處理,新增排序規則。因為排序可以是從小到大排,也可以是從大到小排。

StudentScore.java:

public class StudentScore implements Comparable<StudentScore>{
    
    private String name;
    private int score;
    
    public StudentScore(String name, int score) {
        super();
        this.name = name;
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    
    @Override
    public String toString() {
        return "StudentScore [name=" + name + ", score=" + score + "]";
    }
    
    @Override
    public int compareTo(StudentScore o) {
        return o.score - this.score;
    }
    
}

ParserStart.java:

import java.util.Collections;
import java.util.List;

public class ParserStart {

    public static void main(String[] args) throws Exception{
        // 第一步:讀取資料
        List<StudentScore> dataList = new ExcelReader().read("resource/input.xls");
        System.out.println(dataList);
        // 第二步:排序
        Collections.sort(dataList);
        System.out.println(dataList);
        // 第三部:寫入資料
//      new ExcelWriter().write("output.xls", dataList);
    }

}

v0.4 程式碼:將排序後的資料寫入另一個 excel 表中

在 v0.3 版本中,我們完成了資料的排序,接下來我們需要將排好序的資料寫到 output.xls 中。

ExcelWriter.java

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class ExcelWriter {

    public void write(String fileName, List<StudentScore> list)  {
        HSSFWorkbook workbook = new HSSFWorkbook();

        HSSFSheet sheet = workbook.createSheet("StudentScore");

        // 建立Excel標題行,第一行
        HSSFRow headRow = sheet.createRow(0);
        headRow.createCell(0).setCellValue("姓名");
        headRow.createCell(1).setCellValue("分數");

        // 往Excel表中遍歷寫入資料
        for (StudentScore studentScore : list) {
            createCell(studentScore, sheet);
        }

        File xlsFile = new File(fileName);
        try {
            // 或者以流的形式寫入檔案 workbook.write(new FileOutputStream(xlsFile));
            workbook.write(xlsFile);
        } catch (IOException e) {
            // TODO
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                // TODO
            }   
        }
    }

    // 建立Excel的一行資料。
    private void createCell(StudentScore studentScore, HSSFSheet sheet) {
        HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);
        dataRow.createCell(0).setCellValue(studentScore.getName());
        dataRow.createCell(1).setCellValue(studentScore.getScore());
    }

}

ParserStart.java

import java.util.Collections;
import java.util.List;

public class ParserStart {

    public static void main(String[] args) throws Exception {
        // 第一步:讀取資料
        List<StudentScore> dataList = new ExcelReader().read("resource/input.xls");
        System.out.println(dataList);
        // 第二步:排序
        Collections.sort(dataList);
        System.out.println(dataList);
        // 第三部:寫入資料
        new ExcelWriter().write("resource/output.xls", dataList);
    }

}

到此,通過幾個版本的迭代,我們的需求就實現了。

NOTE:
在本專案中,input.xls 放在 resource 資料夾下面。所以最終版本傳入的路徑是 resource/input.xls。另外輸出的時候這邊發現 Eclipse 沒有顯示出來 output.xls,需要重新整理一下。
此外,下載我的專案執行驗證時,可能需要修改下 JRE。
另外 jar 包不要引入錯位置了:

當然,還有幾個待完善的點需要說明下:

  1. 這裡沒有對輸入表的資料做合法性校驗,比如分數為負數的情況是否需要做一些提示之類的操作。
  2. 這裡判斷檔案不存在時,直接返回 null。而且沒有判斷檔案是否為 excel 檔案。這裡就交由大家完善。而且這邊異常沒有做處理,直接 throws。
  3. 這裡因為簡單就沒有做抽象。但是考慮可能需要讀寫 word 或者 pdf 或者其他檔案,所以可以考慮引入繼承和多型。抽取基類。
  4. 合理組織資料夾和命名。

另外說一下有什麼應用場景吧,其實還真有。

移動端有多語言,想象一下產品給你一張帶有多語言的 excel 表。
如果你一個一個拷貝到多個語言的資原始檔下,這效率難以想象。
而如果你用了這一節的內容,分分鐘讀取 excel 按照你要的規則組裝後輸出到控制檯。
想想就有點 6 啊。

好了,本期內容到此結束,歡迎留言交流討論。

如果你有想了解的知識點,歡迎公眾號留言私信,也許下一個 pick 的就是你。

原始碼獲取地址:
https://github.com/nesger/JavaSamples/tree/master/ParseExcel

參考連結:
Java讀取Excel資料:基於Apache POI(一)
Java讀取和解析Excel資料:基於Apache POI(二)
Java匯出資料行寫入到Excel表格:基於Apache POI

相關推薦

Java excel 實戰完全解析

本文微信公眾號「AndroidTraveler」首發。 背景 時值畢業季,很多畢業生初入職場。 因此,這邊也寫了一些新手相關的 Android 技術點。 比如上一篇的 Android 開發你需要了解的那些事 就是列舉了一些小點,避免新手 Android 開發者踩坑。 同時,也是恰逢暑假,因此大學生處於放假階段

JavaExcel之POI超入門(轉)

num mov war copy rbo workbook mon move dropdown   Apache POI 是用Java編寫的免費開源的跨平臺的 Java API,Apache POI提供API給Java程式對Microsoft Office格式檔案讀和寫的功

javaexcel(POI,支援xls和xlsx兩種格式)

這應該是一個比較全的示例了,更加複雜的功能可以在此基礎上擴充套件。此示例基於apache的POI類庫,相關jar包就不列舉了。這個類庫很通用,網上很好找。 1、不包含單元格合併的寫excel /** * excel匯出到輸出流 * 誰呼叫誰負責關閉輸出流 *

JavaExcel之POI超入門

Apache POI 是建立和維護操作各種符合Office Open XML(OOXML)標準和微軟的OLE 2複合文件格式(OLE2)的Java API。用它可以使用Java讀取和建立,修改MS Excel檔案.而且,還可以使用Java讀取和建立MS Word和MSPowerPoint檔案。Apac

Java 操作Excel poiexcel

Java 操作Excel poi讀寫excel,excel匯入匯出(精簡版) 1.所需jar包 下載地址:https://download.csdn.net/download/u014646662/10734734 2.原始碼 寫操作(excel匯出) package cn

java Workbook excel

1. 讀取具體位置的excel資料   package com.royan.weakey.platform.common.excel; import lombok.extern.slf4j.Slf4j; import org.apache.poi.hssf.usermodel.HSSFW

Java POI Excel 檔案簡單實現

整理FileUtils的一些方法,只是一些初步實現,剛寫完就掛上來了… 友情提示:**過於結構化,沒太多潤色....碼的不好還請諸位海涵並多提意見** 關聯的型別 資源 型別 說明 Workbook 介面 Ex

JAVA使用jxlExcel

java操作Excel一般有兩種方式,jxl和poi,這裡只說明用前一種。 一、使用jxl-2.6.12.jar 寫: File xlsFile = new File("jxl.xls

POI事件驅動模式Excel和格式設定及2007EXCEL解析SAXParser類找不到

POI事件驅動模式讀寫Excel 目前處理Excel的開源javaAPI主要有兩種,一是Jxl(Java Excel API),Jxl只支援Excel2003以下的版本。另外一種是Apache的Jakarta POI,相比於Jxl,POI對微軟辦公文件的支援更加強大,但

Java 利用Apache POI Excel檔案超出行列限制

1.首先說明,不管那個版本的Excel都有行、列數限制 可以開啟EXCEL 2003(xls)或EXCEL 2010以上(xlsx),通過CTRL + ↓與CTRL + → 即可看到: 1

圖文深入解析 JAVA 鎖,為什麼鎖套鎖會死鎖,反過來卻不會?

一、回顧基本的讀寫鎖 我們知道讀寫鎖 #java.util.concurrent.locks.ReentrantReadWrite

使用phpexcel類excel文件

如何 blank 第三方類庫 第三方類 文件 pex ffi bsp 地址 使用原生php讀寫excel文件的博文地址: 基於使用原生php讀寫excel文件的不靠譜,本文將簡單介紹如何使用第三方類庫phpexcel來讀寫excel文件。 首先,需要到githut下載php

pythonexcel

字符串 一行 工作 default print file 設置 logs open python讀寫excel: # coding=utf-8 import xlrd import xlwt import traceback from xlutils.copy imp

Pythonexcel表格的方法

python excel 表格 xls 目的:實現用python做excel的讀取、新增、修改操作。環境:ubuntu 16.04 Python 3.5.2用python讀寫文檔,一般是操作txt文件或者可以用記事本打開的文件,因為這個操作很直接,不需要導入其他模塊,但如果想要對excel表

java 文件常用方法

tools int big cti readline out 隨機 i++ utf package study.bigdata; import org.apache.commons.io.FileUtils; import org.apache.commons.io.I

java Parquet格式的數據 Parquet example

readline byte ble print 三種 每一個 sta cep edr import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io

Java Properties配置文件

int true copy nbsp sys util 保存時間 實現 hashtable 1.Properties類與Properties配置文件   Properties類繼承自Hashtable類並且實現了Map接口,也是使用一種鍵值對的形式來保存屬性集。不過Prop

Pythonexcel表格的方法二

python excel 讀寫表格 目的:實現用python的另一種方法做excel的讀取、新增操作。環境:ubuntu 16.04 Python 3.5.2情景:之前介紹了一種操作excel文件的方法(私鏈),現在使用另一種方法讀寫excel文件,一次性讀出或寫入,讀寫也很方便,讀出為有序字典

[Python3]Excel - openpyxl庫

註釋 出版 logs com lin author arc ltm 一行 什麽是openpyxl openpyxl是一個第三方的pythonexcel讀寫庫,支持Excel2010 xlsx/xlsm/xltx/xltm文件格式。 openpyxl提供哪些能力?

pythonExcel文件--使用xlrd模塊讀取,xlwt模塊寫入

xlrd get sta series 有趣 light log 分享 均值 一、安裝xlrd模塊和xlwt模塊 1. 下載xlrd模塊和xlwt模塊 到python官網http://pypi.python.org/pypi/xlrd下載模塊。下載的文件