vue 中使用spreadJS在线编译excel文档
Vue中使用SpreadJS,并可自定义导入sheet页
目录
1. 安转 以官方最新版 15.1.4为例
npm i @grapecity/spread-excelio@15.1.4
npm i @grapecity/spread-sheets@15.1.4
npm i @grapecity/spread-sheets-barcode@15.1.4
npm i @grapecity/spread-sheets-charts@15.1.4
npm i @grapecity/spread-sheets-designer@15.1.4
npm i @grapecity/spread-sheets-designer-resources-cn@15.1.4
npm i @grapecity/spread-sheets-designer-vue@15.1.4
npm i @grapecity/spread-sheets-languagepackages@15.1.4
npm i @grapecity/spread-sheets-pdf@15.1.4
npm i @grapecity/spread-sheets-pivot-addon@15.1.4
npm i @grapecity/spread-sheets-print@15.1.4
npm i @grapecity/spread-sheets-resources-zh@15.1.4
npm i @grapecity/spread-sheets-shapes@15.1.4
npm i @grapecity/spread-sheets-vue@15.1.4
另外如果不用spreadjs自带的导出 还需安转 file-saver
npm i file-saver
2. 初始化容器
template 部分 需要给容器 宽高
<div class="spreadContainer" >
<!-- 展示的excle表 -->
<div id="gc-designer-container" ref="ssDesigner" style="height:100%; width:100%; text-align: left;"></div>
<!-- 零时备用的excel表 -->
<div id="gc-designer-container-temp" ref="ssDesignerTemp" style="height:100%; width:100%; text-align: left;" v-show="false"></div>
</div>
script 部分
先引入 用不到的自行删除
import * as Excel from '@grapecity/spread-excelio'
import FaverSaver from 'file-saver'
import "@grapecity/spread-sheets-vue"
import "@grapecity/spread-sheets-print";
import "@grapecity/spread-sheets-pdf";
import "@grapecity/spread-sheets-charts";
import '@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css'
import '@grapecity/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css'
import '@grapecity/spread-sheets-resources-zh'
import '@grapecity/spread-sheets-designer-resources-cn'
import GC from '@grapecity/spread-sheets'
import '@grapecity/spread-sheets-designer'
GC.Spread.Common.CultureManager.culture("zh-cn");
初始化容器
data(){
return {
currentExcel: null, //当前excel
designer:null, //speadjs 容器
temp_designer: null, //临时容器
workbook: null, //工作蒲
temp_work: null, //临时工作蒲
mqtt_location: {}, //时时数据展示位置
temp_location: {}, //零时存储位置
}
},
mounted(){
this.spreadInit()
},
methods: {
//初始化
spreadInit(){
//对应容器
this.designer = new GC.Spread.Sheets.Designer.Designer(this.$refs.ssDesigner)
//获取工作薄
this.workbook = this.designer.getWorkbook()
//临时容器
this.temp_designer = new GC.Spread.Sheets.Designer.Designer(this.$refs.ssDesignerTemp)
},
}
如图所示就成功了 上面的一些按钮是在测试功能时添加的 到这一步说明已经配置全部ok
3. 基础相关功能
1. 导入及自定义选择展示sheet页功能 自定义按钮导入
描述: 项目需求, 当用户选择文件导入时可以选择当前excel的sheet页,所以做了一层拦截
思路: 当用户点击导入时,先将导入的excel表所有内容赋值给临时的工作簿,然后通过SpreadJS,提供的 Spread.getSheet(序号).name()方法拿到所有sheet页的名称, 以此来做个弹框供用户选择,将选择好后的所有sheet页赋值给展示的工作蒲就行
// 导入
importXlsx(){
console.log('导入')
const excelIo = new Excel.IO()
//选择文件的input dom
const excelFile = document.getElementById("fileDemo").files[0];
this.currentExcel = excelFile
excelIo.open(excelFile,(json) => {
let workbookObj = json;
this.temp_work = this.temp_designer.getWorkbook()
this.temp_work.fromJSON(workbookObj)
let arr = []
this.temp_work.sheets.forEach((it,idx) => arr.push(this.temp_work.getSheet(idx).name()))
this.$refs.logs.dialogVisible = true
this.$nextTick(() => {
this.$refs.logs.openFunction(arr)
})
return
},(e) => {
alert(e.errorMessage);
})
},
//选择sheet页回调
submitCallBack(ids){
this.formatExcel()
// let towSheet = JSON.stringify(temp_work.sheets[4].toJSON())
// let sheet = this.workbook.getActiveSheet();
//用 work 工作蒲没用 要用sheet
// sheet.fromJSON(JSON.parse(towSheet));
//取多个sheet页
//删除默认初始化的
this.workbook.removeSheet(0)
this.temp_work.sheets.forEach((it, idx) => {
if(ids.includes(idx)){
let sheet_page = JSON.stringify(this.temp_work.sheets[idx].toJSON())
let newSheet = new GC.Spread.Sheets.Worksheet("sheet" + idx + "_")
newSheet.fromJSON(JSON.parse(sheet_page))
//累加
this.workbook.addSheet(this.workbook.getSheetCount(), newSheet)
}
})
//渲染全部sheet
// this.workbook.fromJSON(workbookObj);
let sheet = this.workbook.getActiveSheet();
// sheet.getRange(-1, 3, -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
//单元格选中改变事件 监听初始化时激活的sheet页 如要监听所有的 循环绑定
let selectionChanged = GC.Spread.Sheets.Events.SelectionChanged
sheet.bind(selectionChanged, (sender, info) => {
this.temp_location = JSON.parse(JSON.stringify(info.newSelections[0]))
})
//表单配置
let option = {
allowSelectLockedCells: true,//布尔值, 用户是否可以选中被锁定的单元格。
allowSelectUnlockedCells: true,//布尔值, 用户是否可以选中未被锁定的单元格。
allowSort: false,//布尔值,用户是否可以对一片单元格区域进行排序。
allowFilter: false,//布尔值,用户是否可以对一片单元格区域进行筛选。
allowEditObjects: false,//布尔值,用户是否可以编辑浮动元素。
allowResizeRows: false,//布尔值,用户是否可以改变行高。
allowResizeColumns: false,//布尔值,用户是否可以改变列宽。
allowDragInsertRows: false,//布尔值,用户是否可以拖拽插入行。
allowDragInsertColumns: false,//布尔值,用户是否可以拖拽插入列。
allowInsertRows: false,//布尔值,用户是否可以插入行。
allowInsertColumns: false,//布尔值,用户是否可以插入列。
allowDeleteRows: false,//布尔值,用户是否可以删除行。
allowDeleteColumns: false,//布尔值,用户是否可以删除列。
allowOutlineRows: false,//布尔值,用户是否可以展开或者折叠行组合。
allowOutlineColumns: false//布尔值,用户是否可以展开或者折叠列组合。
}
sheet.options.protectionOptions = option
// sheet.options.isProtected = true
},
2. 监听excel表整体变化的事件
cmds 是表单的一些指令,监听指定事件去做特定的事, 可以不写
//监听excel表单变化
listenExcel(){
const cmds = [
'editCell',
'dragDrop',
'fill',
'clipboardPaste',
'resizeRow',
'resizeColumn',
'gc.spread.contextMenu',
'Designer'
]
// 监听表单内容变化
this.workbook.commandManager().addListener('anyscLicenser', function(){
console.log(arguments)
let isEdited = false
for (let i = 0; i < arguments.length; i++) {
const cmd = arguments[i].command
console.log('触发命令:', arguments)
if (cmd && cmd.cmd) {
const cmdName = cmd.cmd
isEdited = cmds.some((item) => {
return item === cmdName || cmdName.startsWith(item)
})
}
}
if (isEdited) {
//TODO...
}
})
},
3. 自定义清除禁用表单的单元格内容 在表单中对于禁用的单元格 是不可删除的 需要自定义方法
描述: 在上面的初始化时就已经监听了sheet页的单元格切换选中事件, 在用户点击时将位置存进了自定义的对象中, 通过将值设为null,达到效果
也可以在点击清除时直接通过自带的方法获取当前选中单元格的坐标,进行清除
//清除单元格内容
clear(){
if(Object.entries(this.temp_location).length){
let sheet = this.workbook.getActiveSheet()
sheet.setValue(this.temp_location.row, this.temp_location.col, null)
}
},
4. 自定义导出
//导出excel
exportXlsx () {
let ex = new Excel.IO()
let json = this.workbook.toJSON()
ex.save(json, (blob) => {
FaverSaver.saveAs(blob, '名称.xlsx')
}, function (e) {
console.log(e)
})
},
5. 自定义工作蒲左上角文件里的菜单
自带的菜单为:
可通过自带方法进行修改, 以这些为例:
//去掉文件中的新建 导入 按钮
formatExcel(){
/*
这部分禁用“新建 导入 页签”
*/
const fileMenuPanelTemplate = GC.Spread.Sheets.Designer.getTemplate(GC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate)
const pageList = fileMenuPanelTemplate.content[0].children[0].children[1].children
console.log(pageList)
let delContainer = ["activeCategory_main=New", "activeCategory_main=Import"]
delContainer.forEach(it => {
pageList.forEach((i, x) => {
if(i?.visibleWhen == it){
pageList.splice(x, 1)
}
})
})
const itemList = fileMenuPanelTemplate.content[0].children[0].children[0].children[0].children[1].items
console.log(itemList)
let delType = ["New", "Import"]
delType.forEach(it => {
itemList.forEach((i, x) => {
if(i?.value == it){
itemList.splice(x, 1)
}
})
})
GC.Spread.Sheets.Designer.registerTemplate(GC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate, fileMenuPanelTemplate)
},
修改后的选项为:
6. 获取修改后的excel表内容 存至后台
首先拿到的是blob格式,将blob转化为file格式,通过FormData传给后台即可
//获取excel文件流
getWorkFile(){
let ex = new Excel.IO()
let json = this.workbook.toJSON()
ex.save(json, (blob) => {
let bri = new File([blob], this.currentExcel.name, {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', lastModified: Date.now()});
console.log(blob, bri)
return
}, function (e) {
console.log(e)
})
},
最后完整代码奉上
logs 代表用户选择的sheet页弹框 这里没有写出
<template>
<div class="componentContainer">
<h3>导出</h3>
<div>
<div>
<input type="button" @click="exportXlsx" value="导出Excel">
<input style='width: 173px;' type="file" id="fileDemo" class="input">
<input type="button" @click="importXlsx" value="导入">
<input type="button" @click="savePdf" value="导出PDF">
<button @click="place">位置确定</button>
<button @click="clear">清除单元格</button>
</div>
</div>
<div class="spreadContainer" >
<div id="gc-designer-container" ref="ssDesigner" style="height:100%; width:100%; text-align: left;"></div>
<div id="gc-designer-container-temp" ref="ssDesignerTemp" style="height:100%; width:100%; text-align: left;" v-show="false"></div>
</div>
<Log ref="logs" />
</div>
</template>
<script>
import * as Excel from '@grapecity/spread-excelio'
import FaverSaver from 'file-saver'
import "@grapecity/spread-sheets-vue"
import "@grapecity/spread-sheets-print";
import "@grapecity/spread-sheets-pdf";
import "@grapecity/spread-sheets-charts";
import '@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css'
import '@grapecity/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css'
import '@grapecity/spread-sheets-resources-zh'
import '@grapecity/spread-sheets-designer-resources-cn'
import GC from '@grapecity/spread-sheets'
import '@grapecity/spread-sheets-designer'
GC.Spread.Common.CultureManager.culture("zh-cn");
import Log from './dialog.vue'
export default {
name: 'Home',
components: { Log },
data(){
return {
currentExcel: null, //当前excel
designer:null, //speadjs 容器
temp_designer: null, //临时容器
workbook: null, //工作蒲
temp_work: null, //临时工作蒲
mqtt_location: {}, //时时数据展示位置
temp_location: {}, //零时存储位置
}
},
mounted(){
this.spreadInit()
},
methods: {
//初始化
spreadInit(){
//对应容器
this.designer = new GC.Spread.Sheets.Designer.Designer(this.$refs.ssDesigner)
//获取工作薄
this.workbook = this.designer.getWorkbook()
//临时容器
this.temp_designer = new GC.Spread.Sheets.Designer.Designer(this.$refs.ssDesignerTemp)
},
//导出excel
exportXlsx () {
let ex = new Excel.IO()
let json = this.workbook.toJSON()
ex.save(json, (blob) => {
FaverSaver.saveAs(blob, 'export.xlsx')
}, function (e) {
console.log(e)
})
},
//获取excel文件流
getWorkFile(){
let ex = new Excel.IO()
let json = this.workbook.toJSON()
ex.save(json, (blob) => {
let bri = new File([blob], this.currentExcel.name, {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', lastModified: Date.now()});
console.log(blob, bri)
return
}, function (e) {
console.log(e)
})
},
// 导入
importXlsx(){
console.log('导入')
const excelIo = new Excel.IO()
const excelFile = document.getElementById("fileDemo").files[0];
this.currentExcel = excelFile
excelIo.open(excelFile,(json) => {
let workbookObj = json;
//取某个sheet
this.temp_work = this.temp_designer.getWorkbook()
this.temp_work.fromJSON(workbookObj)
let arr = []
this.temp_work.sheets.forEach((it,idx) => arr.push(this.temp_work.getSheet(idx).name()))
this.$refs.logs.dialogVisible = true
this.$nextTick(() => {
this.$refs.logs.openFunction(arr)
})
return
},(e) => {
alert(e.errorMessage);
})
},
//导出PDF
savePdf(){
},
//去掉文件中的新建 导入 按钮
formatExcel(){
/*
这部分禁用“新建 导入 页签”
*/
const fileMenuPanelTemplate = GC.Spread.Sheets.Designer.getTemplate(GC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate)
const pageList = fileMenuPanelTemplate.content[0].children[0].children[1].children
console.log(pageList)
let delContainer = ["activeCategory_main=New", "activeCategory_main=Import"]
delContainer.forEach(it => {
pageList.forEach((i, x) => {
if(i?.visibleWhen == it){
pageList.splice(x, 1)
}
})
})
const itemList = fileMenuPanelTemplate.content[0].children[0].children[0].children[0].children[1].items
console.log(itemList)
let delType = ["New", "Import"]
delType.forEach(it => {
itemList.forEach((i, x) => {
if(i?.value == it){
itemList.splice(x, 1)
}
})
})
GC.Spread.Sheets.Designer.registerTemplate(GC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate, fileMenuPanelTemplate)
},
//用户点击单元格后 时时通讯位置变化
place(){
alert('点击确定')
console.log('改变时时通讯位置')
let sheet = this.workbook.getActiveSheet()
let style = new GC.Spread.Sheets.Style()
//将以前的背景色去掉 要设置null 或者undefined
style.backColor = null
// sheet.setValue(this.mqtt_location.row, this.mqtt_location.col, null)
sheet.setStyle(this.mqtt_location.row, this.mqtt_location.col, style)
//将要展示时时通讯的位置改变背景色
this.mqtt_location = {...this.temp_location}
console.log(this.mqtt_location)
let style1 = new GC.Spread.Sheets.Style()
style1.backColor = '#C3C3C3'
sheet.setStyle(this.mqtt_location.row, this.mqtt_location.col, style1)
},
//选择sheet页回调
submitCallBack(ids){
this.formatExcel()
// let towSheet = JSON.stringify(temp_work.sheets[4].toJSON())
// let sheet = this.workbook.getActiveSheet();
//用 work 工作蒲没用 要用sheet
// sheet.fromJSON(JSON.parse(towSheet));
//取多个sheet页
//删除默认初始化的
this.workbook.removeSheet(0)
this.temp_work.sheets.forEach((it, idx) => {
if(ids.includes(idx)){
let sheet_page = JSON.stringify(this.temp_work.sheets[idx].toJSON())
let newSheet = new GC.Spread.Sheets.Worksheet("sheet" + idx + "_")
newSheet.fromJSON(JSON.parse(sheet_page))
//累加
this.workbook.addSheet(this.workbook.getSheetCount(), newSheet)
}
})
//渲染全部sheet
// this.workbook.fromJSON(workbookObj);
let sheet = this.workbook.getActiveSheet();
// sheet.getRange(-1, 3, -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
//单元格选中改变事件
let selectionChanged = GC.Spread.Sheets.Events.SelectionChanged
sheet.bind(selectionChanged, (sender, info) => {
console.log(1)
this.temp_location = JSON.parse(JSON.stringify(info.newSelections[0]))
})
//表单配置
let option = {
allowSelectLockedCells: true,//布尔值, 用户是否可以选中被锁定的单元格。
allowSelectUnlockedCells: true,//布尔值, 用户是否可以选中未被锁定的单元格。
allowSort: false,//布尔值,用户是否可以对一片单元格区域进行排序。
allowFilter: false,//布尔值,用户是否可以对一片单元格区域进行筛选。
allowEditObjects: false,//布尔值,用户是否可以编辑浮动元素。
allowResizeRows: false,//布尔值,用户是否可以改变行高。
allowResizeColumns: false,//布尔值,用户是否可以改变列宽。
allowDragInsertRows: false,//布尔值,用户是否可以拖拽插入行。
allowDragInsertColumns: false,//布尔值,用户是否可以拖拽插入列。
allowInsertRows: false,//布尔值,用户是否可以插入行。
allowInsertColumns: false,//布尔值,用户是否可以插入列。
allowDeleteRows: false,//布尔值,用户是否可以删除行。
allowDeleteColumns: false,//布尔值,用户是否可以删除列。
allowOutlineRows: false,//布尔值,用户是否可以展开或者折叠行组合。
allowOutlineColumns: false//布尔值,用户是否可以展开或者折叠列组合。
}
sheet.options.protectionOptions = option
// sheet.options.isProtected = true
this.listenExcel()
this.mqtt_data()
},
//监听excel表单变化
listenExcel(){
const cmds = [
'editCell',
'dragDrop',
'fill',
'clipboardPaste',
'resizeRow',
'resizeColumn',
'gc.spread.contextMenu',
'Designer'
]
// 监听表单内容变化
this.workbook.commandManager().addListener('anyscLicenser', function(){
console.log(11, arguments)
let isEdited = false
for (let i = 0; i < arguments.length; i++) {
const cmd = arguments[i].command
console.log('触发命令:', arguments)
if (cmd && cmd.cmd) {
const cmdName = cmd.cmd
isEdited = cmds.some((item) => {
return item === cmdName || cmdName.startsWith(item)
})
}
}
if (isEdited) {
console.log(222)
}
})
},
//清除单元格内容
clear(){
if(Object.entries(this.temp_location).length){
let sheet = this.workbook.getActiveSheet()
sheet.setValue(this.temp_location.row, this.temp_location.col, null)
}
},
//模拟mqtt
mqtt_data(){
console.log('开始时事通讯')
setInterval(() => {
let num = Math.floor(Math.random()*10000)
let sheet = this.workbook.getActiveSheet()
if(JSON.stringify(this.mqtt_location) == '{}'){
return
}
sheet.setValue(this.mqtt_location.row, this.mqtt_location.col, num)
}, 1000)
}
},
}
</script>
<style scoped>
.componentContainer {
width:90%;
height:700px;
margin: 0 auto;
}
.spreadContainer{
width:100%;
height:100%;
margin-top:15px;
box-shadow: 0 0 20px grey;
}
.spread-host{
width: 100%;
height: 100%;
}
</style>
完结 !!!
更多推荐
所有评论(0)