Apache POI: узнайте, сколько текста переполняет следующий столбец - PullRequest
0 голосов
/ 31 мая 2019

Я использую Apache POI для преобразования Excel в HTML.Я хочу, чтобы таблица HTML была точно такой же, как в Excel.Я часто вижу случаи, когда данные в ячейке Excel переполняются до следующего столбца.Есть ли способ узнать, сколько столбцов перекрывает данные, чтобы я мог добавить атрибут colspan к тегу TD?Смотрите этот снимок экрана из Excel:

enter image description here

В этом случае данные в ячейке A2 переполняются в ячейку B2 (также A3 переполняется в B3).Есть ли способ узнать, что для тега TD, соответствующего ячейке A2, требуется атрибут colspan="2"?

Ячейки, в которых данные переполняются, не объединены, поэтому я не могу использовать такие функции, как sheet.getNumMergedRegions()

Я думаю, что я также могу рассчитать его, если каким-то образом я могу узнать "видимую" ширину столбцов в Excel.Однако sheet.getColumnWidth() предоставляет только фактическую ширину.Я не вижу способа узнать «видимую» ширину столбца в Excel.На скриншоте выше видимая ширина столбца A очень мала.Есть ли способ найти эту «видимую» ширину?

Я использую Apache POI 3.17

1 Ответ

1 голос
/ 01 июня 2019

Apache poi может автоматически изменять размеры столбцов в зависимости от их содержимого.Таким образом, он должен быть в состоянии вычислить, какая ширина столбца понадобится специальному контенту.Это то, что SheetUtil.getCellWidth делает.

Кроме того, необходимо знать, какие особые единицы измерения Microsoft введены для ширины столбцов в Excel.Например, в Excel s GUI ширина столбца 10 означает, что 10 символов ширины символов по умолчанию вписываются в ширину ячейки.Но внутренне ширина рассчитывается в единицах 1/25 от ширины символа по умолчанию.Вот почему apache poi решил получить Sheet.getColumnWidth в единицах 1/25 от ширины символа.

Таким образом, если у вас есть 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.

Давайте приведем полный пример, демонстрирующий принцип:

Лист:

enter image description here

Код:

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

 }
}

Результат:

enter image description here

...