This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
k18-ntcs-web-ntc/src/main/java/com/nis/util/excel/ExcelCsv.java
2019-01-28 22:11:24 +08:00

605 lines
20 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.nis.util.excel;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
import com.nis.domain.basics.ServiceDictInfo;
import com.nis.util.DictUtils;
import com.nis.util.Encodes;
import com.nis.util.Reflections;
import com.nis.util.StringUtil;
public class ExcelCsv {
private static Logger log = LoggerFactory.getLogger(ExcelCsv.class);
private static BufferedWriter cs;
/**解决乱码问题
* @see http://www.cnblogs.com/tangkai/p/3818084.html
*/
private final static byte bom[] = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
private final static String charset = "UTF-8";
/**
* 注解列表Object[]{ ExcelField, Field/Method }
*/
List<Object[]> annotationList = Lists.newArrayList();
static Map<String, List<Object[]>> annotationMap=new HashMap<>();
/**
* //递归获取cls实体对象及父级对象的method
* @param list
* @param cls
*/
public static void getMethods(List<Method> list,Class<?> cls) {
Method[] methods=cls.getDeclaredMethods();
if(methods != null && methods.length > 0){
List<Method> tempList=new ArrayList<>();
for (Method method : methods) {
if(list.size()==0) {
tempList.add(method);
}else {
boolean has=false;
for(Method checkM:list) {
if(checkM.getName().equals(method.getName())) {
has=true;
break;
}
}
if(!has) {
tempList.add(method);
}
}
}
list.addAll(tempList);
}
if(cls.getSuperclass() != null){
getMethods(list,cls.getSuperclass());
}
}
/**
* //递归获取cls实体对象及父级对象的属性
* wx:修改,子类覆盖父类的同名方法
* @param list
* @param cls
*/
public static void getFields(List<Field> list,Class<?> cls) {
Field[] fields=cls.getDeclaredFields();
if(fields != null && fields.length > 0){
List<Field> tempList=new ArrayList<>();
for (Field field : fields) {
if(list.size()==0) {
tempList.add(field);
}else {
boolean has=false;
for(Field checkF:list) {
if(checkF.getName().equals(field.getName())) {
has=true;
break;
}
}
if(!has) {
tempList.add(field);
}
}
}
list.addAll(tempList);
}
if(cls.getSuperclass() != null){
getFields(list,cls.getSuperclass());
}
}
/**
* 构造函数
* @param msgProp 国际化配置
* @param title sheet名称
* @param cls 实体对象通过annotation.ExportField获取标题
* @param type 导出类型1:导出数据2导出模板
* @param groups 导入分组
* @return
*/
public static Map<String, List<String>> ExcelCsvHeader(Properties msgProp,List<String> titleList,Map<String,String> noExportMap,Map<String, Class<?>> clsMap, int type, int... groups){
Map<String, List<String>> headerMap=new HashMap<String, List<String>>();
Map<String, List<String>> commentMap=new HashMap<String, List<String>>();
for (String title : titleList) {
String noExportField=noExportMap.get(title);
noExportField=",do_blacklist,"+noExportField;
List<Object[]> annotationList = Lists.newArrayList();
List<Field> list=new ArrayList<Field>();
// Get annotation field
//递归获取cls实体对象及父级对象的属性
getFields(list, clsMap.get(title));
if(!StringUtil.isEmpty(list)){
for (Field f : list){
ExcelField ef = f.getAnnotation(ExcelField.class);
if (ef != null && (ef.type()==0 || ef.type()==type)){
if (groups!=null && groups.length>0){
boolean inGroup = false;
for (int g : groups){
if (inGroup){
break;
}
for (int efg : ef.groups()){
if (g == efg){
inGroup = true;
if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){
annotationList.add(new Object[]{ef, f});
}
break;
}
}
}
}else{
if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){
annotationList.add(new Object[]{ef, f});
}
}
}
}
}
List<Method> ms=new ArrayList<Method>();
// Get annotation method
//递归获取cls实体对象及父级对象的属性
getMethods(ms, clsMap.get(title));
if(!StringUtil.isEmpty(ms)){
for (Method m : ms){
ExcelField ef = m.getAnnotation(ExcelField.class);
if (ef != null && (ef.type()==0 || ef.type()==type)){
if (groups!=null && groups.length>0){
boolean inGroup = false;
for (int g : groups){
if (inGroup){
break;
}
for (int efg : ef.groups()){
if (g == efg){
inGroup = true;
if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){
annotationList.add(new Object[]{ef, m});
}
break;
}
}
}
}else{
if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){
annotationList.add(new Object[]{ef, m});
}
}
}
}
}
// Field sorting
Collections.sort(annotationList, new Comparator<Object[]>() {
public int compare(Object[] o1, Object[] o2) {
return new Integer(((ExcelField)o1[0]).sort()).compareTo(
new Integer(((ExcelField)o2[0]).sort()));
};
});
// Initialize
List<String> headerList = Lists.newArrayList();
List<String> commentList = Lists.newArrayList();
for (Object[] os : annotationList){
String titleStr = ((ExcelField)os[0]).title();
String commentStr = ((ExcelField)os[0]).comment();
// 如果是导出,则去掉注释
if (type==1){
commentStr="";
}
if(!StringUtil.isEmpty(titleStr)){
//去掉不需要展示的header
//去掉不需要展示的header
String noExport="";
if(noExportField.contains("&")){
noExport=noExportField.substring(0,noExportField.indexOf("&"));
}else{
noExport=noExportField;
}
if(!(noExport.indexOf(","+titleStr+",") > -1)){
//需要替换的header
boolean flag=true;
if(noExportField.contains("&")){
String replaceField=noExportField.substring(noExportField.indexOf("&")+1);
String[] replaceStr=replaceField.split("-");
for (int i = 0; i < replaceStr.length; i++) {
String [] fields=replaceStr[i].split(":");
if(fields[0].equals(titleStr)){
titleStr=msgProp.getProperty(fields[1],fields[1]);
flag=false;
break;
}
}
}
if(flag){
titleStr=msgProp.getProperty(titleStr)==null?titleStr:msgProp.getProperty(titleStr,titleStr);
}
headerList.add(titleStr);
commentList.add(commentStr);
}
}
}
headerMap.put(title, headerList);
commentMap.put(title, commentList);
annotationMap.put(title, annotationList);
}
return headerMap;
}
/**
* 添加数据通过annotation.ExportField添加数据
* @param <E>
* @return list 数据列表
*/
public static <E> Map<String,List<List<String>>> setDataList(Properties msgProp, Map<String,List> dataMap, Map<Object,Object> map){
Map<String,List<List<String>>> dataList=new HashMap<String, List<List<String>>>();
Set<String> keyList=dataMap.keySet();
for (String key : keyList) {
List<E> list=dataMap.get(key);
List<List<String>> listT=new ArrayList<List<String>>();
for (E e : list){
int colunm = 0;
List<String> lisb=new ArrayList<String>();
for (Object[] os : annotationMap.get(key)){
ExcelField ef = (ExcelField)os[0];
Object val = null;
// Get entity value
try{
if (StringUtils.isNotBlank(ef.value())){
val = Reflections.invokeGetter(e, ef.value());
}else{
if (os[1] instanceof Field){
val = Reflections.invokeGetter(e, ((Field)os[1]).getName());
}else if (os[1] instanceof Method){
val = Reflections.invokeMethod(e, ((Method)os[1]).getName(), new Class[] {}, new Object[] {});
}
}
// If is dict, get dict label
String valStr=val==null?"":val.toString();
if (StringUtils.isNotBlank(ef.dictType())){
if("type".equals(ef.dictType()) || "attribute".equals(ef.dictType())
|| "label".equals(ef.dictType())){
// Get basic info
val = getBasicInfo(ef.dictType(),map,valStr);
}else{
//字典数据已做国际化处理
String dict=DictUtils.getDictLabel(ef.dictType(), valStr, valStr);
//如果找不到字典国际化值,把字典本身作为默认值放进去,不然导出就是空了
val = msgProp.getProperty(dict,dict);
//业务配置-stream 阻断类型中 阻断 改为 封堵(丢弃)
if("block_type".equals(ef.title()) && dict.equals("action_reject")
&& (Reflections.invokeGetter(e, "serviceId").toString().equals("35")
|| Reflections.invokeGetter(e, "serviceId").toString().equals("33")
|| Reflections.invokeGetter(e, "serviceId").toString().equals("36"))){
dict="block_drop";
val = msgProp.getProperty(dict,dict);
}
//ip spoofing redirect动作修改为Spoofing
if(ef.title().equals("block_type")
&& (Reflections.invokeGetter(e, "serviceId").toString().equals("518"))) {
dict="action_spoofing";
val = msgProp.getProperty(dict,dict);
}
}
}
if(ef.title().equals("whether_area_block")&&!StringUtil.isEmpty(val)){
Integer whetherAreaBlock=Integer.parseInt(valStr);
if(whetherAreaBlock.equals(0)){
val = msgProp.getProperty("all","all");
}else if(whetherAreaBlock.equals(1)){
val = msgProp.getProperty("selective","selective");
}else{
val ="";
}
}
if(ef.title().equals("is_hex") && !StringUtil.isEmpty(val)){
Integer isHex=Integer.parseInt(val.toString());
if(isHex.equals(0) || isHex.equals(2)){
val = msgProp.getProperty("not_hex","not_hex");
}else if(isHex.equals(1)){
val = msgProp.getProperty("hex","hex");
}else{
val ="";
}
}
if(ef.title().equals("is_case_insenstive") && !StringUtil.isEmpty(val)){
Integer isCaseSenstive=Integer.parseInt(val.toString());
if(isCaseSenstive.equals(0)){
val = msgProp.getProperty("case_insenstive","case_insenstive");
}else if(isCaseSenstive.equals(1)){
val = msgProp.getProperty("case_senstive","case_senstive");
}else{
val ="";
}
}
if(!StringUtil.isEmpty(val)) {
if (val instanceof Date){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
val=sdf.format(val);
}
}
}catch(Exception ex) {
log.error("Get entity value failed",ex);
val = "";
}
lisb.add(String.valueOf(val));
}
listT.add(lisb);
//listT.add(String.valueOf(sb));
}
dataList.put(key, listT);
}
return dataList;
}
public static <T> void writeCSVFile(HttpServletResponse response,List<String> titleList,Map<String, List<String>> headMap, Map<String,List<List<String>>> dataMap,String fileName,
String titleTime,Properties msgProp) {
try {
// 写入临时文件
File tempFile = File.createTempFile("vehicle", ".csv");
cs = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile), "utf-8"), 1024);
cs.write(new String(bom, charset));
//获取头部数据
for (int i = 0; i < titleList.size(); i++) {
if(i==0){
//写入时间范围
if(!StringUtils.isEmpty(titleTime)){
cs.write(titleTime);
cs.newLine();
}
}
List<String> heads=headMap.get(titleList.get(i));
if(i>0){
//写入域配置标题
cs.newLine();
if(!StringUtils.isEmpty(titleList.get(i))){
cs.write(msgProp.getProperty(titleList.get(i), titleList.get(i)));
cs.newLine();
}
}
// 写入文件头部
writeHead(heads, cs);
//获取文件内容
List<List<String>> datas=dataMap.get(titleList.get(i));
// 写入文件内容
for (List<String> row: datas) {
writeRow(row, cs);
}
}
cs.flush();
OutputStream out = response.getOutputStream();
byte[] b = new byte[10240];
File fileLoad = new File(tempFile.getCanonicalPath());
response.reset();
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
long fileLength = fileLoad.length();
String length1 = String.valueOf(fileLength);
response.setHeader("Content_Length", length1);
FileInputStream in = new FileInputStream(fileLoad);
int n;
while ((n = in.read(b)) != -1) {
out.write(b, 0, n); // 每次写入out1024字节
}
in.close();
out.close();
deleteFile(tempFile);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean deleteFile( File file) {
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
return true;
} else {
return false;
}
} else {
return false;
}
}
private static void writeHead(List<String> titles, BufferedWriter csvWriter) throws IOException {
// 写入文件头部
for (String title : titles) {
StringBuffer sb = new StringBuffer();
if(isDate(title)){
title=title + "\t";
}
String rowStr = sb.append("\"").append(title).append("\",").toString();
csvWriter.write(rowStr);
}
csvWriter.newLine();
}
private static <T> void writeRow(List<String> data, BufferedWriter csvWriter) throws Exception {
// 写入文件内容
//Html 解码
for (String tag : data) {
tag = Encodes.unescapeHtml(tag.toString());
StringBuffer sb = new StringBuffer();
if("null".equals(tag.trim())){
tag=null;
}
if(StringUtils.isNotBlank(tag)){
// 替换值中双引号
if(tag.contains("\"")){
tag = tag.replace("\"", "");
}
// \t解决数字0开头字符串0显示不出来的问题比如邮编
/*if(tag.startsWith("0") && !tag.contains(".")){
tag = tag + "\t";
}*/
if(isDate(tag)){
tag=tag + "\t";
}
}
String rowStr = sb.append("\"").append(tag==null?"":tag).append("\",").toString();
csvWriter.write(rowStr);
}
csvWriter.newLine();
}
/**
* 设置性质、分类、标签等信息
* @param dictType
* @param map
* @param val
* @return
*/
public static String getBasicInfo(String dictType,Map map,String val) {
String basicInfo="";
List<ServiceDictInfo> list=new ArrayList<ServiceDictInfo>();
if("type".equals(dictType)){
list=(List<ServiceDictInfo>) map.get("fls");
for (String info : val.split(",")) {
for (ServiceDictInfo dictInfo : list) {
if(info.equals(dictInfo.getServiceDictId().toString())){
basicInfo+=","+dictInfo.getItemValue();
}
}
}
}
if("attribute".equals(dictType)){
list=(List<ServiceDictInfo>) map.get("xzs");
for (String info : val.split(",")) {
for (ServiceDictInfo dictInfo : list) {
if(info.equals(dictInfo.getServiceDictId().toString())){
basicInfo+=","+dictInfo.getItemValue();
}
}
}
}
if("label".equals(dictType)){
list=(List<ServiceDictInfo>) map.get("labels");
for (String info : val.split(",")) {
for (ServiceDictInfo dictInfo : list) {
if(info.equals(dictInfo.getServiceDictId().toString())){
basicInfo+=","+dictInfo.getItemValue();
}
}
}
}
if(!StringUtil.isEmpty(basicInfo)){
basicInfo=basicInfo.substring(1);
}
return basicInfo;
}
/**
* 功能:判断字符串是否为日期格式
*
* @param str
* @return
*/
public static boolean isDate(String strDate) {
Pattern pattern = Pattern
.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
boolean flag=false;
if(strDate.trim().length()>=10){
strDate=strDate.trim().substring(0, 10);
Matcher m = pattern.matcher(strDate);
if (m.matches()) {
return true;
} else {
return false;
}
}else{
if(strDate.trim().length()==7){
pattern = Pattern.compile("^\\d{4}-\\d{2}$");
Matcher m = pattern.matcher(strDate);
if (m.matches()) {
return true;
} else {
return false;
}
}else{
return false;
}
}
}
public static <T> void ajaxCSVFile(HttpServletResponse response,List<String>titleList,List<List<String>>dataMap,String fileName,
String titleTime,Properties msgProp) {
try {
// 写入临时文件
File tempFile = File.createTempFile("vehicle", ".csv");
cs = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile), "utf-8"), 1024);
cs.write(new String(bom, charset));
//写入时间范围
if(!StringUtils.isEmpty(titleTime)){
cs.write(titleTime);
cs.newLine();
}
// 写入文件头部
writeHead(titleList, cs);
// 写入文件内容
for (List<String> row: dataMap) {
writeRow(row, cs);
}
cs.flush();
OutputStream out = response.getOutputStream();
byte[] b = new byte[10240];
File fileLoad = new File(tempFile.getCanonicalPath());
response.reset();
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
long fileLength = fileLoad.length();
String length1 = String.valueOf(fileLength);
response.setHeader("Content_Length", length1);
FileInputStream in = new FileInputStream(fileLoad);
int n;
while ((n = in.read(b)) != -1) {
out.write(b, 0, n); // 每次写入out1024字节
}
in.close();
out.close();
deleteFile(tempFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}