Java 通过poi读取excel文件需要使用XSSFWorkbook对象,需要如下依赖包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
功能实现:excel列数据实现度分秒-经纬度转换。
转换公式:度分秒 --> 经纬度
(( 秒数据 ÷ 60 )+ 分数据 )÷ 60 + 度数据
现有如下数据:
转换成目标数据:
测试数据获取
度分秒N 度分秒E
31°58′58.691600″N 118°40′16.130400″E
32°58′59.008700″N 119°40′15.411700″E
33°58′59.367000″N 120°40′14.753100″E
34°58′59.734100″N 121°40′14.159800″E
35°59′00.101700″N 122°40′13.615400″E
36°59′00.469700″N 124°40′13.107800″E
37°59′00.829900″N 125°40′12.628900″E
38°59′01.198400″N 126°40′12.173600″E
39°59′01.567200″N 128°40′11.736300″E
读取EXCEL文件
读取流程从数据对象大小可分为如下:
- XSSFWorkbook 表文件对象
- Sheet 工作表对象 一个表文件可以包含多个工作表
- Row 数据行对象 一个工作表含有多行数据记录
- Cell 单元格对象 一行数据记录包含多个数据单元
创建表文件对象
InputStream in = new FileInputStream(path);
Workbook xwb = new XSSFWorkbook(in);
创建工作表
getSheetAt(index) 下标从0开始
// xwb.getNumberOfSheets() 统计当前表文件中包含的工作表数量
Sheet sheet = xwb.getSheetAt(0);
遍历工作表中行记录
sheet.getLastRowNum() 获得单表最大行数
for(int numRow = 1; numRow <= sheet.getLastRowNum(); numRow++) {
// 获取工作表的每行数据
Row row = sheet.getRow(numRow);
}
遍历每行中的数据单元
row.getLastCellNum() 获得最大行数据单元数量
cell.getCellType() 进行数据类型判断后获取单元格数据
for(int numCell = 0; numCell < row.getLastCellNum(); numCell++) {
Cell cell = row.getCell(numCell);
// 判断单元数据类型 获取数据值
Object val = null; // 获取单元格的具体值
switch(cell.getCellType()) {
case BOOLEAN: // 布尔类型
val = cell.getBooleanCellValue();
break;
case STRING: // 字符串类型
val = cell.getStringCellValue();
break;
case NUMERIC: // 数值类型
val = cell.getNumericCellValue();
break;
default: //其它类型
break;
}
}
新建EXCEL文件并写入数据
创建表文件对象
Workbook wb = new XSSFWorkbook();
创建工作表对象
设定工作表名称
Sheet sheet = wb.createSheet("new_sheetName");
数据行数据设定
第一行数据 0 可为标题
Row titleRow = sheet.createRow(0);
//把已经写好的标题行写入excel文件中
String[] title = {"列1","列2","列3","列4"};
for (int i = 0; i < title.length; i++) {
cell = titleRow.createCell(i);
cell.setCellValue(title[i]);
}
从第二行开始进行数据填充
Row row = null;
for (int i = 0; i < ens.size(); i++) {// ens为需要写入的行数据集合
//创建新行
row = sheet.createRow(i + 1);
//把值一一写进单元格里
//设置第一列为自动递增的序号
row.createCell(0).setCellValue(ens.get(i).getN_dfm());//度分秒-纬度数据
row.createCell(1).setCellValue(ens.get(i).getE_dfm());//度分秒-经度数据
row.createCell(2).setCellValue(ens.get(i).getN_jwd());//纬度数据
row.createCell(3).setCellValue(ens.get(i).getE_jwd());//经度数据
}
设置单元格自适应
for (int i = 0; i < title.length; i++) {
sheet.autoSizeColumn(i, true);
}
数据写入文件
OutputStream fileOut = null;
try {
//创建上传文件目录
fileOut = new FileOutputStream(newFile);
wb.write(fileOut);
fileOut.close();
wb.close();
}catch (Exception e){
e.printStackTrace();
}
完整代码如下
EN.class 数据对象
package boke_simulation.tools;
/**
* @ClassName EN
* @Description TODO
* @Author bb
* @Date 2021/6/8 14:26
*/
public class EN {
private String N_dfm;
private String E_dfm;
private String N_jwd;
private String E_jwd;
public EN(String n_dfm, String e_dfm, String n_jwd, String e_jwd) {
N_dfm = n_dfm;
E_dfm = e_dfm;
N_jwd = n_jwd;
E_jwd = e_jwd;
}
public String getN_dfm() {
return N_dfm;
}
public void setN_dfm(String n_dfm) {
N_dfm = n_dfm;
}
public String getE_dfm() {
return E_dfm;
}
public void setE_dfm(String e_dfm) {
E_dfm = e_dfm;
}
public String getN_jwd() {
return N_jwd;
}
public void setN_jwd(String n_jwd) {
N_jwd = n_jwd;
}
public String getE_jwd() {
return E_jwd;
}
public void setE_jwd(String e_jwd) {
E_jwd = e_jwd;
}
@Override
public String toString() {
return "EN{" +
"N_dfm='" + N_dfm + '\'' +
", E_dfm='" + E_dfm + '\'' +
", N_jwd='" + N_jwd + '\'' +
", E_jwd='" + E_jwd + '\'' +
'}';
}
}
HandlerXLSX.class poi读写excel
package boke_simulation.tools;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
/**
* @ClassName HandlerXLSX
* @Description TODO
* @Author bb
* @Date 2021/5/20 9:39
*/
public class HandlerXLSX {
// 经纬度转换
private static ArrayList<EN> ens = new ArrayList<>();
private static String[] title = {"度分秒N","度分秒E","纬度N","经度E"};
private static String sheetName;
public static void readXlsx(String path) {
Workbook xwb = null;
try{
InputStream is = new FileInputStream(path);
// 读取的时候可以使用流,也可以直接使用文件名
xwb = new XSSFWorkbook(is);
System.out.println("xlsx 文件对象:"+xwb);
// 如有需要可以循环读取工作表sheet
// for(int numSheet = 0; numSheet < xwb.getNumberOfSheets(); numSheet++) {}
// 这里直接读取第一张工作表
Sheet sheet = xwb.getSheetAt(0);
sheetName = sheet.getSheetName();
System.out.println("工作表名"+sheetName);
// 循环row,如果第一行是字段title,则 numRow = 1
for(int numRow = 1; numRow <= sheet.getLastRowNum(); numRow++) {
// 获取工作表的一行数据
Row row = sheet.getRow(numRow);
// 某行数据为空则跳过
if(row == null) {
continue;
}
Object v = ""; //ceil值获取
String[] s=new String[4];
// 循环cell
for(int numCell = 0; numCell < row.getLastCellNum(); numCell++) {
Cell cell = row.getCell(numCell);
// 某个单元格数据为空则跳过
if(cell == null) {
v = "null";
}else {
v = getValue(cell);
}
if ((v instanceof String) && (((String) v).contains("N")||(((String) v).contains("E")))){
//31°58′58.691600″N
String[] split = ((String) v).split("[°′″]");
Double a = (Double.parseDouble(split[2])/60+Double.parseDouble(split[1]))/60+ Double.parseDouble(split[0]);
// 经纬度判断实现
DecimalFormat df = new DecimalFormat("0.000000");
String value = df.format(a)+split[3];
if (((String) v).contains("N")){
s[0] = v+"";
s[2] = value;
}
if (((String) v).contains("E")){
s[1] = v+"";
s[3] = value;
}
}
}
EN en = new EN(s[0], s[1], s[2], s[3]);
ens.add(en);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
try{// 资源释放 poi 读取数据消耗大量内存
if(xwb != null){
xwb.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
return null;
}
// 获取每个ceil的单元数据 String Boolean Number
public static Object getValue(Cell cell) {
Object val = null; // 获取单元格的具体值
switch(cell.getCellType()) {
case BOOLEAN: // 布尔类型
val = String.valueOf(cell.getBooleanCellValue());
break;
case STRING: // 字符串类型
val = cell.getStringCellValue().trim();
break;
case NUMERIC: // 数值类型
val = cell.getNumericCellValue();
break;
default: //其它类型
break;
}
return val;
}
/**
* 已有excel中新增列数据 文件名和已有excel文件名相同
* @param filename
*/
public static void modifyExcel(String filename){
try {
Workbook wb = new XSSFWorkbook(new FileInputStream(filename));
Sheet ENSheet = wb.getSheetAt(0);
int cellnum = ENSheet.getRow(1).getLastCellNum();
// 标题新增列
Row row = ENSheet.getRow(0);
row.createCell(cellnum).setCellValue("纬度");
row.createCell(cellnum+1).setCellValue("经度");
for (int i = 0; i < ens.size(); i++) {
//获取已有行数据
row = ENSheet.getRow(i + 1);
//把值一一写进单元格里
//设置第一列为自动递增的序号
row.createCell(cellnum).setCellValue(ens.get(i).getN_jwd());
row.createCell(cellnum+1).setCellValue(ens.get(i).getE_jwd());
}
OutputStream fileOut = null;
//创建上传文件目录
fileOut = new FileOutputStream(filename);
wb.write(fileOut);
fileOut.close();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 度分秒 经纬度数据写入新表
* @param newfilename
*/
public static void createNewExcel(String newfilename){
Workbook wb = new XSSFWorkbook();
// 设定表名
Sheet sheet = wb.createSheet(sheetName);
Row titleRow = sheet.createRow(0);
Cell cell = null;
//把已经写好的标题行写入excel文件中
for (int i = 0; i < title.length; i++) {
cell = titleRow.createCell(i);
cell.setCellValue(title[i]);
}
Row row = null;
for (int i = 0; i < ens.size(); i++) {
//创建list.size()行数据
row = sheet.createRow(i + 1);
//把值一一写进单元格里
//设置第一列为自动递增的序号
row.createCell(0).setCellValue(ens.get(i).getN_dfm());
row.createCell(1).setCellValue(ens.get(i).getE_dfm());
row.createCell(2).setCellValue(ens.get(i).getN_jwd());
row.createCell(3).setCellValue(ens.get(i).getE_jwd());
}
//设置单元格宽度自适应,在此基础上把宽度调至1.5倍
for (int i = 0; i < title.length; i++) {
sheet.autoSizeColumn(i, true);
sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 15 / 10);
}
OutputStream fileOut = null;
try {
//创建上传文件目录
fileOut = new FileOutputStream(newfilename);
wb.write(fileOut);
fileOut.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
readXlsx("流程数据.xlsx");
createNewExcel("流程数据_new.xlsx");
}
}