使用js将json数据导出excel(xls、xlsx、csv),并过滤掉不需要的数据

vue 专栏收录该内容
30 篇文章 1 订阅

首先看一下json数据的格式,这是其中一条的格式我们只需要label中的值和value中的值导出到excel中

[{
	"type": "text",
	"required": true,
	"label": "姓名",
	"className": "form-control",
	"name": "text-1553770509298",
	"value": "xx",
	"subtype": "text"
}, {
	"type": "text",
	"required": true,
	"label": "学号",
	"className": "form-control",
	"name": "text-1553770509302",
	"value": "1e32ed",
	"subtype": "text"
}, {
	"type": "radio-group",
	"required": true,
	"label": "性别",
	"name": "radio-group-1553770509306",
	"values": [{
		"label": "男",
		"value": "1",
		"selected": true
	}, {
		"label": "女",
		"value": "1"
	}]
}, {
	"type": "number",
	"required": true,
	"label": "年龄",
	"className": "form-control",
	"name": "number-1553770509315",
	"value": "21"
}, {
	"type": "date",
	"required": true,
	"label": "出生年月日",
	"className": "form-control",
	"name": "date-1553770509319",
	"value": "2019-03-01"
}, {
	"type": "text",
	"required": true,
	"label": "籍贯",
	"className": "form-control",
	"name": "text-1553770509322",
	"value": "fsd",
	"subtype": "text"
}, {
	"type": "text",
	"required": true,
	"label": "班级",
	"className": "form-control",
	"name": "text-1553770509327",
	"value": "fewf",
	"subtype": "text"
}, {
	"type": "select",
	"required": true,
	"label": "政治面貌",
	"className": "form-control",
	"name": "select-1553770509330",
	"values": [{
		"label": "党员",
		"value": "option-2"
	}, {
		"label": "团员",
		"value": "option-3",
		"selected": true
	}, {
		"label": "群众",
		"value": "option-3"
	}]
}]

 效果图

在开始之前先看下几个excel格式的区别吧

在导出excel的时候有三种格式,应该选哪种格式呢这就看项目需求了,下面说说三个格式的区别

  1. 如果后缀是xls,在2007版本之后的office打开会有提示(xls在wps上打开没有提示)
  2. 如果后缀是xlsx 在2007版本之后的打开没提示但是在2007之前的版本会打不开。
  3. csv是最通用的一种文件格式,它可以非常容易地被导入各种PC表格及数据库中。 此文件,一行即为数据表的一行。生成数据表字段用半角逗号隔开。但是csv不能设置样式。

 首先导出xls格式

export function JSONToExcelConvertor(JSONData, FileName, title, filter, rowlength) {
  if (!JSONData) { return }
  // 转化json为object
  var arrData = typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData

  var excel = '<table>'

  // 设置表头
  var row = '<tr>'

  if (title) {
    // 使用标题项
    for (var i in title) {
      row += "<th align='center'>" + title[i] + '</th>'
    }
  } else {
    // 不使用标题项
    for (var i in arrData[0]) {
      row += "<th align='center'>" + i + '</th>'
    }
  }

  excel += row + '</tr>'
  // 设置数据
  for (var i = 0; i < arrData.length; i++) {
    if (i === arrData.length - 1) {
      var row = '<tr>'
    } else {
      var row = ''
    }
    for (var index in arrData[i]) {
      // 判断是否有过滤行
      if (filter) {
        var value = ''
        if (filter.indexOf(index) === -1) { // 过滤掉符合关键字的数据
          for (var k = 0; k < (arrData.length / rowlength); k++) { // 循环到一个标题长度换一次行,否则数组会在一行
            if (i === rowlength - 1) {
              for (var j = k * rowlength; j < ((k + 1) * rowlength); j++) {
                if (arrData[j].type === 'radio-group' || arrData[j].type === 'checkbox-group' || arrData[j].type === 'select') { // 如果为这三种格式,则他们的值储存在values中
                  var groupLenght = arrData[j].values.length
                  for (var q = 0; q < groupLenght; q++) {
                    if (arrData[j].values[q].selected === true) { // 获取被选中的值
                      value = value + arrData[j].values[q].label
                    }
                  }
                } else {
                  value = arrData[j].value == null ? '' : arrData[j].value
                }
                row += `<td style='mso-number-format:"\@"'>` + value + '</td>'
                value = ''
              }
            }
            excel += row + '</tr>'
            row = ''
          }
        }
      } else {
        var value = arrData[i][index] == null ? '' : arrData[i][index]
        row += "<td align='center'>" + value + '</td>'
      }
    }

    // excel += row + "</tr>";
  }

  excel += '</table>'

  var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>"
  excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'
  excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel'
  excelFile += '; charset=UTF-8">'
  excelFile += '<head>'
  excelFile += '<!--[if gte mso 9]>'
  excelFile += '<xml>'
  excelFile += '<x:ExcelWorkbook>'
  excelFile += '<x:ExcelWorksheets>'
  excelFile += '<x:ExcelWorksheet>'
  excelFile += '<x:Name>'
  excelFile += '工作蒲'
  excelFile += '</x:Name>'
  excelFile += '<x:WorksheetOptions>'
  excelFile += '<x:DisplayGridlines/>'
  excelFile += '</x:WorksheetOptions>'
  excelFile += '</x:ExcelWorksheet>'
  excelFile += '</x:ExcelWorksheets>'
  excelFile += '</x:ExcelWorkbook>'
  excelFile += '</xml>'
  excelFile += '<![endif]-->'
  excelFile += '</head>'
  excelFile += '<body>'
  excelFile += excel
  excelFile += '</body>'
  excelFile += '</html>' 

  var uri = 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(excelFile)

  var link = document.createElement('a')
  link.href = uri

  link.style = 'visibility:hidden'
  link.download = FileName + '.xls'

  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

这个格式其实就是假的excel文件,只是html披了excel的皮而已(不信你把后缀改成html打开试试)

第二种csv格式

export function JSONToExcelConvertor(JSONData, FileName, title, filter, rowlength) {
  if (!JSONData) { return }
  // 转化json为object
  var arrData = typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData
  var tempData = [] // 存放临时数据
  var exportData = [{ // 存放导出的数据
  }]
  let str = ''

  if (title) {
    // 使用标题项
    for (var i in title) {
      str = str + title[i] + ','
    }
  } else {
    // 不使用标题逻辑
  }

  // excel += row + '</tr>'
  // 设置数据
  for (var i = 0; i < arrData.length; i++) {
    for (var index in arrData[i]) {
      // 判断是否有过滤行
      if (filter) {
        var value = ''
        if (filter.indexOf(index) === -1) {
          for (var k = 0; k < (arrData.length / rowlength); k++) {
            if (i === rowlength - 1) {
              for (var j = k * rowlength; j < ((k + 1) * rowlength); j++) {
                if (arrData[j].type === 'radio-group' || arrData[j].type === 'checkbox-group' || arrData[j].type === 'select') {
                  var groupLenght = arrData[j].values.length
                  for (var q = 0; q < groupLenght; q++) {
                    if (arrData[j].values[q].selected === true) {  
                      // 增加\t为了不让表格显示科学计数法或者其他格式
                      tempData = tempData.concat(arrData[j].values[q].label + '\t')
                    }
                  }
                } else {
                  tempData = tempData.concat(arrData[j].value == null ? '' : arrData[j].value + '\t')
                }

              }
            }
            if (tempData.length !== 0) { // 防止把空数据添加到集合
              exportData.push({ 'value': tempData })
            }
            tempData = [] // 重置为空 以免影响下次循环
          }
        }
      } else {
        // 不过滤逻辑  
      }
    }  
  }
  // 列标题,逗号隔开,每一个逗号就是隔开一个单元格
  for (let i = 0; i < exportData.length; i++) {
    for (const item in exportData[i]) {
      // eslint-disable-next-line quotes
      str += `${exportData[i][item]},`
    }
    str += '\n'
  }
  // encodeURIComponent解决中文乱码
  const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str)
  // 通过创建a标签实现
  const link = document.createElement('a')
  link.href = uri
  // 对下载的文件命名
  link.download = FileName + '.csv'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)

}

csv格式是将一个list转换成excel,csv是以一个逗号隔开一个分隔符的,是这三种格式中最简单的一种方法。

最后一种xlsx格式

这种格式需要借助一个插件 js-xlsx。Github地址:https://github.com/SheetJS/js-xlsx

可以使用npm安装(推荐)或者直接通过js引入 

<script lang="javascript" src="dist/xlsx.full.min.js"></script>

 我这里使用的npm 所以在一定行引入了XLSX

import XLSX from 'xlsx'
// JSONData为导出的json数据,fileName为导出的文件名,title为导出的第一行标题,filter为过滤字段,rowLength为标题长度
export function JSONToExcelConvertor(JSONData, FileName, title, filter, rowlength) {
  if (!JSONData) { return }
  // 转化json为object
  var arrData = typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData

  var excel = '<table id="expoetTable">'

  // 设置表头
  var row = '<tr>'
  if (title) {
    // 使用标题项
    for (var i in title) {
      row += "<th align='center'>" + title[i] + '</th>' // 将标题新增到row中
    }
  } else {
    // 不使用标题项
    for (var i in arrData[0]) {
      row += "<th align='center'>" + i + '</th>'
    }
  }

  excel += row + '</tr>'
  // 设置数据
  for (var i = 0; i < arrData.length; i++) {
    if (i === arrData.length - 1) {
      var row = '<tr>'
    } else {
      var row = ''
    }
    for (var index in arrData[i]) {
      // 判断是否有过滤行
      if (filter) {
        var value = ''
        if (filter.indexOf(index) === -1) { // 过滤掉符合关键字的数据
          for (var k = 0; k < (arrData.length / rowlength); k++) { // 循环到一个标题长度换一次行,否则数组会在一行
            if (i === rowlength - 1) {
              for (var j = k * rowlength; j < ((k + 1) * rowlength); j++) {
                if (arrData[j].type === 'radio-group' || arrData[j].type === 'checkbox-group' || arrData[j].type === 'select') { // 如果为这三种格式,则他们的值储存在values中
                  var groupLenght = arrData[j].values.length
                  for (var q = 0; q < groupLenght; q++) {
                    if (arrData[j].values[q].selected === true) { // 获取被选中的值
                      value = value + arrData[j].values[q].label
                    }
                  }
                } else {
                  value = arrData[j].value == null ? '' : arrData[j].value
                }
                row += `<td>` + value + '</td>'
                value = ''
              }
            }
            excel += row + '</tr>'
            row = ''
          }
        }
      } else {
        // 不过滤的逻辑
        // var value = arrData[i][index] == null ? '' : arrData[i][index]
        // // eslint-disable-next-line quotes
        // row += "<td align='center'>" + value + '</td>'
      }
    }
  }

  excel += '</table>'
  var objE = document.createElement('div') // 因为我们这里的数据是string格式的,但是js-xlsx需要dom格式,则先新建一个div然后把数据加入到innerHTML中,在传childNodes[0]即使dom格式的数据
  objE.innerHTML = excel
  var sheet = XLSX.utils.table_to_sheet(objE.childNodes[0], { raw: true })// 将一个table对象转换成一个sheet对象,raw为true的作用是把数字当成string,身份证不转换成科学计数法
  openDownloadDialog(sheet2blob(sheet, FileName), FileName + '.xlsx')
}

// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {
  sheetName = sheetName || 'sheet1' // 不存在sheetName时使用sheet1代替
  var workbook = {
    SheetNames: [sheetName],
    Sheets: {}
  }
  workbook.Sheets[sheetName] = sheet // 生成excel的配置项

  var wopts = {
    bookType: 'xlsx', // 要生成的文件类型
    bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
    type: 'binary' // 二进制格式
  }
  var wbout = XLSX.write(workbook, wopts)
  var blob = new Blob([s2ab(wbout)], {
    type: 'application/octet-stream'
  }) // 字符串转ArrayBuffer
  function s2ab(s) {
    var buf = new ArrayBuffer(s.length)
    var view = new Uint8Array(buf)
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
    return buf
  }
  return blob
}
// 下载的方法
function openDownloadDialog(url, saveName) {
  if (typeof url === 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url) // 创建blob地址
  }
  var aLink = document.createElement('a')
  aLink.href = url
  aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
  var event
  if (window.MouseEvent) event = new MouseEvent('click')
  else {
    event = document.createEvent('MouseEvents')
    event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
  }
  aLink.dispatchEvent(event)
}

这种方法相对复杂,导出的是真正的excel文件,更多用法请参考官方api

  • 0
    点赞
  • 2
    评论
  • 9
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值