Java ApachePOI获取字体度量

Java ApachePOI获取字体度量,java,excel,apache-poi,Java,Excel,Apache Poi,我想在excel中自动调整列的大小,但不会花费太多的性能。 ApachePOI的内置自动大小非常慢(使用100万行数小时后没有完成)。 为了节省性能,我只想近似计算单元格宽度,但为此我需要字体度量 ApachePOI有一个名为FontDetails的类,但它本身不能工作。 类StaticFontMetrics似乎是实际加载度量的类,但它不是公共的。 但即使将受保护的代码复制到我的工作区并使其可访问,也无法加载字体度量 我如何获得这些指标?java.awt.FontMetrics是否总是返回准确的

我想在excel中自动调整列的大小,但不会花费太多的性能。 ApachePOI的内置自动大小非常慢(使用100万行数小时后没有完成)。 为了节省性能,我只想近似计算单元格宽度,但为此我需要字体度量

ApachePOI有一个名为
FontDetails
的类,但它本身不能工作。 类
StaticFontMetrics
似乎是实际加载度量的类,但它不是公共的。 但即使将受保护的代码复制到我的工作区并使其可访问,也无法加载字体度量

我如何获得这些指标?
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)

apachepoi
使用和以特殊字体获取文本的边界

因此,只要整个列的字体相同,最好的方法是首先获取存储在该列中的最长字符串。然后使用
java.awt.font.TextLayout
获取该字体中该字符串的宽度。然后将其设置为列宽

注意,
Excel
中的列宽设置为默认字符宽度的1/256。因此,除了该字体中字符串的宽度(以像素为单位),还需要默认字符的宽度来计算
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();

 }
}

只填充几行,根据初始数据自动调整大小,然后再不自动调整大小?不起作用,最后可能会出现大字符串,这只在用例的一小部分中起作用感谢响应,这是我将要使用的方法,我只是对获取字符串的实际宽度感到困惑。我还处理了一列中的多种字体。我也已经有一个像素到ApachePOI转换设置。