1. POI 生成WORD文檔為什麼WORD文檔打不開
Jacob解決Word文檔的讀寫問題收藏
Jacob 是java-COM Bridge的縮寫,它在Java與微軟的COM組件之間構建一座橋梁。使用Jacob自帶的DLL動態鏈接庫,並通過JNI的方式實現了在Java平台上對COM程序的調用。Jacob下載的地址為:
http://sourceforge.net/project/showfiles.php?group_id=109543&package_id=118368
配置:
(1)將解壓包中的jacob.dll(x86常用,x64)拷到jdk安裝目錄下的jre\bin文件夾或windows安裝路徑下的WINDOWS\system32文件夾下
(2)將jacob.jar文件拷到classpath下即可
常見問題解決:
對於」java.lang.UnsatisfiedLinkError: C:\WINDOWS\system32\jacob-1.14.3-x86.dll: 由於應用程序配置不正確,應用程序未能啟動。重新安裝應用程序可能會糾正」這個問題,可以通過
重新下載Jacob的jar及dll文件(最好版本比現在的低,如1.11)解決
實例製作(主要功能:標題製作,表格製作,合並表格,替換文本,頁眉頁腳,書簽處理):
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class WordOperate {
public static void main(String args[]) {
ActiveXComponent wordApp = new ActiveXComponent("Word.Application"); // 啟動word
// Set the visible property as required.
Dispatch.put(wordApp, "Visible", new Variant(true));// //設置word可見
Dispatch docs = wordApp.getProperty("Documents").toDispatch();
// String inFile = "d:\\test.doc";
// Dispatch doc = Dispatch.invoke(docs, "Open", Dispatch.Method,
// new Object[] { inFile, new Variant(false), new Variant(false)},//參數3,false:可寫,true:只讀
// new int[1]).toDispatch();//打開文檔
Dispatch document = Dispatch.call(docs, "Add").toDispatch();// create new document
String userName = wordApp.getPropertyAsString("Username");// 顯示用戶信息
System.out.println("用戶名:" + userName);
// 文檔對齊,字體設置////////////////////////
Dispatch selection = Dispatch.get(wordApp, "Selection").toDispatch();
Dispatch align = Dispatch.get(selection, "ParagraphFormat")
.toDispatch(); // 行列格式化需要的對象
Dispatch font = Dispatch.get(selection, "Font").toDispatch(); // 字型格式化需要的對象
// 標題處理////////////////////////
Dispatch.put(align, "Alignment", "1"); // 1:置中 2:靠右 3:靠左
Dispatch.put(font, "Bold", "1"); // 字型租體
Dispatch.put(font, "Color", "1,0,0,0"); // 字型顏色紅色
Dispatch.call(selection, "TypeText", "Word文檔處理"); // 寫入標題內容
Dispatch.call(selection, "TypeParagraph"); // 空一行段落
Dispatch.put(align, "Alignment", "3"); // 1:置中 2:靠右 3:靠左
Dispatch.put(selection, "Text", " ");
Dispatch.call(selection, "MoveDown"); // 游標標往下一行
//表格處理////////////////////////
Dispatch tables = Dispatch.get(document, "Tables").toDispatch();
Dispatch range = Dispatch.get(selection, "Range").toDispatch();
Dispatch table1 = Dispatch.call(tables, "Add", range, new Variant(3),
new Variant(2), new Variant(1)).toDispatch(); // 設置行數,列數,表格外框寬度
// 所有表格
Variant tableAmount = Dispatch.get(tables, "count");
System.out.println(tableAmount);
// 要填充的表格
Dispatch t1 = Dispatch.call(tables, "Item", new Variant(1))
.toDispatch();
Dispatch t1_row = Dispatch.get(t1, "rows").toDispatch();// 所有行
int t1_rowNum = Dispatch.get(t1_row, "count").getInt();
Dispatch.call(Dispatch.get(t1, "columns").toDispatch(), "AutoFit");// 自動調整
int t1_colNum = Dispatch.get(Dispatch.get(t1, "columns").toDispatch(),
"count").getInt();
System.out.println(t1_rowNum + " " + t1_colNum);
for (int i = 1; i <= t1_rowNum; i++) {
for (int j = 1; j <= t1_colNum; j++) {
Dispatch cell = Dispatch.call(t1, "Cell", new Variant(i),
new Variant(j)).toDispatch();// 行,列
Dispatch.call(cell, "Select");
Dispatch.put(selection, "Text", "cell" + i + j); // 寫入word的內容
Dispatch.put(font, "Bold", "0"); // 字型租體(1:租體 0:取消租體)
Dispatch.put(font, "Color", "1,1,1,0"); // 字型顏色
Dispatch.put(font, "Italic", "1"); // 斜體 1:斜體 0:取消斜體
Dispatch.put(font, "Underline", "1"); // 下劃線
Dispatch Range = Dispatch.get(cell, "Range").toDispatch();
String cellContent = Dispatch.get(Range, "Text").toString();
System.out.println((cellContent.substring(0, cellContent
.length() - 1)).trim());
}
Dispatch.call(selection, "MoveDown"); // 游標往下一行(才不會輸入蓋過上一輸入位置)
}
//合並單元格////////////////////////
Dispatch.put(selection, "Text", " ");
Dispatch.call(selection, "MoveDown"); // 游標標往下一行
Dispatch range2 = Dispatch.get(selection, "Range").toDispatch();
Dispatch table2 = Dispatch.call(tables, "Add", range2, new Variant(8),
new Variant(4), new Variant(1)).toDispatch(); // 設置行數,列數,表格外框寬度
Dispatch t2 = Dispatch.call(tables, "Item", new Variant(2))
.toDispatch();
Dispatch beginCell = Dispatch.call(t2, "Cell", new Variant(1),
new Variant(1)).toDispatch();
Dispatch endCell = Dispatch.call(t2, "Cell", new Variant(4),
new Variant(4)).toDispatch();
Dispatch.call(beginCell, "Merge", endCell);
for (int row = 1; row <= Dispatch.get(
Dispatch.get(t2, "rows").toDispatch(), "count").getInt(); row++) {
for (int col = 1; col <= Dispatch.get(
Dispatch.get(t2, "columns").toDispatch(), "count").getInt(); col++) {
if (row == 1) {
Dispatch cell = Dispatch.call(t2, "Cell", new Variant(1),
new Variant(1)).toDispatch();// 行,列
Dispatch.call(cell, "Select");
Dispatch.put(font, "Color", "1,1,1,0"); // 字型顏色
Dispatch.put(selection, "Text", "merge Cell!");
} else {
Dispatch cell = Dispatch.call(t2, "Cell", new Variant(row),
new Variant(col)).toDispatch();// 行,列
Dispatch.call(cell, "Select");
Dispatch.put(font, "Color", "1,1,1,0"); // 字型顏色
Dispatch.put(selection, "Text", "cell" + row + col);
}
}
Dispatch.call(selection, "MoveDown");
}
//Dispatch.call(selection, "MoveRight", new Variant(1), new Variant(1));// 取消選擇
// Object content = Dispatch.get(doc,"Content").toDispatch();
// Word文檔內容查找及替換////////////////////////
Dispatch.call(selection, "TypeParagraph"); // 空一行段落
Dispatch.put(align, "Alignment", "3"); // 1:置中 2:靠右 3:靠左
Dispatch.put(font, "Color", 0);
Dispatch.put(selection, "Text", "歡迎,Hello,world!");
Dispatch.call(selection, "HomeKey", new Variant(6));// 移到開頭
Dispatch find = Dispatch.call(selection, "Find").toDispatch();// 獲得Find組件
Dispatch.put(find, "Text", "hello"); // 查找字元串"hello"
Dispatch.put(find, "Forward", "True");// 向前查找
// Dispatch.put(find, "Format", "True");// 設置格式
Dispatch.put(find, "MatchCase", "false");// 大小寫匹配
Dispatch.put(find, "MatchWholeWord", "True"); // 全字匹配
Dispatch.call(find, "Execute"); // 執行查詢
Dispatch.put(selection, "Text", "你好");// 替換為"你好"
//使用方法傳入的參數parameter調用word文檔中的MyWordMacro宏//
//Dispatch.call(document,macroName,parameter);
//Dispatch.invoke(document,macroName,Dispatch.Method,parameter,new int[1]);
//頁眉,頁腳處理////////////////////////
Dispatch ActiveWindow = wordApp.getProperty("ActiveWindow")
.toDispatch();
Dispatch ActivePane = Dispatch.get(ActiveWindow, "ActivePane")
.toDispatch();
Dispatch View = Dispatch.get(ActivePane, "View").toDispatch();
Dispatch.put(View, "SeekView", "9"); //9是設置頁眉
Dispatch.put(align, "Alignment", "1"); // 置中
Dispatch.put(selection, "Text", "這里是頁眉"); // 初始化時間
Dispatch.put(View, "SeekView", "10"); // 10是設置頁腳
Dispatch.put(align, "Alignment", "2"); // 靠右
Dispatch.put(selection, "Text", "這里是頁腳"); // 初始化從1開始
//書簽處理(打開文檔時處理)////////////////////////
//Dispatch activeDocument = wordApp.getProperty("ActiveDocument").toDispatch();
Dispatch bookMarks = Dispatch.call(document, "Bookmarks").toDispatch();
boolean isExist = Dispatch.call(bookMarks, "Exists", "bookMark1")
.getBoolean();
if (isExist == true) {
Dispatch rangeItem1 = Dispatch.call(bookMarks, "Item", "bookMark1")
.toDispatch();
Dispatch range1 = Dispatch.call(rangeItem1, "Range").toDispatch();
Dispatch.put(range1, "Text", new Variant("當前是書簽1的文本信息!"));
String bookMark1Value = Dispatch.get(range1, "Text").toString();
System.out.println(bookMark1Value);
} else {
System.out.println("當前書簽不存在,重新建立!");
Dispatch.call(bookMarks, "Add", "bookMark1", selection);
Dispatch rangeItem1 = Dispatch.call(bookMarks, "Item", "bookMark1")
.toDispatch();
Dispatch range1 = Dispatch.call(rangeItem1, "Range").toDispatch();
Dispatch.put(range1, "Text", new Variant("當前是書簽1的文本信息!"));
String bookMark1Value = Dispatch.get(range1, "Text").toString();
System.out.println(bookMark1Value);
}
//保存操作////////////////////////
Dispatch.call(document, "SaveAs", "D:/wordOperate.doc");
//Dispatch.invoke((Dispatch) doc, "SaveAs", Dispatch.Method, new Object[]{htmlPath, new Variant(8)}, new int[1]); //生成html文件
// 0 = wdDoNotSaveChanges
// -1 = wdSaveChanges
// -2 = wdPromptToSaveChanges
//Dispatch.call(document, "Close", new Variant(0));
// // worddoc.olefunction("protect",2,true,"");
// // Dispatch bookMarks = wordApp.call(docs,"Bookmarks").toDispatch();
// // System.out.println("bookmarks"+bookMarks.getProgramId());
// //Dispatch.call(doc, "Save"); //保存
// // Dispatch.call(doc, "Close", new Variant(true));
// //wordApp.invoke("Quit",new Variant[]{});
// wordApp.safeRelease();//Finalizers call this method
}
2. 現有MYSQL資料庫,如果要製作復雜的EXCEL報表改怎麼辦
如果你會製作復雜的EXCEL報表,那剩下的問題就是怎樣把MYSQL資料庫的數據導到EXCEL里了,這一般需要編寫一個程序將把MYSQL資料庫的數據導到EXCEL里(要是這個程序不會寫那就上網搜搜看能不能搜到,或者再發一個問題問,或者請會的人寫)。
如果你把MYSQL資料庫的數據導到EXCEL里之後還是不會製作復雜的EXCEL報表,那你就要好好學學EXCEL報表的製作了。
3. phpid=傳參的問題
問題出在: 1、echo "<li><a href='proct_detail.php?id=".$_GET['id']."'>".$row_RS1["name"]."</a></li>";$_GET['id']應改為$row_RS1['id'] 2、……echo $RS['content'];//問題出在你沒有用mysql_fetch_array生成數據集就直接調用$RS['content']進行輸出,所以不能正常顯示你要的結果。 下面是修改後的頁面: proct.php頁面 <?php $conn = mysql_connect("localhost","root","qwepoi") or die ("鏈接失敗"); mysql_select_db("web3"); mysql_query("SET NAMES 'utf8'"); $sql1 = "SELECT * FROM `proct` WHERE type = 'reactor'"; $RS1 = mysql_query($sql1); ?> ------------------------------------- <?php while ($row_RS1 = mysql_fetch_array($RS1)){ echo "<li><a href='proct_detail.php?id=".$row_RS1['id']."'>".$row_RS1["name"]."</a></li>"; } ?> ==================================================== proct_detail.php頁面 <?php $conn = mysql_connect("localhost","root","qwepoi") or die ("鏈接失敗"); mysql_select_db("web3"); mysql_query("SET NAMES 'utf8'"); $id = $_GET['id']; $sql = "SELECT * FROM `proct` WHERE id=".$id; $RS = mysql_query($sql); $row=mysql_fetch_array($RS); ?> ------------------------------------------------------ <?php echo $row['content'];?>
4. js如何用AJAX請求 $.post獲取php中的數據poi_lng/poi_lat/poi2_lng/poi2_lat
$.post("../traffic/php/realtime.php",function(data){})中function的參數data就是後台返回的數據,php看不懂,不曉得你這個php返回的是個什麼數據。你可以直接在瀏覽器的地址欄中輸入那個php頁面的地址訪問一下看回來的數據是什麼樣的。
5. PHP5 點擊新聞列表顯示新聞內容頁面怎麼做
proct.php頁面
<?php
$conn = mysql_connect("localhost","root","qwepoi") or die ("鏈接失敗");
mysql_select_db("web3");
mysql_query("SET NAMES 'utf8'");
$sql1 = "SELECT * FROM `proct` WHERE type = 'reactor'";
$RS1 = mysql_query($sql1);
while ($row_RS1 = mysql_fetch_array($RS1)) {
echo "<li><a href='proct_detail.php?id=".$row_RS1['id']."'>".$row_RS1["name"]."</a></li>";
}
?>
proct_detail.php頁面
<?php
$conn = mysql_connect("localhost","root","qwepoi") or die ("鏈接失敗");
mysql_select_db("web3");
mysql_query("SET NAMES 'utf8'");
$id = $_GET['id'];
$sql = "SELECT * FROM `proct` WHERE `id`=$id";
$RS = mysql_query($sql);
echo $RS['content'];
?>
6. 求凱立德最新的凱立德POI格式的地圖
採納我的意見,然後給我消息,給我聯系方式,我發給你
7. 百度地圖 poi 類型總共有哪些
用php寫後台程序,連接資料庫! http://dev..com/wiki/static/map/API/examples/?v=1.3&3_0#3&0 裡面的自家數據+前端搜索可供參考!
8. Java poi怎麼導入
本篇面向對象為Java的初學者,從下載必備軟體到創建一個空白的POI工程,已經熟練掌握環境搭建的請跳過此文。
開發環境為windowsXP-SP2,Eclipse3.2,JDK1.5.07,其實差不多都行,不會有太大的差異。本文從POI下載開始講解,前提是開發環境包括系統變數等等已經正確設置完畢。
1.POI的下載
截至本文發表,POI最新版本是3.0.1,距離上一個Final版本有3年了吧,以至於我差點兒就把他放棄了——以為沒人管了。官方的公告講,這一版主要是追加了一些新的特性和BUG修正,不過稍微有點兒遺憾的是,還不能很好的操作Excel2007。
POI官方網址:
•http://poi.apache.org/
JAR包下載:
•http://apache.mirror.phpchina.com/poi/release/bin/poi-bin-3.0.1-FINAL-20070705.zip
源碼下載:
•http://apache.mirror.phpchina.com/poi/release/src/poi-src-3.0.1-FINAL-20070705.zip
下載上面的JAR和源碼(源碼不是必須的,但是為了早日修得正果,深入系統的看看POI代碼還是有必要的)並解壓待用。
2.用Eclipse搭建項目
• 打開Eclipse
•依次點擊File->New->Java Project
•輸入項目名稱,本例中設置為POI
•單擊完成
•在項目上點擊右鍵->New->Folder
•輸入文件夾名稱lib
•把剛才解壓的poi-3.0.1-FINAL-20070705.jar復制過來
•右鍵點擊項目,選擇Properties
•在左側列表裡選中Java Build Path,右側選中Libraries
•點擊Add JARs,選擇POI項目的lib下的所有文件
•兩次OK確認,回到Eclipse界面
小技巧,快捷操作:可以用滑鼠左鍵選中poi-3.0.1-FINAL-20070705.jar但不松開,拖到任務欄的Eclipse圖標上等候1秒左右,Eclipse會自動彈起來,依然不松開移動到lib文件夾上,這個時候滑鼠後面跟個十字元號,松開左鍵,就完成了復制動作。這個是對整個windows系統都好用的快捷復制方式,視源盤符和目標盤符的不同偶爾會用到Ctrl鍵。
到此為止,我們做好了POI學習的前提准備,接下來將從最簡單的文檔創建開始一步一步學習怎樣讓POI更好的為我們工作。
第一講 :基本的Excel讀寫
本文主要演示一下POI的基本操作,例如怎樣讀取和創建一個具體的Excel文件。按照慣例,拿HelloWorld說事兒。
說明:本文主要內容皆包含於官方幫助手冊,之所以要拿出來,出於兩個原因,手冊是英文的+手冊是對應2.5.1的。
核心代碼如下,注釋部分為講解。 這里只挑乾的講,完整的代碼請參考(下載代碼)。
//創建一個空白的WorkBook
HSSFWorkbook wb = new HSSFWorkbook();
//基於上面的WorkBook創建屬於此WorkBook的Sheet,
//3.0.1版在使用全形Sheet名的時候不必再setEncdoing了,個人感覺方便了許多。
HSSFSheet st = wb.createSheet("測試頁");
//創建屬於上面Sheet的Row,參數0可以是0~65535之間的任何一個,
//注意,盡管參數是Int類型,但是Excel最多支持65536行
HSSFRow row = st.createRow(0);
//創建屬於上面Row的Cell,參數0可以是0~255之間的任何一個,
//同樣,是因為Excel最大支持的列數為256列
HSSFCell cell = row.createCell((short) 0);
//設置此單元格的格式為文本,此句可以省略,Excel會自動識別。
//其他還有幾種常用的格式,請參考本文底部的補充部分。
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
//此處是3.0.1版的改進之處,上一版可以直接setCellValue("Hello, World!"),
//但是在3.0.1里,被deprecated了。
cell.setCellValue(new HSSFRichTextString("Hello, World!"));
//創建一個文件輸出流,指定到C盤根目錄下(C盤都有吧?)
//xls是Excel97-2003的標准擴展名,2007是xlsx,目前的POI能直接生產的還是xls格式,
//如果此處把擴展名改成xlsx,在用Excel2007打開此文件時會報錯。
FileOutputStream writeFile = new FileOutputStream("c:/helloworld.xls");
//把WorkBook寫到流里
wb.write(writeFile);
//記得手動關閉流,官方文檔已經做了特別說明,說POI不負責關閉用戶打開的流。所以...
writeFile.close();
上面就是創建一個新文檔的簡易代碼,下面的例子是讀取剛才創建的Excel並把讀取到的內容顯示在控制台上。
//指定要讀取的文件,本例使用上面生成的helloworld.xls
FileInputStream readFile = new FileInputStream("c:/helloworld.xls");
//創建一個WorkBook,從指定的文件流中創建,即上面指定了的文件流
HSSFWorkbook wb = new HSSFWorkbook(readFile);
//獲取名稱為「測試頁」的sheet
//注意,如果不能確定具體的名稱,可以用getSheetAt(int)方法取得Sheet
HSSFSheet st = wb.getSheet("測試頁");
//獲得第一行,同上,如果此行沒有被創建過則拋出異常
HSSFRow row = st.getRow(0);
//獲取第一個單元格,如果沒有被創建過則拋出異常
HSSFCell cell = row.getCell((short) 0);
//把cell中的內容按字元串方式讀取出來,並顯示在控制台上
//注意,getRichStringCellValue()方法是3.0.1新追加的,
//老版本中的getStringCellValue()方法被deprecated了
System.out.println(cell.getRichStringCellValue());
//記得關閉流
readFile.close();
上面對創建和讀取分別舉例說明,回顧兩段代碼,不難看出POI操作Excel的「套路」:
•獲得一個WorkBook(准確說是HSSFWorkBook,對於POI來說,WorkBook是「另有其類」,以下類同)
•獲得要讀/寫的Sheet對象
•獲得要操作的Row對象
•獲得最小單位——Cell對象
然後就可以隨意的讀取、寫入了。
--------------------------------------------------------------------------------
關於單元格格式的補充:
單元格一共有如下幾種格式, 都是HSSFCell類的靜態共有屬性,
•CELL_TYPE_NUMERIC - 數字格式
•CELL_TYPE_STRING - 字元串(默認)
•CELL_TYPE_FORMULA - 公式
•CELL_TYPE_BLANK - 空白
•CELL_TYPE_BOOLEAN - 布爾
•CELL_TYPE_ERROR - 錯誤
第二講 :單元格邊框、字體及顏色
此文概要性的講述了一下單元格的邊框、字體以及顏色的設置方式,在POI中,這一切都是通過實例化HSSFCellStyle對象來實現的,HSSFCellStyle類還有很多其他實際有用方法,本例中只是取平時用的比較普遍的一些設置來做演示的。好,開始講解了……
// 設置行號
row.setHeightInPoints((short) 50);
// 設置列寬,(256 * 50)這種寫法是因為width參數單位是單個字元的256分之一
st.setColumnWidth(cell.getCellNum(), (short) (256 * 50));
// 讓HSSFWorkbook創建一個單元格樣式的對象
// 小技巧:在多處用到完全一樣的樣式的時候可以用工廠模式生產
HSSFCellStyle cellStyle = wb.createCellStyle();
// 設置單元格的橫向和縱向對齊方式,具體參數就不列了,參考HSSFCellStyle
cellStyle.setAlignment(HSSFCellStyle.ALIGN_JUSTIFY);
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 這個地方是用來在單元格里畫斜線的
// 原理是在指定的兩個點之間畫線,然後默認情況此線會隨著單元格的變化而變化
// 類似Excel那種設置邊框的方式達到的斜線效果目前好像POI不支持
// 如果是我疏忽了請記得告訴我一些,先行謝過啦
HSSFPatriarch patriarch = st.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor();
anchor.setAnchor(cell.getCellNum(), row.getRowNum(), 0, 0, (short) (cell.getCellNum() + 1),
row.getRowNum() + 1, 0, 0);
patriarch.createSimpleShape(anchor);
// 設置單元格的文本方式為可多行編寫方式
cellStyle.setWrapText(true);
// 設置單元格的填充方式,以及前景顏色和背景顏色
// 三點注意:
// 1.如果需要前景顏色或背景顏色,一定要指定填充方式,兩者順序無所謂;
// 2.如果同時存在前景顏色和背景顏色,前景顏色的設置要寫在前面;
// 3.前景顏色不是字體顏色。
cellStyle.setFillPattern(HSSFCellStyle.DIAMONDS);
cellStyle.setFillForegroundColor(HSSFColor.RED.index);
cellStyle.setFillBackgroundColor(HSSFColor.LIGHT_YELLOW.index);
// 設置單元格底部的邊框及其樣式和顏色
// 這里僅設置了底邊邊框,左邊框、右邊框和頂邊框同理可設
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_SLANTED_DASH_DOT);
cellStyle.setBottomBorderColor(HSSFColor.DARK_RED.index);
// 創建一個字體對象,因為字體也是單元格格式的一部分,所以從屬於HSSFCellStyle
// 下面幾個字體的相關設置望文生義,就不用一一說明了吧
HSSFFont font = wb.createFont();
font.setFontName("宋體");
font.setItalic(true);
font.setColor(HSSFColor.BLUE.index);
font.setFontHeightInPoints((short) 20);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 將字體對象賦值給單元格樣式對象
cellStyle.setFont(font);
// 將單元格樣式對應應用於單元格
cell.setCellStyle(cellStyle);
這樣就OK了,可以可以看到效果了。
補充,各個章節的例子最終都在同一個附件內,下載的時候下任何一個頁面內的都可以,都是一樣的。
Java-Excel報表開發POI—合並、分組及凍結
Java-Excel報表開發POI系列講座
第三講 :單元格的合並、數據行的分組以及Excel窗口的凍結
本來想把這三個東西分開來實現的,後來發現分開後內容都很少,於是就合在一起說吧。那總不能乾巴巴的列幾個例子就完了吧,那就拿比較初級但又會經常遇到的表格類數據的統計的設計來做個小例子。(源碼下載)
結果發現——還真夠辛苦的。
這次先看效果圖吧,其中的豎排並不是真正意義上Excel那種設置的豎排,而是稍微轉變了一下輸出的方式實現的,因為老外的英文單詞沒有這種豎排的可能(頂多是旋轉,但是那樣字體就變了)。除此之外想到的另外一種豎排文字的實現方式就是樣式旋轉+字體旋轉,沒測試,不知道是否可用,誰有功夫實現一下,然後記得告訴我結果啊。
老樣子,把核心的代碼和簡要的說明列出來大家看一下吧。
// 這里首先創建一個單元格樣式對象,設置了四周的邊框以及字體可以換行
// 其中的字體換行是用來豎向顯示其中的一個單元格的
// 更好的一點兒做法是再做一個單獨的單元格樣式對象
// 要不然在處理自動列寬的時候可能會有點兒小問題
HSSFCellStyle normalStyle = wb.createCellStyle();
normalStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
normalStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
normalStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
normalStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
normalStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
normalStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
normalStyle.setWrapText(true);
// 合並單元格A1-C1,填入內容的時候添到第一個格子里就可以
// 但是注意一點:單元格合並後設置邊框只在原第一個上有效,
// 如果想應用的合並後的整體,則需要一個個的Create出單元格並應用樣式
// 這個明顯是一個不太方便的操作,期待POI下一版的改進了
st.addMergedRegion(new Region(0, (short) 0, 0, (short) 2));
HSSFRow row = st.createRow(0);
HSSFCell cell = row.createCell((short) 0);
cell.setCellValue(new HSSFRichTextString("業務一覽表"));
cell.setCellStyle(normalStyle);
row.createCell((short) 1).setCellStyle(normalStyle);
row.createCell((short) 2).setCellStyle(normalStyle);
// 設置列頭,當然也可以一個一個格子的寫,用循環感覺有些取巧而已
// 同樣,需要單獨給每個單元格應用樣式對象
String[] seasonName = { "第一季度", "第二季度", "第三季度", "第四季度" };
for (short i = 3; i < 7; i++)
{
cell = row.createCell(i);
cell.setCellValue(new HSSFRichTextString(seasonName[i - 3]));
cell.setCellStyle(normalStyle);
}
// 這個是豎排文字的實現
// 目前POI沒找到(或許沒提供,或許我無知)讓文字豎排的方法,
// HSSFCellStyle.setRotation()方法是設置旋轉角度的,和豎排不太一樣,
// 後來想了一下,因為只有中文等全形字元才有豎排的可能,
// 一個英文單詞要是豎排看起來恐怕會非常怪異,不過不排除搞藝術的……
st.addMergedRegion(new Region(1, (short) 0, 6, (short) 0));
row = st.createRow(1);
cell = row.createCell((short) 0);
cell.setCellValue(new HSSFRichTextString("地\n區\n代\n理\nA"));
cell.setCellStyle(normalStyle);
for (int i = 2; i < 7; i++)
st.createRow(i).createCell((short) 0).setCellStyle(normalStyle);
// 屬於地區的二級分類,豎向合並相鄰的兩個單元格,其他同上
String[] shopName = { "連鎖店A", "連鎖店B", "連鎖店C" };
for (int i = 1; i < 6; i = i + 2)
{
row = st.createRow(i);
cell = row.createCell((short) 1);
cell.setCellValue(new HSSFRichTextString(shopName[(i - 1) / 2]));
cell.setCellStyle(normalStyle);
st.createRow(i + 1).createCell((short) 1).setCellStyle(normalStyle);
st.addMergedRegion(new Region(i, (short) 1, i + 1, (short) 1));
}
// 屬於連鎖店的下一級,基本也是創建出來然後賦值+應用樣式
for (int i = 1; i < 7; i = i + 2)
{
cell = st.getRow(i).createCell((short) 2);
cell.setCellValue(new HSSFRichTextString("收入"));
cell.setCellStyle(normalStyle);
cell = st.getRow(i + 1).createCell((short) 2);
cell.setCellValue(new HSSFRichTextString("支出"));
cell.setCellStyle(normalStyle);
}
// 數據部分,直接Create然後應用樣式,有數據的話這個地方就打數據好了
for (int i = 1; i < 7; i++)
for (short j = 3; j < 7; j++)
st.createRow(i).createCell(j).setCellStyle(normalStyle);
// 凍結Excel的窗口,邊界為數據部分的邊界
st.createFreezePane(3, 1);
// 按照連鎖店級別分組(當然實際情況這樣分組沒啥意義)
for (int i = 1; i < 7; i = i + 2)
st.groupRow(i, i);
// 按照地區分組
st.groupRow(1, 5);
其實這樣實現起來是不是很麻煩呢?答案是:是。
其實這只是舉個例子,熟悉一下POI的各種API而已,真正要實現這樣一個表格的時候,例如項目需要製作報表等等,通常的做法都是事先把格式一切的東西都手動製作好(這個做好了的文件在實際的項目里我們稱之為「數據模板」,簡稱「模板」),然後在Java應用中適當的時機把這個文件讀進來修改,最後再另存到指定的位置或者傳遞給下一個處理者(例如以流的方式送給Servlet等等),這樣其實POI具體做的事情就是向模板里寫業務的數據,還是很方便快捷的。
9. php 怎麼用post方法獲取高德地圖poi數據
親,您點擊高德地圖PC地圖 「開放平台」——點擊下角綠色圖標「FAQ」——選擇對應的問題分類——找到自己遇到的問題——如果答案沒有解決您的問題,點擊提交「工單」即可
10. 如何通過IP地址進行精準定位
在甲方工作的朋友可能會遇到這樣的問題,伺服器或者系統經常被掃描,通過IP地址我們只能查到某一個市級城市,如下圖:
當我們想具體到街道甚至門牌號,該怎麼辦???
偶然間發現網路地圖有高精度IP定位API的介面,通過該介面我們可以通過IP地址定位到具體的地理位置,甚至能精確到門牌號及周圍的標志性建築。該介面的說明地址為:http://lbsyun..com/index.php?title=webapi/high-acc-ip
若想要使用該介面進行查詢,必須先申請一個密鑰(AK),如下圖:
申請過程就不進行說明了。API的介面參數說明和返回參數說明也不過多的介紹,大家可以看一看。因為我想返回基礎定位結果+地址信息+POI信息,所以我將請求參數extensions的值設置為3。
一次完整的http請求為:http://api.map..com/highacciploc/v1?qcip=183.55.116.90&qterm=pc&ak=「你的 密鑰(AK)」&coord=bd09ll&extensions=3 。請求結果如下圖:
結果為json格式數據:
{"content":{"location":{"lat":23.06588,"lng":115.404586},"locid":"","radius":30,"confidence":0.5,"address_component":{"country":"中國","province":"廣東省","city":"汕尾市","district":"海豐縣","street":"新平路","street_number":"","admin_area_code":441521},"formatted_address":"廣東省汕尾市海豐縣新平路","business":"公平"},"result":{"error":161,"loc_time":"2016-10-19 21:53:28"}}
我們需要的欄位為:content欄位裡面的formatted_address。當然我們也可以將location裡面的經度和緯度提取出來從而顯示在地圖上面。有的IP地址會返回pois數據,比如:183.55.116.95。返回參數如下:
{"content":{"location":{"lat":23.082367,"lng":115.466276},"locid":"","radius":30,"confidence":1.0,"address_component":{"country":"中國","province":"廣東省","city":"汕尾市","district":"海豐縣","street":"S335","street_number":"","admin_area_code":441521},"formatted_address":"廣東省汕尾市海豐縣S335","pois":[{"name":"雙墩村","address":"汕尾市海豐縣三三五省道","tag":"行政地標;村莊","location":{"lat":23.082422,"lng":115.465348},"uid":"18010998377147269119"},{"name":"雙墩村委會","address":"汕尾市海豐縣","tag":"政府機構;各級政府","location":{"lat":23.083394,"lng":115.465914},"uid":"17661602237861855231"},{"name":"長聯塘尾","address":"汕尾市海豐縣","tag":"行政地標;村莊","location":{"lat":23.081358,"lng":115.467315},"uid":"18010998372852301823"},{"name":"雙墩小學","address":"335省道附近","tag":"教育培訓;小學","location":{"lat":23.083336,"lng":115.465061},"uid":"17661601958688980991"},{"name":"大溪頭","address":"汕尾市海豐縣","tag":"行政地標;村莊","location":{"lat":23.090326,"lng":115.465995},"uid":"18010998368557334527"}],"location_description":"雙墩村東104米"},"result":{"error":161,"loc_time":"2016-10-19 22:03:31"}}
此時我們可以把pois欄位也提取出來,值得注意的是pois為數組,我們可以遍歷數組數據。通過上面的分析,用python簡單的寫了一個腳本,具體代碼點擊閱讀原文可見。
大家把腳本上面的參數ak值改為自己的密鑰即可。測試截圖如下:
再放一張自己IP的測試截圖:
確實精確到了路名,很准確,雖然沒有pois的信息。
最後聲明一下,成功率:綜合定位成功率 65% ,精度:90% 誤差 80m 以內;95% 誤差 350m。這是官方給出的數據,所說有一定的概率是查詢失敗的!!!!