java/poi 调整Excel 列宽支持自适应中文字符宽度

apache/poi是apache旗下用于读写Microsoft Office 二进制文件和OOXML 格式文件的开源库。用它来进行excel文件的导出是很趁手的。
一般来说可以直接使用 Sheet.autoSizeColumn方法自动调整每列的宽度。但是遇到包含中文的列,autoSizeColumn方法计算的列宽是不正确的,算出的宽度不能完整显示中文内容。最近项目中就遇到了这个问题,于是参考网上的各类文章,自己实现了自动适应中文字符宽度的方法

代码如下:

	/**
	 * 自动调整列表宽度适应中文字符串
	 * @param sheet
	 * @param startColumnNum 要调整的起始列表号
	 * @param size  要调整的列表数量
	 */
	public static void autoColumnWidthForChineseChar(Sheet sheet, int startColumnNum, int size) {    
	    for (int columnNum = 0; columnNum < size; columnNum++) {
	    	/** 调整每一列宽度 */ 
			sheet.autoSizeColumn(columnNum);
	        /** 获取列宽 */
	        final int columnWidth = sheet.getColumnWidth(columnNum);
	        if(columnNum >= 256*256 ){
	        	/** 列宽已经超过最大列宽则放弃当前列遍历 */
	        	continue;
	        }
	        /** 新的列宽 */
	        int newWidth = columnWidth;
	        /** 遍历所有的行,查找有汉字的列计算新的最大列宽 */
	        for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
	            Row currentRow;
	            if (sheet.getRow(rowNum) == null) {
	                continue;
	            } else {
	                currentRow = sheet.getRow(rowNum);
	            }
	            if (currentRow.getCell(columnNum) != null) {
	                Cell currentCell = currentRow.getCell(columnNum);
	                if (currentCell.getCellType() == CellType.STRING) {
	                	String value = currentCell.getStringCellValue();
	                	/** 计算字符串中中文字符的数量 */
	                    int count = chineseCharCountOf(value);
	                    /**在该列字符长度的基础上加上汉字个数计算列宽 */
	                    int length = value.length()*256+count*256*2;
	                	/** 使用字符串的字节长度计算列宽 */
//	                    int length = value.getBytes().length*256;
	                    if (newWidth < length && length < 256*256) {
	                    	newWidth = length;
	                    }
	                }
	            }
	        }
	        if(newWidth != columnWidth){
	        	//设置列宽
	        	sheet.setColumnWidth(columnNum, newWidth);
	        }
	    }
	}
	/**
	 * 计算字符串中中文字符的数量
	 * 参见 <a hrft="https://www.cnblogs.com/straybirds/p/6392306.html">《汉字unicode编码范围》</a>
	 * @param input
	 * @return
	 */
	private static int chineseCharCountOf(String input){
		int count = 0;//汉字数量
		if(null != input){
			String regEx = "[\\u4e00-\\u9fa5]";
			Pattern p = Pattern.compile(regEx);
			Matcher m = p.matcher(input);
			int len = m.groupCount();
			//获取汉字个数
			while (m.find()) {
				for (int i = 0; i <= len; i++) {
					count = count + 1;
				}
			}
		}
		return count;
	}

说明

  • 上面的代码中计算汉字数量的方法chineseCharCountOf,为简化实现只统计编译范围在4e00-u9fa5的2万多汉字,这也是主要使用的汉字,实际汉字unicode编译的范围并不止这一个,参见 《汉字unicode编码范围》,如果更严谨的话,可以把这个方法再完善,将所有的编译范围都包括进去。

  • 在网还找到另一个实现就是直接用使用字符串的字节长度计算列宽,不需要统计汉字个数,实际测试效果也是一样的。

    	/** 使用字符串的字节长度计算列宽 */
        int length = value.getBytes().length*256;

参考资料
《POI Excel 中文自适用宽度》

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值