WPS Excel 宏使用

WPS Excel 初次宏使用

进入WPS宏编辑器 :WPS Excel-开发工具-切换到JS环境-查看代码
在宏编辑器里添加已有的JS代码:文件-导入文件-选中所需JS文件

以此代码为例,来感受并记录一下整个流程

实现的功能是:将"汇总表"中标绿学生信息,按照学号到"未就业"表中进行匹配,将匹配的行删除。

尚未研究明白如何进行跨模块调用

javascript 复制代码
// 主函数:汇总表含目标绿色单元格的行→提取学号→未就业表匹配标黄→询问删除(批量/逐个)
function highlightAndDeleteMatchedRows() {
    try {
        // 1. 基础配置(核心:指定目标绿色RGB值)
        var config = {
            summaryHeaderRow: 1,    // 汇总表表头行(默认第1行)
            unemployedHeaderRow: 4, // 未就业表表头行(默认第1行)
            targetHeader: "学号",    // 目标表头名称(可修改为实际名称)
            targetGreenRGB: { r: 146, g: 208, b: 80 }, // 目标绿色精确RGB值
            colorTolerance: 5,      // 颜色容差(0-10,兼容轻微偏差)
            checkColumnCount: 50    // 每行检查前50列(可调整)
        };

        // 存储未就业表中匹配并标黄的行信息(行号+学号)
        var highlightedRows = [];

        // 2. 获取当前工作簿
        var currentWorkbook = Application.ActiveWorkbook;
        if (!currentWorkbook) {
            console.log("❌ 未检测到打开的工作簿,请先打开目标表格!");
            return;
        }
        console.log("✅ 成功获取当前工作簿:", currentWorkbook.Name);

        // 3. 获取目标工作表
        var summarySheet = currentWorkbook.Sheets("汇总表");
        var unemployedSheet = currentWorkbook.Sheets("未就业");
        if (!summarySheet) {
            console.log("❌ 未找到名为「汇总表」的工作表,请检查名称!");
            return;
        }
        if (!unemployedSheet) {
            console.log("❌ 未找到名为「未就业」的工作表,请检查名称!");
            return;
        }
        console.log("✅ 成功加载工作表:汇总表、未就业表");

        // 4. 封装函数:查找表头对应的列号 + 输出表头行数据
        function findHeaderColumn(sheet, headerRow, targetHeader, sheetName) {
            try {
                var headerRowData = "📋 " + sheetName + "第" + headerRow + "行(表头行)实际数据:\n";
                var hasData = false;
                for (var col = 1; col <= 10; col++) {
                    var cellValue = sheet.Cells(headerRow, col).Value();
                    var cellText = cellValue ? cellValue.toString().trim() : "【空值】";
                    headerRowData += "第" + col + "列:" + cellText + "\n";
                    if (cellText !== "【空值】") hasData = true;
                }
                console.log(headerRowData);

                if (!hasData) return -2;

                // 查找目标表头(兼容空格)
                for (var col = 1; col <= 100; col++) {
                    var cellValue = sheet.Cells(headerRow, col).Value();
                    var cellText = cellValue ? cellValue.toString().replace(/\s+/g, "") : "";
                    var targetText = targetHeader.replace(/\s+/g, "");
                    if (cellText === targetText) return col;
                }
                return -1;
            } catch (e) {
                console.log("❌ " + sheetName + "表头行查找出错:", e.message);
                return -3;
            }
        }

        // 5. 封装函数:判断单元格是否为目标绿色
        function isTargetGreenCell(cell) {
            try {
                var interiorColor = cell.Interior.Color;
                var red = interiorColor & 0xFF;
                var green = (interiorColor >> 8) & 0xFF;
                var blue = (interiorColor >> 16) & 0xFF;

                var isMatch = 
                    Math.abs(red - config.targetGreenRGB.r) <= config.colorTolerance &&
                    Math.abs(green - config.targetGreenRGB.g) <= config.colorTolerance &&
                    Math.abs(blue - config.targetGreenRGB.b) <= config.colorTolerance;
                
                return { isMatch: isMatch, r: red, g: green, b: blue };
            } catch (e) {
                return { isMatch: false, r: 0, g: 0, b: 0 };
            }
        }

        // 6. 查找汇总表的「学号」列
        var summaryStudentIdCol = findHeaderColumn(summarySheet, config.summaryHeaderRow, config.targetHeader, "汇总表");
        switch (summaryStudentIdCol) {
            case -3: console.log("❌ 汇总表表头查找过程出错,请检查表格是否损坏!"); return;
            case -2: console.log("❌ 汇总表第" + config.summaryHeaderRow + "行(表头行)无有效数据!"); return;
            case -1: console.log("❌ 在汇总表第" + config.summaryHeaderRow + "行未找到「" + config.targetHeader + "」表头!"); return;
            default: console.log("✅ 汇总表「" + config.targetHeader + "」列位置:第" + summaryStudentIdCol + "列");
        }

        // 7. 核心步骤1:遍历汇总表,收集含目标绿色单元格的行的学号
        var summaryUsedRange = summarySheet.UsedRange;
        if (!summaryUsedRange) {
            console.log("❌ 汇总表无有效数据!");
            return;
        }
        var summaryLastRow = summaryUsedRange.Rows.Count;
        if (summaryLastRow <= config.summaryHeaderRow) {
            console.log("❌ 汇总表除表头外无其他数据!");
            return;
        }
        console.log(`ℹ️ 汇总表数据总行数:${summaryLastRow - config.summaryHeaderRow}行,开始查找含目标绿色单元格的行...`);

        var greenRowStudentIds = [];
        var foundGreenRows = new Set();

        for (var row = config.summaryHeaderRow + 1; row <= summaryLastRow; row++) {
            var hasTargetGreen = false;
            var greenCellInfo = "";

            for (var col = 1; col <= config.checkColumnCount; col++) {
                var currentCell = summarySheet.Cells(row, col);
                var { isMatch, r, g, b } = isTargetGreenCell(currentCell);

                if (isMatch) {
                    hasTargetGreen = true;
                    greenCellInfo += `第${col}列(RGB(${r},${g},${b}))、`;
                }
            }

            if (hasTargetGreen) {
                greenCellInfo = greenCellInfo.slice(0, -1);
                console.log(`📌 汇总表第${row}行 → 含目标绿色单元格:${greenCellInfo}`);

                if (!foundGreenRows.has(row)) {
                    var studentId = summarySheet.Cells(row, summaryStudentIdCol).Value();
                    studentId = studentId ? studentId.toString().trim() : "";
                    if (studentId) {
                        greenRowStudentIds.push(studentId);
                        foundGreenRows.add(row);
                        console.log(`   → 该行学号:${studentId}`);
                    } else {
                        console.log(`⚠️  汇总表第${row}行(含目标绿色)但学号列无有效数据,跳过!`);
                    }
                }
            }
        }

        if (greenRowStudentIds.length === 0) {
            console.log("❌ 汇总表中未找到任何含目标绿色(RGB(146,208,80))单元格的行!");
            return;
        }
        console.log(`✅ 共找到${foundGreenRows.size}行含目标绿色单元格,收集到${greenRowStudentIds.length}个有效学号:`, greenRowStudentIds);

        // 8. 查找未就业表的「学号」列
        var unemployedStudentIdCol = findHeaderColumn(unemployedSheet, config.unemployedHeaderRow, config.targetHeader, "未就业表");
        switch (unemployedStudentIdCol) {
            case -3: console.log("❌ 未就业表表头查找过程出错,请检查表格是否损坏!"); return;
            case -2: console.log("❌ 未就业表第" + config.unemployedHeaderRow + "行(表头行)无有效数据!"); return;
            case -1: console.log("❌ 在未就业表第" + config.unemployedHeaderRow + "行未找到「" + config.targetHeader + "」表头!"); return;
            default: console.log("✅ 未就业表「" + config.targetHeader + "」列位置:第" + unemployedStudentIdCol + "列");
        }

        // 9. 核心步骤2:在未就业表中匹配学号,标黄对应行并记录行信息
        var unemployedUsedRange = unemployedSheet.UsedRange;
        if (!unemployedUsedRange) {
            console.log("❌ 未就业表无有效数据!");
            return;
        }
        var unemployedLastRow = unemployedUsedRange.Rows.Count;
        if (unemployedLastRow <= config.unemployedHeaderRow) {
            console.log("❌ 未就业表除表头外无其他数据!");
            return;
        }
        console.log(`ℹ️ 未就业表数据总行数:${unemployedLastRow - config.unemployedHeaderRow}行,开始批量匹配...`);

        // 遍历未就业表,标黄匹配行并记录
        for (var i = config.unemployedHeaderRow + 1; i <= unemployedLastRow; i++) {
            var currentId = unemployedSheet.Cells(i, unemployedStudentIdCol).Value();
            currentId = currentId ? currentId.toString().trim() : "";

            if (greenRowStudentIds.includes(currentId)) {
                var matchedRange = unemployedSheet.Rows(i);
                matchedRange.Interior.Color = RGB(255, 255, 0); // 标黄
                highlightedRows.push({ rowNum: i, studentId: currentId }); // 记录行号和学号
                console.log(`✅ 未就业表第${i}行(学号:${currentId})已标黄!`);
            }
        }

        // 无标黄行时直接结束
        if (highlightedRows.length === 0) {
            console.log("❌ 未就业表中无匹配的学号,未标黄任何行!");
            MsgBox("未就业表中无匹配的学号,未标黄任何行!");
            return;
        }

        // 10. 核心新增:弹窗询问删除方式
        console.log(`ℹ️ 共标黄${highlightedRows.length}行,开始询问删除方式...`);
        var deletePrompt = `已在未就业表中标黄${highlightedRows.length}行匹配数据!\n请选择删除方式:\n1 - 批量删除所有标黄行\n2 - 逐个确认删除标黄行\n3 - 取消删除`;
        var userChoice = MsgBox(deletePrompt, 1 + 32 + 256); // 1=OK/Cancel + 32=问号图标 + 256=默认按钮1

        // 处理用户选择(WPS MsgBox返回值:1=确定,2=取消,3=中止,4=重试,5=忽略,6=是,7=否)
        // 这里通过输入框补充选择(因为MsgBox无法直接获取1/2/3输入,改用InputBox)
        var userInput = InputBox(deletePrompt + "\n请输入数字1/2/3并点击确定", "选择删除方式", "1");
        userInput = userInput ? userInput.trim() : "3"; // 默认为取消删除

        switch (userInput) {
            case "1":
                // 批量删除所有标黄行(注意:删除行时需从下往上删,避免行号偏移)
                console.log("📥 用户选择:批量删除所有标黄行");
                // 按行号降序排序(从下往上删)
                var sortedRows = highlightedRows.sort((a, b) => b.rowNum - a.rowNum);
                var deletedCount = 0;

                for (var idx = 0; idx < sortedRows.length; idx++) {
                    var rowInfo = sortedRows[idx];
                    try {
                        unemployedSheet.Rows(rowInfo.rowNum).Delete();
                        console.log(`✅ 批量删除:未就业表第${rowInfo.rowNum}行(学号:${rowInfo.studentId})`);
                        deletedCount++;
                    } catch (e) {
                        console.error(`❌ 批量删除失败:第${rowInfo.rowNum}行`, e.message);
                    }
                }

                MsgBox(`批量删除完成!\n共删除${deletedCount}行标黄数据(总标黄${highlightedRows.length}行)`);
                console.log(`🎉 批量删除完成!删除${deletedCount}行,剩余${highlightedRows.length - deletedCount}行未删除`);
                break;

            case "2":
                // 逐个确认删除
                console.log("📥 用户选择:逐个确认删除标黄行");
                var deletedCount = 0;
                var skippedCount = 0;

                // 按行号升序排序(从上往下确认)
                var sortedRows = highlightedRows.sort((a, b) => a.rowNum - b.rowNum);
                // 重新获取行号(避免之前删除导致的行号偏移,逐个处理时实时判断)
                for (var idx = 0; idx < sortedRows.length; idx++) {
                    var rowInfo = sortedRows[idx];
                    // 重新验证行是否存在(避免已被删除)
                    try {
                        var rowExists = unemployedSheet.Rows(rowInfo.rowNum).Interior.Color === RGB(255, 255, 0);
                        if (!rowExists) {
                            console.log(`⚠️  第${rowInfo.rowNum}行已不存在,跳过`);
                            skippedCount++;
                            continue;
                        }

                        var confirmDelete = MsgBox(`是否删除未就业表第${rowInfo.rowNum}行?\n学号:${rowInfo.studentId}`, 4 + 32); // 4=是/否 + 32=问号图标
                        if (confirmDelete === 6) { // 6=是
                            unemployedSheet.Rows(rowInfo.rowNum).Delete();
                            console.log(`✅ 逐个删除:未就业表第${rowInfo.rowNum}行(学号:${rowInfo.studentId})`);
                            deletedCount++;
                        } else { // 7=否
                            console.log(`⚠️  用户取消删除:第${rowInfo.rowNum}行(学号:${rowInfo.studentId})`);
                            skippedCount++;
                        }
                    } catch (e) {
                        console.error(`❌ 逐个删除失败:第${rowInfo.rowNum}行`, e.message);
                        skippedCount++;
                    }
                }

                MsgBox(`逐个删除完成!\n共删除${deletedCount}行,跳过${skippedCount}行`);
                console.log(`🎉 逐个删除完成!删除${deletedCount}行,跳过${skippedCount}行`);
                break;

            case "3":
                // 取消删除
                console.log("📥 用户选择:取消删除");
                MsgBox("已取消删除操作,标黄行保留不变!");
                break;

            default:
                // 输入无效,默认取消
                console.log(`⚠️  用户输入无效(${userInput}),默认取消删除`);
                MsgBox("输入无效!请输入1/2/3,已取消删除操作");
                break;
        }

        // 11. 输出最终统计结果
        console.log("🎉 整体操作完成!");
        console.log(`- 汇总表含目标绿色单元格行数:${foundGreenRows.size}行`);
        console.log(`- 未就业表标黄行数:${highlightedRows.length}行`);
        console.log(`- 用户选择删除方式:${userInput === "1" ? "批量删除" : userInput === "2" ? "逐个删除" : "取消删除"}`);

    } catch (e) {
        console.error("❌ 执行失败!", "具体错误:", e.message, "错误类型:", e.name);
        MsgBox("执行失败!具体错误:" + e.message);
    }
}

// 执行函数
//highlightAndDeleteMatchedRows();

只要在同一个Project(工作簿)里每个Module里的函数就能互相调用

(面相对象编程)

相关推荐
GalenZhang8882 小时前
Excel/WPS 表格数据合并操作指南
excel·wps
海拥✘3 小时前
Excel制作跳动爱心动画:一步步创建动态数学心形图
excel
北芝科技3 小时前
WPS知识库文件数超10亿:以AI技术夯实KaaS知识引擎,重构知识服务生态
人工智能·重构·wps
教练、我想打篮球4 小时前
127 apache poi3.11 写 word 中内嵌 表格换行的输出
word·excel·docx·换行
醉卧考场君莫笑17 小时前
EXCEL数据分析基础(没有数据统计和数据可视化)
信息可视化·数据分析·excel
yesyesyoucan1 天前
智能文件格式转换平台:文本/Excel与CSV的无缝互转解决方案
excel
hqyjzsb1 天前
2026年AI证书选择攻略:当“平台绑定”与“能力通用”冲突,如何破局?
大数据·c语言·人工智能·信息可视化·职场和发展·excel·学习方法
牛奔1 天前
Linux 的日志分析命令
linux·运维·服务器·python·excel
爱上妖精的尾巴1 天前
6-13 WPS JS宏 Map实例2--拆分记录到表格
javascript·restful·wps