Apache POI получить метрику шрифта - PullRequest
1 голос
/ 13 января 2020

Я хочу автоматически изменять размер столбцов в Excel, но не тратя слишком много времени. Встроенный авторазмер Apache POI очень медленный (не закончил sh после пары часов с 1 миллионом строк). Чтобы сохранить производительность, я просто хочу приблизить ширину ячейки, но для этого мне нужны метрики шрифта.

Apache POI имеет класс с именем FontDetails, но он не работает сам по себе. Кажется, что класс StaticFontMetrics действительно загружает метрики, но не публикуется c. Но даже если скопировать защищенный код в мое рабочее пространство и сделать его доступным, он не сможет загрузить метрики шрифта.

Как я могу получить эти метрики? Будет ли java.awt.FontMetrics всегда возвращать точный результат?

РЕДАКТИРОВАТЬ: трассировка стека, которую я получаю при попытке получить метрики шрифта:

Caused by: java.lang.IllegalArgumentException: The supplied FontMetrics doesn't know about the font 'Calibri', so we can't use it. Please add it to your font metrics file (see StaticFontMetrics.getFontDetails
at ourpackagestructure.apachepoi.FontDetails.create(FontDetails.java:106)
at ourpackagestructure.apachepoi.StaticFontMetrics.getFontDetails(StaticFontMetrics.java:94)

1 Ответ

1 голос
/ 13 января 2020

Apache poi использует AttributedString и TextLayout , чтобы получить границы текста специальным шрифтом.

Таким образом, пока весь столбец в том же шрифте наилучшим подходом было бы сначала получить самую длинную строку, которая должна храниться в этом столбце. Затем получите ширину этой строки в этом шрифте, используя java.awt.font.TextLayout. Затем установите это как ширину столбца.

Обратите внимание, что ширина столбца в Excel задается в единицах 1/25 от ширины символа по умолчанию. Таким образом, в дополнение к ширине строки этого шрифта в пикселях, вам нужна ширина символа по умолчанию для вычисления ширины столбца Excel.

Пример:

import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.text.AttributedString;
import java.awt.geom.Rectangle2D;

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

public class ApachePoiGetStringWidth {

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

  String testString = "Lorem ipsum semit dolor";
  String fontName = "Calibri";
  short fontSize = 24;
  boolean italic = true;
  boolean bold = false;

  Workbook workbook = new XSSFWorkbook();
  Font font = workbook.createFont();
  font.setFontHeightInPoints(fontSize);
  font.setFontName(fontName);
  font.setItalic(italic);
  font.setBold(bold);
  CellStyle style = workbook.createCellStyle();
  style.setFont(font);

  AttributedString attributedString = new AttributedString(testString);
  attributedString.addAttribute(TextAttribute.FAMILY, font.getFontName(), 0, testString.length());
  attributedString.addAttribute(TextAttribute.SIZE, (float)font.getFontHeightInPoints());
  if (font.getBold()) attributedString.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD,  0, testString.length());
  if (font.getItalic()) attributedString.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE,  0, testString.length());

  FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);

  TextLayout layout = new TextLayout(attributedString.getIterator(), fontRenderContext);
  Rectangle2D bounds = layout.getBounds();
  double frameWidth = bounds.getX() + bounds.getWidth();

System.out.println(frameWidth);

  Sheet sheet = workbook.createSheet();
  Row row = sheet.createRow(2);
  Cell cell = row.createCell(2);
  cell.setCellValue(testString);
  cell.setCellStyle(style);

  int defaultCharWidth = SheetUtil.getDefaultCharWidth(workbook);
  sheet.setColumnWidth(2, (int)Math.round(frameWidth / defaultCharWidth * 256));

  try (java.io.FileOutputStream out = new java.io.FileOutputStream("Excel.xlsx")) {
   workbook.write(out);
  }

  workbook.close();

 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...