POI 與 Microsoft Office
1. POI 簡介
POI 是 Apache 下的 Jakata 項目的一個子項目,主要用於提供 java 操作 Microsoft
Office 辦公套件如 Excel,Word,Powerpoint 等文件的 API.
微軟的Office 辦公軟件在企業的日常辦公中占據着重要的地位,人們已經非常熟悉
Office 的使用。在我們開發的應用系統中,常常需要將數據導出到 Excel 文件中,或者
Word 文件中進行打印。比如移動的話費查詢系統中就提供了將話費清單導入到 excel 表
格中的功能。這樣在web 應用中,我們在瀏覽器中看到的數據可以被導出到 Excel 中了。
-
Excel 文件: xls 格式文件對應 POI API 為 HSSF 。 xlsx 格式為 office 2007 的文件格式,POI 中對應的API 為XSSF
-
Word 文件:doc 格式文件對應的 POI API 為 HWPF。 docx 格式為 XWPF
-
powerPoint 文件:ppt 格式對應的 POI API 為 HSLF。 pptx 格式為 XSLF
-
outlook :對應的 API 為 HSMF
-
Visio: 對應的 API 為 HDGF
-
Publisher : 對應的 API 為 HPBF
下面主要介紹如何操作Excel。
2. 下載 POI
到apache 官方網站下載POI 的jar 包
3. Excel 文件的結構
一個Excel 文檔稱為工作簿(worksheet),一個工作簿包含多個工作表(sheet),
每個工作表看起來像一張二維表格,由很多行(row)組成,每行由多個單元格組成(cell).
下面是POI HSSF API 中的類與Excel 結構的對應關系:
4. 創建空的 Excel 文件
新建java項目,導入jar文件
4.1 創建空的 xls 文件
創建的xls 文件用excel 打開的時候報錯,因為這個 Excel 文件結構不完整。
4.2 創建空的 xlsx 文件
xlsx 文件是 office2007 文件格式,這種文件格式是基於 xml 的,所以需要在項目中加
入xml 文件解析的jar 包。如圖,jar包在 poi 發行包中能夠找到
同樣道理,因為xlsx 文件信息不完整,所以用Excel 打開的時候出現錯誤
5. 創建工作表
在前面創建的工作簿(WorkBook)的基礎之上創建工作表
創建結果:
6. 創建行數據
執行后的結果:
可以看到日期有一些問題。代碼中使用的是”new Date()”,需要做一些轉換。
這個創建好的格式可以反復使用。
7. 單元格對其方式
HSSFCellStyle 中定義了一些對齊方式
為了方便操作,定義一個創建單元格的方法。
調用它創建單元格:
更多單元格,樣式屬性方法請參閱發行文檔 API
8. 合並單元格
先設置好單元格,然后調用工作表的 addMergedRegion 方法合並單元格
結果:
Ok,大功告成!!
使用POI操作PPT文檔
1)如果是創建新的PPT文檔,直接使用SlideShow和Slide類就可以,其中SlideShow表示PPT文檔,Slide表示某一張幻燈片
如下代碼創建空的PPT文檔:
SlideShow ppt = new SlideShow();Slide[] slides = ppt.getSlides();assertTrue(slides.length == 0);savePPTFile(ppt); private void savePPTFile(SlideShow ppt) throws Exception{ FileOutputStream out = new FileOutputStream(\"ppt測試.ppt\"); ppt.write(out); out.close();}
2)設置母版,這樣后續的新建幻燈片都將使用母版的字體,背景等設置
SlideShow ppt = new SlideShow();//設置幻燈片大小ppt.setPageSize(new Dimension(760,600));SlideMaster master = ppt.getSlidesMasters()[0];
//設置母板背景,支持多種圖片格式int picIndex = ppt.addPicture(new File(\"background.png\"), Picture.PNG);Picture background = new Picture(picIndex);
//設置圖片位置background.setAnchor(new java.awt.Rectangle(0, 0, ppt.getPageSize().width , ppt.getPageSize().height));master.addShape(background);
3)創建幻燈片並插入文本
SlideShow ppt = new SlideShow();Slide newSlide = ppt.createSlide();
//添加幻燈片標題TextBox title = newSlide.addTitle();RichTextRun titleRun = title.getTextRun().getRichTextRuns()[0];titleRun.setFontColor(Color.RED);title.setText(\"ppt測試\");
//添加文本框TextBox txt = new TextBox();RichTextRun richTextRun = txt.getTextRun().getRichTextRuns()[0];richTextRun.setFontColor(Color.BLUE);
//setText參數字符串可以包含回車、換行符,但是最后一行不能以\\r\\n結尾,否則設置的格式沒有效果(v3.5)richTextRun.setText(\"這里可以換行\\r\\n第二行文本\");
txt.setAnchor(new java.awt.Rectangle(50,150,400,400));newSlide.addShape(txt); savePPTFile(ppt);
4)插入圖片,支持多種格式
SlideShow ppt = new SlideShow();Slide newSlide = ppt.createSlide();int picIndex = ppt.addPicture(new File(\"圖片.jpg\"), Picture.JPEG);Picture jpg = new Picture(picIndex);
//set image position in the slidejpg.setAnchor(new java.awt.Rectangle(360, 200, 280, 260)); newSlide.addShape(jpg);savePPTFile(ppt);
5)插入表格(v3.5)
SlideShow ppt = new SlideShow();Slide slide = ppt.createSlide(); String[][] datas = { {\"序號\", \"姓名\",\"年齡\"}, {\"1\", \"張三\",\"30\"}, {\"2\", \"李四\",\"27\"},}; //create a table of 3 rows and 3 columnsTable table = new Table(3, 3); for (int i = 0; i < datas.length; i++) { for (int j = 0; j < datas[i].length; j++) { TableCell cell = table.getCell(i, j); RichTextRun rt = cell.getTextRun().getRichTextRuns()[0]; rt.setFontName(\"宋體\"); rt.setFontSize(12); cell.setVerticalAlignment(TextBox.AnchorMiddle); cell.setHorizontalAlignment(TextBox.AlignCenter); cell.setText(datas[i][j]); if(i == 0){//首行背景設置為灰色 cell.setFillColor(Color.GRAY); } }} Line border = table.createBorder();border.setLineColor(Color.black);border.setLineWidth(2.0);table.setAllBorders(border); slide.addShape(table);table.moveTo(160,260);savePPTFile(ppt);
6)如果是讀取已存在的PPT文檔則還要用到HSLFSlideShow,下面代碼將PPT文件導出為圖片(png)格式,如果幻燈片上有中文字符則這些字符的字體需要修改為支持中文的字體(宋體等),否則導出的圖片的中文字符不能正常顯示
SlideShow ppt = new SlideShow(new HSLFSlideShow(\"PPT測試.ppt\"));Dimension pgsize = ppt.getPageSize();Slide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { BufferedImage img = new BufferedImage(pgsize.width, pgsize.height , BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); //clear the drawing area graphics.setPaint(Color.white); graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height)); //render slide[i].draw(graphics); FileOutputStream out = new FileOutputStream(\"slide-\" + (i+1) + \".png\"); javax.imageio.ImageIO.write(img, \"png\", out); out.close();}
7)提取PPT文檔信息
SlideShow ppt = new SlideShow(new HSLFSlideShow(\"PPT測試.ppt\"));Slide[] slides = ppt.getSlides();//提取文本信息 for (Slide each : slides) { System.out.println(each.getTitle()) ; TextRun[] textRuns = each.getTextRuns(); for (int i=0 ;i< textRuns.length; i++ ) { System.out.println(textRuns[i].getText()); RichTextRun[] richTextRuns = textRuns[i].getRichTextRuns(); for (int j = 0; j < richTextRuns.length; j++) { System.out.println(richTextRuns[j].getText()); } }}//提取所有JPEG圖片PictureData[] picDatas = ppt.getPictureData();for (int i=0;i<picDatas.length;i++) { if(picDatas[i].getType() == Picture.JPEG){ FileOutputStream out = new FileOutputStream(\"jpg_\" + i + \".jpg\"); ppt.write(out); out.close(); }}
8)設置PPT文檔摘要信息(文檔點擊鼠標右鍵查看屬性)
HSLFSlideShow hslf = HSLFSlideShow.create();DocumentSummaryInformation dsi= hslf.getDocumentSummaryInformation(); SummaryInformation si= hslf.getSummaryInformation(); dsi.setCompany(\"yourCompany\"); dsi.setCategory(\"ppt測試\"); si.setAuthor(\"yourName\"); si.setTitle(\"標題\"); SlideShow ppt = new SlideShow(hslf);savePPTFile(ppt);
POI處理Word、Excel、PowerPoint 簡單例子
第一:下載POI,在http://jakarta.apache.org/poi/中,下載poi-bin-3.5-beta4-20081128.zip,解壓后把jar包引入項目工程。
第二:處理Word(Word.java)
import org.apache.poi.hwpf.extractor.WordExtractor; import java.io.File; import java.io.InputStream;
publicclass Word { publicstaticvoid main(String[] args)throws Exception { System.out.println(getContent("c://11.doc")); }
publicstatic String getContent(String s)throws Exception { returngetContent(new java.io.FileInputStream(s)); }
publicstatic String getContent(File f)throws Exception { returngetContent(new java.io.FileInputStream(f)); }
publicstatic String getContent(InputStream is)throws Exception { String bodyText = null; WordExtractor ex = new WordExtractor(is); bodyText = ex.getText(); return bodyText; } }
|
第三:處理Excel(Excel.java)
import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFCell; import java.io.File; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.Date;
publicclassExcel { publicstaticvoid main(String[] args)throws Exception { System.out.println(getContent("c://22.xls")); }
publicstatic String getContent(String s)throws Exception { returngetContent(new java.io.FileInputStream(s)); }
publicstatic String getContent(File f)throws Exception { returngetContent(new java.io.FileInputStream(f)); }
publicstatic String getContent(InputStream is)throws Exception { StringBuffer content = new StringBuffer(); HSSFWorkbook workbook = new HSSFWorkbook(is); for (int numSheets = 0; numSheets < workbook.getNumberOfSheets(); numSheets++) { HSSFSheet aSheet = workbook.getSheetAt(numSheets);//獲得一個sheet content.append("/n"); if (null == aSheet) { continue; } for (int rowNum = 0; rowNum <= aSheet.getLastRowNum(); rowNum++) { content.append("/n"); HSSFRow aRow = aSheet.getRow(rowNum); if (null == aRow) { continue; } for (short cellNum = 0; cellNum <= aRow.getLastCellNum(); cellNum++) {
HSSFCell aCell = aRow.getCell(cellNum); if (null == aCell) { continue; } if (aCell.getCellType() == HSSFCell.CELL_TYPE_STRING) { content.append(aCell.getRichStringCellValue() .getString()); } elseif (aCell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) { boolean b = HSSFDateUtil.isCellDateFormatted(aCell); if (b) { Date date = aCell.getDateCellValue(); SimpleDateFormat df =new SimpleDateFormat( "yyyy-MM-dd"); content.append(df.format(date)); } } } } } return content.toString(); } }
|
第四:處理PowerPoint(PowerPoint.java)
import java.io.File; import java.io.InputStream; import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.model.TextRun; import org.apache.poi.hslf.model.Slide; import org.apache.poi.hslf.usermodel.SlideShow;
publicclassPowerPoint { publicstaticvoid main(String[] args)throws Exception { System.out.println(getContent("c://33.ppt")); }
publicstatic String getContent(String s)throws Exception { returngetContent(new java.io.FileInputStream(s)); }
publicstatic String getContent(File f)throws Exception { returngetContent(new java.io.FileInputStream(f)); }
publicstatic String getContent(InputStream is)throws Exception { StringBuffer content = new StringBuffer(""); SlideShow ss = new SlideShow(new HSLFSlideShow(is)); Slide[] slides = ss.getSlides(); for (int i = 0; i < slides.length; i++) { TextRun[] t = slides[i].getTextRuns(); for (int j = 0; j < t.length; j++) { content.append(t[j].getText()); } content.append(slides[i].getTitle()); } return content.toString(); } }
|
java 讀取 2003 ppt 和 2007 pptx
import java.io.IOException; import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.model.Slide; import org.apache.poi.hslf.model.TextRun; import org.apache.poi.hslf.usermodel.SlideShow; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.xslf.XSLFSlideShow; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide; public class PptReader { /** * @param args */ public static String getTextFromPPT2003(String path) { StringBuffer content = new StringBuffer(""); try { SlideShow ss = new SlideShow(new HSLFSlideShow(path));// path為文件的全路徑名稱,建立SlideShow Slide[] slides = ss.getSlides();// 獲得每一張幻燈片 for (int i = 0; i < slides.length; i++) { TextRun[] t = slides[i].getTextRuns();// 為了取得幻燈片的文字內容,建立TextRun for (int j = 0; j < t.length; j++) { content.append(t[j].getText());// 這里會將文字內容加到content中去 } content.append(slides[i].getTitle()); } } catch (Exception e) { System.out.println(e.toString()); } return content.toString(); } public static String getTextFromPPT2007(String path) { XSLFSlideShow slideShow; String reusltString=null; try { slideShow = new XSLFSlideShow(path); XMLSlideShow xmlSlideShow = new XMLSlideShow(slideShow); XSLFSlide[] slides = xmlSlideShow.getSlides(); StringBuilder sb = new StringBuilder(); for (XSLFSlide slide : slides) { CTSlide rawSlide = slide._getCTSlide(); CTGroupShape gs = rawSlide.getCSld().getSpTree(); CTShape[] shapes = gs.getSpArray(); for (CTShape shape : shapes) { CTTextBody tb = shape.getTxBody(); if (null == tb) continue; CTTextParagraph[] paras = tb.getPArray(); for (CTTextParagraph textParagraph : paras) { CTRegularTextRun[] textRuns = textParagraph.getRArray(); for (CTRegularTextRun textRun : textRuns) { sb.append(textRun.getT()); } } } } reusltString=sb.toString(); } catch (OpenXML4JException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlException e) { // TODO Auto-generated catch block e.printStackTrace(); } return reusltString; } public static void main(String[] args) { System.out.println(PptReader.getTextFromPPT2003("c:/test.ppt")); System.out.println(PptReader.getTextFromPPT2007("c:/test.pptx")); } }
excel 單元格字符數限制(from microsoft support)
Microsoft Excel 版本中,一個單元格可包含多達 32,767 個字符。但是,如果某單元格中包含的字符多於 1,024 個,則應遵循以下規則:
-
大約第 1,024 個字符之后的字符不顯示在單元格中;不過,在編輯或選擇該單元格時,它們會出現在編輯欄中。
-
盡管不會顯示大約第 1,024 個字符之后的字符,但可以使用工作表函數(例如 RIGHT 和 MID 函數)和宏命令(例如“字符”屬性)檢測並操作這些字符。
-
如果復制包含 1,024 個以上字符的單元格,然后將其粘貼到另一單元格中,則會將所有字符粘貼到新的單元格中。不過,大約第 1,024 個字符之后的字符不會在目標單元格中顯示。
-
無法打印單元格中大約第 1,024 個字符之后的字符,且這些字符也不會在打印預覽中顯示。
注意 :增加工作表行高和列寬,或修改系統的顯示設置后,可以看到的字符數將多於 1,024 個。
示例
要了解此問題,請按照下列步驟操作:
-
在新工作表的單元格 A1 中,鍵入以下公式:
=REPT("w",1024)&"xyz"
-
選中單元格 A1,單擊“格式”菜單上的“單元格”。
-
單擊“對齊”選項卡。單擊以選中“自動換行”復選框,然后單擊“確定”。
-
在“格式”菜單上,指向“列”,然后單擊“最適合的列寬”。
請注意,您只能在單元格 A1 中看到“w”字符,該單元格結尾處的“xyz”字符不會顯示。 -
在單元格 A2 和 A3 中鍵入以下公式:
A2:=RIGHT(A1,3)
A3:=LEN(A1)單元格 A2 中的公式返回結果“xyz”,即單元格最右側的三個字符。單元格 A3 中包含數字 1027,即單元格 A1 中的字符數。
-
將單元格 A1 中的公式更改為:
=REPT("w",1023)&"xyz"
您可以看到 1,023 個“w”字符及其后的“x”字符。因為存在 1,024 個字符的限制,所以不會顯示“yz”字符。單元格 A3 中的公式現在顯示 1026,即單元格 A1 的長度。