日常开发中,报表导出、数据批量规整、模板修改等场景,经常需要动态对 Excel 表格插入、删除行和列。本文将介绍如何使用 Java 操作 Excel 文件的行和列,包括对.xls、.xlsx格式表格的行、列新增与删除,附带完整可运行示例。
安装依赖
本文示例使用的是Spire.XLS for Java,这是一个专门处理Excel文件的Java库。你可以在pom.xml文件从添加以下代码从Maven安装该库:
Maven依赖
<repositories><repository><id>com.e-iceblue</id><url>https://repo.e-iceblue.cn/repository/maven-public/</url></repository></repositories><dependencies><dependency><groupId>e-iceblue</groupId><artifactId>spire.xls</artifactId><version>14.12.0</version></dependency></dependencies>一、插入行和列
最基础的操作就是插入行和列了。比如要在第2行前面插入一个新行:
importcom.spire.xls.*;publicclassInsertRowsColumns{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetworksheet=workbook.getWorksheets().get(0);// 在第2行位置插入一行worksheet.insertRow(2);// 在第2列位置插入一列worksheet.insertColumn(2);workbook.saveToFile("result.xlsx",ExcelVersion.Version2013);workbook.dispose();}}批量插入也很简单,第二个参数指定插入的数量:
// 从第5行开始,连续插入2行worksheet.insertRow(5,2);// 从第5列开始,连续插入2列worksheet.insertColumn(5,2);实际场景:我经常在生成报表时,根据数据量动态插入行。比如有10条记录,就在表头后面插入10行。
二、删除行和列
删除操作和插入类似,但要注意:删除后后面的行/列会自动前移。
importcom.spire.xls.*;publicclassDeleteRowsColumns{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetworksheet=workbook.getWorksheets().get(0);// 从第5行开始,删除4行(删除第5、6、7、8行)worksheet.deleteRow(5,4);// 从第2列开始,删除2列(删除第2、3列)worksheet.deleteColumn(2,2);workbook.saveToFile("result.xlsx",ExcelVersion.Version2013);workbook.dispose();}}踩过的坑:如果循环删除多行,记得从后往前删,否则索引会乱。
三、删除空白行和列
这个功能特别实用!经常遇到导出的Excel里有很多空白行,手动删太麻烦。
importcom.spire.xls.*;publicclassDeleteBlankRows{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("messy_data.xlsx");Worksheetsheet=workbook.getWorksheets().get(0);// 删除空白行(从后往前遍历)for(inti=sheet.getRows().length-1;i>=0;i--){if(sheet.getRows()[i].isBlank()){sheet.deleteRow(i+1);// 注意:行号从1开始}}// 删除空白列(从后往前遍历)for(intj=sheet.getColumns().length-1;j>=0;j--){if(sheet.getColumns()[j].isBlank()){sheet.deleteColumn(j+1);// 注意:列号从1开始}}workbook.saveToFile("cleaned.xlsx",ExcelVersion.Version2013);workbook.dispose();}}为什么要从后往前删?因为删除一行后,后面的行号会变化。如果从前往后删,可能会跳过某些行或者删错位置。
应用场景:清理从数据库导出的Excel、去除模板中的占位行等。
四、复制行和列
有时候需要在同一个Sheet内复制行,或者跨Sheet复制数据。
同一Sheet内复制
importcom.spire.xls.*;publicclassCopyRows{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetsheet=workbook.getWorksheets().get(0);// 把第1行复制到第3行// 参数:源行、目标行、是否复制值、是否复制格式、是否复制公式sheet.copy(sheet.getRows()[0],sheet.getRows()[2],true,true,true);workbook.saveToFile("result.xlsx",ExcelVersion.Version2010);workbook.dispose();}}跨Sheet复制
Worksheetsheet1=workbook.getWorksheets().get(0);Worksheetsheet2=workbook.getWorksheets().get(1);// 把Sheet1的第1行复制到Sheet2的第2行sheet1.copy(sheet1.getRows()[0],sheet2.getRows()[1],true,true,true);三个布尔参数说明:
- 第一个:是否复制单元格的值
- 第二个:是否复制格式(字体、颜色等)
- 第三个:是否复制公式
实际用途:我经常用它来复制表头到多个Sheet,或者根据模板行批量生成数据行。
五、隐藏和显示行列
有些敏感数据不想直接显示,可以隐藏起来:
importcom.spire.xls.*;publicclassHideRowsColumns{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetworksheet=workbook.getWorksheets().get(0);// 隐藏第2列worksheet.hideColumn(2);// 隐藏第4行worksheet.hideRow(4);workbook.saveToFile("result.xlsx",ExcelVersion.Version2013);workbook.dispose();}}取消隐藏:
// 显示第2列worksheet.showColumn(2);// 显示第4行worksheet.showRow(4);使用场景:财务报表中隐藏中间计算过程、保护敏感信息等。
六、设置行高和列宽
默认的行列尺寸可能不合适,需要自定义:
importcom.spire.xls.*;publicclassSetHeightWidth{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetworksheet=workbook.getWorksheets().get(0);// 设置第4列宽度为30worksheet.setColumnWidth(4,30);// 设置第4行高度为30worksheet.setRowHeight(4,30);workbook.saveToFile("result.xlsx",ExcelVersion.Version2013);workbook.dispose();}}批量设置默认值:
// 设置所有行的默认高度worksheet.setDefaultRowHeight(20);// 设置所有列的默认宽度worksheet.setDefaultColumnWidth(15);经验之谈:中文内容通常需要更宽的列,英文可以窄一些。我一般会根据内容类型预设不同的列宽。
七、自动调整列宽
如果不确定列宽设多少合适,可以让Excel自动调整:
importcom.spire.xls.*;publicclassAutoFitColumns{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetworksheet=workbook.getWorksheets().get(0);// 自动调整指定区域的列宽worksheet.getAllocatedRange().autoFitColumns();// 也可以只调整某几列// worksheet.getCellRange("A1:C10").autoFitColumns();workbook.saveToFile("result.xlsx",ExcelVersion.Version2013);workbook.dispose();}}注意:自动调整会遍历所有单元格,数据量大时会比较慢。如果性能重要,建议手动设置固定宽度。
八、分组行列(大纲功能)
Excel的大纲功能可以把相关行/列折叠起来,适合层级数据:
importcom.spire.xls.*;publicclassGroupRowsColumns{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetsheet=workbook.getWorksheets().get(0);// 对第1到5行进行分组(可以折叠)// 第三个参数:是否在下方显示汇总行sheet.groupByRows(1,5,false);// 对第1到3列进行分组sheet.groupByColumns(1,3,false);workbook.saveToFile("result.xlsx",ExcelVersion.Version2013);workbook.dispose();}}实际场景:财务报表按月分组、项目计划按阶段分组等。用户可以选择展开或折叠查看不同粒度的数据。
九、根据条件删除行
有时候需要根据内容筛选并删除某些行,比如删除包含特定关键词的行:
importcom.spire.xls.*;publicclassRemoveRowByKeyword{publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();workbook.loadFromFile("data.xlsx");Worksheetsheet=workbook.getWorksheets().get(0);Stringkeyword="测试";// 从后往前遍历,删除包含关键词的行for(inti=sheet.getRows().length-1;i>=0;i--){booleanshouldDelete=false;// 检查该行所有单元格for(Objectcell:sheet.getRows()[i]){if(cell!=null&&cell.toString().contains(keyword)){shouldDelete=true;break;}}if(shouldDelete){sheet.deleteRow(i+1);}}workbook.saveToFile("filtered.xlsx",ExcelVersion.Version2013);workbook.dispose();}}应用场景:清理测试数据、过滤无效记录、删除标记为废弃的行等。
十、综合实战:动态生成报表
最后分享一个完整的例子:根据数据动态生成带格式的报表。
importcom.spire.xls.*;importjava.util.List;importjava.util.ArrayList;publicclassDynamicReport{// 模拟数据类staticclassProduct{Stringname;doubleprice;intquantity;Product(Stringname,doubleprice,intquantity){this.name=name;this.price=price;this.quantity=quantity;}}publicstaticvoidmain(String[]args){Workbookworkbook=newWorkbook();Worksheetsheet=workbook.getWorksheets().get(0);// 准备数据List<Product>products=newArrayList<>();products.add(newProduct("产品A",99.9,100));products.add(newProduct("产品B",199.9,50));products.add(newProduct("产品C",299.9,30));// 1. 写入表头String[]headers={"产品名称","单价","数量","总价"};for(inti=0;i<headers.length;i++){sheet.getCellRange(1,i+1).setValue(headers[i]);}// 格式化表头sheet.getCellRange(1,1,1,headers.length).getStyle().getFont().isBold(true);sheet.getCellRange(1,1,1,headers.length).getStyle().setKnownColor(ExcelColors.LightBlue);// 2. 动态插入数据行for(inti=0;i<products.size();i++){introw=i+2;// 从第2行开始(第1行是表头)Productp=products.get(i);sheet.getCellRange(row,1).setValue(p.name);sheet.getCellRange(row,2).setNumberValue(p.price);sheet.getCellRange(row,3).setNumberValue(p.quantity);// 总价 = 单价 * 数量(使用公式)sheet.getCellRange(row,4).setFormula("=B"+row+"*C"+row);sheet.getCellRange(row,4).getStyle().setNumberFormat("¥#,##0.00");}// 3. 添加汇总行intsummaryRow=products.size()+2;sheet.getCellRange(summaryRow,1).setValue("合计");sheet.getCellRange(summaryRow,1).getStyle().getFont().isBold(true);// 汇总公式sheet.getCellRange(summaryRow,3).setFormula("=SUM(C2:C"+(summaryRow-1)+")");sheet.getCellRange(summaryRow,4).setFormula("=SUM(D2:D"+(summaryRow-1)+")");sheet.getCellRange(summaryRow,4).getStyle().setNumberFormat("¥#,##0.00");// 4. 设置列宽sheet.setColumnWidth(1,20);// 产品名称sheet.setColumnWidth(2,15);// 单价sheet.setColumnWidth(3,15);// 数量sheet.setColumnWidth(4,20);// 总价// 5. 自动调整(可选)// sheet.getAllocatedRange().autoFitColumns();// 6. 添加边框sheet.getCellRange(1,1,summaryRow,4).getBorders().setLineStyle(LineStyleType.Thin);workbook.saveToFile("product_report.xlsx",ExcelVersion.Version2013);workbook.dispose();System.out.println("报表生成完成!");}}这个例子展示了:
- 动态插入数据行(根据数据量)
- 使用公式自动计算
- 设置格式(加粗、背景色、数字格式)
- 调整列宽
- 添加边框
小结
总结一下几个关键点:
- 插入行列用
insertRow()和insertColumn(),支持批量插入 - 删除行列用
deleteRow()和deleteColumn(),循环删除要从后往前 - 删除空白用
isBlank()判断,清理脏数据很实用 - 复制行列用
copy()方法,可以控制是否复制值、格式、公式 - 隐藏显示用
hideRow/Column()和showRow/Column() - 设置尺寸用
setRowHeight()和setColumnWidth() - 自动调整用
autoFitColumns(),但大数据量时注意性能 - 分组折叠用
groupByRows/Columns(),适合层级数据
实际使用中,最重要的是理解业务需求。不是所有场景都需要复杂的操作,有时候简单的插入和删除就能解决问题。