前端excel文件处理,vue2 、file-saver、xlsx, excel文件生成与excel文件链接数据导出

文章介绍了如何在前端生成并下载Excel文件,包括使用file-saver库处理文件流下载,axios获取本地文件并下载,以及通过xlsx库进行列宽自适应的Excel生成。同时提供了数据下载和远程Excel文件读取的示例代码。

1、前端excel文件生成

安装插件

npm install file-saver --save
如使用TS开发,可安装file-saver的TypeScript类型定义
npm install @types/file-saver --save-dev
下载文件流
import { saveAs } from 'file-saver'
/**
 *
 * @param {*} fileStream // 文件流
 * @param {*} saveFileName // 文件下载名称
 * @returns
 */
export const downloadFile = (fileStream, saveFileName = '.xlsx') => {
  return new Promise((resolve, reject) => {
    const blob = new Blob([fileStream])
    // 兼容IE
    if (navigator.msSaveBlob) {
      navigator.msSaveBlob(blob, saveFileName)
    } else {
      const url = window.URL.createObjectURL(blob)
      saveAs(url, saveFileName + '.xlsx')
    }
    resolve()
  })
}
/**
 * @description 方法调用
 */
downloadFile(fileStream, saveFileName).then(res => {
  console.log('下载成功!')
})
本地文件下载
import { saveAs } from 'file-saver'
/**
 *
 * @param {*} localFileUrl 本地地址
 * @param {*} saveFileName 文件名称
 * @returns
 */
export const downloadFile = (localFileUrl, saveFileName) => {
  return new Promise((resolve, reject) => {
    axios({
      url: localFileUrl, // 文件地址
      method: 'get',
      responseType: 'blob'
    })
      .then(res => {
        const blob = new Blob([res.data])
        if (navigator.msSaveBlob) {
          navigator.msSaveBlob(blob, saveFileName)
        } else {
          const url = window.URL.createObjectURL(blob)
          saveAs(url, saveFileName)
        }
        resolve()
      })
      .catch(err => {
        if (err.message === 'Request failed with status code 404') {
          // 未找到相关文件
        } else {
          // 下载失败
        }
        reject(err)
      })
  })
}

/**
 * @description 方法调用
 */
downloadFile(localFileUrl, saveFileName).then(res => {
  console.log('下载成功!')
})
文件下载(列宽自适应)
import fs from 'file-saver'
import XLSX from 'xlsx'
export function xlsxGenerate(json, fields, filename = '.xlsx') {
  json.forEach(item => {
    for (let i in item) {
      if (fields.hasOwnProperty(i)) {
        item[fields[i]] = item[i]
      }
      delete item[i]
    }
  })
  let sheetName = filename
  let wb = XLSX.utils.book_new()
  let ws = XLSX.utils.json_to_sheet(json, {
    header: Object.values(fields)
  })
  const defaultCellStyle = {
    font: {
      name: 'Verdana',
      sz: 16,
      color: 'FF00FF88'
    },
    alignment: {
      horizontal: 'center',
      vertical: 'center'
    },
    fill: {
      fgColor: {
        rgb: 'FFFFAA00'
      }
    }
  }
  let headsArr = Object.values(fields)
  const headsWidth = headsArr.map(value => {
    if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
      return parseFloat(value.toString().length * 2.1)
    } else {
      return parseFloat(value.toString().length * 1.1)
    }
  })
  // console.log("所有表头的宽度:", headsWidth);
  // 2.所有表体值的宽度
  json.unshift(fields)
  const rowsWidth = json.map(item => {
    const maxValue = Object.values(item).map((value, index) => {
      let valueWidth
      if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
        valueWidth = parseFloat(value.toString().length * 2.1)
      } else {
        valueWidth = parseFloat(value.toString().length * 1.1)
      }
      return Math.max(valueWidth, headsWidth[index])
    })
    return maxValue
  })
  // console.log("每行数据对比出的最大宽度:", rowsWidth)
  // 3.对比每列最大值
  let aotuWidth = []
  rowsWidth.map((row, index) => {
    let maxWidth = []
    row.map((value, i) => {
      if (index === 0) {
        maxWidth.push({
          wch: value
        })
      } else {
        maxWidth.push({
          wch: Math.max(value, aotuWidth[i].wch)
        })
      }
    })
    aotuWidth = maxWidth
  })
  // ws["!rows"] // 杭高
  ws['!cols'] = aotuWidth // 列宽

  wb.SheetNames.push(sheetName)
  wb.Sheets[sheetName] = ws
  let wopts = {
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary',
    cellStyles: true,
    defaultCellStyle: defaultCellStyle,
    showGridLines: false
  }
  let wbout = XLSX.write(wb, wopts)
  let blob = new Blob([s2ab(wbout)], {
    type: 'application/octet-stream'
  })
  fs.saveAs(blob, filename + '.xlsx')
}
/**
 * 数据下载
 * @param {*} header 表头
 * @param {*} tableData 数据
 */
dataDownload() {
  let headerArr = ['Name', 'Age', 'Address']
  let header = {
    title0: 'Name',
    title1: 'Age',
    title2: 'Address'
  }
  let tableData = [
    {
      Name: '喜洋洋',
      Age: '108',
      Address: '青青草原-羊村-2幢'
    },
    {
      Name: '美羊羊',
      Age: '108',
      Address: '青青草原-羊村-1幢'
    }
  ]
  let tableDataList = []
  tableData.forEach((item, index) => {
    let obj = {}
    for (let i = 0; i < headerArr.length; i++) {
      if (i === 0) {
        obj['title0'] = item.Name
      } else if (i === 1) {
        obj['title1'] = item.Age
      } else if (i === 2) {
        obj['title2'] = item.Address
      }
    }
    tableDataList.push(obj)
  })
  xlsxGenerate(tableDataList, header, '羊村登记表')
}

在这里插入图片描述表格显示,每列列宽自适应

xlsx文件链接数据导出
import fs from 'file-saver'
import XLSX from 'xlsx'
export function readWorkbookFromRemoteFile(url, callback) {
  var xhr = new XMLHttpRequest()
  xhr.open('get', url, true)
  xhr.responseType = 'arraybuffer'
  xhr.onload = function(e) {
    if (xhr.status == 200) {
      var tableData = new Uint8Array(xhr.response)
      var workbook = XLSX.read(tableData, { type: 'array' }) // 该方法接收一个二进制的数据,和数据的类型,返回解析完成后的对象
      if (callback) callback(workbook)
    }
  }
  xhr.send()
}
export function readWorkbook(workbook) {
  let sheetNames = workbook.SheetNames // 工作表名称集合
  let worksheet = workbook.Sheets[sheetNames[0]] // 这里我们只读取第一张sheet
  let csv = XLSX.utils.sheet_to_csv(worksheet)
  return csv2table(csv)
}
// 将csv转换成简单的表格,会忽略单元格合并,在第一行和第一列追加类似excel的索引
export function csv2table(csv) {
  let arrs = []
  let rows = csv.split('\n')
  let first_rows = rows.shift().split(',') // 第一行没用的
  rows.pop() // 最后一行没用的
  rows.forEach(function(row, idx) {
    let columns = row.split(',')
    let obj = {}
    columns.forEach(function(col, idx) {
      obj[first_rows[idx]] = col
    })
    arrs.push(obj)
  })
  return { first_rows, arrs }
}

方法调用

let urlNew = url.replace(/http:/, 'https:') // url xlsx文件链接,转https
readWorkbookFromRemoteFile(
  urlNew,
  workbook => {
    let param = readWorkbook(workbook)
    param.arrs // 表格数据
    param.first_rows // 表头
  }
)
<think>我们正在讨论Vue2中使用file-saver实现Excel导出,并询问是否支持压缩。根据提供的引用,file-saver主要用于保存文件,它本身并不提供压缩功能。引用中提到的例子是保存文本文件,并没有涉及压缩。 但是,我们可以考虑在生成Excel文件时先进行压缩,然后再用file-saver保存。常见的做法是使用JSZip等压缩库将文件压缩后再保存。 因此,回答应该包括: 1. file-saver本身不支持压缩,它仅用于保存文件2. 但我们可以结合其他库(如JSZip)先压缩再保存。 同时,为了帮助用户,我们可以给出一个简单的实现思路。 另外,用户提到的是Excel文件,所以还需要考虑如何生成Excel文件。通常,我们会使用如SheetJS(xlsx)库来生成Excel文件,然后使用JSZip压缩,最后用file-saver保存。 步骤: 1. 使用xlsx生成Excel工作簿(workbook) 2. 将工作簿转换为二进制数据(例如,使用xlsx.write(wb, {bookType:'xlsx', type:'array'})) 3. 使用JSZip创建一个压缩包,将Excel二进制数据作为文件添加到压缩包中 4. 使用JSZip生成压缩包(生成一个blob) 5. 使用file-saver保存这个blob 注意:由于我们是在前端进行压缩,对于非常大的文件可能会影响性能,但一般中小型文件是可以的。 因此,我们可以这样回答: 在Vue2中,file-saver本身不提供文件压缩功能,但可以结合JSZip等压缩库实现。以下是实现步骤: 1. 安装依赖: ```bash npm install file-saver jszip xlsx ``` 2. 在Vue组件中使用: ```javascript import FileSaver from 'file-saver'; import JSZip from 'jszip'; import * as XLSX from 'xlsx'; // 假设我们有一个数据数组需要导出Excel并压缩 export default { methods: { exportCompressedExcel() { // 创建工作簿 const wb = XLSX.utils.book_new(); // 假设data是要导出数据数组 const data = [['姓名', '年龄'], ['张三', 20], ['李四', 22]]; const ws = XLSX.utils.aoa_to_sheet(data); XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); // 将工作簿转换为二进制数组 const wbOut = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); // 创建JSZip实例 const zip = new JSZip(); // 将Excel数据添加到zip中,文件名为'data.xlsx' zip.file('data.xlsx', wbOut, { binary: true }); // 生成zip文件 zip.generateAsync({ type: 'blob' }).then(function(content) { // 使用file-saver保存压缩文件 FileSaver.saveAs(content, 'export.zip'); }); } } } ``` 这样,我们就实现了将Excel文件压缩后导出。 注意:如果不需要压缩,可以直接用file-saver保存Excel文件,但这里我们通过JSZip实现了压缩。 另外,如果用户希望压缩多个文件,也可以将多个文件添加到同一个zip中。 因此,回答用户的问题:file-saver本身不支持压缩,但可以通过配合JSZip等库来实现压缩。 生成相关问题: 1. 如何在不压缩的情况下使用file-saver导出Excel文件2. 使用JSZip压缩大文件时如何避免页面卡顿? 3. 除了JSZip,还有哪些前端压缩库可以使用? 4. 如何将多个Excel文件压缩成一个压缩包?</think>在 Vue2 中实现 Excel 导出功能时,**`file-saver` 本身不支持文件压缩**。它是一个专注于文件保存的轻量级库,核心功能是将 Blob/File 对象保存到客户端,不包含任何压缩逻辑。 ### 解决方案 要实现压缩功能,需结合其他库: 1. **生成 Excel 文件**:使用 `xlsx` 或 `exceljs` 库 2. **压缩文件**:使用 `JSZip` 等压缩库 3. **保存文件**:使用 `file-saver` 保存压缩后的结果 ### 实现示例 ```javascript import FileSaver from 'file-saver'; import JSZip from 'jszip'; import * as XLSX from 'xlsx'; // 1. 创建Excel数据 const data = [["姓名", "年龄"], ["张三", 25], ["李四", 30]]; const ws = XLSX.utils.aoa_to_sheet(data); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); // 2. 生成Excel二进制 const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); // 3. 使用JSZip压缩 const zip = new JSZip(); zip.file("data.xlsx", excelBuffer, { binary: true }); // 4. 生成压缩包并保存 zip.generateAsync({ type: 'blob' }).then(zipContent => { FileSaver.saveAs(zipContent, "compressed-export.zip"); // 保存压缩文件 }); ``` ### 关键说明 1. **压缩流程**: - 先用 `xlsx` 生成 Excel 二进制数据 - 用 `JSZip` 创建 ZIP 容器并添加 Excel 文件 - 生成压缩后的 Blob 对象 - 通过 `file-saver` 保存 ZIP 文件 2. **性能注意**: - 前端压缩适用于中小型数据(建议 < 10MB) -文件压缩可能导致内存问题,建议分片或后端处理 3. **兼容性**: - 所有现代浏览器均支持此方案 - IE 需额外 polyfill(如 `blob-polyfill`) ### 备选方案 若需更高压缩率: - 后端生成压缩文件(如 Node.js 使用 `compression` 库) - 流式压缩(如 `fflate` 库替代 `JSZip`) > 引用参考:如代码示例所示,`file-saver` 仅用于最终文件保存步骤,其文档也明确说明不包含压缩功能[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值