当前位置: 首页 > 知识库问答 >
问题:

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

万俟鸿波
2023-03-14

我正在使用Apache POI将Excel转换为HTML。我希望HTML表完全像它在Excel中出现的那样。我经常看到Excel单元格中的数据溢出到下一列的情况。是否有一种方法可以找出数据跨越了多少列,以便向td标记添加colspan属性?请参见Excel中的这张截图:

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

数据溢出的单元格没有合并,所以我不能真正使用sheet.getNummergedRegions()这样的函数

共有1个答案

公羊光明
2023-03-14

Apache POI能够根据列的内容自动调整列的大小。因此,它需要能够计算特定内容所需的列宽。这就是Sheetutil.GetCellWidth正在做的事情。

此外,还需要知道MicrosoftExcel中为列宽引入的非常特殊的度量单位。例如,在ExcelSGUI中,列宽为10意味着10个默认字符宽度的字符适合单元格宽度。但在内部,宽度是以默认字符宽度的1/256为单位计算的。这就是为什么Apache POI决定以字符宽度的1/256为单位获取sheet.getColumnWidth。

因此,如果您有一个单元格具有单元索引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

让我们举一个完整的例子来说明这个原理:

床单:

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());

 }
}
 类似资料:
  • text-overflow属性用来设置容器内的文本溢出时,如何处理溢出的内容,取值为 clip | ellipsis,默认值为 clip。 clip 表示文本溢出时,简单的把溢出的部分裁剪掉;ellipsis 表示文本溢出时,在溢出的地方显示一个省略标记(…)。 在使用 text-overflow属性时,一定要给容器定义宽度,否则,文本只会撑开容器,而不会溢出。 事实上,text-overflow

  • 问题内容: 我正在固定一个下拉框的宽度(是的,我知道这样做存在跨浏览器问题)。 有没有一种非js的方法来切断溢出的文本并附加省略号?text-overflow:省略号不适用于元素(至少在Chrome中)。 问题答案: HTML在表单控件中指定的内容非常有限。这就为操作系统和浏览器制造商留下了做他们认为合适的空间(例如,iPhone的模式,当打开时,它看起来与传统的弹出菜单完全不同)。 看起来大多数

  • 问题背景:我现在想做一个关于文本溢出,显示展开按钮,文本如果没溢出,就不显示展开按钮 例子:如果文本超出两行,显示按钮,小于等于两行,那么就不显示按钮。 但是不知道如何判断文本是否会超出两行?

  • 我正在尝试实现以下布局:一个网格有几个固定宽度的列,其中一列包含未知宽度的内容,它将由多个元素组成,不会换行,并且必须用省略号截断。 一个更具体的例子: 以下是我使用flexbox尝试但未成功的内容: 同样的例子在jsbin上 我还尝试使用内联网格而不是flexbox,这也没有任何帮助(jsbin上的示例)。 有没有办法让这一切顺利进行? 免责声明:我意识到这个问题的变体已经被问及堆栈溢出;但所有

  • 问题内容: 我正在使用。我想找到一个与此CSS类等效的SVG,如果文本从其包含的div中流出,则会添加省略号: 这是我的SVG: 它的生成如下: 当前文本溢出并且与rect元素重叠。 我有什么办法可以说:“如果文本大于特定宽度,则将其裁剪并添加省略号”? 问题答案: 我不知道SVG的等效CSS类,但是您可以用来将HTML嵌入SVG。这使您可以使用此功能,并且通常更灵活(例如,您可以轻松进行自动换行