You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

684 lines
23 KiB

package com.ccsens.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ccsens.util.exception.BaseException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.springframework.stereotype.Component;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 导入导出excel
* @author wu
*/
@Slf4j
@Component
public class PoiUtil {
@Data
public static class PoiUtilCell {
/**
* 单元格内容
*/
private String value = "";
/**
* 跨列
*/
private int colspan = 1;
/**
* 跨行
*/
private int rowspan = 1;
/**
* 水平居中
*/
private HorizontalAlignment style = HorizontalAlignment.CENTER;
/**
* 垂直居中
*/
private VerticalAlignment verticalAlignment = VerticalAlignment.CENTER;
/**
* 行高
*/
private Integer height = 666;
/**
* 列宽
*/
private Integer wight = 18;
/**
* 跳转的路径
*/
private String path;
/**
* 函数
*/
private String function;
/**
* 是否是数字格式 0否 1是
*/
private byte num = 0;
public PoiUtilCell() {
}
public PoiUtilCell(String value) {
this.value = value;
}
public PoiUtilCell(String value,String function) {
this.value = value;
this.function = function;
}
public PoiUtilCell(String value, int colspan, int rowspan) {
this.value = value;
this.colspan = colspan;
this.rowspan = rowspan;
}
public PoiUtilCell(String value, Integer height, Integer wight) {
this.value = value;
this.height = height;
this.wight = wight;
}
public PoiUtilCell(String value, int colspan, int rowspan, Integer height, Integer wight) {
this.value = value;
this.colspan = colspan;
this.rowspan = rowspan;
this.height = height;
this.wight = wight;
}
}
/**
* 导出Excel
*
* @param sheetName sheet名称
* @param rows 行
* @param wb XSSFWorkbook对象 无则创建
* @return 返回生成的excel数据
*/
public static Workbook exportWB(String sheetName, List<List<PoiUtilCell>> rows, Workbook wb) {
// 第一步,创建一个XSSFWorkbook,对应一个Excel文件
if (wb == null) {
wb = new XSSFWorkbook();
}
if (rows == null) {
return wb;
}
// 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
Sheet sheet = wb.getSheet(sheetName);
if (ObjectUtil.isNull(sheet)) {
sheet = wb.createSheet(sheetName);
}
// // 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制
// HSSFRow row = sheet.createRow(0);
// 第四步,创建单元格,并设置值表头 设置表头居中
for (int i = 0; i < rows.size(); i++) {
List<PoiUtilCell> cells = rows.get(i);
for (int j = 0; j < cells.size(); j++) {
PoiUtilCell cell = cells.get(j);
//设置列宽
if (ObjectUtil.isNotNull(cell.wight)) {
sheet.setColumnWidth(j, cell.wight * 256);
}
mergedRegion(sheet, i, j, cells.get(j));
}
}
//创建内容
for (int i = 0; i < rows.size(); i++) {
Row row = sheet.getRow(i);
if (ObjectUtil.isNull(row)) {
row = sheet.createRow(i);
}
List<PoiUtilCell> cells = rows.get(i);
for (int j = 0; j < cells.size(); j++) {
PoiUtilCell cell = cells.get(j);
if(ObjectUtil.isNull(cell)){
continue;
}
//查找当前单元格
Cell newCell = row.getCell(j);
if(ObjectUtil.isNull(newCell)){
newCell = row.createCell(j);
}
//查找当前单元格的样式
// CellStyle style = newCell.getCellStyle();
// if(ObjectUtil.isNull(style)){
// style = wb.createCellStyle();
// }
CellStyle style = wb.createCellStyle();
//设置内容
if (!WebConstant.CELL_NULL.equals(cell.value)){
// if(cell.num == 1){
// newCell.setCellValue(Integer.parseInt(cell.value));
// }else {
// newCell.setCellValue(cell.value);
// }
if (cell.value.length() <= 14 && cell.value.matches("\\d+")) {
newCell.setCellValue(Long.parseLong(cell.value));
} else {
newCell.setCellValue(cell.value);
}
}
//设置行高
if (ObjectUtil.isNotNull(cell.height)) {
if (j == 0) {
row.setHeight(cell.height.shortValue());
}
}
//设置水平居中和垂直居中
style.setAlignment(cell.style);
style.setVerticalAlignment(cell.verticalAlignment);
//设置跳转路径
if (StrUtil.isNotEmpty(cell.path)) {
XSSFCreationHelper createHelper = (XSSFCreationHelper) wb.getCreationHelper();
XSSFHyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
link.setAddress(cell.path);
newCell.setHyperlink(link);
//设置字体颜色
Font font = wb.createFont();
font.setColor(Font.COLOR_RED);
style.setFont(font);
}
//添加函数
if(StrUtil.isNotEmpty(cell.getFunction())) {
newCell.setCellFormula(cell.getFunction());
}
//设置自动换行
style.setWrapText(true);
//将样式添加至单元格
newCell.setCellStyle(style);
// CellStyle style = wb.createCellStyle();
// 将内容按顺序赋给对应的列对象
// 如果value是cell_null代表次单元格不需要赋值
// if (cell.value.equals(WebConstant.CELL_NULL)){
// continue;
// }
// Cell newCell = row.createCell(j);
// //设置行高
// if (ObjectUtil.isNotNull(cell.height)) {
// if (j == 0) {
// row.setHeight(cell.height.shortValue());
// }
// }
//
// if(cell.num == 1){
// newCell.setCellValue(Integer.parseInt(cell.value));
// }else {
// newCell.setCellValue(cell.value);
// }
// style.setAlignment(cell.style);
// style.setVerticalAlignment(cell.verticalAlignment);
// //设置跳转路径
// if (StrUtil.isNotEmpty(cell.path)) {
// XSSFCreationHelper createHelper = (XSSFCreationHelper) wb.getCreationHelper();
// XSSFHyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
// link.setAddress(cell.path);
// newCell.setHyperlink(link);
// //设置字体颜色
// Font font = wb.createFont();
// font.setColor(Font.COLOR_RED);
// style.setFont(font);
// }
// //添加函数
// if(StrUtil.isNotEmpty(cell.getFunction())) {
// newCell.setCellFormula(cell.getFunction());
// }
// //设置自动换行
// style.setWrapText(true);
// newCell.setCellStyle(style);
}
}
return wb;
}
/**
* 合并单元格
*
* @param sheet 当前sheet
* @param rows 行数
* @param cols 列数
* @param cell 单元格信息
*/
private static void mergedRegion(Sheet sheet, int rows, int cols, PoiUtilCell cell) {
//
// int rowspan = cell.rowspan;
// if (rowspan > 1) {
// sheet.addMergedRegion(new CellRangeAddress(rows, rows + rowspan - 1, cols, cols));
// }
// int colspan = cell.colspan;
//
// if (colspan > 1) {
// sheet.addMergedRegion(new CellRangeAddress(rows, rows, cols, cols + colspan - 1));
// }
int rowspan = cell.rowspan;
int colspan = cell.colspan;
if(rowspan > 1 || colspan > 1){
sheet.addMergedRegion(new CellRangeAddress(rows, rows + rowspan - 1, cols, cols + colspan - 1));
}
}
/**
* @param file
* @param sheetIndex
* @param dataIndex 数据从第几行开始(0)
* @return
*/
public static List<Object[]> readExce(File file, int sheetIndex, String sheetName, int dataIndex, boolean hasImg) throws Exception {
if (!file.getPath().endsWith(".xls") && !file.getPath().endsWith(".xlsx")) {
log.info("文件不是excel类型:{}", file.getName());
throw new BaseException(CodeEnum.FILE_FORMAT_ERROR);
}
log.info("导入解析开始,fileName:{}", file.getPath());
List<Object[]> list = new ArrayList<>();
Sheet sheet = createSheet(file, sheetIndex, sheetName);
//读取放在首列的图片
Map<String, String> imgMap = null;
if (hasImg) {
imgMap = getImg(file, sheet);
}
//获取sheet的行数
int rows = sheet.getPhysicalNumberOfRows();
//读取数据
for (int i = 0; i < rows; i++) {
Row row = getRow(sheet, i, dataIndex);
if (row == null) {
continue;
}
Object[] objects = new Object[row.getLastCellNum()];
if (hasImg && imgMap != null) {
for (String key : imgMap.keySet()) {
if (key.startsWith(i + "-")) {
int index = Integer.parseInt(key.split("-")[1]);
objects[index] = imgMap.get(key);
}
}
}
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (cell == null) {
continue;
}
if (objects[j] == null) {
objects[j] = getCallValue(cell);
}
}
list.add(objects);
}
log.info("导入文件解析成功!");
return list;
}
public static String getCallValue(Cell cell) {
String cellValue = null;
// 判断excel单元格内容的格式,并对其进行转换,以便插入数据库
switch (cell.getCellType()) {
case 0://number类型
//时间类型也被认为是number类型,所以在读取数据时需进行判断
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
cellValue = sdf.format(cell.getDateCellValue());
} else {
cellValue = new DecimalFormat("0").format(cell.getNumericCellValue());
}
break;
case 1:
cellValue = cell.getStringCellValue();
break;
case 2:
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
cellValue = sdf.format(cell.getDateCellValue());
} else {
cellValue = String.valueOf(cell.getNumericCellValue());
}
break;
case 3:
cellValue = "";
break;
case 4:
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case 5:
cellValue = String.valueOf(cell.getErrorCellValue());
break;
}
return cellValue;
}
private PoiUtil() {
super();
}
/**
* 获取图片和位置 (xls)
*
* @param sheet
* @return
* @throws IOException
*/
public static Map<String, String> getXlsPictures(HSSFSheet sheet) {
Map<String, String> map = new HashMap<>();
List<HSSFShape> list = sheet.getDrawingPatriarch().getChildren();
for (HSSFShape shape : list) {
if (shape instanceof HSSFPicture) {
HSSFPicture picture = (HSSFPicture) shape;
HSSFClientAnchor cAnchor = picture.getClientAnchor();
// 行号-列号
String key = cAnchor.getRow1() + "-" + cAnchor.getCol1();
HSSFPictureData pictureData = picture.getPictureData();
map.put(key, createImgPath(pictureData));
}
}
return map;
}
/**
* 将流转储为图片
*
* @param pictureData
* @return
*/
private static String createImgPath(PictureData pictureData) {
//后缀
String suffix = pictureData.suggestFileExtension();
//图片
byte[] data = pictureData.getData();
String fileName = "/poi/img/" + cn.hutool.core.date.DateUtil.today() + "/" + System.currentTimeMillis() + "." + suffix;
String path = PropUtil.path + fileName;
FileOutputStream out = null;
try {
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
out = new FileOutputStream(path);
out.write(data);
return fileName;
} catch (IOException e) {
log.error("文件解析发生异常", e);
if (out != null) {
try {
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
}
/**
* 获取图片和位置 (xlsx)
*
* @param sheet
* @return
* @throws IOException
*/
public static Map<String, String> getXlsxPictures(XSSFSheet sheet) {
Map<String, String> map = new HashMap<>();
List<POIXMLDocumentPart> list = sheet.getRelations();
for (POIXMLDocumentPart part : list) {
if (part instanceof XSSFDrawing) {
XSSFDrawing drawing = (XSSFDrawing) part;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes) {
XSSFPicture picture = (XSSFPicture) shape;
XSSFClientAnchor anchor = picture.getPreferredSize();
CTMarker marker = anchor.getFrom();
String key = marker.getRow() + "-" + marker.getCol();
map.put(key, createImgPath(picture.getPictureData()));
}
}
}
return map;
}
/**
* 获取当前行
*/
private static Row getRow(Sheet sheet, int i, int dataIndex) {
//过滤表头行
if (i < dataIndex) {
return null;
}
//获取当前行的数据
Row row = sheet.getRow(i);
return row;
}
private static Map<String, String> getImg(File file, Sheet sheet) {
Map<String, String> imgMap;
if (file.getPath().endsWith(".xls")) {
imgMap = getXlsPictures((HSSFSheet) sheet);
} else {
imgMap = getXlsxPictures((XSSFSheet) sheet);
}
return imgMap;
}
/**
* 生成sheet
* @param file
* @param index
* @return
* @throws Exception
*/
private static Sheet createSheet(File file, int index, String sheetName) throws Exception {
InputStream inputStream = new FileInputStream(file);
Workbook workbook;
if (file.getPath().endsWith(".xls")) {
workbook = new XSSFWorkbook(inputStream);
} else {
workbook = new XSSFWorkbook(inputStream);
}
if (index < 0) {
return workbook.getSheet(sheetName);
}
return workbook.getSheetAt(index);
}
/**
* 插入图片
* @param row1:起始行
* @param row2:终止行
* @param col1:起始列
* @param col2:终止列
* @throws IOException
*/
public static Workbook setImg(Workbook wb,String sheetName,String imgPath,int row1,int row2,int col1,int col2) throws IOException {
// 第一步,创建一个XSSFWorkbook,对应一个Excel文件
if (wb == null) {
wb = new XSSFWorkbook();
}
// 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
Sheet sheet = wb.getSheet(sheetName);
if (ObjectUtil.isNull(sheet)) {
sheet = wb.createSheet(sheetName);
}
// 插入 PNG 图片至 Excel
InputStream is = new FileInputStream(imgPath);
if(ObjectUtil.isNull(is)){
return wb;
}
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
CreationHelper helper = wb.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
// 图片插入坐标
anchor.setDx1(0);
anchor.setDy1(0);
anchor.setDx2(0);
anchor.setDy2(0);
anchor.setRow1(row1);
anchor.setRow2(row2);
anchor.setCol1(col1);
anchor.setCol2(col2);
// 插入图片
Picture pict = drawing.createPicture(anchor, pictureIdx);
return wb;
}
/**
* 获取excel的列号
* @param num 第几列(从1开始)
* @return 返回列号
*/
public static String toRadix(Integer num) throws Exception{
String[] array = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
int count = 26;
String out = "";
if(num > count){
if(num % count == 0){
out = array[(num / count) - 1 - 1] + array[count - 1];
}else {
out = array[(num / count) - 1] + array[(num % count) - 1];
}
}else{
out = array[num - 1];
}
return out;
}
public static void main(String[] args) throws Exception {
// File file = new File("F:\\wenjian\\3.xlsx");
// file.createNewFile();
// InputStream inputStream = new FileInputStream(file);
Workbook workbook = new XSSFWorkbook();
// XSSFSheet sheet = (XSSFSheet) workbook.getSheetAt(0);
// XSSFRow row = sheet.getRow(6);
// XSSFCell newCell = row.createCell(2);
// XSSFCell newCell1 = row.createCell(3);
// //添加公式
// newCell.setCellFormula("A7+B7");
// newCell1.setCellFormula("A8/B8");
// //设置打印区域
// workbook.setPrintArea(
// 0, //工作薄 下标0开始
// 0, //起始列 下标0开始
// 20, //终止列 下标0开始
// 0, //起始行 下标0开始
// 20 //终止行 下标0开始
// );
//// CellStyle style = workbook.createCellStyle();
//// style.setFillBackgroundColor();
//
// OutputStream stream = new FileOutputStream(new File("D:\\1.xlsx"));
// workbook.write(stream);
// stream.close();
PoiUtilCell poiUtilCell = new PoiUtilCell();
poiUtilCell.setValue("111222333");
poiUtilCell.setColspan(1);
PoiUtilCell poiUtilCell1 = new PoiUtilCell();
poiUtilCell1.setValue("123");
PoiUtilCell poiUtilCell2 = new PoiUtilCell();
poiUtilCell2.setValue("");
poiUtilCell2.setFunction("SUM(A1:B1)");
List<PoiUtilCell> cells = new ArrayList<>();
cells.add(poiUtilCell);
cells.add(poiUtilCell1);
cells.add(poiUtilCell2);
List<List<PoiUtilCell>> list = new ArrayList<>();
list.add(cells);
// list.add(cells);
//
// List<PoiUtilCell> cells1 = new ArrayList<>();
// cells1.add(new PoiUtilCell("两列一行", 2, 1));
// list.add(cells1);
//
// List<PoiUtilCell> cells2 = new ArrayList<>();
// cells2.add(new PoiUtilCell("一列两行", 1, 2));
// list.add(cells2);
// List<PoiUtilCell> cells3 = new ArrayList<>();
// cells3.add(new PoiUtilCell("5"));
// cells3.add(new PoiUtilCell("6"));
// list.add(cells3);
// List<PoiUtilCell> cells4 = new ArrayList<>();
// list.add(cells4);
// List<PoiUtilCell> cells5 = new ArrayList<>();
// cells5.add(new PoiUtilCell("9", 2, 2));
// cells5.add(new PoiUtilCell("9"));
// list.add(cells5);
String fileName = "zzz/" + cn.hutool.core.date.DateUtil.today() + "/" + System.currentTimeMillis() + ".xlsx";
String path = WebConstant.UPLOAD_PATH_BASE + fileName;
File tmpFile = new File(path);
if (!tmpFile.getParentFile().exists()) {
tmpFile.getParentFile().mkdirs();
}
Workbook wbs = exportWB("Sheet1", list, workbook);
OutputStream stream = new FileOutputStream(tmpFile);
wbs.write(stream);
stream.close();
}
}