Apache POI 获取字体规格

2024-03-10

我想自动调整 Excel 中的列大小,但又不会花费太多性能。 Apache POI 的内置自动调整大小非常慢(在几个小时后没有完成 100 万行)。 为了节省性能,我只想近似单元格宽度,但为此我需要字体规格。

Apache POI 有一个类叫做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)

Apache poi uses 属性字符串 https://docs.oracle.com/javase/8/docs/api/java/text/AttributedString.html and 文本布局 https://docs.oracle.com/javase/8/docs/api/java/awt/font/TextLayout.html使特殊字体的文本超出范围。

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

注意,列宽为Excel以默认字符宽度的 1/256 为单位设置。因此,除了该字体中字符串的宽度(以像素为单位)之外,您还需要默认字符的宽度来计算Excel列宽。

Example:

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

 }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Apache POI 获取字体规格 的相关文章

随机推荐

  • 如何测试 Django 自定义模型字段?

    我正在考虑创建一些子类化 Django 模型字段 https docs djangoproject com en dev howto custom model fields 并将它们作为一个包分发PyPI http pypi python
  • 无法将实体导入数据存储模拟器

    我正在尝试将数据存储实体的备份恢复到在本地主机上运行的模拟器中 我正在使用此位置的指南https cloud google com datastore docs tools emulator export import https clou
  • 在 R 中生成移动和变量

    我怀疑这是一个有点简单的问题 有多种解决方案 但我在 R 方面仍然是一个新手 详尽的搜索并没有产生很好地说明我想做的事情的答案 由于缺乏更好的术语 我正在尝试为数据框中的变量创建 移动总和 这些将是 3 年期和 5 年期的总和 滞后一年 因
  • 如何防止特定模板的隐式模板实例化?

    我想阻止特定模板类的所有隐式模板实例化 以防止它被实例化到每个翻译单元中 看来我的选择是 Use fno 隐式模板在 gcc 的命令行上 这 抑制所有隐式模板实例化 这不是我想要的 我只想防止单个模板出现这种情况 使用C 11 外部模板 但
  • Angular 2 组件中重复的“id”属性

    Context 我正在为复选框编写一个自定义 Angular 组件 该组件呈现复选框标记和标签标记 复选框的 id 属性和标签的 for 属性都设置为组件的id财产 一个 Input到组件 以确保单击标签将切换复选框 该模板的简化版本如下所
  • 如何将 XTickLabel 重置为默认值

    在 R2010b 中 我可以通过图形编辑器将刻度标签重置为自动 但我想以编程方式将它们重置为默认值 I tried set gca XTickLabel auto 但它在每个刻度处显示 自动 有什么提示吗 你需要设置XTickLabelMo
  • 如何删除 CreateUserWizard 控件中的表标签

    如何使用 CreateUserWizard 控件而不让它呈现 html 表 我已经自定义了 CreateUserWizard 的布局 并使用 css 对其进行样式设置 由于以下原因 我的按钮距离表单太远 table 默认情况下 asp ne
  • 哪里可以下载 Eclipse 3.6 (Helios) 的 GlassFish 插件

    您能帮我下载 Eclipse 3 6 Helios 的 GlassFish 插件吗 我试过 https ajax dev java net eclipse https ajax dev java net eclipse Eclipse 中新
  • 为什么每次运行调用 Foo::getInstance() 的脚本时 PHP 都会创建一个新的单例实例?

    我怀疑 PHP 单例不是真正的单例 所以我做了一个测试 我创建了以下课程 class MySingleton private static instance private function construct error log I am
  • 将变量值从 main.py 传递到 .kv 文件

    我正在尝试获取名为的变量的值h从 main py 文件到我的 kv文件 但我得到的只是一个空白屏幕 这是我的main py class ExampleApp App def build self h SoME STRING IS HERE
  • struts2中如何调用一个action中定义的不同方法?

    我不熟悉struts2 但我知道在按名称调用操作期间 Action 中默认调用方法execute 但是如何调用同一个动作类中定义的其他方法呢 在下面的示例中 当我在ajax中设置url链接时 会调用execute 方法 如下所示 saveJ
  • 从列表内的微调器获取值

    我已经使用扩展列表活动的列表适配器创建了android应用程序 在列表中我有旋转器 我如何从列表中的旋转器获取值 告诉一些想法 谢谢进步 尝试这个 Override public void onItemSelected AdapterVie
  • 如何将所有 GitHub 机密放入环境变量中以供操作访问(在我的例子中是 powershell)?

    我读过一些类似的帖子 但似乎没有人回答这个问题 如果我知道秘密的名称 我可以将单个 GitHub 秘密设置到操作中的环境变量中 环境 PW ID0007 秘密 PW ID0007 如何在不知道秘密名称的情况下将所有秘密公开为环境变量 批量或
  • 如何避免在任何时候()“通过引用更新”?

    我想将数字变量转换为POSIXct using anytime 我的问题是anytime
  • 如何使用与 Meteor 具有传递依赖关系的 Node.js 库?

    可以在 Meteor 中使用 node js 包作为此处描述 https stackoverflow com questions 11691513 it possible use a nodejs package inside meteor
  • Grails 依赖注入在服务之外?

    我有一个 Grails 应用程序 需要运行一个可能会随着时间的推移而被替换的策略 我知道 Spring 是 Grails 的基础 所以我想知道我是否可以访问 Spring 的 IoC 容器 以便我可以在 xml 文件中外部化实际依赖项 注意
  • Hibernate @PreUpdate:检查已更改的内容

    问题 如何检查注释的方法内哪些字段已更改 PreUpdate 可选 如果上述问题的答案是 不可能 那么也许还有其他方法可以解决我的问题 I want自动更新modified Tourist每次我们改变它的字段时 除了情况当我们只修改loca
  • Laravel 4 测试; “phpunit”无法识别?

    http four laravel com docs testing http four laravel com docs testing说 安装新的 Laravel 应用程序后 只需运行phpunit在命令行上运行测试 phpunit无法
  • 如何将一个 DialogFragment 提升到另一个之上?

    假设我有几个对话框片段 它们是为了响应可以以任何顺序到达的消息和事件而显示的 通常 最后显示的对话框将位于顶部 有没有办法显示对话框片段under是现有的 还是在显示后更改其 z 顺序 我的应用程序一次显示多个对话框的情况应该很少见 但这种
  • Apache POI 获取字体规格

    我想自动调整 Excel 中的列大小 但又不会花费太多性能 Apache POI 的内置自动调整大小非常慢 在几个小时后没有完成 100 万行 为了节省性能 我只想近似单元格宽度 但为此我需要字体规格 Apache POI 有一个类叫做Fo