1. 程式人生 > >讀取Excel資料根據經緯度調取阿里雲API獲取地址名稱 + 柱形圖轉化顯示 實戰

讀取Excel資料根據經緯度調取阿里雲API獲取地址名稱 + 柱形圖轉化顯示 實戰

1、需求:
前兩天接到boss給我的一個任務,需要根據經緯度資訊統計省份分佈,boss給了我一張excel,包含資料包括:經度、緯度、使用次數,想要我統計每一個省份的次數之後
2、解決思路:
通過檔案讀取方式獲得對應經度、緯度、使用次數資料,,然後呼叫阿里雲或者高德地圖的API就可以完成這一工作,思路很清晰,於是下面直接開始上程式碼
3、工具類:

StringToJsonUtil.java

**
 * 通過工具類去獲取String裡面包含的資料資訊
 * User: yinkailong
 * Date: 2018/8/10
 */
public class StringToJsonUtil {

    public
static String StringToGetValue(String address){ String detailAddress = ""; //呼叫阿里雲介面返回資料格式 /**res{"queryLocation":[28.76817,121.501497],"addrList":[{"type":"poi","status":1,"name":"尤氏大藥房(杜東藥店)","id":"ANB02400T4ZW","admCode":"331082","admName":"浙江省,台州市,臨海市,","addr":"杜橋解放街96號","nearestPoint":[121.50180
,28.76764],"distance":61.400}]}*/ //進行轉化獲取值 JSONObject addressList = JSONObject.fromObject(address); //次處需要判斷轉化之後型別是否是Object 否則會報錯 if (addressList != null && !addressList.isNullObject()){ //System.out.println("addressList" + addressList); //根據addrList 獲取list值 //得到json陣列
JSONArray addressArray = JSONArray.fromObject(addressList.getString("addrList")); JSONObject addressObject = JSONObject.fromObject(addressArray.get(0)); //根據admName 獲取省、市、區 String admName = addressObject.getString("admName"); //獲取店鋪名稱 String name = addressObject.getString("name"); //獲取門牌號地址 String addr = ""; if (addressObject.containsKey("addr")){ addr = addressObject.getString("addr"); } //進行拼接得到詳細地址 detailAddress = admName + name + addr; //將查詢的地址輸出 過濾掉 , //System.out.println(detailAddress.replace(",", "")); } return detailAddress; } }

根據緯度和經度呼叫阿里雲API 獲取詳細地址
AddressUtil.java

/**
 * 調取阿里雲的API
 * User: yinkailong
 * Date: 2018/8/7
 */
public class AddressUtil {

    /**
     * 調取阿里雲的API
     * 通過 poi 經緯度查詢地址資料
     *
     * @param lat 必傳
     * @param lng 必傳
     * @return
     */
    public static String getAddress(String lat, String lng) {
        if (lat.contains("-") || lng.contains("-")) {
            return "null";
        }
        //引數解釋: 緯度,經度 type 001 (100代表道路,010代表POI,001代表門址,111可以同時顯示前三項)
        String urlString = "http://gc.ditu.aliyun.com/regeocoding?l=" + lng + "," + lat + "&type=010";
        String res = "";
        try {
            //讀取url請求地址  這裡讀取的是阿里雲的查詢
            URL url = new URL(urlString);
            //開啟連線
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //設定引數編碼
            conn.setRequestMethod("POST");
            //設定輸出屬性
            conn.setDoOutput(true);
            //設定快取
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line = "";
            //讀取的下一行是否為空
            while ((line = in.readLine()) != null) {
                res += line + "\n";
            }
            //關閉緩衝流
            in.close();
        } catch (Exception e) {
            System.out.println("讀取過程中發生異常,請重試!!");
        }
        System.out.println("res" + res);
        return res;
    }

讀取Excel檔案然後進行獲取值
ReadExcelUtil.java

/**
 * 讀取Excel檔案然後呼叫
 * User: yinkailong
 * Date: 2018/8/7
 */

public class ReadExcelUtil {

    public static List<String> readExcel(File file) throws IOException {


        //TODO 儲存  省份和使用次數的map,便於返回後面做特殊需求統計
        List<String> addressAndTime = new ArrayList<>();
        InputStream  filaName= new FileInputStream(file);
        //獲取檔名稱
        String fileName = file.getName();
        //獲取檔名的字尾
        int start = fileName.lastIndexOf(".");
        int length = fileName.length();
        //得到檔名的字尾
        String lastTag = fileName.substring(start + 1, length);
        //建立讀取檔案的WebBook
        Workbook workbook = null;
        //判斷使用檔案解析型別
        // 根據檔名的字尾來判斷使用判斷檔案字尾名是xls ,還是xlsx。
        // 如果是xls使用HSSFWorkbook,否則使用XSSFWorkbook解析
        if (lastTag.equals("xlsx")) {
            //解析xls解析格式
            workbook = new XSSFWorkbook(filaName);
        } else if (lastTag.equals("xls")) {
            workbook = new HSSFWorkbook(filaName);
        } else {
            //暫不支援的excel格式字尾
            return Lists.newArrayListWithCapacity(0);
        }
        Sheet sheet = workbook.getSheetAt(0);//第一個工作表  ,第二個則為1,以此類推...
        int firstRowIndex = sheet.getFirstRowNum();
        int lastRowIndex = sheet.getLastRowNum();
        for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {
            Row row = sheet.getRow(rIndex);
            if (row != null) {
                int firstCellIndex = row.getFirstCellNum();
                // int lastCellIndex = row.getLastCellNum();  //次處暫時不用
                String values = "";
                for (int cIndex = firstCellIndex; cIndex < 3; cIndex++) {
                    Cell cell = row.getCell(cIndex);
                    String value = "";
                    if (cell != null) {
                        value = cell.toString();
                        values += value + ",";
                    }
                    if (value.length() == 3) {
                        String[] split = values.split(",");
                        String address = "";
                        if (split.length >= 2) {
                            address = AddressUtil.getAddress(split[0], split[1]);
                            JSONObject addressList = JSONObject.fromObject(address);
                            if (addressList != null && !addressList.isNullObject()) {
                                JSONArray addressArray = JSONArray.fromObject(addressList.getString("addrList"));
                                JSONObject addressObject = JSONObject.fromObject(addressArray.get(0));
                                //根據admName 獲取省、市、區
                                String admName = addressObject.getString("admName");
                                String arr[] = admName.split(",");

                                if (values.split(",").length >= 3) {
                                    addressAndTime.add(arr[0] + "," + values.split(",")[2]);
                                }
                            }
                        }
                    }
                }
            }
        }
        return addressAndTime;
    }

4、測試方法

   //呼叫main方法獲取輸出值
    public static void main(String[] args) throws IOException {
        //讀取本地Excel檔案 格式如下 100.228635 25.589721 3.0
        File file = new File("D:/jingweidu.xlsx");
        List<String> addressAndTime = readExcel(file);

        //進行擷取然後進行判斷相加
        double T = 0.0d;
        String province = "";
        HashMap<String,Double> provinceAndTime = new HashMap<>();

        // TODO 特殊需求,根據省份相同進行統計使用次數
        for (String subString : addressAndTime){
            String[] splits = subString.split(",");
            province = splits[0];
            double time = Double.valueOf(splits[1]);
            if (provinceAndTime.containsKey(province)){
                T += time;
                provinceAndTime.put(province,T);
            }else if (province != null && !"".equals(province)){
                provinceAndTime.put(province,time);
            }
        }
        System.out.println(provinceAndTime);
    }
}

以前的測試方法有誤,現在重新改進寫法

    //呼叫main方法獲取輸出值
    public static void main(String[] args) throws IOException {

        //讀取本地Excel檔案 格式如下 100.228635 25.589721 3.0
        File file = new File("D:/jingweidu.xlsx");
        List<String> addressAndTime = readExcel(file);

        //進行擷取然後進行判斷相加
        double T = 0.0d;
        String province = "";
        HashMap<String, Double> provinceAndTime = new HashMap<>();

        // TODO 特殊需求,根據省份相同進行統計使用次數
        for (String subString : addressAndTime) {
            String[] splits = subString.split(",");
            province = splits[0];
            double time = Double.parseDouble(splits[1]);
            if (provinceAndTime.containsKey(province)) {
                double value = provinceAndTime.get(province) + time;
                provinceAndTime.put(province, value);
            } else if (province != null && !"".equals(province)) {
                provinceAndTime.put(province, time);
            }
        }
        System.out.println(provinceAndTime);
        List<Map.Entry<String, Double>> infoIds = new ArrayList<Map.Entry<String, Double>>(
                provinceAndTime.entrySet());
        System.out.println("--------------排序前--------------");
        for (int i = 0; i < infoIds.size(); i++) {
            String id = infoIds.get(i).toString();
            System.out.println(id);
        }
        // 排序
        Collections.sort(infoIds, new Comparator<Map.Entry<String, Double>>() {
            public int compare(Map.Entry<String, Double> o1,
                               Map.Entry<String, Double> o2) {
                return (int) (o1.getValue() - o2.getValue());
            }
        });

        System.out.println("--------------排序後--------------");
        for (int i = 0; i < infoIds.size(); i++) {
            Map.Entry<String, Double> ent = infoIds.get(i);
            System.out.println(ent.getKey() + "=" + ent.getValue());
        }
    }
}

5、執行結果:

根據經緯度查詢地址分類統計圖

6、採坑總結

1、Excel檔案讀取需要主要 字尾格式不同,呼叫的方法不同,
 // 根據檔名的字尾來判斷使用判斷檔案字尾名是xls ,還是xlsx。
        // 如果是xls使用HSSFWorkbook,否則使用XSSFWorkbook解析
        if (lastTag.equals("xlsx")) {
            //解析xls解析格式
            workbook = new XSSFWorkbook(filaName);
        } else if (lastTag.equals("xls")) {
            workbook = new HSSFWorkbook(filaName);
        } else {
            //暫不支援的excel格式字尾
            return Lists.newArrayListWithCapacity(0);
        }
2、在得到API呼叫結果之後返回值,需要進行判斷,否則會導致後面獲取結果報錯,使用方法 isNullObject進行校驗

   //進行轉化獲取值
    JSONObject addressList = JSONObject.fromObject(address);
    //次處需要判斷轉化之後型別是否是Object 否則會報錯
    if (addressList != null && !addressList.isNullObject()){
    }
3、獲取 屬性  addrList欄位時候需要進行判斷 是否存在當前屬性,否則會報錯,因為返回值裡面不一定包含欄位addr
 if (addressObject.containsKey("addr")){
            addr = addressObject.getString("addr");
        }    
4、資料擷取時需要進行校驗,否則可能出現下標越出錯誤
   if (values.split(",").length >= 3) {
                                    addressAndTime.add(arr[0] + "," + values.split(",")[2]);
                                }