你在干嘛n 2025-09-01 16:17 采纳率: 25%
浏览 7

前端vue如何解析Excel模板合并和未合并项


 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
                }
            })
        },

![img](https://i-blog.csdnimg.cn/ask/c7e53b9c7dbb4d71bc263c647a477872.jpeg "#left")

  • 写回答

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,
                    // 其他参数...
                };
    
                // 发送请求...
            }
        });
    }
    

    ✅ 三、关键点总结

    1. 获取合并单元格信息:通过 sheet.merge 获取合并区域。
    2. 标记已处理单元格:使用 Set 记录已被处理的单元格。
    3. 跳过合并单元格:在遍历所有单元格时跳过已处理的单元格。
    4. 处理非合并单元格:确保只处理未合并的单元格数据。

    ✅ 四、注意事项

    • 如果你使用的是其他 Excel 解析库(如 xlsx.jsSheetJS),合并单元格的处理方式略有不同,建议查阅对应文档。
    • 确保 Univer 的版本支持 merge 属性,否则可能无法获取合并单元格信息。

    如有更多关于 Excel 数据解析的问题,欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 创建了问题 9月1日