Java 讀寫Excel

  1. 簡介
    最近一個朋友讓我幫他處理一個excel文檔,功能是從excel表中的找到第一個sheet中每個點(經緯度)在第二個地理位置中最近的3個點。給個兩點的經緯度可以求出這兩點之間的距離,主要是如何讀寫excel,幸運的是Apache POI提供API給Java程序對Microsoft Office格式檔案讀和寫的功能。
    POI的主要結構:
    HSSF - 提供讀寫Microsoft Excel格式檔案的功能。
    XSSF - 提供讀寫Microsoft Excel OOXML格式檔案的功能。
    HWPF - 提供讀寫Microsoft Word格式檔案的功能。
    HSLF - 提供讀寫Microsoft PowerPoint格式檔案的功能。
    HDGF - 提供讀寫Microsoft Visio格式檔案的功能。

  2. 使用方式
    Apache POI官網上提供了詳細的使用說明文檔,具體接口如下圖所示。
    這裏寫圖片描述
    我們可以從QuickGuide中快速的學會如何使用POI。
    首先新建一個java工程,將POI的jar包都導入到項目裏面,目錄結構如下圖:
    這裏寫圖片描述

因爲功能比較簡單,我也就沒有劃分爲多個java文件,下面是主要的功能Test類,實現了從Excel不同的sheet中讀取數據並將數據寫會Excel中

package sxd.learn.java;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
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 Test {

    public static void main(String[] args) {
        new Test().run(args[0]);
    }

    public void run(String filePath) {
        Workbook wb = null;
        try {
            InputStream inp = new FileInputStream(filePath);
            wb = WorkbookFactory.create(inp);
        } catch (EncryptedDocumentException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到!");
            e.printStackTrace();
            System.exit(1);
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<BSPoint> listSheet2 = readBSPointFromSheet2(wb);

        Sheet sheet1 = wb.getSheetAt(0);
        int NUM = sheet1.getLastRowNum();
        float progress = 0.0f;
        for (int rowNum = 1; rowNum <= NUM; rowNum++) {
            Row row = sheet1.getRow(rowNum);
            double lon1 = row.getCell(2).getNumericCellValue();
            double lat1 = row.getCell(3).getNumericCellValue();
            List<Dis> disList = new ArrayList<Dis>();
            for (BSPoint point : listSheet2) {
                double lon2 = point.getLon();
                double lat2 = point.getLat();
                double dis = Utils.Distance(lon1, lat1, lon2, lat2);
                if(dis != 0)
                    disList.add(new Dis(dis,
                        point.getName()));
                Collections.sort(disList); //排序
            }

            /**
             * 計算出的數據寫入到該行的指定位置(沒有實際寫到文件中)
             */
            writeExcel(row, disList);
            progress = (float)(rowNum*1.0 / NUM) * 100;
//          Utils.updateProgress(String.valueOf(progress).length());
            Utils.showProgress(progress);
//          System.out.printf("第%d列,%.2f已經處理完成...", rowNum + 1, (rowNum*1.0 / NUM) * 100);
        }
        /*
         * 寫到文件中
         * 只有關閉輸出流,才能將更改寫入到Excel中
         */
        try {
            FileOutputStream fileOut = new FileOutputStream(filePath);
            wb.write(fileOut);
            fileOut.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * 從sheet2中取出所有的4G基站的位置數據
     */
    public List<BSPoint> readBSPointFromSheet2(Workbook wb) {
        List<BSPoint> list = new ArrayList<BSPoint>();
        Sheet sheet2 = wb.getSheetAt(1);
        for (int rowNum = 1; rowNum <= sheet2.getLastRowNum(); rowNum++) {
            Row row = sheet2.getRow(rowNum);
            list.add(new BSPoint(rowNum, row.getCell(1).getStringCellValue(),
                    row.getCell(2).getNumericCellValue(), row.getCell(3)
                            .getNumericCellValue()));
        }
        return list;
    }

    public void writeExcel(Row row, List<Dis> disList) {
        Cell cellDis = row.getCell(4);
        Cell cellName = row.getCell(5);
        if (cellDis == null) {
            cellDis = row.createCell(4);
            cellName = row.createCell(5);
        }
        cellDis.setCellType(Cell.CELL_TYPE_NUMERIC);
        cellName.setCellType(Cell.CELL_TYPE_STRING);
        cellDis.setCellValue(disList.get(0).getDis());
        cellName.setCellValue(disList.get(0).getName());

        cellDis = row.getCell(6);
        cellName = row.getCell(7);
        if (cellDis == null){
            cellDis = row.createCell(6);
            cellName = row.createCell(7);
        }
        cellDis.setCellType(Cell.CELL_TYPE_NUMERIC);
        cellName.setCellType(Cell.CELL_TYPE_STRING);
        cellDis.setCellValue(disList.get(1).getDis());
        cellName.setCellValue(disList.get(1).getName());

        cellDis = row.getCell(8);
        cellName = row.getCell(9);
        if (cellDis == null){
            cellDis = row.createCell(8);
            cellName = row.createCell(9);
        }
        cellDis.setCellType(Cell.CELL_TYPE_NUMERIC);
        cellName.setCellType(Cell.CELL_TYPE_STRING);
        cellDis.setCellValue(disList.get(2).getDis());
        cellName.setCellValue(disList.get(2).getName());
    }

    class BSPoint {
        private Integer id; // 行
        private double lon; // 經度
        private double lat; // 緯度
        private String name; // 基站名

        public BSPoint(Integer id, String name, double lon, double lat) {
            this.id = id;
            this.name = name;
            this.lon = lon;
            this.lat = lat;
        }

        public Integer getId() {
            return id;
        }

        public double getLon() {
            return lon;
        }

        public double getLat() {
            return lat;
        }

        public String getName() {
            return name;
        }
    }

    class Dis implements Comparable<Dis> {
        private double dis;
        private String name;

        public Dis(double dis, String name) {
            this.dis = dis;
            this.name = name;
        }

        public double getDis() {
            return dis;
        }

        public String getName() {
            return name;
        }

        @Override
        public int compareTo(Dis o) {
            // TODO Auto-generated method stub
            return this.dis > o.dis ? 1 : -1;
        }
    }

}

值得注意的是Excel的寫入完成是在關閉輸出流後!!!
下面的是Utils類,計算兩個經緯度之間的距離。

package sxd.learn.java;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class Utils {
    /**
     * 計算地球上任意兩點(經緯度)距離
     * 
     * @param long1
     *            第一點經度
     * @param lat1
     *            第一點緯度
     * @param long2
     *            第二點經度
     * @param lat2
     *            第二點緯度
     * @return 返回距離 單位:米
     */
    public static double Distance(double long1, double lat1, double long2,
            double lat2) {
        double a, b, R;
        R = 6378137; // 地球半徑
        lat1 = lat1 * Math.PI / 180.0;
        lat2 = lat2 * Math.PI / 180.0;
        a = lat1 - lat2;
        b = (long1 - long2) * Math.PI / 180.0;
        double d;
        double sa2, sb2;
        sa2 = Math.sin(a / 2.0);
        sb2 = Math.sin(b / 2.0);
        d = 2
                * R
                * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1)
                        * Math.cos(lat2) * sb2 * sb2));
        return d;
    }

    public static void showProgress(float value) {
        System.out.printf("<<<%.2f%%>>>\n", value);
    }

    public static void updateProgress(int num) {
        for (int i = 0; i < num; i++) {
            System.out.print("\b");
        }
    }

    public static void removeDuplicate(List list) {
          HashSet h = new HashSet(list);
          list.clear();
          list.addAll(h);
    }

    public static void removeDuplicateWithOrder(List list) {
        Set set = new HashSet();
        List newList = new ArrayList();
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Object element = iter.next();
            if (set.add(element))
                newList.add(element);
        }
        list.clear();
        list.addAll(newList);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章