关于vue3中 如何生成 excel 表 下载excel表 和 excel表在页面展示的组件使用

1.需要用到的组件

import { saveAs } from ‘file-saver’; // 用于保存文件
import ExcelJS from ‘exceljs’; // Excel 操作库
import VueOfficeExcel from ‘@vue-office/excel’; // Excel 预览组件
import ‘@vue-office/excel/lib/index.css’; // Excel 预览组件的样式

import axios from ‘axios’; // HTTP 客户端
import { projectWorkItemsList } from ‘@/api/ssei/workItems’; // API 请求函数
//这两段代码是为了获取到数据

2.生成excel文件 比较简单 下载也简单 重要是渲染 (但是知道使用后 渲染最简单 )

1. 安装必要的依赖
在开始之前,您需要确保已经安装了以下库:

ExcelJS:用于操作和生成 Excel 文件。
FileSaver:用于在客户端保存生成的文件。
Axios:用于发送 HTTP 请求(获取数据)。
您可以使用以下命令安装这些依赖:

bash
npm install exceljs file-saver axios
2. 导入必要的库和组件
在您的 Vue 组件中,首先需要导入上述库:

javascript
import { saveAs } from ‘file-saver’; // 用于保存文件
import axios from ‘axios’; // HTTP 客户端
import ExcelJS from ‘exceljs’; // Excel 操作库
import { projectWorkItemsList } from ‘@/api/ssei/workItems’; // API 请求函数(根据您的项目结构调整路径)
import VueOfficeExcel from ‘@vue-office/excel’; // Excel 预览组件(可选)
import ‘@vue-office/excel/lib/index.css’; // Excel 预览组件的样式
3. 设置组件的 data
在组件的 data 中,定义了用于存储表单输入、生成的 Excel 缓冲区、文件名、工作事项等数据:

javascript
data() {
const today = new Date();
return {
attachmentName: ‘’, // 附件名称
filler: ‘’, // 填表人
weekDate: today.toISOString().substr(0, 10), // 默认选择当天的日期,格式为 YYYY-MM-DD
minDate: ‘’, // 当周的星期一日期
maxDate: ‘’, // 当周的星期五日期
excelBuffer: null, // 存储生成的 Excel 文件的缓冲区
excelFileName: ‘’, // 生成的 Excel 文件名
workItems: [], // 本周的工作事项
token: ‘’, // 用户的 token
previewUrl: ‘’, // Excel 预览的 URL
previewType: ‘’ // 预览的文件类型
};
},
4. 生命周期钩子 created
在 created 钩子中,初始化日期范围并获取用户的 token:

javascript
created() {
// 计算并设置当前周的开始和结束日期
this.minDate = this.calculateStartOfWeek(new Date());
this.maxDate = this.calculateEndOfWeek(new Date());
// 获取用户的 token
this.fetchToken();
},
5. 主要方法解释
a. 获取用户 Token
确保您有权限生成 Excel 文件,通常需要用户的认证 token:

javascript
async fetchToken() {
try {
const response = await axios.get(‘/grout/system/getUserInfo’); // 发送 GET 请求
if (response.data && response.data.code === 200) { // 检查响应是否成功
this.token = response.data.data.token; // 设置 token
} else {
console.error(‘Failed to fetch token:’, response.data.msg); // 打印错误信息
}
} catch (error) {
console.error(‘Error fetching token:’, error); // 捕获并打印错误
}
},
b. 生成 Excel 文件
这是生成 Excel 文件的核心方法:

javascript
async generateExcel() {
// 检查所有必填字段是否已填写
if (!this.attachmentName || !this.filler || !this.weekDate) {
alert(‘请填写所有字段’);
return;
}

try {
// 获取工作事项列表
const response = await projectWorkItemsList({
token: this.token
});

// 验证响应数据格式
if (!response || !response.data || !Array.isArray(response.data)) {
  console.error('无效的 API 响应格式');
  alert('获取数据失败');
  return;
}

// 获取本周的开始和结束日期(星期一至星期五)
const weekDateObj = new Date(this.weekDate); // 选择的日期
const weekStart = new Date(this.calculateStartOfWeek(weekDateObj)); // 本周星期一
const weekEnd = new Date(this.calculateEndOfWeek(weekDateObj)); // 本周星期五

// 过滤出本周的数据
const currentWeekItems = response.data.filter(item => {
  const startTime = new Date(item.start_time); // 事项的开始时间
  const endTime = new Date(item.end_time); // 事项的结束时间
  return startTime <= weekEnd && endTime >= weekStart; // 检查是否在本周范围内
});

// 如果没有符合条件的数据,提示并退出
if (currentWeekItems.length === 0) {
  alert('没有符合条件的本周数据');
  return;
}

// 定义项目类型、项目和节点的映射关系
const projectTypeMapping = {
  1: '类型1',
  19: '类型2',
  20: '类型3'
};
const projectMapping = {
  1: '项目1',
  2: '项目2',
  6: '项目4',
  7: '项目5'
};
const nodeMapping = {
  17: '节点1',
  18: '节点2',
  19: '节点3'
};

// 处理本周的数据,映射相应的字段
this.workItems = currentWeekItems.map(data => ({
  project_type_id: projectTypeMapping[data.project_type_id] || '未知', // 项目类型
  project_id: projectMapping[data.project_id] || '未知', // 项目
  project_nodes_id: nodeMapping[data.project_nodes_id] || '未知', // 节点
  work_item_name: data.work_item_name || '', // 工作事项名称
  work_item_code: data.work_item_code || '', // 工作事项编号
  is_completed: data.is_completed ? '是' : '否', // 是否完成
  completion_status: data.completion_status || '', // 完成情况
  work_standards: data.work_standards || '', // 工作标准
  is_coordinate: data.is_coordinate ? '是' : '否', // 是否需要协调
  remarks: data.remarks || '' // 备注
}));

// 创建 Excel 工作簿和工作表
const workbook = new ExcelJS.Workbook(); // 创建工作簿
const worksheet = workbook.addWorksheet('周报'); // 添加工作表

// 定义表格的列和宽度
worksheet.columns = [
  { key: 'col1', width: 10 },
  { key: 'col2', width: 15 },
  { key: 'col3', width: 25 },
  { key: 'col4', width: 15 },
  { key: 'col5', width: 40 },
  { key: 'col6', width: 10 },
  { key: 'col7', width: 10 },
  { key: 'col8', width: 20 },
  { key: 'col9', width: 40 },
  { key: 'col10', width: 20 },
  { key: 'col11', width: 40 }
];

// 填写报告头信息,合并单元格并设置样式
worksheet.mergeCells('A1:K1'); // 合并 A1 到 K1
worksheet.getCell('A1').value = `附件:${this.attachmentName}`; // 设置值
worksheet.getCell('A1').alignment = { horizontal: 'center' }; // 居中对齐
worksheet.getCell('A1').font = { size: 15, bold: true }; // 设置字体大小和加粗

worksheet.mergeCells('A2:K2'); // 合并 A2 到 K2
worksheet.getCell('A2').value = `填表人:${this.filler}`; // 设置值
worksheet.getCell('A2').alignment = { horizontal: 'center' }; // 居中对齐
worksheet.getCell('A2').font = { size: 15, bold: true }; // 设置字体大小和加粗

worksheet.mergeCells('A3:K3'); // 合并 A3 到 K3
worksheet.getCell('A3').value = `时间:${this.formatDate(weekStart)}(星期一) - ${this.formatDate(weekEnd)}(星期五)`; // 设置值
worksheet.getCell('A3').alignment = { horizontal: 'center' }; // 居中对齐
worksheet.getCell('A3').font = { size: 15, bold: true }; // 设置字体大小和加粗

// 设置前3行的行高
worksheet.getRow(1).height = 30; // 第1行高度
worksheet.getRow(2).height = 30; // 第2行高度
worksheet.getRow(3).height = 30; // 第3行高度

// 添加本周工作计划完成情况的标题,合并单元格并设置样式
worksheet.mergeCells('A4:K4'); // 合并 A4 到 K4
worksheet.getCell('A4').value = '本周工作计划完成情况'; // 设置值
worksheet.getCell('A4').alignment = { horizontal: 'center' }; // 居中对齐
worksheet.getCell('A4').font = { size: 13, bold: true }; // 设置字体大小和加粗

// 设置第4行的行高
worksheet.getRow(4).height = 35; // 第4行高度

// 定义本周表头
const headers = [
  '序号', '项目类型', '项目', '节点', '工作事项', '事项编号',
  '是否完成', '完成情况', '工作标准', '是否需要协调', '备注'
];

// 填写表头,并设置样式
const headerRow = worksheet.addRow(headers); // 添加表头行
headerRow.eachCell((cell) => {
  cell.font = { bold: true }; // 加粗字体
  cell.alignment = { horizontal: 'center', vertical: 'middle' }; // 居中对齐
  cell.border = { // 设置边框样式
    top: { style: 'thin' },
    left: { style: 'thin' },
    bottom: { style: 'thin' },
    right: { style: 'thin' }
  };
});

// 填写本周的数据
this.workItems.forEach((data, index) => {
  const row = worksheet.addRow([
    index + 1, // 序号
    data.project_type_id, // 项目类型
    data.project_id, // 项目
    data.project_nodes_id, // 节点
    data.work_item_name, // 工作事项
    data.work_item_code, // 事项编号
    data.is_completed, // 是否完成
    data.completion_status, // 完成情况
    data.work_standards, // 工作标准
    data.is_coordinate, // 是否需要协调
    data.remarks // 备注
  ]);

  // 设置每个单元格的样式
  row.eachCell((cell) => {
    cell.alignment = { vertical: 'middle', horizontal: 'left' }; // 垂直居中,水平左对齐
    cell.border = { // 设置边框样式
      top: { style: 'thin' },
      left: { style: 'thin' },
      bottom: { style: 'thin' },
      right: { style: 'thin' }
    };
  });
});

// 在表格中添加一个空行
worksheet.addRow([]);
// 获取下一行的行号,用于添加下周工作计划标题
const planRowNumber = worksheet.lastRow.number + 1;
// 合并单元格以添加下周工作计划的标题
worksheet.mergeCells(`A${planRowNumber}:K${planRowNumber}`);
const planRow = worksheet.getCell(`A${planRowNumber}`);
planRow.value = '下周工作计划'; // 设置标题
planRow.font = { size:13, bold: true }; // 设置字体大小和加粗
planRow.alignment = { horizontal: 'center' }; // 居中对齐
worksheet.getRow(planRowNumber).height = 35; // 设置行高

// 定义下周工作计划的表头
const nextHeaders = [
  '序号', '项目类型', '项目', '节点', '工作事项', '事项编号',
  '工作标准', '是否需要协调', '备注'
];

// 填写下周工作计划的表头,并设置样式
const nextHeaderRow = worksheet.addRow(nextHeaders); // 添加表头行
nextHeaderRow.eachCell((cell) => {
  cell.font = { bold: true }; // 加粗字体
  cell.alignment = { horizontal: 'center', vertical: 'middle' }; // 居中对齐
  cell.border = { // 设置边框样式
    top: { style: 'thin' },
    left: { style: 'thin' },
    bottom: { style: 'thin' },
    right: { style: 'thin' }
  };
});

// 渲染下周的数据
nextWeekItems.forEach((data, index) => {
  const row = worksheet.addRow([
    index + 1, // 序号
    projectTypeMapping[data.project_type_id] || '未知', // 项目类型
    projectMapping[data.project_id] || '未知', // 项目
    nodeMapping[data.project_nodes_id] || '未知', // 节点
    data.work_item_name, // 工作事项
    data.work_item_code, // 事项编号
    data.work_standards, // 工作标准
    data.is_coordinate ? '是' : '否', // 是否需要协调
    data.remarks // 备注
  ]);

  // 设置每个单元格的样式
  row.eachCell((cell) => {
    cell.alignment = { vertical: 'middle', horizontal: 'left' }; // 垂直居中,水平左对齐
    cell.border = { // 设置边框样式
      top: { style: 'thin' },
      left: { style: 'thin' },
      bottom: { style: 'thin' },
      right: { style: 'thin' }
    };
  });
});

// 根据需求,合并特定列的单元格
await this.mergeCells(worksheet, this.workItems, ['project_type_id'], 'project_type_id', 6);
await this.mergeCells(worksheet, this.workItems, ['project_type_id', 'project_id'], 'project_id', 6);
await this.mergeCells(worksheet, this.workItems, ['project_type_id', 'project_id', 'project_nodes_id'], 'project_nodes_id', 6);

// 设置冻结窗格,使表头固定
worksheet.views = [
  {
    state: 'frozen', // 窗格冻结
    ySplit: 5, // 在第5行下方冻结
    activeCell: 'A6', // 激活单元格
    showGridLines: true // 显示网格线
  }
];

// 再次设置行高,以确保所有内容添加完成后行高是正确的
worksheet.getRow(1).height = 30; // 第1行高度
worksheet.getRow(2).height = 25; // 第2行高度
worksheet.getRow(3).height = 25; // 第3行高度
worksheet.getRow(4).height = 35; // 第4行高度
worksheet.getRow(planRowNumber).height = 35; // “下周工作计划”行高度

// 将工作簿转换为缓冲区
this.excelBuffer = await workbook.xlsx.writeBuffer();
// 设置文件名,包含附件名称和周日期
this.excelFileName = `${this.attachmentName}_${this.weekDate}.xlsx`;

// 提示用户生成成功
alert('生成周报成功');

} catch (error) {
console.error(‘获取数据失败:’, error); // 打印错误信息
alert(‘获取数据失败’); // 提示用户
}
},
关键步骤解析:
1.数据获取与过滤:通过调用 projectWorkItemsList 函数获取工作事项数据,并根据选定的日期范围过滤出本周的数据。

2.数据映射:将原始数据映射到更具可读性的字段,如将 project_type_id 转换为项目类型名称。

3.创建工作簿与工作表:使用 ExcelJS.Workbook 创建一个新的 Excel 工作簿,并添加一个名为“周报”的工作表。

4.设置列宽:通过 worksheet.columns 定义每一列的宽度。

5.添加报告头:使用 mergeCells 合并单元格并设置报告标题、填表人和时间范围。

6.添加表头:定义表头数组并使用 addRow 方法添加到工作表中,同时设置样式(如加粗、居中、边框)。

7.填写数据:遍历工作事项数据,添加每一行到工作表,并设置单元格的样式。

8.添加下周工作计划:类似地,添加下周工作计划的标题和表头,并填写相关数据。

9.合并单元格:根据需要合并特定列的单元格,以提升表格的可读性。

10.冻结窗格:通过设置 worksheet.views 来冻结表头,使其在滚动时保持可见。

11.生成缓冲区与文件名:使用 workbook.xlsx.writeBuffer() 将工作簿转换为缓冲区,并设置文件名。

6. 下载与查看 Excel 文件
a. 下载 Excel 文件
通过 FileSaver 库,将生成的缓冲区保存为文件:

javascript
downloadExcel() {
// 检查是否已生成 Excel 文件
if (!this.excelBuffer || !this.excelFileName) {
alert(‘请先生成周报’);
return;
}

// 创建 Blob 对象
const blob = new Blob([this.excelBuffer], { type: ‘application/octet-stream’ });
// 使用 file-saver 保存文件
saveAs(blob, this.excelFileName);
},
b. 查看 Excel 文件 !!!! (在页面上渲染)
使用 vue-office-excel 组件在页面中预览生成的 Excel 文件:

javascript
viewExcel() {
// 检查是否已生成 Excel 文件
if (!this.excelBuffer) {
alert(‘请先生成周报’);
return;
}

// 创建 Blob 对象
const blob = new Blob([this.excelBuffer], { type: ‘application/octet-stream’ });
// 创建预览 URL
this.previewUrl = URL.createObjectURL(blob);
// 设置预览类型
this.previewType = ‘.xlsx’;
}
在模板部分,使用 vue-office-excel 组件进行预览:

(其实这个很简单 但是我呢花费了好久才找到这个组件)

#完整代码

    <!-- 填表人的标签和输入框 -->
    <label for="filler">输入填表人:</label>
    <input type="text" id="filler" v-model="filler">

    <!-- 选择当周日期的标签和日期选择器 -->
    <label for="weekDate">选择当周日期:</label>
    <input type="date" id="weekDate" v-model="weekDate" :min="minDate" :max="maxDate">
  </div>
  <!-- 生成周报的按钮,点击时调用 generateExcel 方法 -->
  <button @click="generateExcel" class="generate-button">生成周报</button>
</div>

<!-- 表单的第二行:下载和查看按钮 -->
<div class="button-row">
  <!-- 下载按钮,点击时调用 downloadExcel 方法 -->
  <button @click="downloadExcel" class="action-button">下载</button>
  <!-- 查看按钮,点击时调用 viewExcel 方法 -->
  <button @click="viewExcel" class="action-button">查看</button>
</div>

<!-- 使用 VueOfficeExcel 组件来预览生成的 Excel 文件,仅在 previewType 为 '.xlsx' 时显示 -->
<vue-office-excel :src="previewUrl" style="height: 100vh;" v-if="previewType === '.xlsx'" />

效果图
在这里插入图片描述
这个文章可能有点长 按需查看就可以 最长的是生成excel表 因为涉及到了很多逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值