一、背景
目标效果是想导入 Excel 文档,后台接收并读取数据,再将数据传入到数据库中进行查询,得到结果后导出。
二、实现过程
版本一:
版本一和版本二的后台的代码都一样,所以这里主要讲解前端的处理,后端的参考版本二的介绍即可。
首先在 form 表单中放置一个 type=‘file’ 的 input 标签
<form id="formFile" method="post" action="##"
class="report_form" target="_blank">
<div class="easyui-panel" title="Upload File"
style="width: 450px; padding: 30px 70px 50px 70px">
<div style="margin-bottom: 20px">
<div>物料代码文件:</div>
<input class="import-btn" type="file" accept=".xls,.xlsx">
</div>
</div>
</form>
当选择文件发生变化时触发 Ajax 提交。简洁,就是页面不是很好看。
<script type="text/javascript">
$(function () {
$('.import-btn').change(function () {
var formData = new FormData(),
name = $(this).val()
formData.append('file', $(this)[0].files[0])
// 此处可传入多个参数
formData.append('name', name)
console.log(name+', '+$(this)[0].files[0])
$.ajax({
url: "${ctx}/bom/getLatestOrder.do",
type: 'post',
async: false,
data: formData,
// 告诉jQuery不要去处理发送的数据
processData: false,
// 告诉jQuery不要去设置Content-Type请求头
contentType: false,
beforeSend: function () {
console.log('正在进行,请稍候')
},
success: function (data) {
if (data.message != null) {
$.messager.alert("提示",data.message);
}
if (data.infos != null){
location.href = "${ctx }/bom/messageExport.do";
}
}
})
})
});
</script>
版本二:
我想用 EasyUI 的 filebox 来对文件框进行美化,所以做如下修改:
<form id="formFile" method="post" action="##" class="report_form" target="_blank">
<div class="easyui-panel" title="Upload File"
style="width: 450px; padding: 30px 70px 50px 70px">
<div style="margin-bottom: 20px">
<div>物料代码文件:</div>
<input class="easyui-filebox" id="fb" name="fb" type="text"
style="width: 300px; height: 32px;">
</div>
<div>
<a href="javascript:void(0)" class="easyui-linkbutton" style="width: 98%"
onclick="submitForm()" id="submit">提交</a>
</div>
</div>
</form>
改了一下,选择文件变化后是先去进行判断筛选,提交按钮才是触发与后台的交互。
<script type="text/javascript">
$(function () {
//添加对话框,上传控件初始化
$('#fb').filebox({
buttonText: '选择文件', //按钮文本
buttonAlign: 'right', //按钮对齐
//multiple: true, //是否多文件方式
accept: '.xls,.xlsx', //指定文件类型
onChange: function (e) {
change(this);//上传处理
}
});
});
function change(_obj){
var tempFile = $("#fb");
var value=tempFile.filebox('getValue');
// 取后缀名
var ext=value.substring(value.lastIndexOf(".")+1).toLowerCase();
if(ext==''){ // 未选择文件,不作处理
return;
}else if((ext!='xls') && (ext!='xlsx')){
$.messager.alert("消息提示", "文件格式需为*.xls或*.xlsx 类型", "warning");
$('#fb').filebox('setValue',''); // 清空filebox回显框
return;
}
}
function submitForm(){
var fd = new FormData();
var file = document.getElementsByName("fb")[0].files[0];
if (file === undefined) {
$.messager.alert("提示","文件数据为空请正确上传文件!");
return;
}
//上传的参数名 参数值 k-v键值对
fd.append("file", file);
$.ajax({
url:"${ctx}/bom/getLatestOrder.do",
type:"post",
data:fd,
async : true, //此处为异步加载
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false, // 告诉jQuery不要去设置Content-Type请求头
beforeSend: function () {
$("#submit").attr({ disabled: "disabled" });// 禁用按钮防止重复提交
$.messager.progress({
title: '提示',
msg: '文件处理中,请稍候……',
text: ''
});
},
success:function(data){
if (data.message != null) {
$.messager.alert("提示",data.message);
}
if (data.infos != null){
location.href = "${ctx }/bom/messageExport.do";
}
},
complete: function () {
$.messager.progress('close');
$("#submit").removeAttr("disabled");
},
error:function(e){
$.messager.alert("错误","服务器异常,请稍后重试!!!<br/>"+e.message);
},
});
}
</script>
代码我给了许多注释,我这就大致讲解一下。首先文本框的样式 class 设置为 filebox ,type 的值也改成 text ,并且是在 JS 中去设置选择文件的按钮样式,指定选择文件类型以及选择文件变化之后的判断。
接着就是提交按钮,设置了 submitForm()方法,在方法中获取 file 文件,并通过 Ajax 传送到后台进行处理。 需要注意的是,在未换成 filebox 之前,使用 JQuery【 如:$("#fb").get(0).files[0] 】去获取文件是完全没有问题的,但一使用 filebox,就不能这样去获取文件了,会报如下错误
Uncaught TypeError: Cannot read property '0' of null
所以只能像我上面的代码那样,使用原生的方法去获取【如:document.getElementsByName("fb")[0].files[0]; 】
知识点:
---------------------------------------
1、遇到的第一个问题,就是用 Ajax 提交,前后台都没有报错,但就是不会弹出下载框。原因就是导出excel,实际上是文件下载,后台需要往前端(浏览器)写文件流的。而Ajax请求获取数据都是“字符串”,整个交互传输用的都是字符串数据,它没法解析后台返回的文件流,但浏览器可以。
因此,便有了上面的解决办法,在后台我将数据处理后存储在一个全局变量里,等 Ajax 请求成功后,再用 window.location.href = "" 去处理导出的操作,这样子浏览器就可以弹出下载框啦,下面呈上 Service 实现层的代码:
package com.gangdian.qc.service.impl;
@Service
public class LatestOrderServiceImpl implements LatestOrderService {
@Autowired
private LatestOrderDao latestOrderDao;
List<LatestOrderInfos> exportMessage = new ArrayList<LatestOrderInfos>(); // 需要导出的信息
@Override
public Map<String, Object> getLatestOrder(MultipartFile file, HttpServletResponse response,
HttpServletRequest request) {
Map<String, Object> result = new HashMap<String, Object>(); // 返回的结果
String dealResult = null;
try {
InputStream inputStream = file.getInputStream(); // 获取文件的输入流
Integer length = file.getOriginalFilename().split("\\.").length; // 获取文件名数组的长度
String suffix = file.getOriginalFilename().split("\\.")[length - 1]; // 取得文件后缀名
if ("xls".equals(suffix)) {
dealResult = hssfDeal(inputStream, result, response, request); // 如果后缀为.xls则用HSSFWorkbook
result.put("message", dealResult);
} else if ("xlsx".equals(suffix)) {
dealResult = xssfDeal(file, result, response, request); // 后缀为.xlsx则用XSSFWorkbook
result.put("message", dealResult);
}
} catch (Exception e) {
result.put("message", "500!");
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
/**
* *.xlsx文件用XSSFWorkbook处理
*
* @return
*/
private String xssfDeal(MultipartFile file, Map<String, Object> result, HttpServletResponse response,
HttpServletRequest request) throws IOException {
String dealResult = null; // 返回的处理结果
// 创建workbook对象,读取整个文档
XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
// 获取sheet的最大row下标
int lastRowNum = sheet.getLastRowNum();
// 判断第一列标题是否包含 “物料代码”
String title = sheet.getRow(0).getCell(0).getStringCellValue();
if (title.indexOf("物料代码") < 0) {
return "请注意,首列标题须为物料代码!";
} else if (lastRowNum <= 0) {
return "您导入的excel文件为空,请重新导入!";
}
for (Row row : sheet) {
// 读取每一行的单元格
Cell cell = row.getCell(0);
if (cell != null) { // 单元格不为空
cell.setCellType(Cell.CELL_TYPE_STRING); // 将该列单元格类型设置为String
String materialCode = cell.getStringCellValue(); // 第一列数据
if (materialCode != "" && materialCode.indexOf("物料代码") < 0) {
// 获取最新使用订单情况
LatestOrderInfos latestOrderInfos = latestOrderDao.getLatestOrderInfos(materialCode);
exportMessage.add(latestOrderInfos);
}
}
}
result.put("infos", exportMessage);
return dealResult;
}
/**
* *.xls文件用HSSFWorkbook处理
*
* @return
*/
private String hssfDeal(InputStream inputStream, Map<String, Object> result, HttpServletResponse response,
HttpServletRequest request) throws IOException {
String dealResult = null; // 返回的处理结果
// 创建workbook对象,读取整个文档
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(inputStream);
HSSFWorkbook wb = new HSSFWorkbook(poifsFileSystem);
// 读取页脚sheet
HSSFSheet sheetAt = wb.getSheetAt(0);
// 判断第一列标题是否包含 “物料代码”
String title = sheetAt.getRow(0).getCell(0).getStringCellValue();
if (title.indexOf("物料代码") < 0) {
return "首列标题须为物料代码!";
}
// 循环读取某一行
for (Row row : sheetAt) {
// 读取每一行的单元格
Cell cell = row.getCell(0);
if (cell != null) { // 单元格不为空
String materialCode = cell.getStringCellValue(); // 第一列数据
if (materialCode != "" && materialCode.indexOf("物料代码") < 0) {
// 获取最新使用订单情况
LatestOrderInfos latestOrderInfos = latestOrderDao.getLatestOrderInfos(materialCode);
exportMessage.add(latestOrderInfos);
}
}
}
result.put("infos", exportMessage);
return dealResult;
}
}
2、当我导入的文件格式为 *.xlsx ,却用 HSSFWorkbook 去解析的时候,出现如下的错误
org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
直译:文件中的数据是用Office2007+XML保存的,而现在却调用OLE2 Office文档处理,应该使用POI不同的部分来处理这些数据,比如使用XSSF来代替HSSF
因此,在这里,我们需要进行区分,*.xls 用 HSSFWorkbook 进行处理,而 *.xlsx 则用 XSSFWorkbook 处理,处理的前提需要导入以下的 jar 包。网上都有,懒得找可以问我要,我再附上链接,3.8-3.10版本的我都有。
3、在读取 Excel 中的数据时,报错 java.lang.IllegalStateException: Cannot get a text value from a numeric cell
大致意思就是不能从一个数值的列获取一个字符串类型的值。在代码中,我是通过 cell.getStringCellValue() 去获取单元格数据的,POI会判断单元格的类型,如果非字符串类型就会抛出上面的异常。
解决方法:一个个的去 Excel 中将数值的单元格前面加上 ‘ ,变成字符串类型 ?这种方法太扯淡了。我们来看看比较便捷的,就是在获取值前加上以下语句,让服务器去帮你处理就可以啦,完美解决。
cell.setCellType(Cell.CELL_TYPE_STRING); // 将该列单元格类型设置为String
---------------------------------------
最后放上导出 Excel 的代码:
@Override
public void messageExport(HttpServletResponse response, HttpServletRequest request) {
// 生成表格标题行
String[] headers = { "物料代码", "最新使用单号", "最新出库日期", "最新入库日期" };
// -----设置导出表格-----
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet("物料最新使用订单情况");
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(15);
sheet.autoSizeColumn(1, true);
// 生成一个样式
HSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
style.setVerticalAlignment(org.apache.poi.ss.usermodel.CellStyle.VERTICAL_CENTER);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 生成一个字体
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints((short) 12);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 生成另一个字体
HSSFFont font2 = workbook.createFont();
font2.setFontName("宋体");
// 把字体应用到当前的样式
style2.setFont(font2);
// 产生表格标题行
HSSFRow row = sheet.createRow(0);
row.setHeightInPoints(30);
for (int k = 0; k < headers.length; k++) {
HSSFCell cell = row.createCell(k);
cell.setCellStyle(style);
HSSFRichTextString text = new HSSFRichTextString(headers[k]);
cell.setCellValue(text);
}
// 写入数据,并设置样式
for (LatestOrderInfos latestOrderInfos : exportMessage) {
int lastRowNum = sheet.getLastRowNum() + 1;// 当前需要增加行的下标
row = sheet.createRow(lastRowNum);
row.setHeightInPoints(20);
row.createCell(0).setCellValue(latestOrderInfos.getMaterialCode());
row.createCell(1).setCellValue(latestOrderInfos.getLatestOrder());
row.createCell(2).setCellValue(latestOrderInfos.getLatestOutDate());
row.createCell(3).setCellValue(latestOrderInfos.getLatestInDate());
for (int j = 0; j < headers.length; j++) {
row.getCell(j).setCellStyle(style2);
}
}
// 创建response输出流
SimpleDateFormat df = new SimpleDateFormat("yyMMdd-HH.mm");// 设置日期格式
String time = df.format(new Date());// new Date()为获取当前系统时间
OutputStream os = null;
try {
os = response.getOutputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
response.reset();
String filename = "物料最新订单使用情况." + time + ".xls";
response.setContentType("application/msexcel");
try {
// 设定输出文件头
response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
// 定义输出类型
response.setContentType("application/msexcel");
// 写入文件
workbook.write(os);
exportMessage.clear();
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
三、知识拓展
拓展一:使用window.location.href同时导出多个文件
function downloadFiles(){
var files = [];
files.push("${ctx}/MyProject/storageDataExport1");
files.push("${ctx}/MyProject/storageDataExport2");
files.push("${ctx}/MyProject/storageDataExport3");
for(var ii=0; ii<files.length; ii++){
downloadURL(files[ii]);
}
}
var count=0;
var downloadURL = function downloadURL(url){
var hiddenIFrameID = 'hiddenDownloader' + count++;
var iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.src = url;
}
拓展二:使用隐藏form来执行导出操作
当需要传一个很大数据到后台(window.location.href= actionUrl + "?" + data;),就会出问题了,当然,当数据量不大的时候,使用这种方式是极好的。导致这个问题的原因是各种浏览器对URL解析的长度限制是不同的。
- Microsoft Internet Explorer (Browser):IE浏览器对URL的最大限制为2083个字符,如果超过这个数字,提交按钮没有任何反应。
- Firefox (Browser):对于Firefox浏览器URL的长度限制为65,536个字符
- Safari (Browser):URL最大长度限制为 80,000个字符。
- Opera (Browser):URL最大长度限制为190,000个字符。
- Google (chrome):url最大长度限制为8182个字符
解决方法就换成了使用隐藏form来执行导出操作,如下:
<a href="javascript:void(0)" onclick="exportExcel()">导出1</a>
// 导出,使用这种方式 可以,使用 ajax请求不可以 导出excel
function exportExcel(){
var form = $("<form>");
form.attr('style', 'display:none');
form.attr('target', '');
form.attr('method', 'post');
form.attr('action', '${pageContext.request.contextPath}/user/export');
var input1 = $('<input>');
input1.attr('type', 'hidden');
input1.attr('name', 'data1');
input1.attr('value', 'value1');
var input2 = $('<input>');
input1.attr('type', 'hidden');
input1.attr('name', 'data2');
input1.attr('value', 'value2');
......//几个参数就放几个input,value可放很多类型(数组,字符,list,map等)
$('body').append(form);//将表单放置在web中
form.append(input1);//将查询参数控件提交到表单上
form.append(input2);
......
form.submit();
form.remove();
}
拓展二来源:https://www.cnblogs.com/skytoangel/p/11276233.html
拓展三:用iframe实现form表单提交不刷新页面
原理是form提交表单,设置target为iframe的name,iframe为隐藏,实现无刷新提交。
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<script lang="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<link rel="stylesheet" href="js/jquery-ui-1.10.3.custom.css" />
<script lang="text/javascript" src="js/jquery-ui-1.10.4.custom.js"></script>
<link rel="stylesheet" href="ext1/bms.css" />
<script type="text/javascript" src="js/bootstrap-tokenfield.js"></script>
<link rel="stylesheet" href="js/bootstrap.min.alco.css">
<link rel="stylesheet" href="js/css/bootstrap-tokenfield.alco.css"/>
<form method="post" action="${ctx}/exportServlet?action=1" enctype="multipart/form-data" name="bms927" target="if1">
<div>
<table>
<tr>
<td>
<select id="selects" name="selects" class="form-inq-control" >
<option value="SHIPPINGLABEL">SHIPPING Label</option>
<option value="SNLABEL">SN Label</option>
</td>
<td>
<input type="file" name="fileField" id="fileField" accept=".xls,.xlsx" class="form-control" style="margin-left: 10px"/>
</td>
<td>
<input type="submit" class="form-inq-btn" style="margin-left: 10px" value="<%=X10getMessage("LAB927.import")%>" />
</td>
<%-- <td>
<input type="button" class="form-inq-btn" style="margin-left: 10px" value="转换导出Excel" onclick="submitForm()"/>
</td> --%>
</tr>
</table>
</div> <br/>
</form>
<iframe name="if1" style="display: none;"></iframe>
<%@include file="common/alco_footer.jsp"%>
package com.alco.bms.servlets;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.alco.bms.mybatis.dao.BMS927Mapper;
import com.alco.bms.mybatis.entities.Bms927ImgInfos;
import com.alco.bms.mybatis.entities.BsmiLabelInfos;
import com.alco.bms.mybatis.entities.SNLabelInfos;
import com.alco.bms.mybatis.entities.ShippingLabelInfos;
import com.freestyle.common.db.mybatis.MybatisUtils;
import com.freestyle.utils.ArrayUtil;
/****
* Export Servlet
* @author dgmislrh
* 2018年11月12日
*/
public class ExportServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = -1879826989713327690L;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
if ("1".equals(action)) {
labelExport(req, resp);
}
}
/**
* @param req
* @param resp
* @throws IOException
* @throws UnsupportedEncodingException
*/
private void labelExport(HttpServletRequest req, HttpServletResponse resp)
throws IOException, UnsupportedEncodingException {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);//form表单上传的资料
SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmm");// 设置日期格式
String time = df.format(new Date());// new Date()为获取当前系统时间
//获取From表单提交的data
List<String> snList = new ArrayList<String>();
String type= null;//转换的类型
try {
List items = upload.parseRequest(req);
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if (item.isFormField() && "selects".equals(item.getFieldName()) ) {
type = item.getString("UTF-8");
//System.out.println("表单参数名:" + item.getFieldName() + ",表单参数值:" + item.getString("UTF-8"));
} else if(!item.isFormField()) {
if (item.getName() != null && !item.getName().equals("")) {
//System.out.println("上传文件的大小:" + (item.getSize()/1024)+"KB");
//System.out.println("上传文件的类型:" + item.getContentType());
//System.out.println("上传文件的名称:" + item.getName());
snList = readSnExcel(item.getInputStream());
}
}
}
if (snList==null || snList.size()<=0) {
return;
}
}catch (Exception e) {
e.printStackTrace();
}
//System.err.println("type=="+type);
ServletOutputStream sos = resp.getOutputStream();
ZipOutputStream zipOutputStream= new ZipOutputStream(sos);
// 生成表格标题行
String[] headers = null;
List<String> strsToList1 = null;
String[] strsStrings = new String[]{"SN","Itemattribute1","Itemattribute2","Itemattribute3","Itemattribute4","Itemattribute5","Itemattribute6","Itemattribute7","Itemattribute8"};
strsToList1= Arrays.asList(strsStrings);
headers = (String[]) strsToList1.toArray(new String[strsToList1.size()]);
String zipname=type+"-"+time+".zip";
resp.reset();
resp.setContentType("application/x-download");
resp.setHeader("Content-Disposition", "attachment;filename="+ new String((zipname).getBytes(), "iso-8859-1"));
Map<String, List<ShippingLabelInfos>> listMap = getShipData(snList,zipOutputStream,type,time);
for (String key:listMap.keySet()){
System.out.println("key=="+key);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
List<ShippingLabelInfos> list = listMap.get(key);
if (!"error".equals(key)) {
exportShipExcel(type, headers, list, baos);
}else {
//去掉无数据的信息
}
compressFileToZipStream(zipOutputStream, baos, "data/"+type+"-"+key+"-"+time+".xls");
baos.close();
}
zipOutputStream.flush();
zipOutputStream.close();
sos .close();
}
/**
* @param workbook
* @return
*/
@SuppressWarnings("deprecation")
private HSSFCellStyle setContentStyle(HSSFWorkbook workbook) {
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 生成另一个字体
HSSFFont font2 = workbook.createFont();
font2.setFontName("宋体");
// 把字体应用到当前的样式
style2.setFont(font2);
return style2;
}
/**
* @param workbook
* @return
*/
@SuppressWarnings("deprecation")
private HSSFCellStyle setHeaderStyle(HSSFWorkbook workbook) {
HSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
style.setVerticalAlignment(org.apache.poi.ss.usermodel.CellStyle.VERTICAL_CENTER);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 生成一个字体
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints((short) 12);
font.setFontName("宋体");
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
style.setFont(font);
return style;
}
private Map<String, List<ShippingLabelInfos>> getShipData(List<String> snList, ZipOutputStream zipOutputStream, String type, String time) {
SqlSession lvSess=MybatisUtils.getSession();
List<ShippingLabelInfos> shipLabelInfos = new ArrayList<ShippingLabelInfos>();
List<ShippingLabelInfos> errShipLabelInfos = new ArrayList<ShippingLabelInfos>();
try{
BMS927Mapper bms927Mapper=lvSess.getMapper(BMS927Mapper.class);
List<List<String>> ssList=ArrayUtil.subListByCount(snList, 20);
for (List<String>list:ssList) {
bms927Mapper.createSNTable();
for (String sn:list) {
bms927Mapper.insertSN(sn);
}
shipLabelInfos.addAll(bms927Mapper.queryShipData());
}
for(ShippingLabelInfos sl:shipLabelInfos) {
if (sl.getTemplateSize()==null) sl.setTemplateSize("NoSize");
Iterator<String> it = snList.iterator();
while(it.hasNext()){
String sn = it.next();
if(sn.equals(sl.getSn())){
it.remove();//剔除有数据的sn
}
}
}
Map<String, List<ShippingLabelInfos>> listMap = shipLabelInfos.stream().collect(Collectors.groupingBy(t -> t.getTemplateSize()));
if (snList!=null && snList.size()>0) {
for(String sn:snList) {
errShipLabelInfos.add(new ShippingLabelInfos(sn));
}
if (errShipLabelInfos!=null && errShipLabelInfos.size()>0) {
listMap.put("error", errShipLabelInfos);
}
}
return listMap;
}catch (Exception e) {
lvSess.rollback();
e.printStackTrace();
}
finally{
MybatisUtils.closeSession(lvSess);
}
return null;
}
public void exportShipExcel(String type, String[] headers,List<ShippingLabelInfos> shipListInfos, OutputStream out) {
// -----设置导出表格-----
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(type);
// 设置表格默认列宽度为20个字节
sheet.setDefaultColumnWidth(20);
sheet.autoSizeColumn(1, true);
//设置行高
HSSFRow row = sheet.createRow(0);
row.setHeightInPoints(30);
// 生成一个样式
HSSFCellStyle headersStyle = setHeaderStyle(workbook);
// 生成并设置另一个样式
HSSFCellStyle contentStyle = setContentStyle(workbook);
for (int k = 0; k < headers.length; k++) {
HSSFCell cell = row.createCell(k);
cell.setCellStyle(headersStyle);
HSSFRichTextString text = new HSSFRichTextString(headers[k]);
cell.setCellValue(text);
}
// 写入数据,并设置样式
for (ShippingLabelInfos labelInfos: shipListInfos) {
int lastRowNum = sheet.getLastRowNum() + 1;// 当前需要增加行的下标
row = sheet.createRow(lastRowNum);
row.setHeightInPoints(20);
row.createCell(0).setCellValue(labelInfos.getSn());
row.createCell(1).setCellValue(labelInfos.getItemattribute1());
row.createCell(2).setCellValue(labelInfos.getItemattribute2());
row.createCell(3).setCellValue(labelInfos.getItemattribute3());
row.createCell(4).setCellValue(labelInfos.getItemattribute4());
row.createCell(5).setCellValue(labelInfos.getItemattribute5());
row.createCell(6).setCellValue(labelInfos.getItemattribute6());
row.createCell(7).setCellValue(labelInfos.getItemattribute7());
row.createCell(8).setCellValue(labelInfos.getItemattribute8());
for (int j = 0; j < headers.length; j++) {
row.getCell(j).setCellStyle(contentStyle);
}
}
try {
workbook.write(out);
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void compressFileToZipStream(ZipOutputStream zipOutputStream,
ByteArrayOutputStream excelOutputStream,String fileName) {
byte[] buf = new byte[1024];
try {
// Compress the files
byte[] content = excelOutputStream.toByteArray();
ByteArrayInputStream is = new ByteArrayInputStream(content);
BufferedInputStream bis = new BufferedInputStream(is);
// Add ZIP entry to output stream.
zipOutputStream.putNextEntry(new ZipEntry(fileName));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = bis.read(buf)) > 0) {
zipOutputStream.write(buf, 0, len);
}
// Complete the entry
zipOutputStream.closeEntry();
bis.close();
is.close();
// Complete the ZIP file
} catch (IOException e) {
e.printStackTrace();
}
}
// 读取Office 2007excel
public static List<String> readSnExcel(InputStream fileInputStream) throws Exception
{
List<String> list = new LinkedList<String>();
// 构造XSSFWorkbook对象,strPath传入文件路径
XSSFWorkbook xwb = new XSSFWorkbook(fileInputStream);
// 读取第一张表格的内容
XSSFSheet sheet = xwb.getSheetAt(0);
String value = null;
XSSFRow row = null;
XSSFCell cell = null;
//System.out.println("读取2007excel内容如下:");
for (int i = sheet.getFirstRowNum(); i < sheet.getPhysicalNumberOfRows(); i++)
{
row = sheet.getRow(i);
if (i == 0 || row == null)
{
continue;
}
cell = row.getCell(0);
if (cell == null || cell.toString() == "") continue;
DecimalFormat df = new DecimalFormat("0");// 格式化 number string
switch (cell.getCellType())
{
case XSSFCell.CELL_TYPE_STRING:
value = cell.getStringCellValue();
//System.out.println(" " + value + " ");
break;
case XSSFCell.CELL_TYPE_NUMERIC:
value = df.format(cell.getNumericCellValue());
//System.out.println(" " + value + " ");
break;
case XSSFCell.CELL_TYPE_BLANK:
value = "";
//System.out.println(value);
break;
default:
value = cell.toString();
//System.out.println(" " + value + " ");
break;
}
if (value == null || "".equals(value))
{
continue;
}
list.add(value);
}
return list;
}
}
拓展三来源:https://blog.csdn.net/liangwenmail/article/details/52015415 和 https://blog.csdn.net/mqy1023/article/details/80044859
四、留言
我只是想记录的是功能代码的实现过程,主要是Service层的代码,我的目的是记录日常的经验。有些人问我还有没有全一些的代码,我可以直接在这回答你,没有。既然有人问,那我也在这就解释下。你们可能是前后端之间的交互有疑问,建议先去学习搭建和配置好SSM或SSH或较早的Servlet技术再整合一下Mabatis,搭建并测试好后,这样再回来理解代入我的代码会简单很多。我的代码乍一看很多,很乱,但是如果你能看懂的话,用起来会很方便,如果看不懂也没关系,你们可以去查其他的文章笔记,不必纠结我的。