Browse Source

增加插入行和删除行的方法

wwj 5 years ago
parent
commit
f3d20db2eb
1 changed files with 87 additions and 0 deletions
  1. 87 0
      hutool-poi/src/main/java/cn/hutool/poi/excel/RowUtil.java

+ 87 - 0
hutool-poi/src/main/java/cn/hutool/poi/excel/RowUtil.java

@@ -7,9 +7,14 @@ import cn.hutool.poi.excel.cell.CellUtil;
 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.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeUtil;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * Excel中的行{@link Row}封装工具类
@@ -97,4 +102,86 @@ public class RowUtil {
 			i++;
 		}
 	}
+
+	/**
+	 * 插入行
+	 *
+	 * @param sheet        工作表
+	 * @param startRow     插入的起始行
+	 * @param insertNumber 插入的行数
+	 */
+	public static void insertRow(Sheet sheet, int startRow, int insertNumber) {
+		if (insertNumber <= 0) {
+			return;
+		}
+		// 插入位置的行,如果插入的行不存在则创建新行
+		Row sourceRow = Optional.ofNullable(sheet.getRow(startRow)).orElseGet(() -> sheet.createRow(insertNumber));
+		// 从插入行开始到最后一行向下移动
+		sheet.shiftRows(startRow, sheet.getLastRowNum(), insertNumber, true, false);
+
+		// 填充移动后留下的空行
+		IntStream.range(startRow, startRow + insertNumber).forEachOrdered(i -> {
+			Row row = sheet.createRow(i);
+			row.setHeightInPoints(sourceRow.getHeightInPoints());
+			short lastCellNum = sourceRow.getLastCellNum();
+			IntStream.range(0, lastCellNum).forEachOrdered(j -> {
+				Cell cell = row.createCell(j);
+				cell.setCellStyle(sourceRow.getCell(j).getCellStyle());
+			});
+		});
+	}
+
+	/**
+	 * 从工作表中删除指定的行,此方法修复sheet.shiftRows删除行时会拆分合并的单元格的问题
+	 *
+	 * @param row 需要删除的行
+	 * @see <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=56454">sheet.shiftRows的bug</a>
+	 */
+	public static void removeRow(Row row) {
+		if (row == null) {
+			return;
+		}
+		int rowIndex = row.getRowNum();
+		Sheet sheet = row.getSheet();
+		int lastRow = sheet.getLastRowNum();
+		if (rowIndex >= 0 && rowIndex < lastRow) {
+			List<CellRangeAddress> updateMergedRegions = new ArrayList<>();
+			// 找出需要调整的合并单元格
+			IntStream.range(0, sheet.getNumMergedRegions())
+					.forEach(i -> {
+						CellRangeAddress mr = sheet.getMergedRegion(i);
+						if (!mr.containsRow(rowIndex)) {
+							return;
+						}
+						// 缩减以后变成单个单元格则删除合并单元格
+						if (mr.getFirstRow() == mr.getLastRow() - 1 && mr.getFirstColumn() == mr.getLastColumn()) {
+							return;
+						}
+						updateMergedRegions.add(mr);
+					});
+
+			// 将行上移
+			sheet.shiftRows(rowIndex + 1, lastRow, -1);
+
+			// 找出删除行所在的合并单元格
+			List<Integer> removeMergedRegions = IntStream.range(0, sheet.getNumMergedRegions())
+					.filter(i -> updateMergedRegions.stream().
+							anyMatch(umr -> CellRangeUtil.contains(umr, sheet.getMergedRegion(i))))
+					.boxed()
+					.collect(Collectors.toList());
+
+			sheet.removeMergedRegions(removeMergedRegions);
+			updateMergedRegions.forEach(mr -> {
+				mr.setLastRow(mr.getLastRow() - 1);
+				sheet.addMergedRegion(mr);
+			});
+			sheet.validateMergedRegions();
+		}
+		if (rowIndex == lastRow) {
+			Row removingRow = sheet.getRow(rowIndex);
+			if (removingRow != null) {
+				sheet.removeRow(removingRow);
+			}
+		}
+	}
 }