java代码将excel文件中的内容列表转换成JS文件输出

时间:2023-03-09 05:37:53
java代码将excel文件中的内容列表转换成JS文件输出

思路分析

我们想要把excel文件中的内容转为其他形式的文件输出,肯定需要分两步走:

  1.把excel文件中的内容读出来;

  2.将内容写到新的文件中。


举例

一张excel表中有一个表格:

java代码将excel文件中的内容列表转换成JS文件输出

我们需要将表格中的内容写到JS文件中输出:

java代码将excel文件中的内容列表转换成JS文件输出

文件名为expressData.js

地址的经纬度我们就调用百度接口获得。

新建一个springboot工程

java代码将excel文件中的内容列表转换成JS文件输出

因为使用springboot方便,快捷,所以我们就用springboot来演示,如果还没用过springboot的,并且不知道springboot怎么用的也没关系,你只需要注重代码就行,把这些代码放到以SSM为架构的项目中也是一样的。这里的文件,我们一个一个说。

pom.xml

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cetc.excelToJS</groupId>
<artifactId>cetc_excelToJS</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>cetc_excelToJS</name>
<url>http://maven.apache.org</url> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!-- <scope>provided</scope> -->
</dependency>
<!-- 用于监控spring boot 端点 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
</dependency> <!-- 引入poi,解析workbook视图 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<!-- 处理excel和上面功能是一样的-->
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.10</version>
</dependency> </dependencies> <!-- 添加spring-boot 的maven插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

如果你用ssm写的话,在pom.xml文件中添加

  <!-- 引入poi,解析workbook视图 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<!-- 处理excel和上面功能是一样的-->
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.10</version>
</dependency>

application.yml

这里我们用不到任何配置,所以这个文件我们就放个空的就行了。

Util包

ReadExcel.java

首先,当然是要读到excel中的内容撒。

 package com.cetc.excelToJS.util;
import java.io.File; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import org.springframework.stereotype.Component; import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException; @Component
public class ReadExcel {
public static void main(String[] args) {
ReadExcel obj = new ReadExcel();
File file = new File("D:/1234.xls");
List excelList = obj.readExcel(file);
System.out.println("list中的数据打印出来");
for (int i = 0; i < excelList.size(); i++) {
List list = (List) excelList.get(i);
for (int j = 0; j < list.size(); j++) {
System.out.print(list.get(j));
}
System.out.println();
} } public List<List> getContent(String path) {
ReadExcel obj = new ReadExcel();
File file = new File(path);
List<List> excelList = obj.readExcel(file);
return excelList; } // 去读Excel的方法readExcel,该方法的入口参数为一个File对象
public List readExcel(File file) {
try {
// 创建输入流,读取Excel
InputStream is = new FileInputStream(file.getAbsolutePath());
// jxl提供的Workbook类
Workbook wb = Workbook.getWorkbook(is);
// Excel的页签数量
int sheet_size = wb.getNumberOfSheets();
for (int index = 0; index < sheet_size; index++) {
List<List> outerList=new ArrayList<List>();
// 每个页签创建一个Sheet对象
Sheet sheet = wb.getSheet(index);
// sheet.getRows()返回该页的总行数
for (int i = 0; i < sheet.getRows(); i++) {
List innerList=new ArrayList();
// sheet.getColumns()返回该页的总列数
for (int j = 0; j < sheet.getColumns(); j++) {
String cellinfo = sheet.getCell(j, i).getContents();
if(cellinfo.isEmpty()){
continue;
}
innerList.add(cellinfo);
System.out.print(cellinfo);
}
outerList.add(i, innerList);
System.out.println();
}
return outerList;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (BiffException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

点击展开

两个方法:

1.getContent(String path)   返回类型<List<List>>

  很明显,Controller来调用我,给我一个excel文件的路径,我返回给你文件中的内容,以List<List>的形式。外面这个list是一行一个对象(也就是小list),里面这个list就是一行内容有多个字段,每个字段就是一个对象。

2.readExcel(File file) 返回类型<List<List>>

  这是getContent 方法调用的,返回<List<List>>给getContent,就是所有事情都替它干了。注释也很清楚,不用多说了。

TargetInformation.java

这是一个实体类,我们读出了excel文件中的内容,根据需求,我们还要根据地址,查出经纬度,对不对。那我们是不是还要给每个小list对象中加两个值,lng和lat。你可以这样干,但是我是喜欢用对象来处理的,可能有点多余,但你可以不这么干。

 package com.cetc.excelToJS.pojo;

 public class TargetInformation {
private String lng;
private String lat;
private String name;
private String address; public TargetInformation(String lng,String lat,String name,String address) {
this.lng = lng;
this.lat = lat;
this.name = name;
this.address = address;
} public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
} }

点击展开

GetLatAndLngByBaidu.java

百度根据地址查询经纬度的方法类,不用说了。有个注意点就是,你传的地址一定要是准确的,存在的。比如:你输入的地址在百度地图上都找不到,或者输入地址点击查询,地图上出来好多个标记,那接口哪知道是哪一个啊?所以,这两种情况是一定会报错的。

 package com.cetc.excelToJS.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection; import org.springframework.stereotype.Component; /**
* 获取经纬度
*
* @author Sunny
* 密钥:lAGGc3PbOv0KeGTWcp6xOtDbkt6Kuld5
*/
@Component
public class GetLatAndLngByBaidu {
/**
* @param addr
* 查询的地址
* @return
* @throws IOException
*/
public Object[] getCoordinate(String addr) throws IOException {
String lng = null;//经度
String lat = null;//纬度
String address = null;
try {
address = java.net.URLEncoder.encode(addr, "UTF-8");
}catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// String key = "f247cdb592eb43ebac6ccd27f796e2d2";
String key = "lAGGc3PbOv0KeGTWcp6xOtDbkt6Kuld5";
String url = String .format("http://api.map.baidu.com/geocoder?address=%s&output=json&key=%s", address, key);
URL myURL = null;
URLConnection httpsConn = null;
try {
myURL = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
InputStreamReader insr = null;
BufferedReader br = null;
try {
httpsConn = (URLConnection) myURL.openConnection();// 不使用代理
if (httpsConn != null) {
insr = new InputStreamReader( httpsConn.getInputStream(), "UTF-8");
br = new BufferedReader(insr);
String data = null;
int count = 1;
while((data= br.readLine())!=null){
if(count==5){
lng = (String)data.subSequence(data.indexOf(":")+1, data.indexOf(","));//经度
count++;
}else if(count==6){
lat = data.substring(data.indexOf(":")+1);//纬度
count++;
}else{
count++;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(insr!=null){
insr.close();
}
if(br!=null){
br.close();
}
}
return new Object[]{lng,lat};
} public static void main(String[] args) throws IOException {
GetLatAndLngByBaidu getLatAndLngByBaidu = new GetLatAndLngByBaidu();
Object[] o = getLatAndLngByBaidu.getCoordinate("无锡市新吴区旺庄路156号宝龙城市广场f2");
System.out.println(o[0]);//经度
System.out.println(o[1]);//纬度
}
}

点击展开

TargetContent.java

好了,我们现在地址有了,接口也有了。那就查吧,并且查出来封装成对象,把这些对象放到一个新的list中。以备将来所用!

 package com.cetc.excelToJS.util;

 import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Component; import com.cetc.excelToJS.pojo.TargetInformation; @Component
public class TargetContent {
@Resource
private GetLatAndLngByBaidu getLatAndLngByBaidu; public List getTargerList(List<List> excelList) throws IOException {
List<TargetInformation> resultList= new ArrayList<TargetInformation>();
for(int i = 1;i<excelList.size();i++) {
List<String> contentList = (List<String>) excelList.get(i);
// --------------------------------------------------------
// --------------这里看一下该条记录的内容先-------------------
for(int j=0;j<contentList.size();j++) {
System.out.println(contentList.get(j));
}
// --------------------------------------------------------
// 找出该条记录的地址,调用百度接口,获得经纬度
Object[] ouject = getLatAndLngByBaidu.getCoordinate(contentList.get(1));
// 将经纬度封装到对象中存入resultList中
TargetInformation targetInformation = new TargetInformation(ouject[0].toString(),
ouject[1].toString(),
contentList.get(0),
contentList.get(1));
resultList.add(targetInformation); }
return resultList;
}
}

点击展开

WriteJS.java

获得需要写入的对象集合,那我们就写JS文件呗。

 package com.cetc.excelToJS.util;

 import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.List; import org.springframework.stereotype.Component; import com.cetc.excelToJS.pojo.TargetInformation;
@Component
public class WriteJS {
// 这里是创建的路径
private static String path = "D:/";
private static String filenameTemp; // public static void main(String[] args) throws IOException {
// WriteJS.creatJSFile("你好");
// WriteJS.writeJSFile("你好");
// WriteJS.writeJSFile(" 罗大爷1");
// }
public String doWrite(List<TargetInformation> resultList) {
try {
// 创建一个名为expressData 的js文件
this.creatJSFile("expressData");
// 先开个头
this.writeJSFile("var expPointArr = ["); for(int i=0;i<resultList.size()-1;i++) {
TargetInformation targetInformation = resultList.get(i);
// {"lng":118.752696,"lat":32.22832,"name":"盘城揽投部","address":"新华路121号"},
String information = "{\"lng\":"+targetInformation.getLng()
+",\"lat\":"+targetInformation.getLat()
+",\"name\":\""+targetInformation.getName()
+"\",\"address\":\""+targetInformation.getAddress()
+"\"},";
this.writeJSFile(" "+information);
}
// 这里添加最后一条,因为最后一一条后面没逗号
TargetInformation targetInformation_last = resultList.get(resultList.size()-1);
String information_last = "{\"lng\":"+targetInformation_last.getLng()
+",\"lat\":"+targetInformation_last.getLat()
+",\"name\":\""+targetInformation_last.getName()
+"\",\"address\":\""+targetInformation_last.getAddress()
+"\"}";
this.writeJSFile(" "+information_last);
// 这里结束
this.writeJSFile("];"); return "success";
}catch (Exception e) {
return "failure";
}
} /**
* 创建文件
*
* @throws IOException
*/
public boolean creatJSFile(String name) throws IOException {
boolean flag = false;
filenameTemp = path + name + ".js";
File filename = new File(filenameTemp);
if (!filename.exists()) {
filename.createNewFile();
flag = true;
}
return flag;
} /**
* 写文件
*
* @param newStr
* 新内容
* @throws IOException
*/
public boolean writeJSFile(String newStr) throws IOException {
// 先读取原有文件内容,然后进行写入操作
boolean flag = false;
String filein = newStr + "\r\n";
String temp = ""; FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null; FileOutputStream fos = null;
PrintWriter pw = null;
try {
// 文件路径
File file = new File(filenameTemp);
// 将文件读入输入流
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);
StringBuffer buf = new StringBuffer(); // 保存该文件原有的内容
for (int j = 1; (temp = br.readLine()) != null; j++) {
buf = buf.append(temp);
// System.getProperty("line.separator")
// 行与行之间的分隔符 相当于“\n”
buf = buf.append(System.getProperty("line.separator"));
}
buf.append(filein); fos = new FileOutputStream(file);
pw = new PrintWriter(fos);
pw.write(buf.toString().toCharArray());
pw.flush();
flag = true;
} catch (IOException e1) {
// TODO 自动生成 catch 块
throw e1;
} finally {
if (pw != null) {
pw.close();
}
if (fos != null) {
fos.close();
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (fis != null) {
fis.close();
}
}
return flag;
} }

点击展开

代码很好明白。有两个静态属性说一下:

private static String path = "D:/";
private static String filenameTemp;

第一个:path是即将要生成的JS文件要放的位置。你可以改。

第二个:filenameTemp 是JS的文件名,我是让Controller传的。

createExcel.java

这是一个创建excel的工具类,这里可以忽略。有兴趣的下代码去。

IndexController.java

 package com.cetc.excelToJS.controller;

 import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import com.cetc.excelToJS.pojo.TargetInformation;
import com.cetc.excelToJS.util.HandleFile;
import com.cetc.excelToJS.util.ReadExcel;
import com.cetc.excelToJS.util.TargetContent;
import com.cetc.excelToJS.util.WriteJS; @RestController
public class IndexController { @Resource
private ReadExcel readExcel;
@Resource
private WriteJS writeJS;
@Resource
private TargetContent targetContent; @GetMapping("/transfor")
public String transfor() {
try {
String path = "D:/expressData.xls";
List<List> excelList = readExcel.getContent(path);
List<TargetInformation> resultList = targetContent.getTargerList(excelList);
String message = writeJS.doWrite(resultList);
return message;
}catch (Exception e) {
return "操作失败";
}
} /**
* excel生成下载
* @param response
* @return
* @throws Exception
*/
@GetMapping(value = "/createExcel")
public String createExcel(HttpServletResponse response) throws Exception{
Map<String,Object> excelMap = new HashMap<>();
//1.设置Excel表头
List<String> headerList = new ArrayList<>();
headerList.add("name");
headerList.add("address");
excelMap.put("header",headerList); //2.是否需要生成序号,序号从1开始(true-生成序号 false-不生成序)
boolean isSerial = false;
excelMap.put("isSerial",isSerial); //3.sheet名
String sheetName = "统计表";
excelMap.put("sheetName",sheetName); //4.需要放入Excel中的数据
List<String> list = new ArrayList<>();
list.add("鼓楼投递部");
list.add("江苏省南京市玄武区韩家巷10-2号");
List<List<String>> data= new ArrayList<>();
data.add(list); excelMap.put("data",data); //Excel文件内容设置
HSSFWorkbook workbook = HandleFile.createExcel(excelMap); String fileName = "expressData.xls"; //生成excel文件
HandleFile.buildExcelFile(fileName, workbook); //浏览器下载excel
HandleFile.buildExcelDocument(fileName,workbook,response); return "down excel"; } }

点击展开

这个大家不一定一样,只是作为启动这个excel转JS文件功能的...引擎吧。

只要看这个接口就行:

 @GetMapping("/transfor")
public String transfor() {
try {
String path = "D:/expressData.xls";
List<List> excelList = readExcel.getContent(path);
List<TargetInformation> resultList = targetContent.getTargerList(excelList);
String message = writeJS.doWrite(resultList);
return message;
}catch (Exception e) {
return "操作失败";
}
}

它是去读D盘根目录下的expressData.xls文件的。然后生成对象list,然后写JS文件,执行完了你会发现D盘多了一个文件java代码将excel文件中的内容列表转换成JS文件输出

里面的内容嘛,我就不贴了,在上面。

代码下载地址:https://gitee.com/fengyuduke/my_open_resources/blob/master/cetc_excelToJS.zip


到这里本来想结束,但是这里有个问题,大家注意到没?

我是到固定目录下面去找excel文件的,要是用起来肯定多有不便。更多时候我们都是前端上传文件的,然后后台代码来解析读取我们上传的这个文件。那这个时候怎么做?

我们从上到下来修改:

第一步:修改Controller中的接口方法

 @RequestMapping(value="transfor")
public String transfor(@RequestParam(required = true) MultipartFile file) {
try {
// String path = "D:/expressData.xls";
List<List> excelList = readExcel.getContent(file);
List<TargetInformation> resultList = targetContent.getTargerList(excelList);
String message = writeJS.doWrite(resultList);
return message ;
}catch (Exception e) {
return "操作失败";
}
}

我们接收前端传来的文件,然后把文件传给工具类。

第二步:修改ReadExcel.java

 package com.project.ndmp.excelToJS;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile; import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException; @Component
public class ReadExcel {
public static void main(String[] args) {
// ReadExcel obj = new ReadExcel();
// // 此处为我创建Excel路径:E:/zhanhj/studysrc/jxl下
// File file = new File("D:/1234.xls");
// List excelList = obj.readExcel(file);
// System.out.println("list中的数据打印出来");
// for (int i = 0; i < excelList.size(); i++) {
// List list = (List) excelList.get(i);
// for (int j = 0; j < list.size(); j++) {
// System.out.print(list.get(j));
// }
// System.out.println();
// } } public List<List> getContent(MultipartFile mFile) {
ReadExcel obj = new ReadExcel();
// CommonsMultipartFile cFile = (CommonsMultipartFile) mFile;
// DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
// InputStream inputStream = fileItem.getInputStream();
// File file = new File(path);
List<List> excelList = obj.readExcel(mFile);
return excelList; }
/**
*
* @param mFile MultipartFile
* @return
*/
public List readExcel(MultipartFile mFile) {
try {
// -------------------------------------------------------------------
/*
* 从springmvc获取到的文件是MultipartFile类型的,有的时候不能直接用从这种类型获取
* 到的inputstream操作一些事情,比如从中初始化poi的Workbook,这时候要怎么获取到File
* 式的流呢?
有一个方法就是把读到的MultipartFile转存到本地,然后再从本地读取这个转存的这个临
时文件,从中获取文件流。这么写的话可以达到目的但是听起来就很繁琐对不对。 下面这三步,就是通过转换的形式将MultipartFile类型的文件放到输入流里面
*/
CommonsMultipartFile cFile = (CommonsMultipartFile) mFile;
DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
InputStream is = fileItem.getInputStream();
// --------------------------------------------------------------------
/*
* 创建输入流,读取Excel
* 下面这一步不用了,这是文件在本地的情况,根据文件的绝对路径来将文件写到输入流中
*/
// InputStream is = new FileInputStream(file.getAbsolutePath());
// jxl提供的Workbook类
Workbook wb = Workbook.getWorkbook(is);
// Excel的页签数量
int sheet_size = wb.getNumberOfSheets();
for (int index = 0; index < sheet_size; index++) {
List<List> outerList=new ArrayList<List>();
// 每个页签创建一个Sheet对象
Sheet sheet = wb.getSheet(index);
// sheet.getRows()返回该页的总行数
for (int i = 0; i < sheet.getRows(); i++) {
List innerList=new ArrayList();
// sheet.getColumns()返回该页的总列数
for (int j = 0; j < sheet.getColumns(); j++) {
String cellinfo = sheet.getCell(j, i).getContents();
if(cellinfo.isEmpty()){
continue;
}
innerList.add(cellinfo);
System.out.print(cellinfo);
}
outerList.add(i, innerList);
System.out.println();
}
return outerList;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (BiffException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

点击展开

这里最为关键的就是这三行代码

 CommonsMultipartFile cFile = (CommonsMultipartFile) mFile;
DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
InputStream is = fileItem.getInputStream();

这三行代码解决了怎么将MultipartFile类型的文件放到输入流里。这样我们后面的操作都不用变了。


最后

代码中没说的创建excel文件的接口和工具类也很实用。但是我想大家一般都是把模板放到项目里,然后提供下载地址即可,不一定需要代码创建啦!