• JAVA删除excel指定列


    首先POI没有提供删除列的API,所以就需要用其他的方式实现。

    在 java - Apache POI xls column Remove - Stack Overflow 这里找到了实现方式:

    先将该列所有值都清空,然后将该列之后的所有列往前移动。

    下面的工具类中 

    deleteColumns(InputStream excelStream, List delColumnTitleList)方法实现了批量删除列的逻辑。

    1. import lombok.SneakyThrows;
    2. import org.apache.poi.ss.usermodel.Cell;
    3. import org.apache.poi.ss.usermodel.Row;
    4. import org.apache.poi.ss.usermodel.Sheet;
    5. import org.apache.poi.ss.usermodel.Workbook;
    6. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    7. import java.io.ByteArrayOutputStream;
    8. import java.io.InputStream;
    9. import java.util.ArrayList;
    10. import java.util.List;
    11. /**
    12. * @Description
    13. * @ClassName ExcelUtil
    14. * @Date 2022/12/23 11:38
    15. */
    16. public class ExcelUtil {
    17. /**
    18. * 获取sheet表头
    19. * @param sheet
    20. * @return
    21. */
    22. public static List getTitle(Sheet sheet) {
    23. List titleList = new ArrayList<>();
    24. if (sheet.getPhysicalNumberOfRows() > 0) {
    25. Row headerRow = sheet.getRow(0); // 获取第一行(表头行)
    26. for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) {
    27. Cell cell = headerRow.getCell(i);
    28. if (cell != null) {
    29. String headerText = cell.getStringCellValue();
    30. titleList.add(headerText);
    31. }
    32. }
    33. }
    34. return titleList;
    35. }
    36. /**
    37. * 删除excel指定列
    38. * @param excelStream excel流
    39. * @param delColumnTitleList 需要删除的列的表头
    40. * @return
    41. */
    42. @SneakyThrows
    43. public static ByteArrayOutputStream deleteColumns(InputStream excelStream, List delColumnTitleList) {
    44. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    45. Workbook workbook = new XSSFWorkbook(excelStream);
    46. // 获取第一个sheet
    47. Sheet sheet = workbook.getSheetAt(0);
    48. deleteColumns(sheet, delColumnTitleList);
    49. workbook.write(outputStream);
    50. workbook.close();
    51. outputStream.close();
    52. return outputStream;
    53. }
    54. /**
    55. * 删除sheet指定的列
    56. * @param sheet
    57. * @param delColumnTitleList
    58. */
    59. public static void deleteColumns(Sheet sheet, List delColumnTitleList) {
    60. List titleList = getTitle(sheet);
    61. for (String delTitle : delColumnTitleList) {
    62. int i = titleList.indexOf(delTitle);
    63. if (i >= 0) {
    64. deleteColumn(sheet, i);
    65. }
    66. //由于是循环删除,删除后,列所在位置索引会变化,所以titleList相应也移除删除的列
    67. titleList.remove(delTitle);
    68. }
    69. }
    70. /**
    71. * 删除指定列
    72. * poi没有提供删除指定列的api,所以先将该列清空,然后将后续的列往前移动,这样达到删除列的效果
    73. * @param sheet
    74. * @param columnToDelete
    75. */
    76. public static void deleteColumn(Sheet sheet, int columnToDelete) {
    77. int maxColumn = 0;
    78. for (int r = 0; r < sheet.getLastRowNum() + 1; r++) {
    79. Row row = sheet.getRow(r);
    80. // if no row exists here; then nothing to do; next!
    81. if (row == null) {
    82. continue;
    83. }
    84. // if the row doesn't have this many columns then we are good; next!
    85. int lastColumn = row.getLastCellNum();
    86. if (lastColumn > maxColumn) {
    87. maxColumn = lastColumn;
    88. }
    89. if (lastColumn < columnToDelete) {
    90. continue;
    91. }
    92. for (int x = columnToDelete + 1; x < lastColumn + 1; x++) {
    93. Cell oldCell = row.getCell(x - 1);
    94. if (oldCell != null) {
    95. row.removeCell(oldCell);
    96. }
    97. Cell nextCell = row.getCell(x);
    98. if (nextCell != null) {
    99. Cell newCell = row.createCell(x - 1, nextCell.getCellType());
    100. cloneCell(newCell, nextCell);
    101. }
    102. }
    103. }
    104. // Adjust the column widths
    105. for (int c = 0; c < maxColumn; c++) {
    106. sheet.setColumnWidth(c, sheet.getColumnWidth(c + 1));
    107. }
    108. }
    109. /**
    110. * 右边列左移
    111. */
    112. private static void cloneCell(Cell cNew, Cell cOld) {
    113. cNew.setCellComment(cOld.getCellComment());
    114. cNew.setCellStyle(cOld.getCellStyle());
    115. switch (cNew.getCellTypeEnum()) {
    116. case BOOLEAN: {
    117. cNew.setCellValue(cOld.getBooleanCellValue());
    118. break;
    119. }
    120. case NUMERIC: {
    121. cNew.setCellValue(cOld.getNumericCellValue());
    122. break;
    123. }
    124. case STRING: {
    125. //这样不丢样式
    126. cNew.setCellValue(cOld.getRichStringCellValue());
    127. break;
    128. }
    129. case ERROR: {
    130. cNew.setCellValue(cOld.getErrorCellValue());
    131. break;
    132. }
    133. case FORMULA: {
    134. cNew.setCellFormula(cOld.getCellFormula());
    135. break;
    136. }
    137. }
    138. }
    139. }

  • 相关阅读:
    unity 跨屏显示
    什么是覆盖索引?
    线程(下):读写者模型\环形队列\线程池
    死锁Deadlock
    Design Compiler工具学习笔记(6)
    Docker容器相关命令
    常见的一些Linux命令
    ENVI_IDL: 如何读取HDF5文件再优美地做个均值处理?(以OMI数据为例)
    推荐一个 C#写的 支持OCR的免费通用扫描仪软件
    8 个有效的安卓数据恢复软件——可让丢失的文件起死回生!
  • 原文地址:https://blog.csdn.net/kusedexingfu/article/details/134040795