In Java, if you want to parse complex Excel headers, you can use the Apache POI library.
Without further ado, just go to the source code. There are front and back ends
rear end
import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * @Description:Excel tool class (complex table header analysis) * @Author: sh * @Date: 2025/1/2 09:29 */ public class ExcelComplexUtil { /** * Import Excel file, read data line by line, and data format two-dimensional array * @param filePath * @param sheetIndex * @return * @throws IOException */ public String[][] importExcel(String filePath, int sheetIndex) throws IOException { List<String[]> dataList = new ArrayList<>(); try (FileInputStream fis = new FileInputStream(new File(filePath)); Workbook workbook = new XSSFWorkbook(fis)) { Sheet sheet = (sheetIndex); // Get the first worksheet // Get the header row Row headerRow = checkHeaderRow(sheet); if (headerRow != null) { //Encapsulate the header data warpHeaderData(headerRow, dataList); } else { throw new RuntimeException("The header row is not found in the Excel file, please modify the table"); } // Read data rows for (int rowIndex = 1; rowIndex <= (); rowIndex++) { Row row = (rowIndex); if (row == null) { continue; // Skip the empty line } //Encapsulate row data warpRowData(headerRow, row, dataList); } } // Convert List<String[]> to String[][] array String[][] result = new String[()][]; for (int i = 0; i < (); i++) { result[i] = (i); } return result; // Return a two-dimensional array } /** * Check the header row, the header row must be in the first 10 rows * @param sheet * @return */ private Row checkHeaderRow(Sheet sheet) { int i = 0; Row headerRow = null; while (i < 10) { headerRow = (i); if (headerRow != null) { break; } i++; } return headerRow; } /** * Data traversal * @param headerRow * @param dataList * @throws IOException */ public void warpHeaderData(Row headerRow, List<String[]> dataList) { int columnCount = (); short lastCellNum = (); String[] data = new String[columnCount]; // Create a one-dimensional array to store header data for (int colIndex = 0; colIndex < columnCount; colIndex++) { Cell cell = (lastCellNum - columnCount + colIndex); String cellValue = (cell != null) ? () : ""; // Process empty cells data[colIndex] = cellValue; // Put cell values into the header array } (data); // Add the header array to the list } public void warpRowData(Row headerRow, Row row, List<String[]> dataList) { int columnCount = (); short lastCellNum = (); String[] data = new String[columnCount]; // Create a one-dimensional array to store header data for (int colIndex = 0; colIndex < columnCount; colIndex++) { Cell cell = (lastCellNum - columnCount + colIndex); String cellValue = (cell != null) ? () : ""; // Process empty cells data[colIndex] = cellValue; // Put cell values into the header array } (data); // Add the header array to the list } /** * Get all merged cells in excel * @param filePath * @param sheetIndex * @throws IOException */ public List<MergedCell> checkMergedCells(String filePath, int sheetIndex) throws IOException { try (FileInputStream fis = new FileInputStream(new File(filePath)); Workbook workbook = new XSSFWorkbook(fis)) { Sheet sheet = (sheetIndex); // Get the first worksheet int numberOfMergedRegions = (); // Get the number of merged cells List<MergedCell> mergedCellArray = new ArrayList<>(); for (int i = 0; i < numberOfMergedRegions; i++) { MergedCell mergedCell = new MergedCell(); CellRangeAddress range = (i); // Get the merged cell area (()); // Get the starting cell of the merged cell area int firstRow = (); int firstCol = (); // Get the content of the merged cell Row row = (firstRow); Cell cell = (firstCol); String cellValue = (cell != null) ? () : ""; // Process empty cells (cellValue); (mergedCell); } return mergedCellArray; } } /** * Check whether a specific cell is a merged cell * @param sheet * @param row * @param col * @return */ private boolean isMergedCell(Sheet sheet, int row, int col) { int numberOfMergedRegions = (); for (int i = 0; i < numberOfMergedRegions; i++) { CellRangeAddress range = (i); if ((row, col)) { return true; // If the cell is in the merge area, return true } } return false; // If not in any merge area, return false } class MergedCell { private String range; private String value; public String getRange() { return range; } public void setRange(String range) { = range; } public String getValue() { return value; } public void setValue(String value) { = value; } @Override public String toString() { return "MergedCell{" + "range='" + range + '\'' + ", value='" + value + '\'' + '}'; } } // public static void main(String[] args) { // String filePath = "/ceshi/"; // Excel file path// try { // String[][] strings = importExcel(filePath, 0); // for (String[] row : strings) { // ((", ", row)); // Print each line with a comma as a separator// } // List<MergedCell> mergedCells = checkMergedCells(filePath, 0); // for (MergedCell row : mergedCells) { // (row); // Print each line with a comma as a separator// } // // } catch (IOException e) { // (); // } // } }
front end
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Merge Cell Viewer</title> <style> table { border-collapse: collapse; width: 500px; /* Set the table width */ } td { border: 1px solid black; padding: 0; /* Clear the inner margin */ text-align: center; vertical-align: middle; /* Vertical centering */ height: 50px; /* Set the height of each cell */ } .merged { background-color: #f0f0f0; /* Background color of merged cells */ font-weight: bold; /* Merge cell font bold */ } </style> </head> <body> <div > <h1>Merge Cell Viewer</h1> <table> <tr v-for="(row, rowIndex) in tableData" :key="rowIndex"> <td v-for="(cell, colIndex) in row" :key="colIndex" v-if="!isCellOccupied(rowIndex, colIndex)" :rowspan="getRowSpan(rowIndex, colIndex)" :colspan="getColSpan(rowIndex, colIndex)" :class="{ merged: isMergedCell(rowIndex, colIndex) }" > {{ getCellValue(rowIndex, colIndex) }} </td> </tr> </table> </div> <script src="/npm/[email protected]/dist/"></script> <script> new Vue({ el: '#app', data() { return { mergedCells: [ { range: "C1:D1", value: "Merge cell 1" }, { range: "B2:C2", value: "Merge cell 2" }, { range: "B3:C3", value: "Merge cells" }, { range: "A2:A3", value: "Merge cells" }, { range: "F2:F3", value: "Merge cells" } ], normalData: [ ["Supervisor Area", "total", "efficient", "", "Effective political category", ""], ["Pinggu District Supervisor", "244", "", "197", "28", "169"], ["", "244", "", "197", "28", ""], ["data 16", "data 17", "data 18", "data 19", "data 20"], ["data 21", "data 22", "data 23", "data 24", "data 25"], ["", "", "", "", ""] ], occupiedCells: [] }; }, computed: { // Generate complete tabular data tableData() { const rows = ; const cols = [0].length; const emptyTable = ({ length: rows }, () => Array(cols).fill(null)); // Fill in merged cells (({ range, value }) => { const [start, end] = (':'); const startRow = parseInt((/\d+/)[0]) - 1; const startCol = (0) - 65; const endRow = parseInt((/\d+/)[0]) - 1; const endCol = (0) - 65; // Fill the position of merged cells for (let r = startRow; r <= endRow; r++) { for (let c = startCol; c <= endCol; c++) { if (r === startRow && c === startCol) { emptyTable[r][c] = value; // Merge the values of cells } else { [r] = [r] || []; [r][c] = true; // Marking occupancy } } } }); // Fill in the data of ordinary cells ((row, r) => { ((cell, c) => { if (![r] || ![r][c]) { emptyTable[r][c] = cell; } }); }); return emptyTable; } }, methods: { isCellOccupied(rowIndex, colIndex) { return [rowIndex] && [rowIndex][colIndex]; }, getCellValue(rowIndex, colIndex) { return [rowIndex][colIndex]; }, getRowSpan(rowIndex, colIndex) { let rowspan = 1; const firstValue = (rowIndex, colIndex); const mergedCell = (({ range }) => { const [start, end] = (':'); const startRow = parseInt((/\d+/)[0]) - 1; const startCol = (0) - 65; const endRow = parseInt((/\d+/)[0]) - 1; const endCol = (0) - 65; return rowIndex === startRow && colIndex === startCol; }); if (mergedCell) { const [start, end] = (':'); const startRow = parseInt((/\d+/)[0]) - 1; const endRow = parseInt((/\d+/)[0]) - 1; rowspan = endRow - startRow + 1; } return rowspan; }, getColSpan(rowIndex, colIndex) { let colspan = 1; const firstValue = (rowIndex, colIndex); const mergedCell = (({ range }) => { const [start, end] = (':'); const startRow = parseInt((/\d+/)[0]) - 1; const startCol = (0) - 65; const endRow = parseInt((/\d+/)[0]) - 1; const endCol = (0) - 65; return rowIndex === startRow && colIndex === startCol; }); if (mergedCell) { const [start, end] = (':'); const startCol = (0) - 65; const endCol = (0) - 65; colspan = endCol - startCol + 1; } return colspan; }, isMergedCell(rowIndex, colIndex) { return (({ range }) => { const [start, end] = (':'); const startRow = parseInt((/\d+/)[0]) - 1; const startCol = (0) - 65; return rowIndex === startRow && colIndex === startCol; }); } } }); </script> </body> </html>
This is the end of this article about Java implementation parsing Excel complex table headers. For more related Java analysis of Excel content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!