若依微服务版导入模板增加下拉框匹配词典

本文介绍了一种解决微服务版若依系统中Excel工具类互相依赖问题的方法,通过增加词典功能避免了系统包与核心包间的循环依赖,并详细展示了如何在Excel注解中使用词典实现下拉列表。

因为微服务版的若依,导入工具类ExcelUtils实在common-core包下,而词典属于system包下,ExcelUtils中要用到词典的数据就需要使用到system下的词典接口,但是system是存在common-core依赖的,这样就存在了互相依赖的问题,也可以不使用system下的词典接口,单独连接数据库去查询词典数据,但是这样不太好,于是就想到了另一个办法,在需要使用excelUtils的时候将词典数据传递过去,然后在做逻辑处理。
1.字典工具类DictUtils中增加 根据key获取value集的方法

    public static String[] getDictCacheArray(String key)
    {
        String[] strings = new String[]{};
        List<SysDictData> dictData = getDictCache(key);
        if (StringUtils.isEmpty(dictData)){
            return strings;
        }
        strings = dictData.stream().map(SysDictData::getDictLabel).collect(Collectors.toList()).toArray(new  String[dictData.size()]);
        return strings;
    }

2.Excel注解增加dic 用来存放这个字段所对应的词典的key

    public String dic() default ""; //词典key

在这里插入图片描述

3.更改ExcelUtil工具类


import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
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.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
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.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Excel相关处理
 *
 * @author carbon
 */
public class ExcelUtil<T>
{
    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);

    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";

    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };

    /**
     * Excel sheet最大行数,默认65536
     */
    public static final int sheetSize = 65536;

    /**
     * 工作表名称
     */
    private String sheetName;

    /**
     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
     */
    private Type type;

    /**
     * 工作薄对象
     */
    private Workbook wb;

    /**
     * 工作表对象
     */
    private Sheet sheet;

    /**
     * 样式列表
     */
    private Map<String, CellStyle> styles;

    /**
     * 导入导出数据列表
     */
    private List<T> list;

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

    /**
     * 当前行号
     */
    private int rownum;

    /**
     * 标题
     */
    private String title;

    /**
     * 最大高度
     */
    private short maxHeight;

    /**
     * 合并后最后行数
     */
    private int subMergedLastRowNum = 0;

    /**
     * 合并后开始行数
     */
    private int subMergedFirstRowNum = 1;

    /**
     * 对象的子列表方法
     */
    private Method subMethod;

    /**
     * 对象的子列表属性
     */
    private List<Field> subFields;

    /**
     * 统计列表
     */
    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();

    /**
     * 数字格式
     */
    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");

    /**
     * 实体对象
     */
    public Class<T> clazz;

    public HashMap<String, String[]> map; // key 为词典key(Excel的dic) value为词典值

    /**
     * 需要排除列属性
     */
    public String[] excludeFields;

    public ExcelUtil(Class<T> clazz,HashMap<String, String[]> map)
    {
        this.clazz = clazz;
        this.map = map;
    }

    /**
     * 隐藏Excel中列属性
     *
     * @param fields 列属性名 示例[单个"name"/多个"id","name"]
     * @throws Exception
     */
    public void hideColumn(String... fields)
    {
        this.excludeFields = fields;
    }

    public void init(List<T> list, String sheetName, String title, Type type)
    {
        if (list == null)
        {
            list = new ArrayList<T>();
        }
        this.list = list;
        this.sheetName = sheetName;
        this.type = type;
        this.title = title;
        createExcelField();
        createWorkbook();
        createTitle();
        createSubHead();
    }

    /**
     * 创建excel第一行标题
     */
    public void createTitle()
    {
        if (StringUtils.isNotEmpty(title))
        {
            subMergedFirstRowNum++;
            subMergedLastRowNum++;
            int titleLastCol = this.fields.size() - 1;
            if (isSubList())
            {
                titleLastCol = titleLastCol + subFields.size() - 1;
            }
            Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
            titleRow.setHeightInPoints(30);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellStyle(styles.get("title"));
            titleCell.setCellValue(title);
            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
        }
    }

    /**
     * 创建对象的子列表名称
     */
    public void createSubHead()
    {
        if (isSubList())
        {
            subMergedFirstRowNum++;
            subMergedLastRowNum++;
            Row subRow = sheet.createRow(rownum);
            int excelNum = 0;
            for (Object[] objects : fields)
            {
                Excel attr = (Excel) objects[1];
                Cell headCell1 = subRow.createCell(excelNum);
                headCell1.setCellValue(attr.name());
                headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
                excelNum++;
            }
            int headFirstRow = excelNum - 1;
            int headLastRow = headFirstRow + subFields.size() - 1;
            if (headLastRow > headFirstRow)
            {
                sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
            }
            rownum++;
        }
    }

    /**
     * 对excel表单默认第一个索引名转换成list
     * 
     * @param is 输入流
     * @return 转换后集合
     */
    public List<T> importExcel(InputStream is) throws Exception
    {
        List<T> list =  importExcel(is, 0);
        //过滤空白行
        list = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
        return list;
    }

    /**
     * 对excel表单默认第一个索引名转换成list
     * 
     * @param is 输入流
     * @param titleNum 标题占用行数
     * @return 转换后集合
     */
    public List<T> importExcel(InputStream is, int titleNum) throws Exception
    {
        return importExcel(StringUtils.EMPTY, is, titleNum);
    }

    /**
     * 对excel表单指定表格索引名转换成list
     * 
     * @param sheetName 表格索引名
     * @param titleNum 标题占用行数
     * @param is 输入流
     * @return 转换后集合
     */
    public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
    {
        this.type = Type.IMPORT;
        this.wb = WorkbookFactory.create(is);
        List<T> list = new ArrayList<T>();
        // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet
        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
        if (sheet == null)
        {
            throw new IOException("文件sheet不存在");
        }

        // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
        int rows = sheet.getLastRowNum();

        if (rows > 0)
        {
            // 定义一个map用于存放excel列的序号和field.
            Map<String, Integer> cellMap = new HashMap<String, Integer>();
            // 获取表头
            Row heard = sheet.getRow(titleNum);
            for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
            {
                Cell cell = heard.getCell(i);
                if (StringUtils.isNotNull(cell))
                {
                    String value = this.getCellValue(heard, i).toString();
                    cellMap.put(value, i);
                }
                else
                {
                    cellMap.put(null, i);
                }
            }
            // 有数据时才处理 得到类的所有field.
            List<Object[]> fields = this.getFields();
            Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
            for (Object[] objects : fields)
          
### 实现若依系统中Excel导入功能并为指定列设置下拉框选项 在若依系统中实现Excel导入功能时,如果希望为某些特定的列添加下拉框选择项,则可以考虑通过前端页面配置以及后台逻辑控制来完成这一需求。具体来说: 对于前端部分,可以在上传模板下载接口返回带有预定义下拉列表样式的Excel文件给用户作为标准模板。这可以通过使用`openpyxl`库创建具有数据验证规则(即下拉菜单)的工作簿[^3]。 ```python from openpyxl import Workbook from openpyxl.worksheet.datavalidation import DataValidation def create_template_with_dropdown(): wb = Workbook() ws = wb.active # 添加一些示例数据 ws.append(['Column1', 'Column2']) # 定义下拉列表的内容 dv = DataValidation(type="list", formula1='"Option1,Option2,Option3"', allow_blank=True) ws.add_data_validation(dv) # 将此验证应用于某一范围内的单元格 dv.add('B2:B10') wb.save("template.xlsx") ``` 上述代码片段展示了如何利用Python中的`openpyxl`模块生成包含下拉列表的Excel文档。这样做的好处在于能够确保最终用户的输入符合预期格式,并减少错误发生的可能性。 至于后端方面,在接收到客户端提交上来的Excel文件之后,除了常规的数据解析外还需要额外检查这些受控字段是否确实来自允许的选择集内。这部分可通过读取Excel文件中的实际值并与事先设定好的合法选项集合对比来进行校验。 ```python import pandas as pd def validate_imported_excel(file_path): df = pd.read_excel(file_path) allowed_options = ['Option1', 'Option2', 'Option3'] invalid_entries = [] for index, row in df.iterrows(): if str(row['Column2']) not in allowed_options and pd.notna(row['Column2']): invalid_entries.append((index + 2, row['Column2'])) # 行号从1开始计数 return invalid_entries ``` 这段脚本用于检验已上传的Excel文件里某列下的条目是否属于预先规定的几个可接受值之一。如果有任何不符合条件的情况发生,那么程序会记录下来具体的违规位置以便后续通知相关人员修正问题所在之处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值