浏览器H5中渲染excel/xlsx文件
本文主要使用 [SheetJS](Overview | SheetJS Community Edition)来实现在web浏览器公众号H5等页面中实现预览excel的功能。
1. 安装使用SheetJS
-
通过cdn网络引入sheetjs
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js"></script>
-
把js文件下载到项目本地调用
把cdn或者npm中对应js代码保存的项目本地然后调用。
-
npm/yarn安装。[npm地址](xlsx - npm (npmjs.com))
yarn add https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz npm install xlsx
2. 页面展示
-
把oss或者服务器上获取的表格文件转换成json格式,然后用json数据在页面渲染出来效果,可以自定义表格样式。推荐使用该方式
-
web浏览器原生html实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Excel xlsx</title> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js"></script> <style> #app { width: 100%; height: 100%; border: 1px solid red; } </style> </head> <body> <table id="table-container" border="1"></table> <script> window.onload = async () => { const filePath = 'https://oss.xxxxx/demo-slxs.xlsx' // xlsx链接地址 const wb = XLSX.read(await (await fetch(filePath)).arrayBuffer()) const ws = wb.Sheets[wb.SheetNames[0]] const data = XLSX.utils.sheet_to_json(ws, {header: 1}) /** * 解析出的data中第一行[index === 0]是table header 下的是对应每一行的数据。 * 得到json格式的数据后,可以根据自己工程使用的技术框架选择如何渲染表格 * 这里使用原生html拼接生成table */ const tableEl = document.getElementById('table-container') let theaderContent = '' data[0].forEach(headItem => { // index = 0 是表头信息 theaderContent += `<th>${headItem}</th>` }) let tableRowContent = '' data.forEach((row,index) => { if (index !== 0) { let currRow = `<tr>` row.forEach(rowItem => { currRow += `<td>${rowItem}</td>` }) currRow += `</tr>` tableRowContent += currRow } }) tableEl.innerHTML = `<table> <thead><tr>${theaderContent}</tr></thead> <tbody>${tableRowContent}</tbody> </table>` } </script> </body> </html>
-
-
VUE项目中实现。需要npm安装sheetjs。
<script setup lang="ts"> import { read, utils } from 'xlsx' import { ref, onMounted } from 'vue' const tableData = ref([]) const tableHead = ref([]) onMounted(() => { InitTableData() }) const InitTableData = async () => { const filePath = 'https://oss.xxxx/demo-slxs.xlsx' // 表格链接地址 const wb:any = read(await (await fetch(filePath)).arrayBuffer()) const ws = wb.Sheets[wb.SheetNames[0]] const data:any = utils.sheet_to_json(ws, {header: 1}) /** * 解析出的data中第一行[index === 0]是table header 下的是对应每一行的数据。 * 得到json格式的数据后,可以根据自己工程使用的技术框架选择如何渲染表格 * 这里使用原生vue3+elementPlus-table生成table */ tableHead.value = data[0] data.forEach((row:any, index:number) => { if (index !== 0) { // 第一行是表头信息 const tmp:any = {} row.forEach((item:any, i:number) => { tmp[data[0][i]] = item || '-' }) tableData.value.push(tmp) } }) } </script> <template> <el-table :data="tableData" style="width: 100%; height: 600px;"> <el-table-column v-for="item in tableHead" :prop="item" :label="item" :key="item" /> </el-table> </template>
-
uniapp H5中实现(如果是小程序或者app等可以使用 uniapp原生uni.openDocument(object)方法实现)
<template> <view class="xlsx-container"> <zb-table border :show-header="true" :columns="tableColumns" :stripe="true" :fit="true" :data="tableData"></zb-table> </view> </template> <script> /** * 在页面渲染xlsx文件,使用sheetjs来做。 还可以调用微软的链接地址进行渲染xlsx。 * 本组件有两种渲染方式heetjs。 开源可以npm下载源码方式。 * npm i --save https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz * 1. 把拿到的xlsx文件直接使用 sheet_to_html 来渲染,样式默认,不好看。 * 2. 先把拿到xlsx文件解析成js识别的 json 格式的数据,然后使用 ui 的table相关组件进行渲染。 * 推荐使用第2种方式。调用了uniapp 插件市场的 zb-table。 * 需要接收的参数是 xlsx 文件的oss的链接地址。 */ import { read, utils } from 'xlsx' import zbTable from 'uni_modules/components/zb-table/components/zb-table/zb-table.vue' export default { name: 'scanXlsx', props: { filePath: { type: String, default: '', required: true } }, data () { return { tableColumns: [], tableData: [] } }, components: { zbTable }, mounted () { this.initViewer() }, methods: { async initViewer () { const filePath ='https://oss.xxxxx/demo-slxs.xlsx' let wb = null try { read(await (await fetch(filePath)).arrayBuffer()) } catch (error) { uni.showToast({ title: '预览失败!', icon: 'none', mask: true }) } if (wb) { const ws = wb.Sheets[wb.SheetNames[0]] // 把数据解析成json然后再渲染 const data = utils.sheet_to_json(ws, {header: 1}) // data数据是json数据,第一行是表头数据 if (data && data.length > 1) { data.forEach((row, index) => { if (index === 0) { this.tableColumns = row.map((th, index) => ({label: th, name: `prop${index}`})) } else { const tmp = {} row.forEach((td, index) => { tmp[`prop${index}`] = td || '-' }) this.tableData.push(tmp) } }) } } // 使用sheet_to_html直接渲染table,样式不好看 /* const viewer = document.getElementById('xlsx-container') viewer.innerHTML = utils.sheet_to_html(ws) */ } } } </script> <style scoped> .xlsx-container { width: 100%; height: 100%; overflow: scroll; } </style>
- 其他平台遇见再更新
-
把oss或者服务器返回的数据转成 arrayBuffer 文件格式,然后使用sheetjs的sheet_to_html方法渲染在web浏览器页面上。
-
web浏览器原生html实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Excel xlsx</title> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js"></script> <style> #app { width: 100%; height: 100%; border: 1px solid red; } </style> </head> <body> <table id="table-container" border="1"></table> <script> window.onload = async () => { const filePath = 'https://prod-any-image.oss-cn-shenzhen.aliyuncs.com/bigscreen/project/bjl4/lines-json/demo-slxs.xlsx' const wb = XLSX.read(await (await fetch(filePath)).arrayBuffer()) const ws = wb.Sheets[wb.SheetNames[0]] const output = document.getElementById('table-container') output.innerHTML = XLSX.utils.sheet_to_html(ws) } </script> </body> </html>
-
VUE项目中实现。需要npm安装sheetjs。
<script setup lang="ts"> import { read, utils } from 'xlsx' import { ref, onMounted } from 'vue' onMounted(() => {InitTableData()}) const InitTableData = async () => { const filePath = 'https://osss.xxxxxxxxx/demo-slxs.xlsx' // 表格链接地址 const wb:any = read(await (await fetch(filePath)).arrayBuffer()) const ws = wb.Sheets[wb.SheetNames[0]] /** * 使用 sheet_to_html 渲染原生table的样式 */ const output:any = document.getElementById('table-container') output.innerHTML = utils.sheet_to_html(ws) } </script> <template> <table id="table-container" border="1"></table> </template>
-