async onSubmit2() {
if (this.fetching) return
this.$refs.submitModelRef.validate(async valid => {
if (valid) {
const activeWorkbook = this.univerAPI.getActiveWorkbook()
var sheetData = activeWorkbook.save()
let data2 = JSON.stringify(sheetData)
let sheet = sheetData.sheets[sheetData.sheetOrder[0]]
let styles = sheetData.styles
let cellData = sheet.cellData
let realData = []
let entities = []
let sceneImgStr = ''
//判断this.submitForm.sceneImg如果是数组,就转化为逗号隔开的字符串
if (this.submitForm.sceneImg && this.submitForm.sceneImg.length > 0 && typeof this.submitForm.sceneImg === 'object' && Array.isArray(this.submitForm.sceneImg)) {
sceneImgStr = this.submitForm.sceneImg.join(',')
} else {
sceneImgStr = this.submitForm.sceneImg
}
Object.keys(cellData).forEach(key => {
const value = cellData[key]
if (!value['0'] || !value['0'].v) {
//console.log(key + "行没有样品编号")
delete cellData[key]
} else {
realData.push(JSON.stringify(value))
// 查找样品
const _find = this.data.sampleList.find(item => {
return item.sampleNo.trim() === value['0'].v.trim()
})
console.log("sceneImgStr",sceneImgStr)
if(sceneImgStr!=null ||sceneImgStr!=""){
if (_find) {
entities.push({
entityId: _find.id,
entityType: '1',
sceneImgL: sceneImgStr,
entityNo: _find.sampleNo,
getTime: _find.getTime,
departCode: _find.departCode || this.data.departCode,
customerAreaCode: _find.customerAreaCode || this.data.areaCode,
..._find
})
} else {
console.log('未找到样品:', value['0'].v.trim())
}
}else {
console.log('样品图片不能为空')
}
}
})
let rows = Object.keys(cellData)
let newRows = {}
rows.forEach(row => {
let cols = Object.keys(cellData[row])
cols.forEach(col => {
let cell = cellData[row][col]
if (cell && (cell.v || cell.v == 0 || cell.p)) {
newRows[row] = newRows[row] || {}
if (cell.s && this.Number(cell.v) && styles[cell.s] && styles[cell.s].n && styles[cell.s].n.pattern) {
newRows[row][col] = this.formatNumber(cell.v, styles[cell.s].n.pattern)
} else if (cell.s && cell.p && cell.p.body && cell.p.body.dataStream) {
newRows[row][col] = cell.p.body.dataStream
} else {
newRows[row][col] = cell.v
}
}
})
})
this.fetching = true
const request = {
orderId: this.data.orderId,
templateId: this.data.templateId,
canvasId: this.data.canvasId,
oriCanvasId: this.oriCanvasId,
productId: this.data.productId,
reportNo: this.data.reportNo,
expireDate: this.data.expireDate,
tag: this.data.productCode,
serial: this.data.serial,
canvasData: realData,
workbook: data2,
newCanvasData: newRows,
entityList: entities,
qualified: this.submitForm.qualified,
mainCheckUser: this.submitForm.mainCheckUser,
checkUsers: this.submitForm.checkUsers?.toString()
}
const result = await postAction(this.url.submit, request)
if (result.message) {
this.runText += result.message.replaceAll('<br>', '\\n').replaceAll('nbsp;', ' ')
}
this.fetching = false
}
})
},

前端vue如何解析Excel模板合并和未合并项
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
4条回答 默认 最新
檀越@新空间 2025-09-01 16:18关注下午好🌅🌅🌅
本答案参考通义千问在使用 Vue 进行前端开发时,解析 Excel 模板中的合并和未合并单元格是一个常见的需求。尤其在处理表格数据、导出或导入 Excel 文件时,需要对 合并的单元格(merged cells) 和 未合并的单元格(unmerged cells) 进行区分处理。
你提供的代码片段中涉及了从
Univer(一个基于 Web 的表格库)中获取工作表数据,并尝试提取单元格内容进行处理。但目前并未涉及对 合并单元格 的解析逻辑。以下将详细说明如何实现这一功能。
✅ 一、问题分析
当前代码中:
- 获取了
sheetData; - 提取了
cellData; - 遍历了
cellData,但没有处理 合并单元格; - 未对合并单元格进行特殊处理,导致合并区域内的数据可能被重复处理或遗漏。
🔍 问题点:
- 合并单元格通常会有一个主单元格(如 A1),其他单元格可能为空或不包含实际值;
- 当前代码遍历所有单元格,可能会重复处理合并单元格中的内容;
- 缺乏对合并区域的识别和处理逻辑。
✅ 二、解决方案
1. 获取合并单元格信息
在
sheetData中,通常会有一个merge字段,记录了合并区域的信息,格式如下:"merge": [ { "s": { "r": 0, "c": 0 }, // 起始行和列 "e": { "r": 1, "c": 1 } // 结束行和列 } ]2. 遍历合并单元格并标记已处理单元格
我们需要遍历合并区域,只保留第一个单元格的内容,其他单元格跳过处理。
3. 修改后的代码逻辑
以下是修改后的完整代码片段,重点部分加粗展示:
async onSubmit2() { if (this.fetching) return; this.$refs.submitModelRef.validate(async valid => { if (valid) { const activeWorkbook = this.univerAPI.getActiveWorkbook(); const sheetData = activeWorkbook.save(); const sheet = sheetData.sheets[sheetData.sheetOrder[0]]; const styles = sheetData.styles; const cellData = sheet.cellData; const mergeCells = sheet.merge || []; // 获取合并单元格信息 let realData = []; let entities = []; let sceneImgStr = ''; // 判断 this.submitForm.sceneImg 是否为数组并转换为逗号分隔字符串 if (Array.isArray(this.submitForm.sceneImg) && this.submitForm.sceneImg.length > 0) { sceneImgStr = this.submitForm.sceneImg.join(','); } else { sceneImgStr = this.submitForm.sceneImg; } // 创建一个 Set 来记录已经被处理的单元格 const processedCells = new Set(); // 遍历合并单元格 mergeCells.forEach(merge => { const startRow = merge.s.r; const startCol = merge.s.c; const endRow = merge.e.r; const endCol = merge.e.c; // 标记该区域的所有单元格为已处理 for (let r = startRow; r <= endRow; r++) { for (let c = startCol; c <= endCol; c++) { const key = `${r}-${c}`; processedCells.add(key); } } }); // 遍历所有单元格,跳过已处理的 Object.keys(cellData).forEach(rowKey => { const row = parseInt(rowKey); const cols = cellData[rowKey]; Object.keys(cols).forEach(colKey => { const col = parseInt(colKey); const key = `${row}-${col}`; if (processedCells.has(key)) { return; // 跳过已处理的单元格 } const value = cols[colKey]; if (!value['0'] || !value['0'].v) { delete cellData[rowKey]; return; } realData.push(JSON.stringify(value)); const _find = this.data.sampleList.find(item => { return item.sampleNo.trim() === value['0'].v.trim(); }); console.log("sceneImgStr", sceneImgStr); if (sceneImgStr != null && sceneImgStr !== "") { if (_find) { entities.push({ entityId: _find.id, entityType: '1', sceneImgL: sceneImgStr, entityNo: _find.sampleNo, getTime: _find.getTime, departCode: _find.departCode || this.data.departCode, customerAreaCode: _find.customerAreaCode || this.data.areaCode, ..._find }); } else { console.log('未找到样品:', value['0'].v.trim()); } } else { console.log('样品图片不能为空'); } }); }); // 处理非合并单元格数据 let newRows = {}; Object.keys(cellData).forEach(row => { let cols = Object.keys(cellData[row]); cols.forEach(col => { let cell = cellData[row][col]; if (cell && (cell.v || cell.v == 0 || cell.p)) { newRows[row] = newRows[row] || {}; if (cell.s && this.Number(cell.v) && styles[cell.s] && styles[cell.s].n && styles[cell.s].n.pattern) { newRows[row][col] = this.formatNumber(cell.v, styles[cell.s].n.pattern); } else if (cell.s && cell.p && cell.p.body && cell.p.body.dataStream) { newRows[row][col] = cell.p.body.dataStream; } else { newRows[row][col] = cell.v; } } }); }); this.fetching = true; const request = { orderId: this.data.orderId, // 其他参数... }; // 发送请求... } }); }
✅ 三、关键点总结
- 获取合并单元格信息:通过
sheet.merge获取合并区域。 - 标记已处理单元格:使用
Set记录已被处理的单元格。 - 跳过合并单元格:在遍历所有单元格时跳过已处理的单元格。
- 处理非合并单元格:确保只处理未合并的单元格数据。
✅ 四、注意事项
- 如果你使用的是其他 Excel 解析库(如
xlsx.js或SheetJS),合并单元格的处理方式略有不同,建议查阅对应文档。 - 确保
Univer的版本支持merge属性,否则可能无法获取合并单元格信息。
如有更多关于 Excel 数据解析的问题,欢迎继续提问!
解决 无用评论 打赏 举报- 获取了