1.前言
有时候项目中需要预览Excel文件,特别是对于.xls格式的Excel文件许多插件都不支持,经过尝试,最终有三种方案可以实现.xlsx和.xls格式的Excel文件的预览,各有优缺点
2.luckyexcel插件
2.1说明
该插件优点在于能保留源文件的样式和保留图片,缺点在于只支持.xlsx,无法编辑更改(可能是我没有去查找资料),适用于需要保留样式只用于预览不用于编辑的场景
2.2使用过程
2.2.1安装
npm install luckyexcel
2.2.2引入
引入方式有两种
(1)使用CDN引入
<script src="https://cdn.jsdelivr.net/npm/luckyexcel/dist/luckyexcel.umd.js"></script>
这个路径意思是会拉取到最新的luckysheet代码,但是如果Luckysheet刚刚发布,jsdelivr网站可能还没来得及从npm上同步过去,故而使用这个路径还是会拉到上一个版本,我们推荐您直接指定版本。
<script src="https://cdn.jsdelivr.net/npm/luckysheet@2.1.12/dist/luckysheet.umd.js"></script>
(2)本地静态文件方式引入
先从luckyexcel项目中获静态资源用https://gitcode.com/gh_mirrors/lu/Luckyexcel
在public文件夹中新建luckyexcel文件夹,将静态资源全部放入该文件夹中
两种引入方式前提都已说明,下面开始引入
在项目入口文件index.html中引入
// 实用CDN方式引入-拉取最新代码
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css' />
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>
<title>kanno</title>
</head>
// 使用静态文件方式引入
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico">
<link rel='stylesheet' href='/luckyexcel/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='/luckyexcel/plugins/plugins.css' />
<link rel='stylesheet' href='/luckyexcel/css/luckysheet.css' />
<link rel='stylesheet' href='/luckyexcel/assets/iconfont/iconfont.css' />
<script src="/luckyexcel/plugins/js/plugin.js"></script>
<script src="/luckyexcel/luckysheet.umd.js"></script>
<title>kanno</title>
</head>
2.2.3使用
<template>
<div id="luckysheet" ref="luckysheet" style="width:100%;height:100%;position: absolute;left: 0;top: 0;z-index: 0;" ></div>
</template>
<script setup>
import LuckyExcel from 'luckyexcel'
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue';
const props = defineProps({
excelUrl: {
default:'',
type: String
}
});
// const emit = defineEmits([]);
let { excelUrl } = toRefs(props)
onMounted(()=>{
viewOpen('Excel文件')
})
async function viewOpen(fileName) {
const data = await fetchBlob(excelUrl.value);
console.log("excelUrl.value",excelUrl.value);
if (!data) {
console.log("无法获取文件数据");
return;
}
LuckyExcel.transformExcelToLucky(data, function (exportJson, luckysheetfile) {
if (!exportJson || exportJson.sheets == null || exportJson.sheets.length == 0) {
console.log("出错了");
return;
}
if (window.luckysheet) {
window.luckysheet.destroy();
}
window.luckysheet.create({
data: exportJson.sheets,
title: fileName,
userInfo: exportJson.info?.creator,
container: 'luckysheet', // 设定DOM容器的id
showtoolbar: false, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showstatisticBar: false, // 是否显示底部计数栏
sheetBottomConfig: false, // sheet页下方的添加行按钮和回到顶部按钮配置
allowEdit: false, // 是否允许前台编辑
enableAddRow: false, // 是否允许增加行
enableAddCol: false, // 是否允许增加列
sheetFormulaBar: false, // 是否显示公式栏
enableAddBackTop: false, // 返回头部按钮
showsheetbar: false, // 是否显示底部sheet页按钮
showsheetbarConfig: {
add: false,
menu: false
}
});
});
}
async function fetchBlob(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error("Network response was not ok.");
return await response.blob();
} catch (error) {
console.error("Failed to fetch blob:", error);
return null;
}
}
</script>
2.2.4效果
3.微软在线查看excel文件
3.1说明
微软在线查看excel是使用iframe嵌入微软查看的页面,有点在于开发简单,能支持.xlsx和.xls格式,缺点在于无法编辑(可能通过注册微软账号可以进行编辑)和限制文件大小在5M以下,需要文件能通过链接访问,适用于小文件查看
3.2使用
<iframe id="iframeId" scrolling="no" frameborder="0" width="100%" height="118%"
style="margin-top: -80px;"></iframe>
let iframeId = document.getElementById('iframeId')
iframeId.src = `https://view.officeapps.live.com/op/view.aspx?src=` + encodeURIComponent(data.data.fileUrl) // 微软网页
3.3代码说明
Your request has been blocked. This could be due to several reasons.是微软用来在线查看excel文件的网页;encodeURIComponent()方法是用来解析文件地址,无需引入
3.4效果展示
4.使用XLSX插件
4.1说明
XLSX支持.xlsx和.xls格式的Excel文件的预览,能通过js方法来更改excel表格,可操作性好,缺点在于不能保留源文件样式、渲染出来的表格和源文件有出入,适用于简单表格文件的预览
4.2安装
npm install xlsx
4.3引入使用
<template>
<div :id="'excelDom'+id" style="width: 100%;height: 100%;overflow: auto;"></div>
</template>
<script setup>
import * as XLSX from "xlsx";
import axios from "axios";
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue';
const props = defineProps({
excelUrl: {
default: '',
type: String
},
id:{
default: 1,
type: Number
}
});
// const emit = defineEmits([]);
let { excelUrl,id } = toRefs(props)
// Excel显示
getFileObjectFromUrl(excelUrl.value, function (file) {
loadExcelAndRender(file);
});
function getFileObjectFromUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob'; // 重要:设置响应类型为blob
xhr.onload = function () {
if (this.status === 200) {
// 请求成功,this.response包含Blob对象
var blob = this.response;
let fileName = new Date().getTime()
// 创建File对象
var file = new File([blob], fileName + '.xlsx', { type: blob.type });
// 调用回调函数,传入File对象
callback(file);
} else {
console.error('Failed to download file:', this.status);
}
};
xhr.onerror = function () {
console.error('Request error');
};
xhr.send();
}
async function loadExcelAndRender(file) {
try {
const reader = new FileReader();
reader.onload = function (e) {
let excelDom = document.getElementById('excelDom'+id.value);
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: 'array' });
const firstSheetName = workbook.SheetNames[0]; // 获取第一个sheet的名称
const worksheet = workbook.Sheets[firstSheetName];
const html = XLSX.utils.sheet_to_html(worksheet, { id: firstSheetName }); // 只渲染第一个sheet
excelDom.innerHTML = html; // 将HTML渲染到指定的div中
// 动态添加细线表格样式
const table = excelDom.querySelector('table');
if (table) {
// 设置表格整体样式
table.style.borderCollapse = 'collapse'; // 合并边框
table.style.width = '100%'; // 宽度占满容器
table.style.fontSize = '12px'; // 字体大小
table.style.lineHeight = '1.5'; // 行高
table.style.textAlign = 'center'; // 文字居中
table.style.border = '1px solid #ddd'; // 外边框细线
// 设置表头样式
const thead = table.querySelector('tr');
if (thead) {
thead.style.backgroundColor = '#f2f2f2'; // 表头背景颜色
thead.style.fontWeight = 'bold'; // 表头字体加粗
thead.style.whiteSpace = 'nowrap'; // 防止内容换行,确保宽度自适应
}
// 设置单元格样式
const cells = table.querySelectorAll('td, th');
cells.forEach(cell => {
cell.style.border = '1px solid #ddd'; // 细线边框
cell.style.padding = '5px'; // 内边距
});
// 为所有非表头的 td 添加点击事件
const tds = table.querySelectorAll('tbody td'); // 获取 tbody 中的 td
tds.forEach((td) => {
td.addEventListener('click', () => {
// 清除所有单元格的背景色
tds.forEach(cell => {
cell.style.backgroundColor = ''; // 清除背景色
});
// 为当前点击的单元格设置背景色
td.style.backgroundColor = '#cfe2ff'; // 设置背景色为浅蓝色
// 计算行号和列号
const row = td.parentNode.rowIndex; // 获取行号(从 0 开始)
const col = td.cellIndex; // 获取列号(从 0 开始)
});
});
}
};
reader.readAsArrayBuffer(file);
} catch (error) {
console.error('Error loading or rendering Excel:', error);
}
}
</script>