使用wps js宏合并当前工作簿中所有未隐藏工作表,其中表头占前4行,跳过最后一行不合并,并在最后追加一列标明源表名,并生成新表命名为“四好合并”,将“四好合并”中第2列重复的数据所在行的所有数据输出到命名为“四好重复”的新表中,并在最下方统计重复数据相关信息。注意整个过程不生成新的工作簿
时间: 2025-07-20 20:26:36 浏览: 6
<think>我们已经在同一个工作簿内操作,不生成新工作簿。因此,我们只需要在当前工作簿中创建两个新工作表("四好合并"和"四好重复")即可。
注意:如果这两个工作表已经存在,我们需要先删除它们(或者覆盖),但根据要求,我们不需要新工作簿,所以就在当前工作簿操作。
步骤:
1. 遍历当前工作簿中所有未隐藏的工作表(Visible属性为xlSheetVisible,即-1)。
2. 对于每个工作表,读取数据(忽略前4行表头,忽略最后一行)。
3. 将数据合并到一个数组中,同时为每一行添加一列,内容为源工作表名称。
4. 将合并后的数据写入新工作表“四好合并”中。
5. 在“四好合并”工作表中,检查第2列(即B列)的数据,找出重复的数据行(整行)。
6. 将这些重复的行复制到新工作表“四好重复”中。
7. 在“四好重复”工作表的最后,统计重复数据的信息(例如:重复的值、重复的次数等)。
注意:WPS JS宏中,数组索引从0开始,但工作表的行和列从1开始。
我们将分步实现:
第一步:合并工作表
- 创建“四好合并”工作表
- 遍历每个未隐藏的工作表(跳过“四好合并”和“四好重复”,如果存在的话,但一开始可能不存在,不过我们会在合并前删除这两个工作表,避免冲突)
- 读取每个工作表的数据(UsedRange),转换为二维数组
- 跳过前4行(即从第5行开始),到倒数第二行(即最后一行不取)
- 每一行添加源表名
第二步:处理重复数据
- 在“四好合并”表中,检查第2列(即数组的第二列,索引1)的重复值
- 将重复的行(包括表头)复制到“四好重复”工作表
第三步:在“四好重复”工作表的末尾添加统计信息
- 统计重复值出现的次数,以及重复的具体值
另外,为了避免重复运行导致工作表已经存在,我们在创建新表前先删除已存在的同名工作表。
代码实现如下:</think># WPS JS宏实现工作表合并与重复数据统计
下面是一个完整的WPS JS宏解决方案,用于合并当前工作簿中所有未隐藏工作表,并按要求生成"四好合并"和"四好重复"工作表,整个过程完全在当前工作簿内完成。
```javascript
function MergeSheetsAndFindDuplicates() {
const wb = Application.ActiveWorkbook;
try {
Application.ScreenUpdating = false; // 禁止屏幕刷新,提高性能
// 步骤1: 创建"四好合并"表
const mergedSheet = CreateMergedSheet(wb);
// 步骤2: 创建"四好重复"表
CreateDuplicateSheet(wb, mergedSheet);
// 步骤3: 在"四好重复"表底部添加统计信息
AddDuplicateStatistics(wb.Sheets.Item("四好重复"));
// 激活合并后的工作表
mergedSheet.Activate();
Application.StatusBar = "操作完成!已创建'四好合并'和'四好重复'工作表";
} catch (e) {
Application.StatusBar = "发生错误: " + e.message;
} finally {
Application.ScreenUpdating = true; // 恢复屏幕刷新
}
}
// 创建合并表
function CreateMergedSheet(wb) {
// 删除可能已存在的旧表
DeleteSheetIfExists(wb, "四好合并");
// 创建新表并设置位置
const mergedSheet = wb.Sheets.Add();
mergedSheet.Name = "四好合并";
mergedSheet.Move(wb.Sheets[wb.Sheets.Count]); // 移到工作表末尾
// 添加标题
mergedSheet.Range("A1").Value = "四好合并数据表";
mergedSheet.Range("A1").Font.Bold = true;
mergedSheet.Range("A1").Font.Size = 16;
mergedSheet.Range("A1").HorizontalAlignment = -4108; // 居中
// 初始化合并数据
let allData = [];
let hasHeaders = false;
// 遍历所有工作表
for (let i = 1; i <= wb.Sheets.Count; i++) {
const sheet = wb.Sheets.Item(i);
// 跳过隐藏工作表和自己创建的表
if (sheet.Visible !== -1 || sheet.Name === "四好合并" || sheet.Name === "四好重复")
continue;
// 获取已使用区域
const usedRange = sheet.UsedRange;
if (!usedRange || usedRange.Count === 0) continue;
// 获取数据数组
const data = usedRange.Value;
const rowCount = data.length;
// 跳过表头(前4行)和最后一行
const startRow = 4; // 第5行开始(索引4)
const endRow = rowCount - 2; // 倒数第二行(索引length-2)
if (startRow <= endRow) {
// 如果是第一个工作表,添加表头
if (!hasHeaders && rowCount > 0) {
const headers = data[0].slice(); // 复制第一行作为表头
headers.push("源表名"); // 添加源表名列
allData.push(headers);
hasHeaders = true;
}
// 处理数据并添加源表名
for (let r = startRow; r <= endRow; r++) {
if (r >= data.length) continue; // 确保行存在
const rowData = data[r].slice(); // 复制行数据
rowData.push(sheet.Name); // 添加源表名
allData.push(rowData);
}
}
}
// 写入合并数据
if (allData.length > 0) {
// 写入数据
const outputRange = mergedSheet.Range(
mergedSheet.Cells(3, 1),
mergedSheet.Cells(3 + allData.length - 1, allData[0].length)
);
outputRange.Value = allData;
// 设置格式
outputRange.Borders.LineStyle = 1; // 添加边框
mergedSheet.Columns.AutoFit(); // 自动调整列宽
// 设置表头格式
if (allData.length > 0) {
mergedSheet.Rows("3:3").Font.Bold = true; // 表头加粗
mergedSheet.Rows("3:3").Interior.Color = 13434828; // 浅蓝色背景
// 冻结表头
mergedSheet.Activate();
mergedSheet.Range("A4").Select();
Application.ActiveWindow.FreezePanes = true;
}
} else {
mergedSheet.Range("A3").Value = "没有找到可合并的数据";
}
return mergedSheet;
}
// 创建重复数据表
function CreateDuplicateSheet(wb, mergedSheet) {
// 删除可能已存在的旧表
DeleteSheetIfExists(wb, "四好重复");
// 创建新表
const duplicateSheet = wb.Sheets.Add();
duplicateSheet.Name = "四好重复";
duplicateSheet.Move(wb.Sheets[wb.Sheets.Count]); // 移到工作表末尾
// 添加标题
duplicateSheet.Range("A1").Value = "四好重复数据表";
duplicateSheet.Range("A1").Font.Bold = true;
duplicateSheet.Range("A1").Font.Size = 16;
duplicateSheet.Range("A1").HorizontalAlignment = -4108; // 居中
// 获取合并表数据
const mergedData = mergedSheet.UsedRange.Value;
if (!mergedData || mergedData.length < 2) {
duplicateSheet.Range("A3").Value = "没有重复数据";
return duplicateSheet;
}
// 找出第2列(B列)的重复值
const colIndex = 1; // 第2列索引(0-based)
const valueMap = new Map(); // 使用Map存储值及其行索引
// 第一遍:统计每个值出现的行
for (let r = 1; r < mergedData.length; r++) { // 跳过标题行
const value = mergedData[r][colIndex];
if (value === null || value === undefined) continue;
if (!valueMap.has(value)) {
valueMap.set(value, []);
}
valueMap.get(value).push(r);
}
// 收集重复行
const duplicateRows = [];
const duplicateValues = [];
for (const [value, rows] of valueMap) {
if (rows.length > 1) { // 重复值
duplicateValues.push(value);
for (const row of rows) {
duplicateRows.push(mergedData[row]);
}
}
}
// 如果没有重复数据
if (duplicateRows.length === 0) {
duplicateSheet.Range("A3").Value = "没有重复数据";
return duplicateSheet;
}
// 写入重复数据
// 添加标题行
const headers = mergedData[0];
duplicateSheet.Range("A3").Resize(1, headers.length).Value = [headers];
// 写入重复数据
const outputRange = duplicateSheet.Range(
duplicateSheet.Cells(4, 1),
duplicateSheet.Cells(4 + duplicateRows.length - 1, headers.length)
);
outputRange.Value = duplicateRows;
// 设置格式
outputRange.Borders.LineStyle = 1;
duplicateSheet.Columns.AutoFit();
// 设置表头格式
duplicateSheet.Rows("3:3").Font.Bold = true;
duplicateSheet.Rows("3:3").Interior.Color = 13434828; // 浅蓝色背景
// 高亮显示重复值
const colLetter = String.fromCharCode(65 + colIndex); // B列
const duplicateRange = duplicateSheet.Range(
`${colLetter}4:${colLetter}${3 + duplicateRows.length}`
);
duplicateRange.Interior.Color = 13431551; // 浅黄色背景
// 冻结表头
duplicateSheet.Activate();
duplicateSheet.Range("A4").Select();
Application.ActiveWindow.FreezePanes = true;
return duplicateSheet;
}
// 添加重复数据统计信息
function AddDuplicateStatistics(sheet) {
if (!sheet || !sheet.UsedRange || sheet.UsedRange.Count === 0) return;
// 获取重复数据
const data = sheet.UsedRange.Value;
if (data.length < 4) return; // 无重复数据
// 统计重复项(第2列)
const colIndex = 1; // 第2列(B列)
const valueCount = new Map();
// 统计重复次数(从第4行开始)
for (let r = 3; r < data.length; r++) {
const value = data[r][colIndex];
if (value === null || value === undefined) continue;
if (!valueCount.has(value)) {
valueCount.set(value, 0);
}
valueCount.set(value, valueCount.get(value) + 1);
}
// 找到最后一行
const lastRow = sheet.UsedRange.Row + sheet.UsedRange.Rows.Count;
// 添加统计标题
sheet.Cells(lastRow + 2, 1).Value = "重复数据统计:";
sheet.Cells(lastRow + 2, 1).Font.Bold = true;
sheet.Cells(lastRow + 2, 1).Font.Size = 12;
// 写入统计信息
let rowOffset = 3;
for (const [value, count] of valueCount) {
sheet.Cells(lastRow + rowOffset, 1).Value = `值: ${value}`;
sheet.Cells(lastRow + rowOffset, 2).Value = `重复次数: ${count}`;
rowOffset++;
}
// 添加总计
sheet.Cells(lastRow + rowOffset, 1).Value = "总计:";
sheet.Cells(lastRow + rowOffset, 1).Font.Bold = true;
sheet.Cells(lastRow + rowOffset, 2).Value = `重复数据行数: ${valueCount.size} 个值, ${data.length - 3} 行`;
// 设置统计区域格式
const startRow = lastRow + 2;
const endRow = lastRow + rowOffset;
const statRange = sheet.Range(
sheet.Cells(startRow, 1),
sheet.Cells(endRow, 2)
);
statRange.Borders.LineStyle = 1;
statRange.Font.Bold = true;
statRange.Interior.Color = 13434828; // 浅蓝色背景
// 自动调整列宽
sheet.Columns("A:B").AutoFit();
}
// 辅助函数:删除已存在的工作表
function DeleteSheetIfExists(wb, sheetName) {
try {
const sheet = wb.Sheets.Item(sheetName);
sheet.Delete();
return true;
} catch (e) {
// 工作表不存在,忽略错误
return false;
}
}
// 执行主函数
MergeSheetsAndFindDuplicates();
```
## 代码功能详解
### 1. 主流程 `MergeSheetsAndFindDuplicates()`
- 禁用屏幕刷新提高性能
- 创建合并表
- 创建重复数据表
- 添加统计信息
- 异常处理和状态更新
### 2. 创建合并表 `CreateMergedSheet()`
- **智能表头处理**:只从第一个工作表中提取表头
- **数据过滤**:跳过前4行表头和最后一行
- **源表名添加**:在每行末尾添加源工作表名称
- **格式优化**:自动调整列宽、添加边框、冻结表头
### 3. 创建重复数据表 `CreateDuplicateSheet()`
- **重复检测**:使用Map数据结构高效检测重复值
- **高亮显示**:对重复值所在单元格添加黄色背景
- **格式优化**:自动调整列宽、添加边框、冻结表头
### 4. 添加统计信息 `AddDuplicateStatistics()`
- **重复值统计**:计算每个重复值的出现次数
- **数据汇总**:显示重复值总数和重复行总数
- **可视化展示**:使用浅蓝色背景突出统计区域
### 5. 辅助函数 `DeleteSheetIfExists()`
- 安全删除已存在的工作表,避免命名冲突
## 使用说明
1. 打开包含多个工作表的工作簿
2. 确保需要合并的工作表为可见状态(非隐藏)
3. 运行此宏
4. 宏将在当前工作簿内创建两个新表:
- **"四好合并"表**:包含所有工作表的合并数据
- **"四好重复"表**:包含第2列重复的数据行及统计信息
## 特点与优势
1. **高效处理**:使用`ScreenUpdating = false`提升性能
2. **智能识别**:自动跳过隐藏工作表和宏创建的表
3. **数据完整性**:保留原始数据格式和类型
4. **可视化设计**:使用颜色和格式增强可读性
5. **错误处理**:完善的异常捕获和状态反馈
## 注意事项
- 确保工作表中的数据区域是连续的
- 如果数据量非常大,处理可能需要一些时间
- 宏不会修改原始工作表,所有操作都在新表中进行
阅读全文
相关推荐



















