Closed
Description
Version
1.19.1
Link to Minimal Reproduction
Steps to Reproduce
1、使用xlsxjs 解析一个excel表格,表格内容不限
2、拿到解析到的数据,使用vtable渲染
3、我使用cellType + fieldFormat 来处理可能出现图片的单元格,合并单元格用customMergeCell 来处理
整体效果不理想,1、图片无法定义宽高、2、合并单元格含有图片的时候,本该合并的单元格未合并,且每个单元格都加载了图片
Current Behavior
用vtable渲染excel表格,数据量可能很大,所以选择了vtable
Expected Behavior
主要代码如下
async loadOnlineExcel(excelUrl) {
this.fileOrigin = excelUrl.split('file-server')[0]
const response = await axios.get(excelUrl, { responseType: 'arraybuffer' })
// 解析 Excel
const workbook = XLSX.read(response.data, {
type: 'array'
// row: true,
// blankrows: false,
// cellStyles: true,
// cellHTML: true,
})
this.workbook = workbook
const sheetNames = workbook.SheetNames
console.log(`🚀 ~ sheetNames:`, sheetNames)
this.sheetNames = sheetNames
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
const startRow = this.getStartRow(worksheet)
// 获取合并单元格信息
this.merges = worksheet['!merges'] || []
// 转换为 JSON 数据
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
header: 1,
row: true,
blankrows: true,
range: worksheet['!ref']
})
// 添加起始空白行
const newRow = new Array(jsonData[0].length).fill('')
for (let i = 0; i < startRow; i++) {
jsonData.unshift(newRow)
}
this.fillMergedCells(jsonData)
this.initExcelData(jsonData)
},
initExcelData(jsonData) {
const that = this
console.log(`🚀 ~ jsonData:`, jsonData)
this.mergedCells = this.workbook.Sheets[this.sheetNames[this.currentSheet]]['!merges'] || []
if (jsonData.length > 0) {
const headers = [''] // 第一行作为表头
const strArr = [] // A-Z
for (let i = 65; i <= 90; i++) {
const letter = String.fromCharCode(i) // A, B, C, ..., Z
// console.log(letter);
strArr.push(letter)
}
jsonData[0].map((col, index) => {
let str = ''
if (index < 26) {
str = strArr[index]
} else if (index < 26 * 26) {
const beforeStr = Math.floor(index / 26) - 1
str = strArr[beforeStr] + strArr[index % 26]
} else {
str = index + 1
}
// console.log(str)
headers.push(str)
})
this.headers = headers
this.data = jsonData // 其余行作为数据
this.vColumns = this.headers.map((header, headerIndex) => {
return {
title: header || '',
field: header || 'myIndex',
cellType(args) {
if (!header) return 'text'
const value = jsonData[args.row - 1][headerIndex] || ''
if (value && String(value).includes('IMAGE:')) {
return 'image'
}
return 'text';
},
fieldFormat(record) {
if (!header) return record.myIndex
let content = record[header]
if (content && content.includes('IMAGE:')) {
content = that.fileOrigin + content.replace(/^IMAGE:/, '')
}
return content
},
width: 'auto',
height: 200,
imageOptions: {
width: 100,
height100: 100,
maxWidth: 200, // 最大宽度
maxHeight: 150, // 最大高度
minWidth: 50, // 最小宽度
style: { // 自定义样式
objectFit: 'contain', // 保持比例填充
border: '1px solid #eee'
},
keepAspectRatio: true
},
keepAspectRatio: true
}
})
this.vData = this.data.map((item, index) => {
const row = {}
this.headers.map((col, colIndex) => {
row[col || 'myIndex'] = col ? item[colIndex] : (index + 1)
})
return row
})
console.log(this.vData)
console.log(this.mergedCells)
// const tableMerges = this.convertExcelMerges(this.mergedCells)
const tableInstance = new VTable.ListTable(this.$refs.vTable, {
columns: this.vColumns,
records: this.vData,
widthMode:'autoWidth',
disableHtmlEscape: true, imageOptions: {
width: 120,
height: 80,
keepAspectRatio: true,
placeholder: 'data:image/svg+xml;base64,...', // 加载占位图
margin: 5
},
customMergeCell: that.mergedCells.map(merge => {
console.log(`${merge.s.r},${merge.s.c}--${merge.e.r},${merge.e.c}`)
const isImage = jsonData[merge.s.r][merge.s.c].startsWith('IMAGE:')
const styleObj ={}
isImage && (styleObj.width = '150px')
const obj = {
range: {
start: { row: merge.s.r + 1, col: merge.s.c },
end: { row: merge.e.r + 1, col: merge.e.c },
},
// 可以添加自定义样式
style: {
bgColor: '#fff',
textAlign: 'center',
...styleObj
}
}
if(isImage) {
obj.html = `<img src="${that.fileOrigin + jsonData[merge.s.r][merge.s.c].replace(/^IMAGE:/, '')}" style="width: 100px" />`
} else {
obj.text = jsonData[merge.s.r][merge.s.c]
}
return obj
})
});
this.loading = false
} else {
this.data = []
}
},
Environment
- OS:
- Browser:
- Framework:
Any additional comments?
我尝试使用customRender也未达到理想效果