1. 程式人生 > >使用Apache POI精確設定Excel的行高和列寬

使用Apache POI精確設定Excel的行高和列寬

EXCEL的行高度和列寬度單位是不一樣的。

1,EXCEL列高度的單位是磅,Apache POI的行高度單位是緹(twip)

1英寸=72磅=25.4毫米=1440緹
1磅=0.353毫米=20緹

POI中的行高=Excel的行高度*20

Excel的行高度=POI中的行高/20

這裡順便把畫素的換行方法說一下:

DPI = 1英寸內可顯示的畫素點個數。通常電腦螢幕是96DPI, IPhone4s的螢幕是326DPI, 普通鐳射黑白印表機是400DPI

要計算POI行高或者Excel的行高,就先把它行轉換到英寸,再乘小DPI就可以得到畫素

畫素 = (磅/72)*DPI

畫素= (Excel的行高度/72)*DPI

畫素= (POI中的行高/20/72)*DPI

Excel的行高度=畫素/DPI*72

POI中的行高=畫素/DPI*72*20

例如在電腦螢幕上, Excel預設行高度為13.5,  (13.5/72)*96=18畫素,而Excel中也確實顯示的就是18畫素。

2,EXCEL列寬度的單位是字元個數

(2014-08-18備註:關於Excel的寬度計算的詳細介紹在這篇文章Excel的寬度怎麼算的?

在excel2003以上的版本中,可以建立一個空白的xls文件並將第一列寬度拉到10。然後在A1單元格中輸入1234567890可以看到單元格正好可以容納這十個字元。一個字元的寬度是通過測量1234567890這十個字元在預設字型(通常是宋體11號字,視版本可能不同)下的平均寬度得到的。

只要記住一個字元的寬度是8畫素 (2013-10-29備註:一個字元的寬度取決於Excel檔案中的第一個字型大小,並不一定就是8畫素)就可以了。

一個單元格實際的畫素寬度還要在 (字元個數 * 預設字元的寬度)的基礎上前後各加2個畫素的空白邊。另外字元之間會疊加一個畫素,在計算時也要減去:

(2013-10-29備註:一個字元的邊距不一定只是2畫素,和字型有關係)

畫素 = 2個畫素空白 + (字元個數 * 預設字元的寬度) + 2個畫素空白 - (字元個數 - 1)

整理一下,公式變成:

畫素 = 5 + (字元個數 * (預設字元的寬度 - 1))

代入預設字元寬度8:

畫素 = 5 + (字元個數 * 7)

POI中的字元寬度演算法是:

double 寬度 = (字元個數 * (字元寬度 - 1) + 5) / (字元寬度 - 1) * 256;

然後再四捨五入成整數。

最後把我寫的一個工具類貼上來,方便使用。

public class HSSFUtil {
	private static final short TWIPS_PER_PIEXL = 15; //1 Pixel = 1440 TPI / 96 DPI = 15 Twips
	
	public static short pixel2PoiHeight(int pixel) {
		return (short) (pixel * TWIPS_PER_PIEXL);
	}

	public static int poiHeight2Pixel(short height) {
		return height / TWIPS_PER_PIEXL;
	}

	//畫素轉poi寬度
	public static int pixel2PoiWidth(FontInfo fontInfo, int pixel) {
		double numChars = pixel2Character(fontInfo, pixel);
		numChars *= fontInfo.charWidth;
		numChars += fontInfo.spacing;
		numChars /= fontInfo.charWidth;
		numChars *= 256;
		return (int)numChars;
	}
	
	//poi寬度轉畫素
	public static int poiWidth2Pixel(FontInfo fontInfo, int poiWidth) {
		double numChars = poiWidth2Character(fontInfo, poiWidth);
		return character2Piexl(fontInfo, numChars);
	}
	
	public static double poiWidth2Character(FontInfo fontInfo, int poiWidth){
		double numChars = poiWidth / 256.0 - (fontInfo.spacing * 1.0 / fontInfo.charWidth);
		//2位小數
		return new BigDecimal(numChars).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	public static int character2PoiWidth(FontInfo fontInfo, double numChars){
		double w = (numChars + (fontInfo.spacing * 1.0 / fontInfo.charWidth)) * 256;
		return (int) w;
	}
	
	//excel字元轉畫素
	public static int character2Piexl(FontInfo fontInfo, double numChars){
		double pixel = fontInfo.charWidth * numChars + fontInfo.spacing;
		return (int)pixel;
	}
	
	//excel畫素轉字元
	public static double pixel2Character(FontInfo fontInfo, int pixel){
		double numChars =  (pixel - fontInfo.spacing) * 1.0 / fontInfo.charWidth;
		return new BigDecimal(numChars).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	//獲得工作簿預設字元寬度
	public static FontInfo getDefaultCharWidth(Workbook book){
		//部落格沒人氣,我已刪除此段程式碼,請自行研究或者留郵箱
	}
	
	//獲得不同字型的字元邊距 
	private static int getSpacing(int fontHeightInPoints, int charWidth){
		//部落格沒人氣,我已刪除此段程式碼,請自行研究或者留郵箱
	}
}