zoukankan      html  css  js  c++  java
  • 若依管理系统源码分析-导出Excel时怎样通过注解中readConverterExp实现格式化导出列的显示格式(0和1格式化为是否)

    场景

    在数据库中存储某些个是否的字段时,有时会使用tinint进行存储

    这样会在实体类中生成布尔类型的变量

    private Boolean sfkt;

    有时也会用int进行存储是否

    那么在实体类中就可能用Integer和String进行是否字段的存取

    private String sfcl;

    那么在使用若依自带的导出时,如果不加修改,则会直接将对应的字段的列导出为0或者1,true或者false。

    如果想要根据此列的0和1进而显示是和否怎样显示。

    注:

    博客:
    https://blog.csdn.net/badao_liumang_qizhi
    关注公众号
    霸道的程序猿
    获取编程相关电子书、教程推送与免费下载。

    实现

    如果是0和1格式化为是和否

    找到对应的实体类中的属性,在注解上添加

    @Excel(name = "是否处理完成",readConverterExp = "0=否,1=是")
    private String sfcl;

    添加读取转换表达式属性readConverterExp就可以实现,具体见下面源码分析。

    如果是true和false格式化为是和否

    @Excel(name = "是否跨天",readConverterExp = "false=否,true=是")
    private Boolean sfkt;

    表达式的格式要固定如上,值可以自己根据要求去添加。

    下面分析为什么这样添加就可以。

    源码分析

    在SpringbBoot后台接口中

        @GetMapping("/export")
        public AjaxResult export(KqBcgl kqBcgl)
        {
            List<KqBcgl> list = kqBcglService.getBcListByNameToExport(kqBcgl);
            ExcelUtil<KqBcgl> util = new ExcelUtil<KqBcgl>(KqBcgl.class);
            return util.exportExcel(list, "bcgl");
        }

    其中list是查询数据库的数据。

    然后调用工具类生成工具类对象,主要是调用exportExcel方法来生成Excel

    在方法中

        public AjaxResult exportExcel(List<T> list, String sheetName)
        {
            this.init(list, sheetName, Type.EXPORT);
            return exportExcel();
        }

    调用了init方法,生成一些工作簿以及列等相关信息的对象。

    在方法createExcelField中

       private void createExcelField()
        {
            this.fields = new ArrayList<Object[]>();
            List<Field> tempFields = new ArrayList<>();
            tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
            tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            for (Field field : tempFields)
            {
                // 单注解
                if (field.isAnnotationPresent(Excel.class))
                {
                    putToField(field, field.getAnnotation(Excel.class));
                }
    
                // 多注解
                if (field.isAnnotationPresent(Excels.class))
                {
                    Excels attrs = field.getAnnotation(Excels.class);
                    Excel[] excels = attrs.value();
                    for (Excel excel : excels)
                    {
                        putToField(field, excel);
                    }
                }
            }
        }

    和方法createWorkbook中

        public void createWorkbook()
        {
            this.wb = new SXSSFWorkbook(500);
        }

    主要是读取注解和调用了POI的一些方法用来初始化Excel的相关对象。

    构建excel数据的方法主要是exportExcel()

       public AjaxResult exportExcel()
        {
            OutputStream out = null;
            try
            {
                // 取出一共有多少个sheet.
                double sheetNo = Math.ceil(list.size() / sheetSize);
                for (int index = 0; index <= sheetNo; index++)
                {
                    createSheet(sheetNo, index);
    
                    // 产生一行
                    Row row = sheet.createRow(0);
                    int column = 0;
                    // 写入各个字段的列头名称
                    for (Object[] os : fields)
                    {
                        Excel excel = (Excel) os[1];
                        this.createCell(excel, row, column++);
                    }
                    if (Type.EXPORT.equals(type))
                    {
                        fillExcelData(index, row);
                    }
                }
                String filename = encodingFilename(sheetName);
                out = new FileOutputStream(getAbsoluteFile(filename));
                wb.write(out);
                return AjaxResult.success(filename);
            }
            catch (Exception e)
            {
                log.error("导出Excel异常{}", e.getMessage());
                throw new CustomException("导出Excel失败,请联系网站管理员!");
            }
            finally
            {
                if (wb != null)
                {
                    try
                    {
                        wb.close();
                    }
                    catch (IOException e1)
                    {
                        e1.printStackTrace();
                    }
                }
                if (out != null)
                {
                    try
                    {
                        out.close();
                    }
                    catch (IOException e1)
                    {
                        e1.printStackTrace();
                    }
                }
            }
        }

    这其中使用填充excel的方法fillExcelData

        public void fillExcelData(int index, Row row)
        {
            int startNo = index * sheetSize;
            int endNo = Math.min(startNo + sheetSize, list.size());
            for (int i = startNo; i < endNo; i++)
            {
                row = sheet.createRow(i + 1 - startNo);
                // 得到导出对象.
                T vo = (T) list.get(i);
                int column = 0;
                for (Object[] os : fields)
                {
                    Field field = (Field) os[0];
                    Excel excel = (Excel) os[1];
                    // 设置实体类私有属性可访问
                    field.setAccessible(true);
                    this.addCell(excel, row, vo, field, column++);
                }
            }
        }

    上面的fields是读取的注解列表,

         /**
         * 注解列表
         */
        private List<Object[]> fields;

    遍历每个注解对象后调用addCell方法

       public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
        {
            Cell cell = null;
            try
            {
                // 设置行高
                row.setHeight((short) (attr.height() * 20));
                // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
                if (attr.isExport())
                {
                    // 创建cell
                    cell = row.createCell(column);
                    cell.setCellStyle(styles.get("data"));
    
                    // 用于读取对象中的属性
                    Object value = getTargetValue(vo, field, attr);
                    String dateFormat = attr.dateFormat();
                    String readConverterExp = attr.readConverterExp();
                    if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
                    {
                        cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
                    }
                    else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
                    {
                        cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp));
                    }
                    else
                    {
                        // 设置列类型
                        setCellVo(value, attr, cell);
                    }
                }
            }
            catch (Exception e)
            {
                log.error("导出Excel失败{}", e);
            }
            return cell;
        }

    在这里是执行填充单元格的方法,其中

      String readConverterExp = attr.readConverterExp();

    就是获取上面设置的注解readConverterExp属性

     else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
         {
              cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp));
          }

    判断如果不为空的话将单元格的值和传递的表达式传递给方法convertByExp

        /**
         * 解析导出值 0=男,1=女,2=未知
         * 
         * @param propertyValue 参数值
         * @param converterExp 翻译注解
         * @return 解析后值
         * @throws Exception
         */
        public static String convertByExp(String propertyValue, String converterExp) throws Exception
        {
            try
            {
                String[] convertSource = converterExp.split(",");
                for (String item : convertSource)
                {
                    String[] itemArray = item.split("=");
                    if (itemArray[0].equals(propertyValue))
                    {
                        return itemArray[1];
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return propertyValue;
        }

    首先将表达式按照逗号分隔,获取分隔后的数组,然后遍历数组。

    再根据=分隔,如果等号左边即分割后数组的第一个值与单元格的值相等,就返回等号右边的值即分隔后的第二个值。

    这样就实现了按照指定表达式将单元格的值进行格式化显示。

  • 相关阅读:
    JVM发生OOM调优
    行云创新完成B轮融资,阿里云独家投资
    行云创新直播回顾:DDD“爱”上Dapr
    如何通过Dapr快速实现DDD?
    通过Dapr快速落地DDD,实现高并发
    上K8s,研发团队如何从容一点?
    直播来了!等你围观!聊聊服务网格那些事儿
    服务网格出现流量故障该咋办?SolarMesh发布重大功能
    mysql 授权问题
    Centos Mysql5.7 安装
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/13508012.html
Copyright © 2011-2022 走看看