动态配置导入excel

Controller

 /**
     * 导出填报配置列表
     */
    @PostMapping("/importData")
    public R importData(@RequestPart("file") MultipartFile file, @NotNull(message = "报表ID不可为空") Integer id) throws Exception {

        try {
            // 查询表的列配置
            List<TbFieldsConfig> headers = iTbConfigService.getFieldsConfigList(id);
            // 解析excel
            TbTableDataImportListener listener = new TbTableDataImportListener(headers);
            EasyExcel.read(file.getInputStream(), listener).sheet().doRead();
            List<JSONObject> dataList = listener.getDataList();
            // 插入数据
            iTbConfigService.insertDataList(dataList, id);
        return R.ok("导入成功");
        } catch (IOException e) {
            return R.ok("导入失败:" + e.getMessage());
        }
    }

Listener

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.zhby.common.exception.ServiceException;
import com.zhby.tb.domain.TbFieldsConfig;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class TbTableDataImportListener extends AnalysisEventListener<Map<Integer, Object>> {


    private Map<String, String> headerConfig = null;
    private Map<Integer, String> headerIndexToDbField = new LinkedHashMap<>(); // 列索引到数据库字段名的映射

    private final List<TbFieldsConfig> headers;
    private final List<JSONObject> dataList = new ArrayList<>();


    public TbTableDataImportListener( List<TbFieldsConfig> headers) {
        this.headers = headers;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        if (null == headers || headers.size() <= 0) {
            throw new ServiceException("没有配置报表的字段配置信!!!");
        }
        // 获取表头配置
        headerConfig = new LinkedHashMap<>();
        for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
            String chineseHeader = entry.getValue(); // 假设这是中文表头
            if (StrUtil.isNotBlank(chineseHeader)) { // 只保留有效的列
                String dbFieldName = getDbFieldName(chineseHeader); // 从中文表头获取数据库字段名
                if (StrUtil.isNotBlank(dbFieldName)) {
                    // 只保留有效的列
                    headerConfig.put(dbFieldName, chineseHeader);
                    headerIndexToDbField.put(entry.getKey(), dbFieldName);
                }
            }
        }
    }

    private String getDbFieldName(String chineseHeader) {
        String key = null;
        for (int i = 0; i < headers.size(); i++) {
            if (chineseHeader.equals(headers.get(i).getFieldName())) {
                key = headers.get(i).getFieldCode();
            }
        }
        return key;
    }

    @Override
    public void invoke(Map<Integer, Object> object, AnalysisContext context) {
        JSONObject row = new JSONObject();
        for (Map.Entry<Integer, String> entry : headerIndexToDbField.entrySet()) {
            Integer columnIndex = entry.getKey();
            String dbFieldName = entry.getValue();
            Object cellValue = object.get(columnIndex);
            row.put(dbFieldName, cellValue);
        }
        dataList.add(row);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

    public List<JSONObject> getDataList() {
        return dataList;
    }
}

Service

   @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertDataList(List<JSONObject> datas, Integer id) {
        // 根据表名查询所有指标表的字段
        List<TbFieldsConfig> fields = getFieldsConfigList(id);
        List<Map> dataMaps = new ArrayList<>(); 
        //把数据转换成code的map
格式
        datas.forEach(data -> {
            Map<String, Object> dataMap = new HashMap<>();
            for (TbFieldsConfig field : fields) {
                dataMap.put( field.getFieldCode(), data.get(field.getFieldCode()));
            } 
            Map<String, Object> params = new HashMap<>();
            params.put("tableName", id);
            params.put("columnMap", dataMap);
            dataMaps.add(params);
        });
        dataMaps.forEach(params -> {
            try {
                // 插入数据
                baseMapper.insertByMap(params); 
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        return datas.size();
    }

Mapper

 <insert id="insertByMap"   parameterType="java.util.Map" useGeneratedKeys="true" keyColumn="id"  keyProperty="id">

        INSERT INTO  ${tableName} (
        <foreach collection="columnMap" item="value" index="key" separator=",">
            ${key}
        </foreach>
        )
        values (
        <foreach collection="columnMap" item="value" index="key" separator=",">
            #{value}
        </foreach>

        )
    </insert>

Vue


      <el-button type="warning" plain icon="Top" @click="handleImport">导入 </el-button>
 <el-dialog :title="upload.title" v-model="upload.open" width="400px" :append-to-body="true">
        <el-upload
          ref="uploadRef"
          :limit="1"
          accept=".xlsx, .xls"
          :headers="upload.headers"
          :action="upload.url+'?id='+upload.id"
          :on-progress="handleFileUploadProgress"
          :on-success="handleFileSuccess"
          :auto-upload="false"
          drag
        >
          <el-icon class="el-icon--upload">
            <i-ep-upload-filled/>
          </el-icon>
          <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
          <template #tip>
            <div class="text-center el-upload__tip">
              <div class="el-upload__tip">
                是否更新已经存在的指标数据
              </div>
              <span>仅允许导入xls、xlsx格式文件。</span>
            </div>
          </template>
        </el-upload>
        <template #footer>
          <div class="dialog-footer">
            <el-button type="primary" @click="submitFileForm">确 定</el-button>
            <el-button @click="upload.open = false">取 消</el-button>
          </div>
        </template>
      </el-dialog>

Js


const uploadRef = ref();
/*** 用户导入参数 */
const upload = ref({
  // 是否显示弹出层
  open: false,
  // 弹出层标题
  title: "",
  // 设置上传的请求头部
  headers: globalHeaders(),
  id: "",
  // 上传的地址
  url: import.meta.env.VITE_APP_BASE_API + "/tb/config/importData"
});
/** 导入按钮操作 */
const handleImport = () => {
  upload.value.title = checkbb.value.name + "报表数据导入";
  upload.value.id = checkbb.value.id;
  upload.value.open = true;
};
/**文件上传中处理 */
const handleFileUploadProgress = () => {
  upload.value.isUploading = true;
};
/** 文件上传成功处理 */
const handleFileSuccess = (response, file) => {
  upload.value.open = false;
  upload.value.isUploading = false;
  uploadRef.value?.handleRemove(file);
  proxy.$modal.msgSuccess(response.msg);
  handleSearch();
};

/** 提交上传文件 */
function submitFileForm() {
  uploadRef.value?.submit();
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容