編寫csv導出工具類,爲了提高複用性,使用泛型和反射,傳入一個任意類型的Vo的List就可以導出.
業務要求導出訂單,訂單中有多個商品,vo中商品是一個list
剛開始使用superCsv,不知道superCsv怎麼處理這種情況,乾脆自己寫了一個.
import java.math.BigDecimal;
import java.util.Date;
import com.tunynet.groupmall.base.utils.DateUtil;
import com.tunynet.groupmall.base.utils.csvexportutil.CellList;
/**
* @author wanrq
* @version 0.5
* @date Created in 2019/12/5 15:04
* @description 導出訂單表(有快遞的訂單)
* @modified By
*/
public class CourieredOrderVo {
/** 接龍號 **/
private Long id;
/** 微信暱稱 **/
private String weChatName;
/** 每個商品類型的個數 **/
private CellList goodsNumberList;
/** 訂單金額 **/
private BigDecimal price;
/** 在線支付金額 **/
private BigDecimal onlinePrice;
/** 在線退款金額 **/
private BigDecimal refundPrice;
/** 用戶備註 **/
private String userRemarks;
/** 管理備註 **/
private String adminRemarks;
/** 下單時間 **/
private Date createDate;
/** 訂單狀態 **/
private String status;
/** 聯繫人 **/
private String Contact;
/** 聯繫電話 **/
private String phone;
/** 省 **/
private String province;
/** 市 **/
private String city;
/** 區(縣) **/
private String district;
/** 詳細地址 **/
private String address;
/** 物流公司 **/
private String LogisticsCompany;
/** 物流單號 **/
private String LogisticsNumber;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public CellList getGoodsNumberList() {
return goodsNumberList;
}
public void setGoodsNumberList(CellList goodsNumberList) {
this.goodsNumberList = goodsNumberList;
}
public String getWeChatName() {
return weChatName;
}
public void setWeChatName(String weChatName) {
this.weChatName = weChatName;
}
public String getCreateDate() {
return " "+DateUtil.parseDateToStr(createDate,DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI);
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public BigDecimal getOnlinePrice() {
return onlinePrice;
}
public void setOnlinePrice(BigDecimal onlinePrice) {
this.onlinePrice = onlinePrice;
}
public BigDecimal getRefundPrice() {
return refundPrice;
}
public void setRefundPrice(BigDecimal refundPrice) {
this.refundPrice = refundPrice;
}
public String getUserRemarks() {
return userRemarks;
}
public void setUserRemarks(String userRemarks) {
this.userRemarks = userRemarks;
}
public String getAdminRemarks() {
return adminRemarks;
}
public void setAdminRemarks(String adminRemarks) {
this.adminRemarks = adminRemarks;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getContact() {
return Contact;
}
public void setContact(String contact) {
Contact = contact;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getLogisticsCompany() {
return LogisticsCompany;
}
public void setLogisticsCompany(String logisticsCompany) {
LogisticsCompany = logisticsCompany;
}
public String getLogisticsNumber() {
return LogisticsNumber;
}
public void setLogisticsNumber(String logisticsNumber) {
LogisticsNumber = logisticsNumber;
}
}
import java.util.Map;
/**
* @author wanrq
* @version 0.5
* @date Created in 2019/12/6 16:34
* @description 泛型導出excel,vo裏有list,需要確定list裏有多少個元素,
* 每個元素對應位置,這樣有null也不會顯示錯位
* @modified By
*/
public class CellList {
/** 每個值對應的單元格位置 **/
private Map<Integer,Object> map;
/** 一共有多少單元格 **/
private Integer size;
public CellList() {
}
public CellList(Integer size) {
this.size = size;
}
public CellList(Map<Integer, Object> map, Integer size) {
this.map = map;
this.size = size;
}
public Map<Integer, Object> getMap() {
return map;
}
public void setMap(Map<Integer, Object> map) {
this.map = map;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author wanrq
* @version 0.5
* @date Created in 2019/12/5 17:47
* @description 傳入vo導出csv文件,通過getter自定義顯示效果, list爲空顯示有bug處理待加強
* @modified By
*/
public class CsvWrite {
private PrintWriter printWriter;
public CsvWrite(PrintWriter printWriter) {
this.printWriter = printWriter;
}
/**
* @author [email protected]
* @date Created in 2019/12/9 11:04
* @description csv文件編碼
* @version 0.5
* @modified By
* @param o 要編碼的一個單元格的數據
* @return String
*/
private String encode(Object o) {
if (null == o) {
return "";
}
String cell = o.toString();
if("".equals(cell)){
return "";
}
StringBuilder sb = new StringBuilder();
// 避免公式
if ('=' == cell.charAt(0)) {
sb.append(" ");
}
// 有,和\n的單元格需要引號引起來
boolean needQMarks = false;
char[] cellChars = cell.toCharArray();
for (char cellChar : cellChars) {
switch (cellChar) {
case ',':
case '\n':
needQMarks = true;
sb.append(cellChar);
break;
case '\"':
needQMarks = true;
sb.append("\"\"");
break;
default:
sb.append(cellChar);
break;
}
}
String encodeCell = sb.toString();
if (needQMarks) {
encodeCell = "\"" + encodeCell + "\"";
}
return encodeCell;
}
/**
* @author wanrq
* @date Created in 2019/12/9 11:05
* @description 包裝成一行csv文件數據
* @version 0.5
* @modified By
* @param vo 文件傳送類對象
* @return String
*/
private <T> String rowContent(T vo) {
String[] fieldNames = Reflection.getFieldNames(vo);
List<String> cellList = new LinkedList<>();
for (String fieldName : fieldNames) {
String cell = null;
Object valueByName = null;
try {
// 通過getter獲取單元格數據,用戶要自定義單元格顯示可以修改vo的getter返回
valueByName = Reflection.getFieldValueByName(fieldName, vo);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// 部分私有變量沒有getter,獲取不到不進行任何操作
continue;
}
if (valueByName instanceof CellList) {
// 如果是單元格列表,導出多個單元格
CellList cells = (CellList) valueByName;
Map<Integer, Object> map = cells.getMap();
Integer size = cells.getSize();
for (int i = 0; i < size; i++) {
Object o;
if(null == map){
o = "";
}else{
o=map.get(i);
}
cell = encode(o);
cellList.add(cell);
}
} else {
// 普通值調用toString後編碼
cell = encode(valueByName);
cellList.add(cell);
}
}
String row = String.join(",", cellList);
return row;
}
/**
* @author wanrq
* @date Created in 2019/12/9 11:07
* @description 寫一行
* @version 0.5
* @modified By
* @param vo VO
*/
public <T> void writeRow(T vo) {
printWriter.println(rowContent(vo));
}
/**
* @author wanrq
* @date Created in 2019/12/9 11:07
* @description 寫多行
* @version 0.5
* @modified By
* @param voList VO
*/
public <T> void writeAll(List<T> voList) {
for (T vo : voList) {
writeRow(vo);
}
}
/**
* @author wanrq
* @date Created in 2019/12/9 11:07
* @description 寫表頭
* @version 0.5
* @modified By
* @param titles 表頭
*/
public <T> void writeTitle(T[] titles) {
List<String> encodeList = new LinkedList<>();
for (T title : titles) {
encodeList.add(encode(title.toString()));
}
String headerContent = String.join(",", encodeList);
printWriter.println(headerContent);
}
}