Explorar o código

Excel注解支持Image图片导出

RuoYi %!s(int64=5) %!d(string=hai) anos
pai
achega
06074571f5

+ 1 - 1
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java

@@ -144,7 +144,7 @@ public @interface Excel
144 144
 
145 145
     public enum ColumnType
146 146
     {
147
-        NUMERIC(0), STRING(1);
147
+        NUMERIC(0), STRING(1), IMAGE(2);
148 148
         private final int value;
149 149
 
150 150
         ColumnType(int value)

+ 29 - 0
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileTypeUtils.java

@@ -44,4 +44,33 @@ public class FileTypeUtils
44 44
         }
45 45
         return fileName.substring(separatorIndex + 1).toLowerCase();
46 46
     }
47
+
48
+    /**
49
+     * 获取文件类型
50
+     * 
51
+     * @param photoByte 文件字节码
52
+     * @return 后缀(不含".")
53
+     */
54
+    public static String getFileExtendName(byte[] photoByte)
55
+    {
56
+        String strFileExtendName = "JPG";
57
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
58
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
59
+        {
60
+            strFileExtendName = "GIF";
61
+        }
62
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
63
+        {
64
+            strFileExtendName = "JPG";
65
+        }
66
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
67
+        {
68
+            strFileExtendName = "BMP";
69
+        }
70
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
71
+        {
72
+            strFileExtendName = "PNG";
73
+        }
74
+        return strFileExtendName;
75
+    }
47 76
 }

+ 86 - 0
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/ImageUtils.java

@@ -0,0 +1,86 @@
1
+package com.ruoyi.common.core.utils.file;
2
+
3
+import java.io.ByteArrayInputStream;
4
+import java.io.ByteArrayOutputStream;
5
+import java.io.InputStream;
6
+import java.net.URL;
7
+import java.net.URLConnection;
8
+import java.util.Arrays;
9
+import org.apache.poi.util.IOUtils;
10
+import org.slf4j.Logger;
11
+import org.slf4j.LoggerFactory;
12
+
13
+/**
14
+ * 图片处理工具类
15
+ *
16
+ * @author ruoyi
17
+ */
18
+public class ImageUtils
19
+{
20
+    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
21
+
22
+    public static byte[] getImage(String imagePath)
23
+    {
24
+        InputStream is = getFile(imagePath);
25
+        try
26
+        {
27
+            return IOUtils.toByteArray(is);
28
+        }
29
+        catch (Exception e)
30
+        {
31
+            log.error("图片加载异常 {}", e);
32
+            return null;
33
+        }
34
+        finally
35
+        {
36
+            IOUtils.closeQuietly(is);
37
+        }
38
+    }
39
+
40
+    public static InputStream getFile(String imagePath)
41
+    {
42
+        try
43
+        {
44
+            byte[] result = readFile(imagePath);
45
+            result = Arrays.copyOf(result, result.length);
46
+            return new ByteArrayInputStream(result);
47
+        }
48
+        catch (Exception e)
49
+        {
50
+            log.error("获取图片异常 {}", e);
51
+        }
52
+        return null;
53
+    }
54
+
55
+    /**
56
+     * 读取文件为字节数据
57
+     * 
58
+     * @param key 地址
59
+     * @return 字节数据
60
+     */
61
+    public static byte[] readFile(String url)
62
+    {
63
+        InputStream in = null;
64
+        ByteArrayOutputStream baos = null;
65
+        try
66
+        {
67
+            // 网络地址
68
+            URL urlObj = new URL(url);
69
+            URLConnection urlConnection = urlObj.openConnection();
70
+            urlConnection.setConnectTimeout(30 * 1000);
71
+            urlConnection.setReadTimeout(60 * 1000);
72
+            urlConnection.setDoInput(true);
73
+            in = urlConnection.getInputStream();
74
+            return IOUtils.toByteArray(in);
75
+        }
76
+        catch (Exception e)
77
+        {
78
+            log.error("访问文件异常 {}", e);
79
+            return null;
80
+        }
81
+        finally
82
+        {
83
+            IOUtils.closeQuietly(baos);
84
+        }
85
+    }
86
+}

+ 76 - 3
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java

@@ -20,10 +20,12 @@ import org.apache.poi.ss.usermodel.BorderStyle;
20 20
 import org.apache.poi.ss.usermodel.Cell;
21 21
 import org.apache.poi.ss.usermodel.CellStyle;
22 22
 import org.apache.poi.ss.usermodel.CellType;
23
+import org.apache.poi.ss.usermodel.ClientAnchor;
23 24
 import org.apache.poi.ss.usermodel.DataValidation;
24 25
 import org.apache.poi.ss.usermodel.DataValidationConstraint;
25 26
 import org.apache.poi.ss.usermodel.DataValidationHelper;
26 27
 import org.apache.poi.ss.usermodel.DateUtil;
28
+import org.apache.poi.ss.usermodel.Drawing;
27 29
 import org.apache.poi.ss.usermodel.FillPatternType;
28 30
 import org.apache.poi.ss.usermodel.Font;
29 31
 import org.apache.poi.ss.usermodel.HorizontalAlignment;
@@ -35,6 +37,7 @@ import org.apache.poi.ss.usermodel.Workbook;
35 37
 import org.apache.poi.ss.usermodel.WorkbookFactory;
36 38
 import org.apache.poi.ss.util.CellRangeAddressList;
37 39
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
40
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
38 41
 import org.apache.poi.xssf.usermodel.XSSFDataValidation;
39 42
 import org.slf4j.Logger;
40 43
 import org.slf4j.LoggerFactory;
@@ -45,6 +48,8 @@ import com.ruoyi.common.core.annotation.Excels;
45 48
 import com.ruoyi.common.core.text.Convert;
46 49
 import com.ruoyi.common.core.utils.DateUtils;
47 50
 import com.ruoyi.common.core.utils.StringUtils;
51
+import com.ruoyi.common.core.utils.file.FileTypeUtils;
52
+import com.ruoyi.common.core.utils.file.ImageUtils;
48 53
 import com.ruoyi.common.core.utils.reflect.ReflectUtils;
49 54
 
50 55
 /**
@@ -97,6 +102,11 @@ public class ExcelUtil<T>
97 102
     private List<Object[]> fields;
98 103
 
99 104
     /**
105
+     * 最大高度
106
+     */
107
+    private short maxHeight;
108
+
109
+    /**
100 110
      * 统计列表
101 111
      */
102 112
     private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
@@ -233,7 +243,15 @@ public class ExcelUtil<T>
233 243
                         }
234 244
                         else
235 245
                         {
236
-                            val = Convert.toStr(val);
246
+                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
247
+                            if (StringUtils.isNotEmpty(dateFormat))
248
+                            {
249
+                                val = DateUtils.parseDateToStr(dateFormat, (Date) val);
250
+                            }
251
+                            else
252
+                            {
253
+                                val = Convert.toStr(val);
254
+                            }
237 255
                         }
238 256
                     }
239 257
                     else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
@@ -512,6 +530,47 @@ public class ExcelUtil<T>
512 530
         {
513 531
             cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
514 532
         }
533
+        else if (ColumnType.IMAGE == attr.cellType())
534
+        {
535
+            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
536
+                    cell.getRow().getRowNum() + 1);
537
+            String imagePath = Convert.toStr(value);
538
+            if (StringUtils.isNotEmpty(imagePath))
539
+            {
540
+                byte[] data = ImageUtils.getImage(imagePath);
541
+                getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
542
+                        cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
543
+            }
544
+        }
545
+    }
546
+    
547
+    /**
548
+     * 获取画布
549
+     */
550
+    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
551
+    {
552
+        if (sheet.getDrawingPatriarch() == null)
553
+        {
554
+            sheet.createDrawingPatriarch();
555
+        }
556
+        return sheet.getDrawingPatriarch();
557
+    }
558
+
559
+    /**
560
+     * 获取图片类型,设置图片插入类型
561
+     */
562
+    public int getImageType(byte[] value)
563
+    {
564
+        String type = FileTypeUtils.getFileExtendName(value);
565
+        if ("JPG".equalsIgnoreCase(type))
566
+        {
567
+            return Workbook.PICTURE_TYPE_JPEG;
568
+        }
569
+        else if ("PNG".equalsIgnoreCase(type))
570
+        {
571
+            return Workbook.PICTURE_TYPE_PNG;
572
+        }
573
+        return Workbook.PICTURE_TYPE_JPEG;
515 574
     }
516 575
 
517 576
     /**
@@ -527,7 +586,6 @@ public class ExcelUtil<T>
527 586
         {
528 587
             // 设置列宽
529 588
             sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
530
-            row.setHeight((short) (attr.height() * 20));
531 589
         }
532 590
         // 如果设置了提示信息则鼠标放上去提示.
533 591
         if (StringUtils.isNotEmpty(attr.prompt()))
@@ -552,7 +610,7 @@ public class ExcelUtil<T>
552 610
         try
553 611
         {
554 612
             // 设置行高
555
-            row.setHeight((short) (attr.height() * 20));
613
+            row.setHeight(maxHeight);
556 614
             // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
557 615
             if (attr.isExport())
558 616
             {
@@ -851,6 +909,21 @@ public class ExcelUtil<T>
851 909
             }
852 910
         }
853 911
         this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
912
+        this.maxHeight = getRowHeight();
913
+    }
914
+    
915
+    /**
916
+     * 根据注解获取最大行高
917
+     */
918
+    public short getRowHeight()
919
+    {
920
+        double maxHeight = 0;
921
+        for (Object[] os : this.fields)
922
+        {
923
+            Excel excel = (Excel) os[1];
924
+            maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
925
+        }
926
+        return (short) (maxHeight * 20);
854 927
     }
855 928
 
856 929
     /**