Apache POI:找出溢出到下一列的文本的 colspan

Apache POI: Find out colspan of text overflowing to next column

我正在使用 Apache POI 将 Excel 转换为 HTML。我希望 HTML table 与 Excel 中显示的完全一样。我经常看到 Excel 单元格中的数据溢出到下一列的情况。有没有办法找出数据跨越多少列,以便我可以将 colspan 属性添加到 TD 标记?请参阅来自 Excel 的屏幕截图:

在这种情况下,单元格A2中的数据溢出到单元格B2(也是A3溢出到B3)。有没有办法查到A2单元格对应的TD标签需要colspan="2"属性?

数据溢出的单元格没有合并所以我不能真正使用像sheet.getNumMergedRegions()

这样的函数

我想如果我能以某种方式找出 Excel 中列的 "visible" 宽度,我想我也可以计算它。但是,sheet.getColumnWidth() 仅提供实际宽度。我没有看到找出 Excel 中列的 "visible" 宽度的方法。在上面的屏幕截图 link 中,A 列的可见宽度非常小。有没有办法找到 "visible" 宽度?

我正在使用 Apache POI 3.17

Apache poi 可以根据内容自动调整列的大小。所以它需要能够计算特殊内容需要的列宽。这就是 SheetUtil.getCellWidth 正在做的事情。

此外,还需要知道 MicrosoftExcel 中为列宽引入的非常特殊的测量单位。例如,在 Excels GUI 中,列宽为 10 表示单元格宽度可容纳 10 个默认字符宽度的字符。但在内部,宽度是以默认字符宽度的 1/256 为单位计算的。这就是 apache poi 决定以字符宽度的 1/256 为单位得到 Sheet.getColumnWidth 的原因。

因此,如果您有 Cell cell 单元格索引 c 和特殊内容,则使用

Workbook workbook...
...
DataFormatter dataFormatter = new DataFormatter();
...
int defaultCharWidth = SheetUtil.getDefaultCharWidth(workbook);
...
double cellValueWidth = SheetUtil.getCellWidth(cell, defaultCharWidth, dataFormatter, false);
int neededColunmnWidth = (int)cellValueWidth*256;
int columnWidth = sheet.getColumnWidth(c);
...

您可以确定内容是否适合单元格。如果 columnWidth >= neededColunmnWidth 适合,否则不适合,必须使用 colspan

来一个完整的例子来说明原理:

Sheet:

代码:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.SheetUtil;

import java.io.*;

class ExcelToHTMLColspan {

 public static void main(String[] args) throws Exception{

  Workbook workbook = WorkbookFactory.create(new FileInputStream("Test.xlsx"));

  DataFormatter dataFormatter = new DataFormatter();

  int defaultCharWidth = SheetUtil.getDefaultCharWidth(workbook);

  int lastColumnToExport = 5; // column E

  Sheet sheet = workbook.getSheetAt(0);

  Row row;
  Cell cell;
  String cellValue;

  StringBuilder tableHTML = new StringBuilder();

  tableHTML.append("<TABLE>");
  tableHTML.append("<COLGROUP>");
  for (int c = 0; c < lastColumnToExport; c++) {
   long columnWidthPx = Math.round(sheet.getColumnWidthInPixels(c));
   tableHTML.append("<COL width=\"" + columnWidthPx + "\"/>");
  }
  tableHTML.append("</COLGROUP>");

  for (int r = 0; r <= sheet.getLastRowNum(); r++) {
   row = sheet.getRow(r); if (row == null) row = sheet.createRow(r);
   long rowHeightPx = Math.round(row.getHeightInPoints() * 92f / 72f);
   tableHTML.append("<TR height=\"" + rowHeightPx + "\">");
   int c = 0;
   while(c < lastColumnToExport) {
    tableHTML.append("<TD");
    cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
    cellValue = dataFormatter.formatCellValue(cell);
    double cellValueWidth = SheetUtil.getCellWidth(cell, defaultCharWidth, dataFormatter, false);
    int neededColunmnWidth = (int)cellValueWidth*256;
    int columnWidth = sheet.getColumnWidth(c);
    if (columnWidth < neededColunmnWidth) {
     int colSpan = 1;
     while(columnWidth < neededColunmnWidth) {
      colSpan++;
      c++;
      columnWidth += sheet.getColumnWidth(c);
     } 
     tableHTML.append(" colspan=\"" + colSpan + "\""  + ">" + cellValue);
     c++;
    } else {
     tableHTML.append(">" + cellValue);
     c++;
    }
    tableHTML.append("</TD>");
   }
   tableHTML.append("</TR>");
  }

  tableHTML.append("</TABLE>");

  workbook.close();

System.out.println(tableHTML.toString());

  //creating a sample HTML file 
  String encoding = "UTF-8";
  FileOutputStream fos = new FileOutputStream("result.html");
  OutputStreamWriter writer = new OutputStreamWriter(fos, encoding);
  writer.write("<!DOCTYPE html>\n");
  writer.write("<html lang=\"en\">");
  writer.write("<head>");
  writer.write("<meta charset=\"utf-8\"/>");
  writer.write("<style>");
  writer.write("table {border-collapse: collapse; table-layout: fixed;}");
  writer.write("table, tr, td {border: 1px solid black;}");
  writer.write("td {font: 11pt Calibri, arial, sans-serif;}");
  writer.write("</style>");
  writer.write("</head>");
  writer.write("<body>");

  writer.write(tableHTML.toString());

  writer.write("</body>");
  writer.write("</html>");
  writer.close();

  java.awt.Desktop.getDesktop().browse(new File("result.html").toURI());

 }
}

结果: