SpreadJS 个人学习及项目遇到的一些问题的总结
以下就是他的优缺点,百度的
优点:
-
跨平台兼容性:SpreadJS 支持多种浏览器和操作系统,包括桌面和移动设备。
-
丰富的功能:SpreadJS 提供了丰富的表格功能,包括单元格编辑、格式设置、公式计算、数据验证等。
-
性能:由于它是基于 HTML5 的,因此具有较好的性能和响应速度。
-
集成性:SpreadJS 可以与其他前端框架(如 Vue、React 等)集成,方便开发和维护。
-
API 丰富:SpreadJS 提供了一系列的 API,允许开发者通过编程方式控制表格的各个方面。
缺点:
-
成本:SpreadJS 是一个商业产品,需要购买许可证才能使用。对于开源或预算有限的开发项目,这可能是一个障碍。
-
社区支持:虽然 SpreadJS 有一个活跃的社区,但与一些流行的开源项目相比,它的社区规模可能较小。
-
文档和教程:虽然 SpreadJS 的文档和教程相对完整,但与一些开源项目相比,它们可能不够详细或易于理解。
-
定制性:虽然 SpreadJS 提供了丰富的功能和 API,但对于一些特定的定制需求,可能需要额外的开发工作。
-
更新频率:SpreadJS 的更新频率可能不如一些开源项目频繁,这可能会影响项目的维护和扩展。
这个是技术文档
https://demo.grapecity.com.cn/spreadjs/help/api/modules/GC.Data
我这边只涉及展示部分,表格编辑部分的,目前还没接触过,后期会了再更新,目前是一些常用的情况代码展示
简单的入门开始
视图部分
<gc-spread-sheets style="height: 75vh" @workbookInitialized="initWorkbook"></gc-spread-sheets>
组件引用
import { message } from 'ant-design-vue'
import '@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css'
import GC from '@grapecity/spread-sheets'
import '@grapecity/spread-sheets-resources-zh'
GC.Spread.Common.CultureManager.culture('zh-cn')
GC.Spread.Sheets.LicenseKey = VITE_SHEETS_LICENSE_KEY
let _spread = null
------------------代码部分--------------
async function initWorkbook(spread) {
_spread = spread
detectionResult.value = []
const file = await getFile('https://www.baidu.com') // 模板地址
spread.import(file, () => {
// 获取活动工作表的名称列表 这个是多个活动页的时候获取的
var sheetNames = []
for (var i = 0; i < spread.getSheetCount(); i++) {
sheetNames.push(spread.getSheet(i).name())
// console.log('---i---------', i)
let sheet = spread.getSheet(i)
sheet.zoom(1)
let printInfo = sheet.printInfo() // 这是是导出pdf的时候正常情况下,使用的设置部分
// 这个是底部的页码
printInfo.pageHeaderFooter({
normal: {
footer: {
center: '第' + '&P' + '页 共' + '&N' + '页'
}
}
})
printInfo.margin({ top: 35, bottom: 75, left: 15, right: 15, header: 10, footer: 20 }) // 这个是外边距,导出的pdf部分,有的页面内容多的情况下,显示不出来
// 获取或设置是否在整个控件周围打印分组列边框
printInfo.showBorder(false)
// 获取或设置打印页面居中的方式
printInfo.centering(GC.Spread.Sheets.Print.PrintCentering.horizontal)
// 重复表头 打印列表的时候,表头在新的页中是否包含
printInfo.repeatRowStart(0)
printInfo.repeatRowEnd(1)
//是否打印列头/行头 如下图部分
printInfo.showColumnHeader(GC.Spread.Sheets.Print.PrintVisibilityType.hide)
printInfo.showRowHeader(GC.Spread.Sheets.Print.PrintVisibilityType.hide)
spread.bind(GC.Spread.Sheets.Events.CellClick, cellClick) // 这个是点击的时候,获取对应的点位坐标
spread.setActiveSheetIndex(0) // 从第一个开始 设置默认选中
printInfo.fitPagesWide(1) // 使用场景,当前表格pdf,纵列展示展示不全的解决方案
// 挂起绘制和事件处理
spread.suspendPaint()
spread.suspendEvent()
// 执行大量更新操作 在这里写逻辑 ..............................
// 恢复事件处理/
spread.resumeEvent()
// 恢复绘制
spread.resumePaint()
registerServerFont('st', 'normal', import.meta.env.VITE_PROJECT_BASE + '/simsun.ttf') // 导出的时候会有乱码,这是解决方案
}) }
代码说明
//是否打印列头/行头 如下图部分 printInfo.showColumnHeader(GC.Spread.Sheets.Print.PrintVisibilityType.hide) printInfo.showRowHeader(GC.Spread.Sheets.Print.PrintVisibilityType.hide)

spread.setActiveSheetIndex(0) // 从第一个开始 设置默认选中

printInfo.fitPagesWide(1)
// 使用场景,当前表格pdf,纵列展示展示不全的解决方案

常用的一些事件方法
// 下面是常用的一些方法封装
// 导出的时候会有乱码,这是解决方案
const registerServerFont = (name, type, serverPath) => {
var xhr = new XMLHttpRequest()
xhr.open('GET', serverPath, true)
xhr.responseType = 'blob'
xhr.onload = function (e) {
console.log(xhr)
if (xhr.status == 200) {
var blob = xhr.response
var reader = new FileReader()
reader.onload = function (e) {
var fontrrayBuffer = reader.result
var fonts = GC.Spread.Sheets.PDF.PDFFontsManager.getFont(name) || {}
fonts[type] = fontrrayBuffer
GC.Spread.Sheets.PDF.PDFFontsManager.registerFont(name, fonts)
// console.log("字体注册完成");
GC.Spread.Sheets.PDF.PDFFontsManager.fallbackFont = function () {
return fontrrayBuffer
}
}
reader.readAsArrayBuffer(blob)
}
}
xhr.send()
}
点击获取横纵坐标
const cellClick = (sender, args) => {
console.log('click', args.row, args.col, _spread.getActiveSheet().name())
}
单元格的高度自适应
// 整理 高度自适应
const arrangeLIst = (sheetFour) => {
const rowCountFour = sheetFour.getRowCount(GC.Spread.Sheets.SheetArea.viewport) // 横
for (let index = 0; index < rowCountFour; index++) {
adjustRowHeightIfNecessary(sheetFour, index)
}
}
// 根据高度自适应
const adjustRowHeightIfNecessary = (sheet, row) => {
// 获取当前行的高度
var originalHeight = sheet.getRowHeight(row) // 计算自动适应后的行高
sheet.autoFitRow(row)
var newHeight = sheet.getRowHeight(row) // 如果新高度小于或等于原高度,则将高度重新设回原高度
if (newHeight <= originalHeight) {
sheet.setRowHeight(row, originalHeight < 25 ? 30 : originalHeight)
} else if (newHeight < 25) {
sheet.setRowHeight(row, 30)
}
}
使用方法,
// 整理 高度自适应
arrangeLIst(sheetFour)
删除多余的行
// 删除多余的行
const deletionExcess = (spread) => {
const dataR = spread.getUsedRange(GC.Spread.Sheets.UsedRangeType.data)
const rowCount = dataR.rowCount // 横
// console.log('-----删除多余的行--', rowCount)
// 遍历工作表的行,找到最后一个非空白行
var lastNonBlankRowIndex = -1
for (var i = rowCount - 1; i >= 0; i--) {
var isBlank = true
for (var j = 0; j < spread.getColumnCount(); j++) {
if (spread.getCell(j).value !== null && spread.getCell(j).value !== '') {
isBlank = false
break
}
}
if (!isBlank) {
lastNonBlankRowIndex = i
break
}
}
// console.log(spread.getRowCount(), '-----lastNonBlankRowIndex-------', lastNonBlankRowIndex)
// 如果找到了最后一个非空白行,删除所有底部的空白行
if (lastNonBlankRowIndex !== -1) {
for (var i = spread.getRowCount() - 1; i > lastNonBlankRowIndex; i--) {
spread.deleteRows(i, 1)
}
}
}
使用方法
deletionExcess(sheetSix)
添加图片
const imageSignature = (spreadJsTool, sheet, val, x, y) => {
// 签名图片
let picture = sheet.pictures.add(spreadJsTool, 'data:image/jpg;base64,' + val)
picture.isVisible(false)
setTimeout(() => {
picture.width((50 / picture.height()) * picture.width())
picture.height(48)
picture.y(1)
// 这个顺序不对会导致报错
picture.startRow(x)
picture.startColumn(y)
picture.isVisible(true)
}, 100)
}
// 图片名称,我用的随机数
const randomString =(length)=> {
const array = new Uint32Array(length);
window.crypto.getRandomValues(array);
return Array.from(array, (dec) => {
return dec.toString(36).padStart(2, '0'); // 转换为36进制(包含数字和字母)
}).join('');
}
console.log(randomString(10)); // 生成长度为10的随机字符串
使用方法
imageSignature(
randomString(15),
sheetSix,
item.img,
nullAr1,
nullAr - nullAr2 > 0 ? nullAr - nullAr2 : 0
)
还有种场景,需要删除当前表格中的文件图片

// 删除多余的图片
// 获取工作表的形状管理器
var shapeColl = sheet.pictures //shapes 废弃
// 参照此方式获取图片或形状名称
// var pictName = shapeColl.all()[0].name()
shapeColl.all().forEach((element) => {
if (element.name() != '图片 5') { // 图片5是我想保留的图片
shapeColl.remove(element.name())
}
if (element.isSelected()) { // 这是点击选中图片的时候,然后可以删除
shapeColl.remove(element.name())
}
})
删除选中的图片
你在点击了以后,这个图片的isSelected属性就会变成true,这个时候你点击单元格,然后去遍历图片数组,找到isSeletecd属性为true的这个元素,拿到它的name,然后就可以删掉了。
获取指定单元格内容是否合并
sheet.getSpan(row, col)
导出文件
const toExcel = async () => {
// 导出xlsx
_spread.export(
function (blob) {
saveAs(blob, containerTitle.value + '.xlsx')
},
function (e) {
console.log(e)
},
{
fileType: GC.Spread.Sheets.FileType.excel
}
)
// 导出pdf
_spread.savePDF(
function (blob) {
saveAs(blob, containerTitle.value + '.pdf')
},
function (e) {
console.log(e)
},
{
fileType: GC.Spread.Sheets.FileType.excel
}
)
}
使用方法 @click
注: 1.导入文件的时候,文件格式必须是 .xlsx,不然出不来
2.图片必须是base64的,不然导出文件 图片出不来,活着是那种在线的那种文件地址,如htttp://www.baidu.com?id=100861120 这种,不然打印不出来(本人自测是这样的,依照你自己做的为准)

浙公网安备 33010602011771号