乐于分享
好东西不私藏

WPS JS宏:通用数据分组求和

WPS JS宏:通用数据分组求和

                        
function demo123() {    // ========== 第1步:选择数据区域(包含标题行) ==========    var dataRng = null;    try {        dataRng = Application.InputBox(            "请框选数据区域(第一行为列标题,以下为数据行)",            "选择数据区域",            nullnullnullnullnull8        );    } catch (e) {        alert("输入框调用失败,请确认 WPS 版本支持。");        return;    }    if (dataRng === false || dataRng === nullreturn;    if (typeof dataRng === "string") {        try { dataRng = Range(dataRng); } catch (e) { alert("无效的区域地址:" + dataRng); return; }    }    if (!dataRng || typeof dataRng.Address !== "function") {        alert("未获取到有效的数据区域,请重新选择。");        return;    }    // 读取数据并转为二维数组    var arr = dataRng.Value();    if (arr === null || arr === undefined) { alert("所选区域无数据"); return; }    // 若为单个值,转为二维    if (!Array.isArray(arr)) { arr = [[arr]]; }    else if (arr.length > 0 && !Array.isArray(arr[0])) { arr = [arr]; }    if (arr.length === 0 || !Array.isArray(arr[0])) { alert("数据格式异常"); return; }    var totalRows = arr.length;    var colCount = arr[0].length;    var startCol = dataRng.Column; // 数据区域起始列号(1-based)    // 至少需要一行标题 + 一行数据,且至少2列    if (totalRows < 2) {        alert("数据区域至少需要一行标题和一行数据。");        return;    }    if (colCount < 2) {        alert("数据区域至少需要2列。");        return;    }    // 分离标题行和数据行    var headerRow = arr[0];               // 标题行(一维数组)    var dataRows = arr.slice(1);          // 数据行(二维数组)    // ========== 第2步:选择分类列 ==========    var classRng = null;    try {        classRng = Application.InputBox(            "请点击分类列(分组依据)中的任意单元格(含标题行)",            "选择分类列",            nullnullnullnullnull8        );    } catch (e) { alert("输入框调用失败"); return; }    if (classRng === false || classRng === nullreturn;    if (typeof classRng === "string") {        try { classRng = Range(classRng); } catch (e) { alert("无效的单元格地址"); return; }    }    if (!classRng || typeof classRng.Address !== "function") {        alert("未获取到有效的分类列单元格");        return;    }    var classColAbs = classRng.Column;    var classColIdx = classColAbs - startCol;    if (classColIdx < 0 || classColIdx >= colCount) {        alert("分类列不在所选数据区域内,请重新选择。");        return;    }    var classHeader = headerRow[classColIdx]; // 获取分类列标题    // ========== 第3步:选择求和列 ==========    var sumRng = null;    try {        sumRng = Application.InputBox(            "请点击求和列(数值列)中的任意单元格(含标题行)",            "选择求和列",            nullnullnullnullnull8        );    } catch (e) { alert("输入框调用失败"); return; }    if (sumRng === false || sumRng === nullreturn;    if (typeof sumRng === "string") {        try { sumRng = Range(sumRng); } catch (e) { alert("无效的单元格地址"); return; }    }    if (!sumRng || typeof sumRng.Address !== "function") {        alert("未获取到有效的求和列单元格");        return;    }    var sumColAbs = sumRng.Column;    var sumColIdx = sumColAbs - startCol;    if (sumColIdx < 0 || sumColIdx >= colCount) {        alert("求和列不在所选数据区域内,请重新选择。");        return;    }    var sumHeader = headerRow[sumColIdx];   // 获取求和列标题    // ========== 第4步:分组汇总(使用用户指定的列,从数据行开始) ==========    // 提取唯一分类值(过滤空值)    var groupSet = new Set();    for (var i = 0; i < dataRows.length; i++) {        var val = dataRows[i][classColIdx];        if (val !== undefined && val !== "") groupSet.add(val);    }    var group = [...groupSet];    if (group.length === 0) { alert("分类列没有有效数据"); return; }    // 构建结果二维数组,先放入表头(动态获取)    var result = [];    result.push([classHeader, sumHeader]); // 表头行    // 对各分组求和    for (var gIdx = 0; gIdx < group.length; gIdx++) {        var g = group[gIdx];        var sum = 0;        for (var i = 0; i < dataRows.length; i++) {            if (dataRows[i][classColIdx] == g) {                var num = Number(dataRows[i][sumColIdx]);                if (!isNaN(num)) sum += num;            }        }        result.push([g, sum]);    }    // ========== 第5步:选择存放起始单元格 ==========    var targetRng = null;    try {        targetRng = Application.InputBox(            "请选择结果存放的起始单元格(如 E1,表头将写入该行)",            "选择目标单元格",            nullnullnullnullnull8        );    } catch (e) { alert("输入框调用失败"); return; }    if (targetRng === false || targetRng === nullreturn;    if (typeof targetRng === "string") {        try { targetRng = Range(targetRng); } catch (e) { alert("无效的单元格地址"); return; }    }    if (!targetRng || typeof targetRng.Address !== "function") {        alert("未获取到有效的目标单元格");        return;    }    // 写入结果(包含动态表头)    targetRng.Resize(result.length, 2).Value2 = result;    alert("汇总完成!结果已从 " + targetRng.Address() + " 开始输出。\n表头为:" + classHeader + " | " + sumHeader);}
需要源码文件? 关注后回复”260627″,获取完整 示例文件下载链接。