一、POI簡介
Jakarta POI 是apache的子項目,目標是處理ole2對象。它提供了一組操縱Windows文檔的Java API
目前比較成熟的是HSSF接口,處理MS Excel(97-2002)對象。它不象我們僅僅是用csv生成的沒有格式的可以由Excel轉換的東西,而是真正的Excel對象,你可以控制一些屬性如sheet,cell等等。
二、HSSF概況
HSSF 是Horrible SpreadSheet Format的縮寫,也即“討厭的電子表格格式”。 也許HSSF的名字有點滑稽,就本質而言它是一個非常嚴肅、正規的API。通過HSSF,你可以用純Java代碼來讀取、寫入、修改Excel文件。
HSSF 為讀取操作提供了兩類API:usermodel和eventusermodel,即“用戶模型”和“事件-用戶模型”。前者很好理解,后者比較抽象,但操作效率要高得多。
三、實現
1. 在sheet中特定位置插入圖片
Excel插入圖片步驟 :
畫圖的頂級管理器對象HSSFPatriarch, 一個sheet只能獲取一個
創建一個新的客戶端錨點HSSFClientAnchor
圖片轉換為字節流byte[]
向Excel中添加一張圖片,返回圖片在excel中的索引,base 1
創建圖片
2.示例:
<code class="language-java">// patriarch負責在sheet中創建圖片
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
/**
* 創建一個新的客戶端錨點,附加到excel工作表,並設置左上角和右下角
*
* @param realX1 圖片的左上角在開始單元格(col1,row1)中的橫坐標
* @param realY1 圖片的左上角在開始單元格(col1,row1)中的縱坐標
* @param realX2 圖片的右下角在結束單元格(col2,row2)中的橫坐標
* @param realY2 圖片的右下角在結束單元格(col2,row2)中的縱坐標
* @param col1 開始單元格所處的列號, base 0, 圖片左上角在開始單元格內
* @param row1 開始單元格所處的行號, base 0, 圖片左上角在開始單元格內
* @param col2 結束單元格所處的列號, base 0, 圖片右下角在結束單元格內
* @param row2 結束單元格所處的行號, base 0, 圖片右下角在結束單元格內
* */
HSSFClientAnchor anchor = new HSSFClientAnchor(realX1, realY1, realX2, realY2, col1, row1, col2, row2);
// 圖片字節流
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
BufferedImage bufferImg = ImageIO.read(new File("ok.jpg"));
ImageIO.write(bufferImg, "jpg", byteArrayOut);
byte[] imgtypes = byteArrayOut.toByteArray();
/*
* 在工作簿中添加一張圖片,返回圖片的索引,base 1
* @param pictureType 圖片類型 PICTURE_TYPE_JPEG|PICTURE_TYPE_PNG
**/
int puctureIndex = workbook.addPicture(imgtypes, pictureType);
// 創建圖片
patriarch.createPicture(anchor, puctureIndex);</code>
生成簡單的Excel文件
在現實的辦公中,我們常常會有這樣一個要求:要求把報表直接用excel打開。在實習中有這樣一個需求。根據所選擇的資源查詢用戶所提供附件的全部信息並生成excel供下載。但是在查詢的時候我們需要來檢測用戶所提供的附件里面的信息是否有錯誤(身份證)。有錯誤的生成錯誤信息excel。
Apache的POI項目,是目前比較成熟的HSSF接口,用來處理Excel對象。其實POI不僅僅只能處理excel,它還可以處理word、PowerPoint、Visio、甚至Outlook。
這里我先介紹利用POI如何生成excel。
首先在生成Excel前,我們需要理解一下Excel文件的組織形式。在POI中,是這樣理解的:一個Excel文件對應一個workbook,一個workerbook是有若干個sheet組成的。一個sheet有多個row,一個row一般存在多個cell。
對於上面的四個名詞我們可以在下圖理解

對於生成Excel,POI提供了如下幾個基本對象:
- HSSFWorkbook:excel 的文檔對象
- HSSFSheet:excel 的表單
- HSSFRow :excel 的行
- HSSFCell:excel 的格子單元
從上面的圖片和Excel的組織結構,我們就可以明白創建Excel的步驟。
1、生成文檔對象HSSHWorkbook。
2、通過HSSFWorkbook生成表單HSSFSheet。
3、通過HSSFSheet生成行HSSFRow
4、通過HSSFRow生成單元格HSSFCell。
下面是展示代碼:
身份證錯誤Bean(ErrorCondition.java)
public class ErrorCondition {
private String name; // 姓名
private String idCard; // 身份證
private String status; // 錯誤狀態
private String message; // 錯誤信息
ErrorCondition(String name,String idCard,String status,String message){
this.name = name;
this.idCard = idCard;
this.status = status;
this.message = message;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
處理類(ExportErrorExcel.java)
public class ExportErrorExcel {
public static void main(String[] args) {
//第一步創建workbook
HSSFWorkbook wb = new HSSFWorkbook();
//第二步創建sheet
HSSFSheet sheet = wb.createSheet("身份證錯誤信息");
//第三步創建行row:添加表頭0行
HSSFRow row = sheet.createRow(0);
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER); //居中
//第四步創建單元格
HSSFCell cell = row.createCell(0); //第一個單元格
cell.setCellValue("姓名"); //設定值
cell.setCellStyle(style); //內容居中
cell = row.createCell(1); //第二個單元格
cell.setCellValue("身份證");
cell.setCellStyle(style);
cell = row.createCell(2); //第三個單元格
cell.setCellValue("錯誤狀態");
cell.setCellStyle(style);
cell = row.createCell(3); //第四個單元格
cell.setCellValue("錯誤信息");
cell.setCellStyle(style);
//第五步插入數據
List<ErrorCondition> list = ExportErrorExcel.getErrorCondition();
for (int i = 0; i < list.size(); i++) {
ErrorCondition errorCondition = list.get(i);
//創建行
row = sheet.createRow(i+1);
//創建單元格並且添加數據
row.createCell(0).setCellValue(errorCondition.getName());
row.createCell(1).setCellValue(errorCondition.getIdCard());
row.createCell(2).setCellValue(errorCondition.getStatus());
row.createCell(3).setCellValue(errorCondition.getMessage());
}
//第六步將生成excel文件保存到指定路徑下
try {
FileOutputStream fout = new FileOutputStream("D:\\errorCondition.xls");
wb.write(fout);
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Excel文件生成成功...");
}
public static List<ErrorCondition> getErrorCondition(){
List<ErrorCondition> list = new ArrayList<ErrorCondition>();
ErrorCondition r1 = new ErrorCondition("張三", "4306821989021611", "L", "長度錯誤");
ErrorCondition r2 = new ErrorCondition("李四", "430682198902191112","X", "校驗錯誤");
ErrorCondition r3 = new ErrorCondition("王五", "", "N", "身份證信息為空");
list.add(r1);
list.add(r2);
list.add(r3);
return list;
}
}
通過上面六個步驟就可以在指定的位置生成Excel文件了。

java POI實現向Excel中插入圖片
做Web開發免不了要與Excel打交道。今天老大給我一個任務-導出Excel。開始想的還是蠻簡單的,無非就是查找,構建Excel,response下載即可。但是有一點不同,就是要加入圖片,就是這個加入圖片搞了好久。同時網絡上確實沒有發現比較好的資料,所以寫這篇博文記錄之,供自己和博友們查詢,參考。
在POI中有HSSFPatriarch對象,該對象為畫圖的頂級管理器,它的createPicture(anchor, pictureIndex)方法就能夠在Excel插入一張圖片。所以要在Excel中插入圖片,三步就可以搞定。一、獲取HSSFPatriarch對象,二、new HSSFClientAnchor對象,三、調用createPicture方法即可。實現倒是非常容易實現,如果想把它做好還是有點兒難度的。這里我們先插入一張圖片:
public class ExcelImageTest {
public static void main(String[] args) {
FileOutputStream fileOut = null;
BufferedImage bufferImg = null;
//先把讀進來的圖片放到一個ByteArrayOutputStream中,以便產生ByteArray
try {
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
bufferImg = ImageIO.read(new File("F:/圖片/照片/無名氏/小昭11.jpg"));
ImageIO.write(bufferImg, "jpg", byteArrayOut);
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet1 = wb.createSheet("test picture");
//畫圖的頂級管理器,一個sheet只能獲取一個(一定要注意這點)
HSSFPatriarch patriarch = sheet1.createDrawingPatriarch();
//anchor主要用於設置圖片的屬性
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 255, 255,(short) 1, 1, (short) 5, 8);
anchor.setAnchorType(3);
//插入圖片
patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
fileOut = new FileOutputStream("D:/測試Excel.xls");
// 寫入excel文件
wb.write(fileOut);
System.out.println("----Excle文件已生成------");
} catch (Exception e) {
e.printStackTrace();
}finally{
if(fileOut != null){
try {
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
如下為執行后的結果:

至於為什么會是這樣的結果,主要是因為HSSFClientAnchor(0, 0, 255, 255,(short) 1, 1, (short) 5, 8)這個構造函數造成的,下面我就來解釋這個構造函數:HSSFClientAnchor(int dx1,int dy1,int dx2,int dy2,short col1,int row1,short col2, int row2);各個參數的含義如下:
- dx1:the x coordinate within the first cell。
- dy1:the y coordinate within the first cell。
- dx2:the x coordinate within the second cell。
- dy2:the y coordinate within the second cell。
- col1:the column (0 based) of the first cell。
- row1:the row (0 based) of the first cell。
- col2:the column (0 based) of the second cell。
- row2:the row (0 based) of the second cell。
這里dx1、dy1定義了該圖片在開始cell的起始位置,dx2、dy2定義了在終cell的結束位置。col1、row1定義了開始cell、col2、row2定義了結束cell。

下面是有兩個不同的構造函數所創建的,從這幅圖中我們可以清晰看到上面八個參數的含義和不同之處。

上面是插入一張圖片,那么實現插入多張圖片呢?其實很簡單,構造多個不同的HSSFClientAnchor對象,控制好那八個參數,如下:
HSSFClientAnchor anchor1 = new HSSFClientAnchor(0, 0, 1023,100,(short) 1, 1, (short)5, 8);
HSSFClientAnchor anchor2 = new HSSFClientAnchor(0, 0, 1023,100,(short) 1, 9, (short)5, 16);
//插入圖片
patriarch.createPicture(anchor1, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
patriarch.createPicture(anchor2, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
其余代碼一樣,得到如下結果:

參考:https://blog.csdn.net/lipinganq/article/details/54572469?utm_source=blogxgwz6 https://m.jb51.net/article/79982.htm
