POI如何自动调整Excel单元格中字体的大小
问题
目的是要将Excel中的文字全部显示出来,可以设置对齐格式为【缩小字体填充】,但是这样的话只能展示出一行数据,字体会变得很小。还有一种办法,设置对齐格式为【自动换行】,然后让单元格中的字体自动调整大小。
我的实现思路是,设置单元格中的字体大小,最大10号字,最小5号字,判断优先使用大的字体;如果最小的5号字也放不下,那就只能调整模板了。关键点就是判断当前字号能否将内容完全展示在单元格中。
需要提前说明一点,我的这个方法是不精确的算法,excel设置字体的时候太强大了,不同的字体的字间距、行间距都会不同。
关键点
判断字体大小是否合理的思路:
1、计算出单元格的总宽度、总高度
2、计算出其中的内容的总长度,不同的字号,长度是不同的
3、内容总长度除以单元格宽度,得出实际上一共有多少行数据 x
4、单元格的总高度除以内字体的高度,得出能展示出来的数据有多少行 y
5、如果 y>=x ,那么表示所有的数据都能展示出来
这个判断单元格中的字体大小是否合理的思路也不难,难的是如何获取到需要的参数。
注意点
1、设置单元格字体大小的方法是:font.setFontHeightInPoints(k),但是获取字体宽度和高度的方法并不精确,因为字体间会有字间距,换行以后行之间也有间距,所以这个算法并不精确。
这个例子中,我的获取字体高度的方法是直接取 k,获取字体宽度的方法是 k*2
2、在上诉关键点的第5步中,本来我的想法是 y向下取整, x向上取整,然后再进行比较。但是测试后发现,设置的字体都会偏小。 直接取y>=x,结果反而更合理些。
3、进行相除运算,单位必须相同。POI中Point(坐标点)和Pixel(像素点)的大小关系,我在之前的文章有介绍过,引用结论,获取行高的像素值的方法就是: (row.getHeightInPoints() / 72) * 96
代码实例
样例中的单元格是合并单元格,起始坐标 (3,5),结束坐标 (3,8)
public static void main(String[] args) {
try (InputStream is = new FileInputStream("E:\\test1.xls");
Workbook book = new HSSFWorkbook(is);) {
Cell cell = book.getSheetAt(0).getRow(3).getCell(5);
String str = "一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十";
cell.setCellValue(str);
setFontSize(book, cell);
File f = new File("E:\\test2.xls");
FileOutputStream out = new FileOutputStream(f);
book.write(out);
} catch (IOException e) {
//return;
}
}
/**
* 设置单元格字体大小
*/
private static void setFontSize(Workbook book, Cell cell) {
Font font = book.createFont();
font.setFontName("EUDC");
for (short k = 10; k >= 5; k--) {
font.setFontHeightInPoints(k);
if (checkCellReasonable(cell, k)) {
break;
}
}
//解决单元格样式覆盖的问题
CellStyle cStyle = book.createCellStyle();
cStyle.cloneStyleFrom(cell.getCellStyle());
cStyle.setWrapText(true);
cStyle.setFont(font);
cell.setCellStyle(cStyle);
}
/**
* 校验单元格中的字体大小是否合理
*/
private static boolean checkCellReasonable(Cell cell, short fontSize) {
int sum = cell.getStringCellValue().length();
double cellWidth = getTotalWidth(cell);
double fontWidth = (double) fontSize / 72 * 96 * 2;
double cellHeight = cell.getRow().getHeightInPoints();
double rows1 = fontWidth * sum / cellWidth;
double rows2 = cellHeight / fontSize;
return rows2 >= rows1;
}
/**
* 获取单元格的总宽度(单位:像素)
*/
private static double getTotalWidth(Cell cell) {
int x = getColNum(cell.getSheet(), cell.getRowIndex(), cell.getColumnIndex());
double totalWidthInPixels = 0;
for (int i = 0; i < x; i++) {
totalWidthInPixels += cell.getSheet().getColumnWidthInPixels(i + cell.getColumnIndex());
}
return totalWidthInPixels;
}
/**
* 获取单元格的列数,如果是合并单元格,就获取总的列数
*/
private static int getColNum(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
//判断该单元格是否是合并区域的内容
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if (row >= firstRow && row <= lastRow && column >= firstColumn && column <= lastColumn) {
return lastColumn - firstColumn + 1;
}
}
return 1;
}
其中,获取单元格总宽度的方法getTotalWidth(Cell cell),有更简单的方法,在《我的POI代码库》里介绍
原创文章,欢迎转载,转载请注明出处!
POI如何自动调整Excel单元格中字体的大小的更多相关文章
- 如何在excel单元格中插入图片批注
在excel单元格中插入图片批注的方法: 1.选定要插入图片的单元格,然后右键选择插入批注. 2.然后会插入一个批注框,为了不影响图片效果,可以将批注文字都删除.然后鼠标移动到批注框边角再右键. 3. ...
- Java 在Excel单元格中应用一种/多种字体样式
在Excel表格中,设置单元格字体样式时,可以对单元格内的所有字符应用同一样式,即获取指定单元,应用样式即可:另外也可以对单元格内的不同字符内容应用不同字体样式,即获取单元格中的字符位置,应用样式:本 ...
- C#/VB.NET 在Excel单元格中应用多种字体格式
在Excel中,可对单元格中的字符串设置多种不同样式,通常只需要获取到单元格直接设置样式即可,该方法设置的样式会应用于该单元格中的所有字符.如果需要对单元格中某些字符设置样式,则可以参考本文中的方法. ...
- excel单元格中批量加入固定字符
excel单元格前怎么批量加字母 现在我要在联系人这列,每个姓名前加入衡阳的首字母简写(HY). 3 在同行上面随便找列,我找D列.输入公式:="HY"&A2. 5 输入后 ...
- 通过VBA,当在EXCEL单元格中输入任意的日期格式时,都能自动转换为指定的标准格式的日期值
在日常录入EXCEL表格的单元格里 ,我们输入一些一般性的日期内容,如:2017-10-17 或 2017/10/17时,EXCEL会自动识别为日期并按单元格设计格式显示,单元格中存储的值也是日期格式 ...
- POI获取excel单元格红色字体,淡蓝色前景色的内容
如果是Microsoft Excel 97-2003 工作表 (.xls) if(31 == cell.getCellStyle().getFillForegroundColor()) //判断单元格 ...
- 使用Excel对象模型在Excel单元格中设置不同的字体
效果是这样的: 首先找到这个单元格或区域Range cell,然后代码: ((Range)cell). Characters[, ].Font.Color = Color.Blue; ((Range) ...
- POI HSSFCellStyle 设置 Excel 单元格样式
POI中可能会用到一些需要设置EXCEL单元格格式的操作小结: 先获取工作薄对象: HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb ...
- 在excel单元格中提取信息
平时在excel中处理数据的时候,肯定会遇到在单元格提取信息的情况,比如在地址中提取省.市.地区等,如果数据源内容规整的话,可以直接使用left().right().mid()等函数直接提取,但是大多 ...
随机推荐
- python3 pip 安装Scrapy在win10 安装报错error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools
问题描述 当前环境win10,python_3.6.1,64位. 在windows下,在dos中运行pip install Scrapy报错: building 'twisted.test.raise ...
- H5 29-div和span标签
29-div和span标签 --> 努力到无能为力, 拼搏到感动自己 --> 我是div 我是div 我是span 我是span --> --> 我是段落 我是标题 --> ...
- Mike and gcd problem CodeForces - 798C (贪心思维+数论)
题目链接 比较棒的一道题, 题意: 给你一个N个数的数组,让你用尽量少的操作使整个数组的gcd大于1,即gcd(a1 ,a2,,,,an) > 1 如果可以输出YES和最小的次数,否则输出NO ...
- VO和DO转换(三) Dozer
VO和DO转换(一) 工具汇总 VO和DO转换(二) BeanUtils VO和DO转换(三) Dozer VO和DO转换(四) MapStruct 可参考的资料: dozer官网 Dozer(Jav ...
- 【学习总结】Git学习-参考廖雪峰老师教程六-分支管理
学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...
- 11 The superlative
1 最高级用来表明三个或更多事物之间的关系.最高级是通过在形容词之前加 "the" 并在之后加 "-est",或在形容词之前加 "the most&q ...
- Windows 机器上面同时安装mysql5.6 和 mysql5.7 的方法
1. 自己遇到的两个坑: . mysql 登录的时候 需要使用-P 来指定端口号 不然默认走 呢 . mysql 5.6 和 mysql 5.7 更改用户密码的命令不一样.. 我这边浪费了很长时间: ...
- ToroiseGit提交代码上传到阿里云的Gitlab
https://blog.csdn.net/xiaomogg/article/details/51903004(copy) 准备 具体过程 准备 1.拥有一个GitHub账户 2.安装了Tortois ...
- bootstrap3兼容IE8
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 剑指offer(7)
今天的几道题目都是关于斐波那契数列的. 题目1: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 传统的方法采用递归函数,这种 ...