讀取Excel資料根據經緯度調取阿里雲API獲取地址名稱 + 柱形圖轉化顯示 實戰
阿新 • • 發佈:2018-11-10
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]);
}