工作簿中名称为“合并数据”的工作表表头占三行,数据行从第四行开始,。用JS宏查找当前工作簿中名称为“合并数据”的工作表中第三列重复的数据所在行中的所有内容,并将其输出在一张新工作表中,命名为”日期重复“,并在最后添加统计重复数据个数,如果已存在名为“日期重复”的表格,则删除“日期重复”旧表后再输出新表
时间: 2025-07-20 14:29:51 浏览: 8
<think>我们需要注意以下几点:
1. 表头占三行,数据从第四行开始。
2. 第三列重复的数据:注意第三列在数组中是索引2(因为第一列索引0,第二列1,第三列2)。
3. 如果存在名为“日期重复”的工作表,则先删除再创建。
4. 输出重复数据行到新表,并在最后添加统计重复数据个数。
步骤:
a. 获取当前工作簿和工作表“合并数据”。
b. 检查“日期重复”表是否存在,存在则删除。
c. 读取“合并数据”表的数据(从第四行开始)。
d. 遍历数据,统计第三列重复的数据,并记录重复行。
e. 创建新工作表“日期重复”,写入重复行数据(注意表头处理,我们只保留第三行作为新表的表头?或者保留前三行?根据需求,这里只输出重复的数据行,所以新表我们只写一行表头(使用第三行)?但原表头有三行,我们可能需要在新表中只使用一行表头(第三行)作为列名。
f. 在数据下方添加统计信息:每个重复值出现的次数,以及总共有几个重复值。
但是,根据问题描述,我们只需要输出重复数据所在行(所有内容)到新表,并在最后添加统计重复数据个数(可能是指每个重复值出现的次数,以及重复项的总个数?)
我们这样设计:
1. 新表的第一行是表头(原表的第三行表头)。
2. 然后写入所有重复的数据行(注意:重复的数据行包括重复出现的每一行,包括第一次出现和后续重复出现)。
3. 在数据下方,我们添加一个统计区域:列出每个重复的日期和重复次数,最后一行给出总重复行数(即重复数据的总行数,注意:同一个日期重复出现多次,那么重复行数为该日期出现次数-1,但这里我们统计的是所有重复出现的行,即每个重复日期除了第一次出现外,其余都算重复行。但我们收集的是所有重复行(包括第一次和后续重复)?实际上,我们通常将重复行定义为第二次及以后出现的行。所以,重复行数 = 总行数 - 唯一日期数。
然而,问题要求输出的是重复的数据所在行中的所有内容,所以我们在收集重复行时,对于每个重复的日期,除了第一次出现的那一行,其他行都算重复行。但注意,第一次出现的那一行如果被重复,那么它也是重复数据的一部分?实际上,当有重复时,第一次出现的行也应该被包括在重复数据中,因为它是重复数据的一部分(比如有两个相同日期,那么这两行都是重复数据行)。所以,我们收集所有出现次数大于1的日期对应的所有行。
因此,步骤:
- 首先,遍历数据,统计每个日期出现的次数和每一行的数据。
- 然后,对于出现次数大于1的日期,将其对应的所有行都收集起来。
另外,统计重复数据个数:我们可以在新表的最后添加一个统计表,列出每个重复日期及其出现次数,并计算总重复行数(即所有重复日期对应的行数之和,注意每个重复日期对应的行数就是它的出现次数,但这里我们统计的是重复行,所以总重复行数 = 所有重复日期的行数之和 - 重复日期的种类数(因为每个重复日期的第一次出现不算重复?)?但根据我们的收集方式,我们收集了重复日期的所有行,所以总重复行数就是收集的行数。
我们可以在新表的数据区域下方,添加一个统计区域:
例如:
重复日期统计:
日期 重复次数
2020/1/1 3
2020/1/2 2
...
总重复行数:5
具体实现:
1. 删除已存在的“日期重复”表。
2. 读取源数据(从第4行开始)。
3. 使用一个对象(或Map)来记录每个日期对应的行数据数组和行号(可选)。
4. 遍历所有数据行,将第三列的值作为键,将行数据存入该键对应的数组中。
5. 遍历这个对象,将长度大于1的数组中的所有行数据收集起来(这些就是重复行)。
6. 将收集的重复行写入新表,从第一行开始(第一行写入表头,即原表的第三行)。
7. 在重复行数据下方空几行,然后写入统计信息:每个重复日期和重复次数,最后一行写总重复行数(即收集的重复行的总行数)。
注意:重复次数就是该日期出现的次数,统计信息中我们只列出重复日期(即出现次数大于1的日期)。
代码实现:
由于WPS JS宏的限制,我们使用ActiveX对象来操作。
注意:删除工作表时,如果不存在,会报错,所以先检查。
另外,表头处理:原表头占三行,我们只需要第三行作为新表的表头。
具体代码:</think>### 解决方案:处理表头占三行的重复数据查找与统计(带旧表删除功能)
以下代码实现了在表头占三行的"合并数据"工作表中查找第三列重复数据,并输出到"日期重复"工作表。如果"日期重复"工作表已存在,会先删除旧表再创建新表:
```javascript
function 查找日期重复数据() {
try {
const workbook = ThisWorkbook;
// 检查并删除已存在的"日期重复"工作表
try {
const oldSheet = workbook.Sheets.Item("日期重复");
Application.DisplayAlerts = false; // 禁用删除确认提示
oldSheet.Delete();
Application.DisplayAlerts = true;
console.log("已删除旧表'日期重复'");
} catch (e) {
// 表不存在,无需处理
}
// 获取源数据表
const sourceSheet = workbook.Sheets.Item("合并数据");
if (!sourceSheet) throw new Error("找不到名为'合并数据'的工作表");
// 获取数据区域(跳过前三行表头)
const dataRange = sourceSheet.UsedRange;
const totalRows = dataRange.Rows.Count;
const totalCols = dataRange.Columns.Count;
// 验证数据行数
if (totalRows <= 3) {
console.log("数据行不足,无法处理");
return;
}
// 获取数据(从第4行开始)
const dataValues = sourceSheet.Range(
`A4:${String.fromCharCode(64 + totalCols)}${totalRows}`
).Value2;
// 获取表头(第三行作为新表头)
const headerRow = sourceSheet.Range("A3").Resize(1, totalCols).Value2[0];
// 统计重复数据
const { duplicateRows, dateStats } = findDuplicateRows(dataValues, 2); // 第三列索引为2
// 创建新工作表
const dupSheet = workbook.Sheets.Add(null, workbook.Sheets(workbook.Sheets.Count));
dupSheet.Name = "日期重复";
// 写入重复数据
if (duplicateRows.length > 0) {
// 写入表头
dupSheet.Range("A1").Resize(1, headerRow.length).Value2 = headerRow;
// 写入重复数据行
dupSheet.Range("A2").Resize(duplicateRows.length, headerRow.length).Value2 = duplicateRows;
// 设置表头样式
const headerRange = dupSheet.Range("A1").Resize(1, headerRow.length);
headerRange.Font.Bold = true;
headerRange.Interior.Color = RGB(200, 200, 200);
} else {
dupSheet.Range("A1").Value2 = "无重复日期数据";
}
// 添加统计信息
if (duplicateRows.length > 0) {
addStatistics(dupSheet, duplicateRows.length, dateStats);
}
return "处理完成!";
} catch (error) {
console.error("处理出错: " + error.message);
return "处理失败!";
}
}
// 查找重复行并统计
function findDuplicateRows(data, colIndex) {
const duplicateRows = [];
const dateStats = new Map();
const seen = new Map();
// 遍历所有数据行
for (let i = 0; i < data.length; i++) {
const dateValue = data[i][colIndex];
// 初始化统计信息
if (!dateStats.has(dateValue)) {
dateStats.set(dateValue, {
count: 0,
firstRow: i + 4, // 实际行号(表头占3行)
rows: []
});
}
// 更新统计信息
const stat = dateStats.get(dateValue);
stat.count++;
stat.rows.push(i + 4); // 记录实际行号
// 收集重复行(重复次数>1)
if (seen.has(dateValue)) {
// 如果是首次发现重复,添加之前出现的行
if (seen.get(dateValue) !== -1) {
duplicateRows.push(data[seen.get(dateValue)]);
seen.set(dateValue, -1); // 标记为已处理
}
duplicateRows.push(data[i]);
} else {
seen.set(dateValue, i);
}
}
return { duplicateRows, dateStats };
}
// 添加统计信息到工作表
function addStatistics(sheet, duplicateCount, dateStats) {
const startRow = duplicateCount + 3; // 数据行数 + 表头行 + 2行空白
// 添加统计标题
sheet.Range(`A${startRow}`).Value2 = "日期重复统计";
sheet.Range(`A${startRow}`).Font.Bold = true;
sheet.Range(`A${startRow}`).Font.Size = 14;
// 添加表头
const statHeaders = ["日期值", "出现次数", "首次出现行", "所有行号"];
const headerRange = sheet.Range(`A${startRow + 1}`).Resize(1, statHeaders.length);
headerRange.Value2 = statHeaders;
headerRange.Font.Bold = true;
headerRange.Interior.Color = RGB(220, 220, 220);
// 添加统计数据
let rowIndex = startRow + 2;
let totalDuplicates = 0;
let duplicateDates = 0;
for (const [dateValue, stat] of dateStats) {
if (stat.count > 1) {
sheet.Range(`A${rowIndex}`).Value2 = dateValue;
sheet.Range(`B${rowIndex}`).Value2 = stat.count;
sheet.Range(`C${rowIndex}`).Value2 = stat.firstRow;
// 合并行号显示(避免过多列)
const rowNumbers = stat.rows.join(", ");
sheet.Range(`D${rowIndex}`).Value2 = rowNumbers;
// 高亮重复次数多的行
if (stat.count > 2) {
sheet.Range(`A${rowIndex}:D${rowIndex}`).Interior.Color = RGB(255, 200, 200);
}
rowIndex++;
totalDuplicates += stat.count;
duplicateDates++;
}
}
// 添加汇总信息
const summaryRow = rowIndex + 1;
sheet.Range(`A${summaryRow}`).Value2 = "汇总统计";
sheet.Range(`A${summaryRow}`).Font.Bold = true;
sheet.Range(`A${summaryRow}`).Font.Size = 12;
sheet.Range(`A${summaryRow + 1}`).Value2 = "重复日期总数";
sheet.Range(`B${summaryRow + 1}`).Value2 = duplicateDates;
sheet.Range(`A${summaryRow + 2}`).Value2 = "总重复行数";
sheet.Range(`B${summaryRow + 2}`).Value2 = totalDuplicates;
sheet.Range(`A${summaryRow + 3}`).Value2 = "实际重复数据行";
sheet.Range(`B${summaryRow + 3}`).Value2 = duplicateCount;
// 添加说明
sheet.Range(`A${summaryRow + 5}`).Value2 = "注:实际重复数据行 = 总重复行数 - 重复日期数";
sheet.Range(`A${summaryRow + 5}`).Font.Italic = true;
sheet.Range(`A${summaryRow + 5}`).Font.Color = RGB(100, 100, 100);
// 自动调整列宽
sheet.UsedRange.Columns.AutoFit();
}
// 执行函数
查找日期重复数据();
```
### 代码功能详解
#### 1. 主函数 `查找日期重复数据()`
- **旧表处理**:
```javascript
try {
const oldSheet = workbook.Sheets.Item("日期重复");
Application.DisplayAlerts = false; // 禁用删除确认提示
oldSheet.Delete();
Application.DisplayAlerts = true;
} catch (e) {
// 表不存在,无需处理
}
```
- **数据获取**:
- 跳过前三行表头(第1-3行)
- 从第4行开始读取数据
- 使用第三行作为新工作表的表头
- **结果输出**:
- 创建"日期重复"工作表
- 写入重复数据行(带样式处理)
- 添加详细统计信息
#### 2. 关键增强功能
1. **安全删除旧表**:
```javascript
Application.DisplayAlerts = false; // 禁用系统警告
oldSheet.Delete();
Application.DisplayAlerts = true; // 恢复系统警告
```
2. **样式增强**:
```javascript
// 表头样式
headerRange.Font.Bold = true;
headerRange.Interior.Color = RGB(200, 200, 200);
// 统计表头样式
headerRange.Font.Bold = true;
headerRange.Interior.Color = RGB(220, 220, 220);
// 说明文字样式
sheet.Range(`A${summaryRow + 5}`).Font.Italic = true;
sheet.Range(`A${summaryRow + 5}`).Font.Color = RGB(100, 100, 100);
```
3. **空数据处理**:
```javascript
if (duplicateRows.length > 0) {
// 写入数据...
} else {
dupSheet.Range("A1").Value2 = "无重复日期数据";
}
```
#### 3. 统计函数 `addStatistics()` 增强
- **视觉层次**:
- 主标题:14号加粗字体
- 副标题:12号加粗字体
- 说明文字:斜体灰色
- **数据高亮**:
```javascript
// 高亮重复次数多的行
if (stat.count > 2) {
sheet.Range(`A${rowIndex}:D${rowIndex}`).Interior.Color = RGB(255, 200, 200);
}
```
- **汇总信息**:
- 重复日期总数
- 总重复行数
- 实际重复数据行数
- 关系说明:`实际重复行 = 总重复行 - 重复日期数`
### 输出结果说明
1. **"日期重复"工作表结构**:
- 表头行:灰色背景加粗文字(使用原表第三行)
- 数据区域:所有重复数据行
- 统计区域(间隔2行):
- 标题:"日期重复统计"
- 表头:["日期值", "出现次数", "首次出现行", "所有行号"]
- 数据:每个重复日期的统计信息
- 汇总区域:
- 重复日期总数
- 总重复行数
- 实际重复数据行数
- 关系说明
2. **无数据处理**:
- 当没有重复数据时,显示"无重复日期数据"
3. **视觉效果**:
- 表头和统计表头使用不同灰度背景
- 重复次数>2的行标记为浅红色
- 汇总标题使用12号加粗字体
- 说明文字使用斜体灰色
### 使用说明
1. 在WPS中打开包含"合并数据"工作表的文件
2. 确保"合并数据"工作表:
- 表头占1-3行
- 数据从第4行开始
3. 打开JS宏编辑器,粘贴完整代码
4. 运行`查找日期重复数据()`函数
5. 查看结果:
- 新建的"日期重复"工作表(自动删除旧表)
- 重复数据行(带样式)
- 详细的重复统计信息
- 汇总数据
### 处理流程说明
1. **旧表清理**:
- 检查"日期重复"表是否存在
- 禁用系统警告提示
- 删除旧表
- 恢复系统警告设置
2. **数据获取**:
- 定位"合并数据"工作表
- 跳过前三行表头
- 获取数据区域(从第4行开始)
3. **重复检测**:
- 使用Map记录每个日期值的出现次数
- 记录首次出现行号和所有行号
- 收集所有重复行(包括首次出现的行)
4. **结果输出**:
- 创建新工作表
- 写入表头和数据行
- 添加样式增强可读性
- 添加详细统计信息
- 自动调整列宽优化显示
阅读全文
相关推荐



















