一、概述
在应用程序的开发过程中,经常需要使用 Excel文件来进行数据的导入或导出。所以,在通过Java语言实现此类需求的时候,往往会面临着Excel文件的解析(导入)或生成(导出)。
在Java技术生态圈中,可以进行Excel文件处理的主流技术包括: Apache POI 、JXL、Alibaba EasyExcel等。
Apache POI基于 DOM方式进行解析,将文件直接加载内存,所以速度较快,适合 Excel文件数据量不︰大的应用场景。JXL只支持Excel 2003以下版本,所以不太常见。
Alibaba EasyExcel采用逐行读取的解析模式,将每一行的解析结果以观察者的模式通知处理(AnalysisEventListener),所以比较适合数据体量较大的Excel文件解析。
超大文件的Excel读写:
使用SXSSFWorkbook进行写入,通过设置SXXFWorkbook的构造参数,可以设置每次在内存中保持的行数,当达到这个值的时候,那么会把这些数据flush到磁盘上,这样就不会出现内存不够的情况。
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.UUID;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
public class Demo01 {
public static void main(String[] args) {
try (// 设置内存中最多保留的行数
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
OutputStream os = new FileOutputStream("E:\\apesourcefile\\homework\\apachepoibig.xlsx")) {
Sheet sheet = workbook.createSheet();
for (int i = 0; i < 100000; i++) {
Row row = sheet.createRow(i);
row.createCell(0).setCellValue(UUID.randomUUID().toString().substring(0, 8));
row.createCell(1).setCellValue(new Date());
}
workbook.write(os);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("内容写出结束");
}
}
二、Apache POl
Apache POI 是用Java编写的免费开源的跨平台的 Java API , Apache POI提供给Java程序对Microsoft Office格式档案进行读写功能的API开源类库。
它分别提供对不同格式文件的解析:
HSSF-提供读写Microsoft Excel格式档案的功能。
XSSF-提供读写Microsoft Excel OOXML格式档案的功能。
HWPF-提供读写Microsoft Word格式档案的功能。
HSLF-提供读写Microsoft PowerPoint格式档案的功能。
HDGF-提供读写Microsoft Visio格式档案的功能。
三、XSSF解析Excel文件
HSSF 用于解析旧版本(*.xls)Excel文件,由于旧版本的Excel文件只能存在65535行数据,所以目前已经不常用。所以目前主要采用XSSF 进行新版本(*.xlsx) Exce文件的解析。
添加Jar包依赖:
1.excel文件写出
workbook接口代表一个Excel 文件,用于创建或加载(解析) Excel文件。常见实现类是XSSFWorkbook 。
指定区域写出
public class Demo01 {
public static void main(String[] args) throws IOException {
// 创建工作薄对象
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建一个工作表
XSSFSheet sheet = workbook.createSheet();
// 创建一个行对象
Row row = sheet.createRow(0);
// 创建单元格对象
Cell cell1 = row.createCell(0);
cell1.setCellValue("Python");
// 创建单元格对象
Cell cell2 = row.createCell(1);
cell2.setCellValue("C#");
Row row1 = sheet.createRow(1);
row1.createCell(0).setCellValue("Pandas");
row1.createCell(1).setCellValue("EasyX");
// 输出操作
OutputStream os = new FileOutputStream("E:\\apesourcefile\\homework\\excel1.xlsx");
workbook.write(os);
// 关闭流
workbook.close();
os.close();
System.out.println("写出结束");
}
}
一列一列写出
public class Demo02 {
public static void main(String[] args) throws IOException {
String path = "E:\\apesourcefile\\homework\\excel2.xlsx";
OutputStream os = new FileOutputStream(path);
// 创建工作薄对象
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建一个工作表
XSSFSheet sheet = workbook.createSheet("检验码表");
// 创建一个行对象
Row row1 = sheet.createRow(0);
row1.createCell(0).setCellValue("序号");
row1.createCell(1).setCellValue("优惠码");
row1.createCell(2).setCellValue("校验码");
row1.createCell(3).setCellValue("创建日期");
for (int i = 1; i <= 1000; i++) {
Row row = sheet.createRow(i);
row.createCell(0).setCellValue(i);
String uuid = UUID.randomUUID().toString();
row.createCell(1).setCellValue(uuid.substring(0, 8));
row.createCell(2).setCellValue(uuid.substring(32));
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
row.createCell(3).setCellValue(now.format(formatter));
}
// 输出操作
workbook.write(os);
// 关闭流
workbook.close();
os.close();
System.out.println("写出结束");
}
}
设置单元格数据格式
public class Demo03 {
public static void main(String[] args) {
String path = "E:\\apesourcefile\\homework\\excel3.xlsx";
try (OutputStream os = new FileOutputStream(path); XSSFWorkbook workbook = new XSSFWorkbook()) {
// 设置单元格数据格式
// 1.DateFormate数据格式化对象
XSSFDataFormat dataFormat = workbook.createDataFormat();
// 2.进行不同的格式编号
Short dateShort = dataFormat.getFormat("yyyy-MM-dd");
Short moneyShort = dataFormat.getFormat("¥###,#");
// 3.创建单元格样式对象,并为其赋值
// 3.1创建日期格式
CellStyle dateStyle = workbook.createCellStyle();
dateStyle.setDataFormat(dateShort);
// 3.2创建金额格式
CellStyle moneyStyle = workbook.createCellStyle();
moneyStyle.setDataFormat(moneyShort);
// 3.3创建加粗居中等单元格样式
CellStyle headerCellStyle = workbook.createCellStyle();
// 设置单元格的水平对齐类型,此时水平居中
headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
// 设置单元格的垂直对齐类型,此时垂直靠底边
headerCellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
// 创建并设置字体
Font font = workbook.createFont();
font.setBold(true);
font.setColor(Font.COLOR_RED);
headerCellStyle.setFont(font);
XSSFSheet sheet = workbook.createSheet("金额表");
Row row = sheet.createRow(0);
row.createCell(0).setCellValue("序号");
row.createCell(1).setCellValue("金额");
row.createCell(2).setCellValue("日期");
// 创建数据
for (int i = 1; i <= 100; i++) {
Row row1 = sheet.createRow(i);
Cell cell0 = row1.createCell(0);
cell0.setCellStyle(headerCellStyle);
cell0.setCellValue(i);
Cell cell1 = row1.createCell(1);
cell1.setCellStyle(moneyStyle);
cell1.setCellValue((int) (Math.random() * 100000));
Cell cell2 = row1.createCell(2);
cell2.setCellStyle(dateStyle);
cell2.setCellValue(new Date());
}
// 输出操作
workbook.write(os);
System.out.println("写出结束");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.excel文件写入
指定sheet遍历
//POI进行数据的读入
public class Demo04 {
public static void main(String[] args) {
try (// 创建输入流,将输入流和工作薄连接起来
InputStream is = new FileInputStream("E:\\apesourcefile\\homework\\excel3.xlsx");
Workbook workbook = new XSSFWorkbook(is)) {
// 获取sheet表
Sheet sheet = workbook.getSheet("金额表");
for (Row row : sheet) {
for (Cell cell : row) {
System.out.print(cell + " ");
}
System.out.println();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
一行一行读取
//POI进行数据的读取
public class Demo05 {
public static void main(String[] args) {
try (// 创建输入流,将输入流和工作薄连接起来
InputStream is = new FileInputStream("E:\\apesourcefile\\homework\\excel3.xlsx");
Workbook workbook = new XSSFWorkbook(is)) {
// 获取sheet表
Sheet sheet = workbook.getSheetAt(0);
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
// 获取行对象
Row row = sheet.getRow(i);
for (int j = 0; j < row.getLastCellNum(); j++) {
// 通过行对象获取单元格对象
Cell cell = row.getCell(j);
// 获取单元格的类型
CellType cellType = cell.getCellType();
// 根据单元格的类型获取单元格中的值
if (CellType.STRING == cellType) {
System.out.print(cell.getStringCellValue() + " ");
} else if (CellType.NUMERIC == cellType) {
System.out.print(cell.getNumericCellValue() + " ");
}
}
System.out.println();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
例子:对上述Excel文件进行检查,找出优惠码和校验码中包含“0”的数据,并保存至一个文本文件。
public class Demo06 {
public static void main(String[] args) {
try (// 创建输入流,将输入流和工作薄连接起来
InputStream is = new FileInputStream("E:\\apesourcefile\\homework\\excel2.xlsx");
Workbook workbook = new XSSFWorkbook(is);
OutputStream os = new FileOutputStream("E:\\apesourcefile\\homework\\result.txt")) {
// 获取sheet表
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for (int i = 1; i <= 2; i++) {
Cell cell = row.getCell(i);
if (cell.getCellType() == CellType.STRING) {
String str = cell.getStringCellValue();
if (str.contains("0")) {
os.write((str + System.lineSeparator()).getBytes());
}
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
例题:我这里有一个userData.xlsx类型的文件,请你读取我这个文件里的:
Data [no=99999, name=察合台, dept=教学保障中心]
data类型的对象:
public class Data {
private int no;
private String name;
private String dept;
public Data(int no, String name, String dept) {
super();
this.no = no;
this.name = name;
this.dept = dept;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Data [no=" + no + ", name=" + name + ", dept=" + dept + "]";
}
}
测试类:
public class Demo07 {
public static void main(String[] args) {
String path = "E:\\apesourcefile\\homework\\userData.xlsx";
List<Data> listDatas = new ArrayList<Data>();
try (InputStream is = new FileInputStream(path); Workbook workbook = new XSSFWorkbook(is);) {
// 获取sheet表
Sheet sheet = workbook.getSheetAt(0);
// 通过增强for循环获取行和单元格
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
int no = (int) row.getCell(0).getNumericCellValue();
String dept = row.getCell(1).getStringCellValue();
String name = row.getCell(2).getStringCellValue();
Data data = new Data(no, name, dept);
listDatas.add(data);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Data data : listDatas) {
System.out.println(data);
}
}
}
输出结果:
四、相关例题
题目
Test01:按照指定逻辑验证指定Excel文件demo-data.xlsx,并按照格式输出验证结果。
public class Work {
public static void main(String[] args) {
// 1.序号是否连续
// 2.检查性别是否为男或女
// 3.身份证号
// 3.1 身份证号码格式(必须为18位)
// 3.2 身份证号码不能重复
// 3.3 身份证号码开头两位是否与籍贯符合
// 北京 11 天津12 河北 13 山西14 内蒙古 15
// 陕西61 甘肃62 青海 63
// 4.学历只能填写:大专、本科、硕士、其它
// 5.体重在40-120之间
List<String> errorMsgList =
validateDataExcel("c:\\test\\run\\demo-data.xlsx");
if (errorMsgList.size() == 0) {
System.out.println("文件检查无误!");
} else {
// 显示所有错误信息
for (String err : errorMsgList) {
System.out.println(err);
}
}
}
public static List<String> validateDataExcel(String excelDataFilePath) {
return null;
}
}
验证结果:
第3行身份证与籍贯不符!
第4行序号有误!
第7行身份证号码长度有误!
第9行身份证号码长度有误!
第10行身份证与籍贯不符!
第11行身份证号码长度有误!
第12行序号有误!
第13行身份证号码长度有误!
第16行性别有误!
第18行序号有误!
第22行身份证与籍贯不符!
第24行身份证号码(61252319930120222X)重复!
第25行性别有误!
第33行身份证号码(610523199203206313)重复!
第36行身份证号码长度有误!
第39行身份证与籍贯不符!
第41行身份证与籍贯不符!
第43行身份证与籍贯不符!
第44行身份证与籍贯不符!
第46行身份证与籍贯不符!
解答
方法1:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class Work03_result {
public static void main(String[] args) {
List<String> errorMsgList = validateDataExcel("E:\\apesourcefile\\homework\\demo-data.xlsx");
if (errorMsgList.size() == 0) {
System.out.println("文件检查无误!");
} else {
// 显示所有错误信息
for (String err : errorMsgList) {
System.out.println(err);
}
}
}
public static List<String> validateDataExcel(String excelDataFilePath) {
List<String> resultList = new ArrayList<String>();
Set<String> identifySet = new HashSet<String>();
HashMap<String, String> localcationMap = new HashMap<String, String>();
// 北京 11 天津12 河北 13 山西14 内蒙古 15
// 陕西61 甘肃62 青海 63
localcationMap.put("北京", "11");
localcationMap.put("天津", "12");
localcationMap.put("河北", "13");
localcationMap.put("山西", "14");
localcationMap.put("内蒙古", "15");
localcationMap.put("陕西", "61");
localcationMap.put("甘肃", "62");
localcationMap.put("青海", "63");
List<String> studyList = new ArrayList<String>(Arrays.asList("大专", "本科", "硕士", "其他"));
try (InputStream is = new FileInputStream(excelDataFilePath); XSSFWorkbook workbook = new XSSFWorkbook(is)) {
XSSFSheet sheet = workbook.getSheetAt(0);
// 读取行
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
// 1.序号是否连续
int num = (int) row.getCell(0).getNumericCellValue();
if (i != num) {
resultList.add("第" + i + "行序号有误!");
}
// 2.检查性别是否为男或者女
String sex = row.getCell(2).getStringCellValue();
if (!("男".equals(sex) || "女".equals(sex))) {
resultList.add("第" + i + "行性别有误!");
}
// 3.身份证号
// 3.1 身份证号码格式(必须为18位)
String identifyCard = row.getCell(3).getStringCellValue();
if (identifyCard.length() != 18) {
resultList.add("第" + i + "行身份证号码长度有误!");
}
// 3.2 身份证号码不能重复
if (!identifySet.add(identifyCard)) {
resultList.add("第" + i + "行身份证号码" + identifyCard + "重复!");
}
// 3.3 身份证号码开头两位是否与籍贯符合
String id = row.getCell(6).getStringCellValue();
if (!localcationMap.get(id).equals(identifyCard.substring(0, 2))) {
resultList.add("第" + i + "行身份证与籍贯不符合!");
}
// 4.学历只能填写:大专、本科、硕士、其它
String study = row.getCell(7).getStringCellValue();
if (!studyList.contains(study)) {
resultList.add("第" + i + "行学历有误!");
}
// 5.体重在40-120之间
double weight = row.getCell(8).getNumericCellValue();
if (weight >= 120 || weight <= 40) {
resultList.add("第" + i + "体重有误!");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resultList;
}
}
方法2:
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Work03 {
public static void main(String[] args) {
String path = "E:\\apesourcefile\\homework\\demo-data.xlsx";
List<String> list = DataExcel(path);
if (list.size() == 0) {
System.out.println("文件检查无误!");
} else {
// 错误信息
for (String err : list) {
System.out.println(err);
}
}
}
public static List<String> DataExcel(String excelDataFilePath) {
List<String> msg = new ArrayList<>();
Set<String> identifyNumberSet = new HashSet<>();
try (FileInputStream fis = new FileInputStream(excelDataFilePath);
Workbook workbook = new XSSFWorkbook(fis)) {
Sheet sheet = workbook.getSheetAt(0);
int previousSeq = 0;
for (Row row : sheet) {
int rowIndex = row.getRowNum();
if (rowIndex == 0) {
continue; // 跳过第一行
}
// 获取序号格
Cell seqCell = row.getCell(0);
// 判断是否为空或者不是String类型的
if (seqCell == null || seqCell.getCellType() != CellType.NUMERIC) {
msg.add("序号错误或缺失: 第 " + (rowIndex + 1) + " 行");
continue;
}
// 1.序号是否连续
int seq = (int) seqCell.getNumericCellValue();
if (seq != previousSeq + 1) {
msg.add("序号不连续: 第 " + (rowIndex + 1) + " 行");
}
previousSeq = seq;
// 性别
Cell genderCell = row.getCell(1);
// 判断是否为空或者不是String类型的
if (genderCell == null || genderCell.getCellType() != CellType.STRING) {
msg.add("性别错误或缺失: 第 " + (rowIndex + 1) + " 行");
continue;
}
// 2.检查性别是否为男或女
String gender = genderCell.getStringCellValue();
if (!gender.equals("男") && !gender.equals("女")) {
msg.add("性别错误: 第 " + (rowIndex + 1) + " 行");
}
// 身份证号
Cell idNumberCell = row.getCell(2);
// 判断是否为空或者不是String类型的
if (idNumberCell == null || idNumberCell.getCellType() != CellType.STRING) {
msg.add("身份证号码错误或缺失: 第 " + (rowIndex + 1) + " 行");
continue;
}
String idNumber = idNumberCell.getStringCellValue();
// 3.身份证号
// 3.1 身份证号码格式(必须为18位)
if (idNumber.length() != 18) {
msg.add("身份证号码长度错误: 第 " + (rowIndex + 1) + " 行");
}
// 3.2 身份证号码不能重复
if (identifyNumberSet.contains(idNumber)) {
msg.add("身份证号码重复: 第 " + (rowIndex + 1) + " 行");
} else {
identifyNumberSet.add(idNumber);
}
// 3.3 身份证号码开头两位是否与籍贯符合
// 北京 11 天津12 河北 13 山西14 内蒙古 15
// 陕西61 甘肃62 青海 63
if (idNumber.length() >= 2) {
String location = idNumber.substring(0, 2);
if (!Location(location)) {
msg.add("身份证号码开头与籍贯不符: 第 " + (rowIndex + 1) + " 行");
}
} else {
msg.add("身份证号码长度不足以验证开头: 第 " + (rowIndex + 1) + " 行");
}
// 学历
Cell educationCell = row.getCell(3);
// 判断是否为空或者不是String类型的
if (educationCell == null || educationCell.getCellType() != CellType.STRING) {
msg.add("学历错误或缺失: 第 " + (rowIndex + 1) + " 行");
continue;
}
// 4.学历只能填写:大专、本科、硕士、其它
String education = educationCell.getStringCellValue();
if (!education.equals("大专") && !education.equals("本科") && !education.equals("硕士")
&& !education.equals("其它")) {
msg.add("学历填写错误: 第 " + (rowIndex + 1) + " 行");
}
// 体重
Cell weightCell = row.getCell(4);
if (weightCell == null || weightCell.getCellType() != CellType.NUMERIC) {
msg.add("体重错误或缺失: 第 " + (rowIndex + 1) + " 行");
continue;
}
// 5.体重在40-120之间
double weight = weightCell.getNumericCellValue();
if (weight < 40 || weight > 120) {
msg.add("体重错误: 第 " + (rowIndex + 1) + " 行");
}
}
} catch (IOException e) {
e.printStackTrace();
msg.add("文件读取失败: " + e.getMessage());
}
return msg;
}
private static boolean Location(String location) {
// 判断地区是否正确
// 北京 11 天津12 河北 13 山西14 内蒙古 15
// 陕西61 甘肃62 青海 63
String[] validPrefixes = { "11", "12", "13", "14", "15", "61", "62", "63" };
for (String prefix : validPrefixes) {
if (prefix.equals(location)) {
return true;
}
}
return false;
}
}
Test02:请将demo-data.xlsx文件中Sheet1中的数据复制到文件的最后一个Sheet中,并根据身份证号码,补充出生日期和年龄两列里的值。
解答:
方法1:
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.DateTimeException;
import java.time.format.DateTimeFormatter;
public class Work04 {
public static void main(String[] args) {
String path = "E:\\apesourcefile\\homework\\demo-data.xlsx";
try (FileInputStream fis = new FileInputStream(path); XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
// 获取 Sheet1
Sheet sheet1 = workbook.getSheetAt(0);
// 创建一个新的 Sheet 作为最后一个 Sheet
Sheet newSheet = workbook.createSheet("Copied");
// 复制 Sheet1 中的数据到新创建的 Sheet 中
copySheetData(sheet1, newSheet);
// 计算出生日期和年龄并填充数据
for (int i = 1; i <= newSheet.getLastRowNum(); i++) {
Row row = newSheet.getRow(i);
Cell identityCard = row.getCell(3); // 身份证号码
if (identityCard != null) { // 判断是否为空
String idCard = identityCard.getStringCellValue();
if (idCard.length() >= 18) {
// 提取出生日期字段
String birthDateStr = idCard.substring(6, 14);
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);
// 计算年龄
int age = calculateAge(birthDate, LocalDate.now());
// 填充出生日期和年龄
Cell birthDateCell = row.createCell(4);
birthDateCell.setCellValue(birthDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
Cell ageCell = row.createCell(5);
ageCell.setCellValue(age);
} catch (DateTimeException e) {
System.err.println("生日参数不合法,无法计算年龄 " + birthDateStr);
}
}
}
}
// 写入到文件
try (FileOutputStream fos = new FileOutputStream(path)) {
workbook.write(fos);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static int calculateAge(LocalDate birthDate, LocalDate currentDate) {
// 计算年龄方法
int age = currentDate.getYear() - birthDate.getYear();
// 检查是否需要减少一年
if (currentDate.getMonthValue() < birthDate.getMonthValue()
|| (currentDate.getMonthValue() == birthDate.getMonthValue()
&& currentDate.getDayOfMonth() < birthDate.getDayOfMonth())) {
age--;
}
return age;
}
private static void copySheetData(Sheet sourceSheet, Sheet destinationSheet) {
for (int i = 0; i <= sourceSheet.getLastRowNum(); i++) {// 遍历原工作表的所有行
Row sourceRow = sourceSheet.getRow(i);
Row newRow = destinationSheet.createRow(i);// 创建目标工作表的新行
if (sourceRow != null) {
for (int j = 0; j < sourceRow.getLastCellNum(); j++) {// 遍历当前行中的所有单元格
Cell newCell = newRow.createCell(j);
Cell sourceCell = sourceRow.getCell(j);
if (sourceCell != null) {// 复制单元格内容到目标行
switch (sourceCell.getCellType()) {
case STRING:
newCell.setCellValue(sourceCell.getStringCellValue());
break;
case NUMERIC:
newCell.setCellValue(sourceCell.getNumericCellValue());
break;
case BOOLEAN:
newCell.setCellValue(sourceCell.getBooleanCellValue());
break;
case FORMULA:
newCell.setCellFormula(sourceCell.getCellFormula());
break;
case BLANK:
newCell.setBlank();
break;
default:
break;
}
}
}
}
}
}
}
方法2:
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.time.LocalDate;
public class Work04_result {
public static void main(String[] args) {
String excelDataFilePath = "E:\\apesourcefile\\homework\\demo-data.xlsx";
try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(excelDataFilePath));
OutputStream os = new FileOutputStream(excelDataFilePath)) {
// 根据旧的表获取数据进行数据处理
XSSFSheet sheet = workbook.getSheetAt(0);
// 根据工作薄对象创建一个新的表
XSSFSheet sheet1 = workbook.createSheet("新表");
// 复制头信息
Row r = sheet.getRow(0);// 获取要复制的表的第一个行
Row row0 = sheet1.createRow(0);// 新表创建头信息行
// 获取表头单元格的信息并复制到新表的头信息中
for (int i = 0; i < r.getLastCellNum(); i++) {
String valueString = r.getCell(i).getStringCellValue();
row0.createCell(i).setCellValue(valueString);
}
// 复制表中数据--并进行数据处理
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);// 旧数据的行
Row row1 = sheet1.createRow(i);// 新表行
String cardId = null;// 每行的身份证需要保留,在进行年龄和出生日期保存时使用
// 循环获取单元格
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (j == 3) {
cardId = row.getCell(j).getStringCellValue();
}
// 如果是下标为4或者5的单元格,通过保存身份证信息处理出生日期和年龄
if (j == 4) {
Cell cell1 = row.createCell(4);
cell1.setCellValue(cardId.substring(6, 14));
}
if (j == 5) {
Cell cell2 = row1.createCell(5);
int age = LocalDate.now().getYear() - Integer.parseInt(cardId.substring(6, 10));
cell2.setCellValue(age);
}
// 除了45单元格,其他单元格信息直接从旧表复制
if (cell.getCellType() == CellType.STRING) {
row1.createCell(j).setCellValue(cell.getStringCellValue());
} else if (cell.getCellType() == CellType.NUMERIC) {
row1.createCell(j).setCellValue(cell.getNumericCellValue());
}
}
}
workbook.write(os);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("输出结束");
}
}