Excel注解支持Image图片导出
This commit is contained in:
parent
a9c6ba12e6
commit
0187344798
|
@ -149,7 +149,7 @@ public @interface Excel
|
||||||
|
|
||||||
public enum ColumnType
|
public enum ColumnType
|
||||||
{
|
{
|
||||||
NUMERIC(0), STRING(1);
|
NUMERIC(0), STRING(1), IMAGE(2);
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
ColumnType(int value)
|
ColumnType(int value)
|
||||||
|
|
|
@ -44,4 +44,33 @@ public class FileTypeUtils
|
||||||
}
|
}
|
||||||
return fileName.substring(separatorIndex + 1).toLowerCase();
|
return fileName.substring(separatorIndex + 1).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件类型
|
||||||
|
*
|
||||||
|
* @param photoByte 文件字节码
|
||||||
|
* @return 后缀(不含".")
|
||||||
|
*/
|
||||||
|
public static String getFileExtendName(byte[] photoByte)
|
||||||
|
{
|
||||||
|
String strFileExtendName = "JPG";
|
||||||
|
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
|
||||||
|
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
|
||||||
|
{
|
||||||
|
strFileExtendName = "GIF";
|
||||||
|
}
|
||||||
|
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
|
||||||
|
{
|
||||||
|
strFileExtendName = "JPG";
|
||||||
|
}
|
||||||
|
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
|
||||||
|
{
|
||||||
|
strFileExtendName = "BMP";
|
||||||
|
}
|
||||||
|
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
|
||||||
|
{
|
||||||
|
strFileExtendName = "PNG";
|
||||||
|
}
|
||||||
|
return strFileExtendName;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.ruoyi.common.utils.file;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片处理工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class ImageUtils
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
|
||||||
|
|
||||||
|
public static byte[] getImage(String imagePath)
|
||||||
|
{
|
||||||
|
InputStream is = getFile(imagePath);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return IOUtils.toByteArray(is);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("图片加载异常 {}", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputStream getFile(String imagePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] result = readFile(imagePath);
|
||||||
|
result = Arrays.copyOf(result, result.length);
|
||||||
|
return new ByteArrayInputStream(result);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("获取图片异常 {}", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取文件为字节数据
|
||||||
|
*
|
||||||
|
* @param key 地址
|
||||||
|
* @return 字节数据
|
||||||
|
*/
|
||||||
|
public static byte[] readFile(String url)
|
||||||
|
{
|
||||||
|
InputStream in = null;
|
||||||
|
ByteArrayOutputStream baos = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (url.startsWith("http"))
|
||||||
|
{
|
||||||
|
// 网络地址
|
||||||
|
URL urlObj = new URL(url);
|
||||||
|
URLConnection urlConnection = urlObj.openConnection();
|
||||||
|
urlConnection.setConnectTimeout(30 * 1000);
|
||||||
|
urlConnection.setReadTimeout(60 * 1000);
|
||||||
|
urlConnection.setDoInput(true);
|
||||||
|
in = urlConnection.getInputStream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 本机地址
|
||||||
|
String localPath = RuoYiConfig.getProfile();
|
||||||
|
String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
|
||||||
|
in = new FileInputStream(downloadPath);
|
||||||
|
}
|
||||||
|
return IOUtils.toByteArray(in);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("获取文件路径异常 {}", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtils.closeQuietly(baos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,10 +22,12 @@ import org.apache.poi.ss.usermodel.BorderStyle;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.CellStyle;
|
import org.apache.poi.ss.usermodel.CellStyle;
|
||||||
import org.apache.poi.ss.usermodel.CellType;
|
import org.apache.poi.ss.usermodel.CellType;
|
||||||
|
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||||
import org.apache.poi.ss.usermodel.DataValidation;
|
import org.apache.poi.ss.usermodel.DataValidation;
|
||||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||||
import org.apache.poi.ss.usermodel.DateUtil;
|
import org.apache.poi.ss.usermodel.DateUtil;
|
||||||
|
import org.apache.poi.ss.usermodel.Drawing;
|
||||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||||
import org.apache.poi.ss.usermodel.Font;
|
import org.apache.poi.ss.usermodel.Font;
|
||||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||||
|
@ -37,6 +39,7 @@ import org.apache.poi.ss.usermodel.Workbook;
|
||||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
|
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -51,6 +54,8 @@ import com.ruoyi.common.exception.CustomException;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.DictUtils;
|
import com.ruoyi.common.utils.DictUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.file.FileTypeUtils;
|
||||||
|
import com.ruoyi.common.utils.file.ImageUtils;
|
||||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,16 +107,21 @@ public class ExcelUtil<T>
|
||||||
*/
|
*/
|
||||||
private List<Object[]> fields;
|
private List<Object[]> fields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大高度
|
||||||
|
*/
|
||||||
|
private short maxHeight;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计列表
|
* 统计列表
|
||||||
*/
|
*/
|
||||||
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
|
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数字格式
|
* 数字格式
|
||||||
*/
|
*/
|
||||||
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
|
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体对象
|
* 实体对象
|
||||||
*/
|
*/
|
||||||
|
@ -239,7 +249,15 @@ public class ExcelUtil<T>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Convert.toStr(val);
|
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
|
||||||
|
if (StringUtils.isNotEmpty(dateFormat))
|
||||||
|
{
|
||||||
|
val = DateUtils.parseDateToStr(dateFormat, (Date) val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = Convert.toStr(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
|
else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
|
||||||
|
@ -521,6 +539,47 @@ public class ExcelUtil<T>
|
||||||
{
|
{
|
||||||
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
|
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
|
||||||
}
|
}
|
||||||
|
else if (ColumnType.IMAGE == attr.cellType())
|
||||||
|
{
|
||||||
|
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
|
||||||
|
cell.getRow().getRowNum() + 1);
|
||||||
|
String imagePath = Convert.toStr(value);
|
||||||
|
if (StringUtils.isNotEmpty(imagePath))
|
||||||
|
{
|
||||||
|
byte[] data = ImageUtils.getImage(imagePath);
|
||||||
|
getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
|
||||||
|
cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取画布
|
||||||
|
*/
|
||||||
|
public static Drawing<?> getDrawingPatriarch(Sheet sheet)
|
||||||
|
{
|
||||||
|
if (sheet.getDrawingPatriarch() == null)
|
||||||
|
{
|
||||||
|
sheet.createDrawingPatriarch();
|
||||||
|
}
|
||||||
|
return sheet.getDrawingPatriarch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图片类型,设置图片插入类型
|
||||||
|
*/
|
||||||
|
public int getImageType(byte[] value)
|
||||||
|
{
|
||||||
|
String type = FileTypeUtils.getFileExtendName(value);
|
||||||
|
if ("JPG".equalsIgnoreCase(type))
|
||||||
|
{
|
||||||
|
return Workbook.PICTURE_TYPE_JPEG;
|
||||||
|
}
|
||||||
|
else if ("PNG".equalsIgnoreCase(type))
|
||||||
|
{
|
||||||
|
return Workbook.PICTURE_TYPE_PNG;
|
||||||
|
}
|
||||||
|
return Workbook.PICTURE_TYPE_JPEG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -536,7 +595,6 @@ public class ExcelUtil<T>
|
||||||
{
|
{
|
||||||
// 设置列宽
|
// 设置列宽
|
||||||
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
|
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
|
||||||
row.setHeight((short) (attr.height() * 20));
|
|
||||||
}
|
}
|
||||||
// 如果设置了提示信息则鼠标放上去提示.
|
// 如果设置了提示信息则鼠标放上去提示.
|
||||||
if (StringUtils.isNotEmpty(attr.prompt()))
|
if (StringUtils.isNotEmpty(attr.prompt()))
|
||||||
|
@ -561,7 +619,7 @@ public class ExcelUtil<T>
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 设置行高
|
// 设置行高
|
||||||
row.setHeight((short) (attr.height() * 20));
|
row.setHeight(maxHeight);
|
||||||
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
||||||
if (attr.isExport())
|
if (attr.isExport())
|
||||||
{
|
{
|
||||||
|
@ -737,7 +795,7 @@ public class ExcelUtil<T>
|
||||||
}
|
}
|
||||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析字典值
|
* 解析字典值
|
||||||
*
|
*
|
||||||
|
@ -763,7 +821,7 @@ public class ExcelUtil<T>
|
||||||
{
|
{
|
||||||
return DictUtils.getDictValue(dictType, dictLabel, separator);
|
return DictUtils.getDictValue(dictType, dictLabel, separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合计统计信息
|
* 合计统计信息
|
||||||
*/
|
*/
|
||||||
|
@ -800,7 +858,7 @@ public class ExcelUtil<T>
|
||||||
cell = row.createCell(0);
|
cell = row.createCell(0);
|
||||||
cell.setCellStyle(styles.get("total"));
|
cell.setCellStyle(styles.get("total"));
|
||||||
cell.setCellValue("合计");
|
cell.setCellValue("合计");
|
||||||
|
|
||||||
for (Integer key : keys)
|
for (Integer key : keys)
|
||||||
{
|
{
|
||||||
cell = row.createCell(key);
|
cell = row.createCell(key);
|
||||||
|
@ -916,6 +974,21 @@ public class ExcelUtil<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
||||||
|
this.maxHeight = getRowHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据注解获取最大行高
|
||||||
|
*/
|
||||||
|
public short getRowHeight()
|
||||||
|
{
|
||||||
|
double maxHeight = 0;
|
||||||
|
for (Object[] os : this.fields)
|
||||||
|
{
|
||||||
|
Excel excel = (Excel) os[1];
|
||||||
|
maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
|
||||||
|
}
|
||||||
|
return (short) (maxHeight * 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue