软件教程 2025年08月6日
0 收藏 0 点赞 384 浏览 7102 个字
摘要 :

文章目录 一、安装所需依赖 二、完整组件的实现过程 (一)模板部分(template) (二)脚本部分(script setup) 前端开发实现Excel模板数据导入表格想必大家都遇到……




  • 一、安装所需依赖
  • 二、完整组件的实现过程
    • (一)模板部分(template)
    • (二)脚本部分(script setup)

    前端开发实现Excel模板数据导入表格想必大家都遇到过,本文将详细介绍如何利用Vue3和Ant Design搭建一个具备此功能的组件。

    一、安装所需依赖

    在开始编写代码前,需要安装一些必要的依赖包。这些依赖包将帮助我们处理Excel文件的读取、下载以及实现界面上的各种交互功能。使用npm或yarn都可以进行安装,命令如下:

    npm install xlsx file-saver @ant-design/icons-vue
    # 或
    yarn add xlsx file-saver @ant-design/icons-vue
    

    xlsx 用于处理Excel文件的解析和生成;file-saver 能够帮助我们实现文件的下载功能;@ant-design/icons-vue 则提供了Ant Design风格的图标,方便在界面中使用。

    二、完整组件的实现过程

    (一)模板部分(template)

    模板部分主要负责构建组件的用户界面,代码如下:

    <template>   
      <div class=\"excel-import-container\">    
        <a-space direction=\"vertical\" style=\"width: 100%\">      
          <a-space>        
            <a-upload
              :before-upload=\"beforeUpload\"
              :show-upload-list=\"false\"
              accept=\".xlsx,.xls\"
            >
              <a-button type=\"primary\">
                <template #icon><UploadOutlined /></template>
                导入Excel
              </a-button>
            </a-upload>
            <a-button @click=\"downloadTemplate\">
              <template #icon><DownloadOutlined /></template>
              下载模板
            </a-button>
          </a-space>
          <a-alert
            v-if=\"importErrors.length > 0\"
            type=\"error\"
            message=\"导入数据存在以下问题:\"
            :description=\"importErrors.join(\'\\n\')\"
            show-icon
            closable
            @close=\"() => importErrors = []\"
          />
          <a-table
            :columns=\"columns\"
            :data-source=\"importedData\"
            :row-key=\"(record, index) => index\"
            :scroll=\"{ x: 2000 }\"
            bordered
            size=\"middle\"
          >
            <template #bodyCell=\"{ column, text, record }\">
              <template v-if=\"column.dataIndex === \'index\'\">
                {{ record.index + 1 }}
              </template>
              <template v-else-if=\"[\'isImports\', \'coreProduct\', \'efficient\', \'waterSaving\', \'environment\', \'infoInnovationProduct\', \'govService\'].includes(column.dataIndex)\">
                {{ text == 1 ? \'是\' : \'否\' }}
              </template>
              <template v-else-if=\"column.dataIndex === \'operation\'\">
                <a-button type=\"link\" danger @click=\"removeItem(record.index)\">
                  删除
                </a-button>
              </template>
            </template>
          </a-table>
          <div class=\"action-buttons\" v-if=\"importedData.length > 0\">
            <a-button @click=\"clearData\">清空数据</a-button>
            <a-button
              type=\"primary\"
              @click=\"submitData\"
              :loading=\"isSubmitting\"
            >
              提交数据
            </a-button>
          </div>
        </a-space>
      </div> 
    </template> 
    

    在这个模板中:

    • 首先定义了一个包含导入和下载功能按钮的区域。a-upload 组件实现文件上传功能,before-upload 属性绑定了上传前的处理函数 beforeUploadshow-upload-list 设置为 false 表示不显示上传列表,accept 限定了可上传的文件类型为 .xlsx.xls 。旁边的 a-button 用于下载模板,点击时会触发 downloadTemplate 函数。
    • a-alert 组件用于在导入数据出现错误时显示错误信息,错误信息通过 importErrors 数组获取,用户点击关闭按钮时会清空错误信息数组。
    • a-table 组件展示导入的数据表格。columns 定义表格列配置,data-source 绑定导入的数据,row-key 用于指定每行的唯一标识。表格的单元格根据不同的 dataIndex 进行不同的显示处理,如序号列、布尔值列以及操作列等。
    • 最后,当导入数据存在时,会显示清空数据和提交数据的按钮,分别对应 clearDatasubmitData 函数,提交按钮还会根据 isSubmitting 的值显示加载状态。

    (二)脚本部分(script setup)

    脚本部分负责实现组件的逻辑功能,代码如下:

    <script setup>
    import { ref } from \'vue\';
    import * as XLSX from \'xlsx\';
    import { saveAs } from \'file-saver\';
    import { UploadOutlined, DownloadOutlined } from \'@ant-design/icons-vue\';
    import { message, Modal } from \'ant-design-vue\';
    
    // 导入表格列配置
    const columns = tempColumns; 
    // 响应式数据
    const importedData = ref([]);
    const importErrors = ref([]);
    const isSubmitting = ref(false);
    
    // 处理文件上传
    const beforeUpload = (file) => {
      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          const data = e.target.result;
          const workbook = XLSX.read(data, { type: \'array\' });
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const jsonData = XLSX.utils.sheet_to_json(worksheet);
          // 处理导入数据
          processImportedData(jsonData);
        } catch (error) {
          message.error(\'文件解析失败: \' + error.message);
        }
      };
      reader.readAsArrayBuffer(file);
      return false; // 阻止自动上传
    };
    
    // 处理导入的数据
    const processImportedData = (data) => {
      const errors = [];
      data.forEach((row, index) => {
        // 检查必填字段
        if (!row[\'商品/服务名称\']) {
          errors.push(`第 ${index + 2} 行: 商品/服务名称为必填项`);
        }
        if (!row[\'采购品目名称\']) {
          errors.push(`第 ${index + 2} 行: 采购品目名称为必填项`);
        }
        // 检查数字字段
        const numberFields = [\'总金额/首购费用(元)\', \'采购数量\', \'单价(元)\'];
        numberFields.forEach(field => {
          if (row[field] && isNaN(Number(row[field]))) {
            errors.push(`第 ${index + 2} 行: ${field} 必须为数字`);
          }
        });
        // 检查是否类字段(应为0或1)
        const booleanFields = [
          \'是否采购进口产品\', \'是否核心产品\', \'是否强制采购节能产品\',
          \'是否强制采购节水产品\', \'是否优先采购环保产品\',
          \'是否属于政府采购需求标准(2023年版)规范产品\', \'是否属于政府购买服务\'
        ];
        booleanFields.forEach(field => {
          if (row[field]!== undefined && row[field]!== null && row[field]!== \'\' && row[field]!= 0 && row[field]!= 1) {
            errors.push(`第 ${index + 2} 行: ${field} 必须为\"是\"(1)或\"否\"(0)`);
          }
        });
      });
      if (errors.length > 0) {
        importErrors.value = errors;
        message.error(`发现 ${errors.length} 处错误,请修正后重新导入`);
        return;
      }
      // 转换数据格式
      const formattedData = data.map((row, index) => ({
        index,
        goodsName: row[\'商品/服务名称\'],
        purCatalogName: row[\'采购品目名称\'],
        totalPrice: row[\'总金额/首购费用(元)\']? Number(row[\'总金额/首购费用(元)\']) : null,
        num: row[\'采购数量\']? Number(row[\'采购数量\']) : null,
        unit: row[\'计量单位\'],
        price: row[\'单价(元)\']? Number(row[\'单价(元)\']) : null,
        isImports: row[\'是否采购进口产品\'] == 1? 1 : 0,
        coreProduct: row[\'是否核心产品\'] == 1? 1 : 0,
        efficient: row[\'是否强制采购节能产品\'] == 1? 1 : 0,
        waterSaving: row[\'是否强制采购节水产品\'] == 1? 1 : 0,
        environment: row[\'是否优先采购环保产品\'] == 1? 1 : 0,
        infoInnovationProduct: row[\'是否属于政府采购需求标准(2023年版)规范产品\'] == 1? 1 : 0,
        industrialClass: row[\'采购标的所属国民经济分类\'],
        govService: row[\'是否属于政府购买服务\'] == 1? 1 : 0,
        govServiceCatalogName: row[\'政府购买服务指导性目录名称\'],
        spec: row[\'规格参数/服务要求\']
      }));
      importedData.value = formattedData;
      message.success(`成功导入 ${formattedData.length} 条数据`);
    };
    
    // 下载模板
    const downloadTemplate = () => {
      // 准备表头
      const headers = columns
      .filter(col => col.dataIndex!== \'index\' && col.dataIndex!== \'operation\')
      .map(col => col.title);
      // 示例数据
      const sampleData = [
        [
          \'示例商品\',          // 商品/服务名称
          \'办公设备\',         // 采购品目名称
          1000,              // 总金额/首购费用(元)
          10,                // 采购数量
          \'台\',              // 计量单位
          100,               // 单价(元)
          0,                 // 是否采购进口产品
          1,                 // 是否核心产品
          0,                 // 是否强制采购节能产品
          0,                 // 是否强制采购节水产品
          1,                 // 是否优先采购环保产品
          0,                 // 是否属于政府采购需求标准(2023年版)规范产品
          \'C3910\',           // 采购标的所属国民经济分类
          0,                 // 是否属于政府购买服务
          \'\',                // 政府购买服务指导性目录名称
          \'规格参数示例\'      // 规格参数/服务要求
        ]
      ];
      // 创建工作表
      const ws = XLSX.utils.aoa_to_sheet([headers, ...sampleData]);
      // 创建工作簿
      const wb = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws, \'采购数据\');
      // 设置列宽
      if (!ws[\'!cols\']) ws[\'!cols\'] = [];
      headers.forEach((_, index) => {
        ws[\'!cols\'][index] = { wch: 20 }; // 设置每列宽度
      });
      // 生成Excel文件
      const wbout = XLSX.write(wb, { bookType: \'xlsx\', type: \'array\' });
      saveAs(
        new Blob([wbout], { type: \'application/octet-stream\' }),
        \'采购数据模板.xlsx\'
      );
    };
    
    // 删除单条数据
    const removeItem = (index) => {
      importedData.value = importedData.value.filter((_, i) => i!== index);
      // 重新生成index
      importedData.value = importedData.value.map((item, i) => ({...item, index: i }));
    };
    
    // 清空数据
    const clearData = () => {
      Modal.confirm({
        title: \'确认清空数据吗?\',
        content: \'这将清除所有已导入的数据\',
        onOk() {
          importedData.value = [];
          importErrors.value = [];
        }
      });
    };
    
    // 提交数据
    const submitData = async () => {
      isSubmitting.value = true;
      try {
        // 这里替换为实际的API调用
        // const response = await api.submitImportData(importedData.value);
        message.success(\'数据提交成功\');
        importedData.value = [];
      } catch (error) {
        // 这里可添加错误处理逻辑,比如提示用户提交失败原因
      } finally {
        isSubmitting.value = false;
      }
    };
    </script>
    
    • 首先导入了Vue的 ref 函数用于创建响应式数据,XLSX 库用于处理Excel文件,saveAs 用于文件下载,UploadOutlinedDownloadOutlined 是Ant Design的图标,messageModal 用于显示提示信息和确认弹窗。
    • beforeUpload 函数在文件上传前被调用,它使用 FileReader 读取文件内容,然后通过 XLSX 库将文件解析为JSON数据,并调用 processImportedData 函数处理这些数据。如果解析过程中出现错误,会使用 message.error 提示用户。
    • processImportedData 函数主要负责检查导入数据的合法性,如必填字段是否填写、数字字段是否为数字、某些字段是否为0或1等。如果存在错误,将错误信息收集到 errors 数组中,并显示错误提示,阻止数据导入。若数据合法,则对数据进行格式转换,将其存入 importedData 响应式数据中,并提示成功导入的信息。
    • downloadTemplate 函数用于生成并下载Excel模板文件。它先准备好表头和示例数据,然后使用 XLSX 库创建工作表和工作簿,设置好列宽后,将工作簿转换为二进制数据并通过 saveAs 实现文件下载。
    • removeItem 函数用于删除表格中的某一条数据,它通过过滤数组的方式移除指定索引的数据,并重新生成数据的 index
    • clearData 函数通过 Modal.confirm 弹窗询问用户是否确认清空数据,确认后清空 importedDataimportErrors 数组。
    • submitData 函数用于提交数据,在提交过程中设置 isSubmittingtrue 显示加载状态,目前代码中只是模拟了数据提交成功的提示,实际使用时需要替换为真实的API调用,并在 catch 块中添加错误处理逻辑,在 finally 块中将 isSubmitting 设置为 false

    通过上述步骤,我们就成功实现了一个基于Vue3和Ant Design的Excel模板数据导入表格的功能组件。这个组件涵盖了文件导入、数据校验、模板下载、数据删除、清空以及提交等一系列功能,满足了常见的业务需求。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6938.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

270
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

108
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

684
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

340
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

844
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号