新老数据的维护工具,例如:A文件有a、b、c列共十条数据,B文件有a、b、c、d列数据共15条数据(其中有包含A的一些数据)如何快速的将A里有的数据放入到B中(长点心吧!可别一条条比对着录入数据)
下面是一个完整的 Java 实现,
使用 Apache POI 库处理 Excel 文件,对比 A、B 文件中的"测点标识"列(定位到相同的数据行),并将 A 文件中的"标签值"列填充到 B 文件对应的位置。
1. 添加 Maven 依赖
XML
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
2. 完整代码实现
java
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
public class ExcelDataComparator {
public static void main(String[] args) {
String fileAPath = "path/to/FileA.xlsx";
String fileBPath = "path/to/FileB.xlsx";
String outputPath = "path/to/OutputFile.xlsx";
try {
// 1. 读取文件A的数据(测点标识 -> 标签值)
Map<String, String> pointToTagMap = readFileA(fileAPath);
// 2. 处理文件B并填充数据
processFileB(fileBPath, outputPath, pointToTagMap);
System.out.println("数据处理完成!输出文件: " + outputPath);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取文件A,构建测点标识到标签值的映射
*/
private static Map<String, String> readFileA(String filePath) throws Exception {
Map<String, String> map = new HashMap<>();
FileInputStream fis = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0); // 假设使用第一个工作表
// 获取表头行确定列索引
Row headerRow = sheet.getRow(0);
int pointIdIndex = -1;
int tagValueIndex = -1;
for (Cell cell : headerRow) {
String headerName = cell.getStringCellValue().trim();
if ("测点标识".equals(headerName)) {
pointIdIndex = cell.getColumnIndex();
} else if ("标签值".equals(headerName)) {
tagValueIndex = cell.getColumnIndex();
}
}
if (pointIdIndex == -1 || tagValueIndex == -1) {
throw new RuntimeException("文件A中缺少必要的表头列");
}
// 遍历数据行
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
String pointId = getCellStringValue(row.getCell(pointIdIndex));
String tagValue = getCellStringValue(row.getCell(tagValueIndex));
if (pointId != null && !pointId.isEmpty()) {
map.put(pointId, tagValue);
}
}
workbook.close();
fis.close();
return map;
}
/**
* 处理文件B并填充数据
*/
private static void processFileB(String inputPath, String outputPath,
Map<String, String> pointToTagMap) throws Exception {
FileInputStream fis = new FileInputStream(inputPath);
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
// 获取表头行确定列索引
Row headerRow = sheet.getRow(0);
int pointIdIndex = -1;
int tagValueIndex = -1;
for (Cell cell : headerRow) {
String headerName = cell.getStringCellValue().trim();
if ("测点标识".equals(headerName)) {
pointIdIndex = cell.getColumnIndex();
} else if ("标签值".equals(headerName)) {
tagValueIndex = cell.getColumnIndex();
}
}
if (pointIdIndex == -1) {
throw new RuntimeException("文件B中缺少'测点标识'列");
}
// 如果文件B没有"标签值"列,可以创建(这里假设已有该列)
if (tagValueIndex == -1) {
tagValueIndex = headerRow.getLastCellNum();
Cell newHeaderCell = headerRow.createCell(tagValueIndex);
newHeaderCell.setCellValue("标签值");
}
// 遍历数据行并填充
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
String pointId = getCellStringValue(row.getCell(pointIdIndex));
if (pointId == null || pointId.isEmpty()) continue;
// 从文件A的映射中获取对应的标签值
String tagValue = pointToTagMap.get(pointId);
if (tagValue != null) {
Cell targetCell = row.getCell(tagValueIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
targetCell.setCellValue(tagValue);
}
}
// 保存修改后的文件
FileOutputStream fos = new FileOutputStream(outputPath);
workbook.write(fos);
workbook.close();
fos.close();
}
/**
* 安全获取单元格字符串值
*/
private static String getCellStringValue(Cell cell) {
if (cell == null) return "";
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue().trim();
case NUMERIC:
return String.valueOf((int) cell.getNumericCellValue());
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula();
default:
return "";
}
}
}
关键点说明
-
数据结构:
- 使用
Map<String, String>
存储文件A中的"测点标识"->"标签值"映射关系
- 使用
-
列索引定位:
- 动态查找"测点标识"和"标签值"所在的列索引
-
单元格处理:
-
getCellStringValue()
方法处理各种类型的单元格数据 -
使用
Row.MissingCellPolicy.CREATE_NULL_AS_BLANK
处理可能为空的单元格
-
-
文件处理:
-
读取文件A构建映射关系
-
读取文件B并修改数据
-
输出到新文件(避免修改原始文件)
-
使用示例
假设:
-
文件A.xlsx:
测点标识 标签值 P001 温度 P002 压力 -
文件B.xlsx:
测点标识 其他数据 标签值 P001 xxx P003 yyy
运行程序后,输出文件将变为:
测点标识 | 其他数据 | 标签值 |
---|---|---|
P001 | xxx | 温度 |
P003 | yyy |
注意事项
-
文件格式支持:代码使用
.xlsx
格式(POI的XSSF) -
性能优化:对于大文件,可以考虑使用
SXSSFWorkbook
-
错误处理:实际应用中应添加更完善的异常处理
-
表头检查:确保两个文件都有"测点标识"列
如果需要处理更复杂的情况(如多sheet、不同表头等),可以进一步扩展此代码。