问题

  目的是要将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单元格中字体的大小的更多相关文章

  1. 如何在excel单元格中插入图片批注

    在excel单元格中插入图片批注的方法: 1.选定要插入图片的单元格,然后右键选择插入批注. 2.然后会插入一个批注框,为了不影响图片效果,可以将批注文字都删除.然后鼠标移动到批注框边角再右键. 3. ...

  2. Java 在Excel单元格中应用一种/多种字体样式

    在Excel表格中,设置单元格字体样式时,可以对单元格内的所有字符应用同一样式,即获取指定单元,应用样式即可:另外也可以对单元格内的不同字符内容应用不同字体样式,即获取单元格中的字符位置,应用样式:本 ...

  3. C#/VB.NET 在Excel单元格中应用多种字体格式

    在Excel中,可对单元格中的字符串设置多种不同样式,通常只需要获取到单元格直接设置样式即可,该方法设置的样式会应用于该单元格中的所有字符.如果需要对单元格中某些字符设置样式,则可以参考本文中的方法. ...

  4. excel单元格中批量加入固定字符

    excel单元格前怎么批量加字母 现在我要在联系人这列,每个姓名前加入衡阳的首字母简写(HY). 3 在同行上面随便找列,我找D列.输入公式:="HY"&A2. 5 输入后 ...

  5. 通过VBA,当在EXCEL单元格中输入任意的日期格式时,都能自动转换为指定的标准格式的日期值

    在日常录入EXCEL表格的单元格里 ,我们输入一些一般性的日期内容,如:2017-10-17 或 2017/10/17时,EXCEL会自动识别为日期并按单元格设计格式显示,单元格中存储的值也是日期格式 ...

  6. POI获取excel单元格红色字体,淡蓝色前景色的内容

    如果是Microsoft Excel 97-2003 工作表 (.xls) if(31 == cell.getCellStyle().getFillForegroundColor()) //判断单元格 ...

  7. 使用Excel对象模型在Excel单元格中设置不同的字体

    效果是这样的: 首先找到这个单元格或区域Range cell,然后代码: ((Range)cell). Characters[, ].Font.Color = Color.Blue; ((Range) ...

  8. POI HSSFCellStyle 设置 Excel 单元格样式

    POI中可能会用到一些需要设置EXCEL单元格格式的操作小结: 先获取工作薄对象: HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb ...

  9. 在excel单元格中提取信息

    平时在excel中处理数据的时候,肯定会遇到在单元格提取信息的情况,比如在地址中提取省.市.地区等,如果数据源内容规整的话,可以直接使用left().right().mid()等函数直接提取,但是大多 ...

随机推荐

  1. Linux常见问题汇总

    Linux问题: ifconfig查看IP地下载报错:bash: ifconfig: commandnotfound 解决方法: 先执行 export PATH="$PATH:/sbin&q ...

  2. 小L的项链切割 (回文串)

    题目描述 小T送给了小L了一串项链.为了方便,我们把项链上形态不同钻石用不同的字母表示.这样小L的项链就变成了一个字符串.小L忽然想把这串项链优美地切割一下,她想把它切割成尽量少的回文项链,啊也就是回 ...

  3. 16-使用Selenium模拟浏览器抓取淘宝商品美食信息

    淘宝由于含有很多请求参数和加密参数,如果直接分析ajax会非常繁琐,selenium自动化测试工具可以驱动浏览器自动完成一些操作,如模拟点击.输入.下拉等,这样我们只需要关心操作而不需要关心后台发生了 ...

  4. python中的Init方法, new 方法 call 方法

    new 方法实现单列模式思考 class Single: _single = None _single_only = None def __init__(self, value): self.v = ...

  5. Python_内置函数之zip

    zip函数用于将可迭代的对象作为参数,将对象中的元素打包成一个个元祖,然后返回这些元祖组成的列表.如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同. l1 = [1, 2, 3] l2 ...

  6. Python_守护进程、锁、信号量、事件、队列

    1.创建进程 守护进程(*****) _.daemon = True #  _进程成为守护进程 守护进程也是一个子进程. 主进程的<代码>执行结束之后守护进程自动结束. import ti ...

  7. promise-笔记

    promise 封装Promise var fs = require('fs') function pReadFile(filePath) { return new Promise(function ...

  8. vue动态class——实现tag的选中状态

    vue动态class——实现tag的选中状态 <template> <div class="common-nav"> <div class=" ...

  9. python之路--初识函数

    一 . 函数 什么是函数 f(x) = x + 1 y = x + 1 # 函数是对功能或者动作的封装 函数的语法 def 函数名(): 函数体 调用: 函数名() def play(): print ...

  10. Fetch API & Delete & HTTP Methods

    Fetch API & Delete & HTTP Methods vue https://developer.mozilla.org/en-US/docs/Web/API/Fetch ...