1. 程式人生 > >轉:java 解析excel,帶合並單元的excel

轉:java 解析excel,帶合並單元的excel

void lena words ger add leo main 下標 解析excel

  收集了一些對博主有幫助的博文,如下

>>>>>>>>>>>第一部分:

首先,mavn導入jar包

<!-- 解析excel需要導入的 jar包 begin -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>
<!-- 解析excel需要導入的 jar包 end -->

其次,代碼如下:

package excel;

import java.io.File;
import java.io.IOException;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.junit.Test;

/**
*
* @author wcyong
*
* @date 2013-6-21
*/
public class TestReadMergeRegionExcel {


@Test
public void testReadExcel() {
readExcelToObj("C:\\Users\\Administrator\\Desktop\\11.xls");
}

/**
* 讀取excel數據
* @param path
*/
private void readExcelToObj(String path) {

Workbook wb = null;
try {
wb = WorkbookFactory.create(new File(path));
readExcel(wb, 0, 0, 0);
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 讀取excel文件
* @param wb
* @param sheetIndex sheet頁下標:從0開始
* @param startReadLine 開始讀取的行:從0開始
* @param tailLine 去除最後讀取的行
*/
private void readExcel(Workbook wb,int sheetIndex, int startReadLine, int tailLine) {

Sheet sheet = wb.getSheetAt(sheetIndex);
Row row = null;

for(int i=startReadLine; i<sheet.getLastRowNum()-tailLine+1; i++) {

row = sheet.getRow(i);
for(Cell c : row) {
c.setCellType(Cell.CELL_TYPE_STRING);
boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex());
//判斷是否具有合並單元格
if(isMerge) {
String rs = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex());
System.out.print(rs + " ");
}else {
System.out.print(c.getRichStringCellValue()+" ");
}
}
System.out.println();

}

}

/**
* 獲取合並單元格的值
* @param sheet
* @param row
* @param column
* @return
*/
public String getMergedRegionValue(Sheet sheet ,int row , int column){

int sheetMergeCount = sheet.getNumMergedRegions();

for(int i = 0 ; i < sheetMergeCount ; i++){
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();

if(row >= firstRow && row <= lastRow){

if(column >= firstColumn && column <= lastColumn){
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell) ;
}
}
}

return null ;
}

/**
* 判斷合並了行
* @param sheet
* @param row
* @param column
* @return
*/
private boolean isMergedRow(Sheet sheet,int row ,int column) {

int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if(row == firstRow && row == lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}

/**
* 判斷指定的單元格是否是合並單元格
* @param sheet
* @param row 行下標
* @param column 列下標
* @return
*/
private boolean isMergedRegion(Sheet sheet,int row ,int column) {

int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {

CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}

/**
* 判斷sheet頁中是否含有合並單元格
* @param sheet
* @return
*/
private boolean hasMerged(Sheet sheet) {
return sheet.getNumMergedRegions() > 0 ? true : false;
}

/**
* 合並單元格
* @param sheet
* @param firstRow 開始行
* @param lastRow 結束行
* @param firstCol 開始列
* @param lastCol 結束列
*/
private void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
}

/**
* 獲取單元格的值
* @param cell
* @return
*/
public String getCellValue(Cell cell){

if(cell == null) return "";

if(cell.getCellType() == Cell.CELL_TYPE_STRING){

return cell.getStringCellValue();

}else if(cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){

return String.valueOf(cell.getBooleanCellValue());

}else if(cell.getCellType() == Cell.CELL_TYPE_FORMULA){

return cell.getCellFormula() ;

}else if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){

return String.valueOf(cell.getNumericCellValue());

}
return "";
}
}

>>>>>>>>>>>第二部分:

通過這個例子,演示以下如何用java生成excel文件:
import org.apache.poi.hssf.usermodel.*;
import java.io.FileOutputStream;
import java.io.IOException;
publicclass CreateCells
{
publicstaticvoid main(String[] args)
throws IOException
{
HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook對象
HSSFSheet sheet = wb.createSheet("new sheet");//建立新的sheet對象
// Create a row and put some cells in it. Rows are 0 based.
HSSFRow row = sheet.createRow((short)0);//建立新行
// Create a cell and put a value in it.
HSSFCell cell = row.createCell((short)0);//建立新cell
cell.setCellValue(1);//設置cell的整數類型的值
// Or do it on one line.
row.createCell((short)1).setCellValue(1.2);//設置cell浮點類型的值
row.createCell((short)2).setCellValue("test");//設置cell字符類型的值
row.createCell((short)3).setCellValue(true);//設置cell布爾類型的值
HSSFCellStyle cellStyle = wb.createCellStyle();//建立新的cell樣式
cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));//設置cell樣式為定制的日期格式
HSSFCell dCell =row.createCell((short)4);
dCell.setCellValue(new Date());//設置cell為日期類型的值
dCell.setCellStyle(cellStyle); //設置該cell日期的顯示格式
HSSFCell csCell =row.createCell((short)5);
csCell.setEncoding(HSSFCell.ENCODING_UTF_16);//設置cell編碼解決中文高位字節截斷
csCell.setCellValue("中文測試_Chinese Words Test");//設置中西文結合字符串
row.createCell((short)6).setCellType(HSSFCell.CELL_TYPE_ERROR);//建立錯誤cell
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
}
}
從以上例子,可以清楚的看到xls文件從大到小包擴了 HSSFWorkbook HSSFSheet HSSFRow HSSFCell這樣幾個對象。還可以在cell中設置各種類型的值。尤其要註意的是如果你想正確的顯示非歐美的字符時,尤其象中日韓這樣的語言,必須 設置編碼為16位的即是HSSFCell.ENCODING_UTF_16,才能保證字符的高8位不被截斷而引起編碼失真形成亂碼。
其他測試可以通過參考examples包中的測試例子掌握poi的詳細用法,包括字體的設置,cell大小和低紋的設置等。需要註意的是POI是一 個仍然在完善中的公開代碼的項目,所以有些功能正在不斷的擴充。如HSSFSheet的getFooter() getHeader()和 setFooter(HSSFFooter hsf) setHeader(HSSFHeader hsh)是在POI1.7中才有的,而POI1.5中就沒有。運行測試熟悉代碼或者使用它做項目時請註意POI的版本。
另外需要註意的是HSSF也有它的對xls基於事件的解析。可以參考例程中的EventExample.java。它通過實現 HSSFListener完成從普通流認知Xls中包含的內容,在apache Cocoon中的 org.apache.cocoon.serialization.HSSFSerializer中用到了這個解析。因為Cocoon2 是基於事件的,所以POI為了提供快速的解析也提供了相應的事件。當然我們自己也可以實現這個事件接口。
因為POI還不是一個足夠成熟的項目,所以有必要做進一步的開發和測試。但是它已經為我們用純java操作ole2對象提供了可能,而且克服了ole對象調用的缺陷,提供了服務器端的Excel解決方案。
利用Java 創建和讀取Excel文檔
為了保證示例程序的運行,必須安裝Java 2 sdk1.4.0 和Jakarta POI,Jakarta POI的Web站點是: http://jakarta.apache.org/poi/
示例1將演示如何利用Jakarta POI API 創建Excel 文檔。
示例1程序如下:
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.FileOutputStream;
publicclass CreateXL {
/** Excel 文件要存放的位置,假定在D盤JTest目錄下*/
publicstatic String outputFile="D:/JTest/ gongye.xls";
publicstaticvoid main(String argv[])
{
try
{
// 創建新的Excel 工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
// 在Excel工作簿中建一工作表,其名為缺省值
// 如要新建一名為"效益指標"的工作表,其語句為:
// HSSFSheet sheet = workbook.createSheet("效益指標");
HSSFSheet sheet = workbook.createSheet();
// 在索引0的位置創建行(最頂端的行)
HSSFRow row = sheet.createRow((short)0);
//在索引0的位置創建單元格(左上端)
HSSFCell cell = row.createCell((short) 0);
// 定義單元格為字符串類型
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
// 在單元格中輸入一些內容
cell.setCellValue("增加值");
// 新建一輸出文件流
FileOutputStream fOut = new FileOutputStream(outputFile);
// 把相應的Excel 工作簿存盤
workbook.write(fOut);
fOut.flush();
// 操作結束,關閉文件
fOut.close();
System.out.println("文件生成...");
}catch(Exception e) {
System.out.println("已運行 xlCreate() : " + e );
}
}
}
這裏演示創建和設置字體和單元格的格式,然後再應用這些格式:

1、創建字體,設置其為紅色、粗體:
HSSFFont font = workbook.createFont();
font.setColor(HSSFFont.COLOR_RED);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
2、創建格式
HSSFCellStyle cellStyle= workbook.createCellStyle();
cellStyle.setFont(font);
3、應用格式
HSSFCell cell = row.createCell((short) 0);
cell.setCellStyle(cellStyle);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue("標題 ");

總之,如本篇文章所演示的一樣,Java程序員不必擔心Excel工作表中的數據了,利用Jakarta POI API, 就可以輕易的在程序中存取Excel文檔。



>>>>>>>>>>>第三部分:


利用java操作Excel,有個開源的東東-jxl.jar,可以到http://sourceforge.net/project/showfiles.php?group_id=79926下載。

一.讀取Excel文件內容

java 代碼
  1. public static String readExcel(File file){
  2. StringBuffer sb = new StringBuffer();
  3. Workbook wb = null;
  4. try {
  5. //構造Workbook(工作薄)對象
  6. wb=Workbook.getWorkbook(file);
  7. } catch (BiffException e) {
  8. e.printStackTrace();
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. if(wb==null)
  13. return null;
  14. //獲得了Workbook對象之後,就可以通過它得到Sheet(工作表)對象了
  15. Sheet[] sheet = wb.getSheets();
  16. if(sheet!=null&&sheet.length>0){
  17. //對每個工作表進行循環
  18. for(int i=0;i
  19. //得到當前工作表的行數
  20. int rowNum = sheet[i].getRows();
  21. for(int j=0;j
  22. //得到當前行的所有單元格
  23. Cell[] cells = sheet[i].getRow(j);
  24. if(cells!=null&&cells.length>0){
  25. //對每個單元格進行循環
  26. for(int k=0;k
  27. //讀取當前單元格的值
  28. String cellValue = cells[k].getContents();
  29. sb.append(cellValue+"\t");
  30. }
  31. }
  32. sb.append("\r\n");
  33. }
  34. sb.append("\r\n");
  35. }
  36. }
  37. //最後關閉資源,釋放內存
  38. wb.close();
  39. return sb.toString();
  40. }

二.寫入Excel文件

這裏有很多格式了,比如文本內容加粗,加上某些顏色等,可以參考jxl的api,同時還推薦一篇不錯的文章:http://www.ibm.com/developerworks/cn/java/l-javaExcel/?ca=j-t10

java 代碼
  1. public static void writeExcel(String fileName){
  2. WritableWorkbook wwb = null;
  3. try {
  4. //首先要使用Workbook類的工廠方法創建一個可寫入的工作薄(Workbook)對象
  5. wwb = Workbook.createWorkbook(new File(fileName));
  6. } catch (IOException e) {
  7. e.printStackTrace();
  8. }
  9. if(wwb!=null){
  10. //創建一個可寫入的工作表
  11. //Workbook的createSheet方法有兩個參數,第一個是工作表的名稱,第二個是工作表在工作薄中的位置
  12. WritableSheet ws = wwb.createSheet("sheet1", 0);
  13. //下面開始添加單元格
  14. for(int i=0;i<10;i++){
  15. for(int j=0;j<5;j++){
  16. //這裏需要註意的是,在Excel中,第一個參數表示列,第二個表示行
  17. Label labelC = new Label(j, i, "這是第"+(i+1)+"行,第"+(j+1)+"列");
  18. try {
  19. //將生成的單元格添加到工作表中
  20. ws.addCell(labelC);
  21. } catch (RowsExceededException e) {
  22. e.printStackTrace();
  23. } catch (WriteException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. try {
  29. //從內存中寫入文件中
  30. wwb.write();
  31. //關閉資源,釋放內存
  32. wwb.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. } catch (WriteException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }

三.在一個Excel文件中查找是否包含某一個關鍵字

java 代碼
  1. public static boolean searchKeyWord(File file,String keyWord){
  2. boolean res = false;
  3. Workbook wb = null;
  4. try {
  5. //構造Workbook(工作薄)對象
  6. wb=Workbook.getWorkbook(file);
  7. } catch (BiffException e) {
  8. return res;
  9. } catch (IOException e) {
  10. return res;
  11. }
  12. if(wb==null)
  13. return res;
  14. //獲得了Workbook對象之後,就可以通過它得到Sheet(工作表)對象了
  15. Sheet[] sheet = wb.getSheets();
  16. boolean breakSheet = false;
  17. if(sheet!=null&&sheet.length>0){
  18. //對每個工作表進行循環
  19. for(int i=0;i
  20. if(breakSheet)
  21. break;
  22. //得到當前工作表的行數
  23. int rowNum = sheet[i].getRows();
  24. boolean breakRow = false;
  25. for(int j=0;j
  26. if(breakRow)
  27. break;
  28. //得到當前行的所有單元格
  29. Cell[] cells = sheet[i].getRow(j);
  30. if(cells!=null&&cells.length>0){
  31. boolean breakCell = false;
  32. //對每個單元格進行循環
  33. for(int k=0;k
  34. if(breakCell)
  35. break;
  36. //讀取當前單元格的值
  37. String cellValue = cells[k].getContents();
  38. if(cellValue==null)
  39. continue;
  40. if(cellValue.contains(keyWord)){
  41. res = true;
  42. breakCell = true;
  43. breakRow = true;
  44. breakSheet = true;
  45. }
  46. }
  47. }
  48. }
  49. }
  50. }
  51. //最後關閉資源,釋放內存
  52. wb.close();
  53. return res;
  54. }

四.往Excel中插入圖片圖標

插入圖片的實現很容易,參看以下代碼:

java 代碼
  1. public static void insertImg(WritableSheet dataSheet, int col, int row, int width,
  2. int height, File imgFile){
  3. WritableImage img = new WritableImage(col, row, width, height, imgFile);
  4. dataSheet.addImage(img);
  5. }

以上代碼的註釋已經很清楚了,大概也就不用再解釋了,我們可以用如下程序驗證:

java 代碼
  1. try {
  2. //創建一個工作薄
  3. WritableWorkbook workbook = Workbook.createWorkbook(new File("D:/test1.xls"));
  4. //待插入的工作表
  5. WritableSheet imgSheet = workbook.createSheet("Images",0);
  6. //要插入的圖片文件
  7. File imgFile = new File("D:/1.png");
  8. //圖片插入到第二行第一個單元格,長寬各占六個單元格
  9. insertImg(imgSheet,0,1,6,6,imgFile);
  10. workbook.write();
  11. workbook.close();
  12. catch (IOException e) {
  13. e.printStackTrace();
  14. catch (WriteException e) {
  15. e.printStackTrace();

但是jxl只支持png格式的圖片,jpg格式和gif格式都不支持

五.插入頁眉頁腳

一般的頁眉頁腳都分為三個部分,左,中,右三部分,利用如下代碼可實現插入頁眉頁腳

java 代碼
  1. public static void setHeader(WritableSheet dataSheet,String left,String center,String right){
  2. HeaderFooter hf = new HeaderFooter();
  3. hf.getLeft().append(left);
  4. hf.getCentre().append(center);
  5. hf.getRight().append(right);
  6. //加入頁眉
  7. dataSheet.getSettings().setHeader(hf);
  8. //加入頁腳
  9. //dataSheet.getSettings().setFooter(hf);
  10. }

我們可以用如下代碼測試該方法:

java 代碼
  1. try {
  2. //創建一個工作薄
  3. WritableWorkbook workbook = Workbook.createWorkbook(new File("D:/test1.xls"));
  4. //待插入的工作表
  5. WritableSheet dataSheet = workbook.createSheet("加入頁眉",0);
  6. ExcelUtils.setHeader(dataSheet, "chb", "2007-03-06", "第1頁,共3頁");
  7. workbook.write();
  8. workbook.close();
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. } catch (WriteException e) {
  12. e.printStackTrace();
  13. }
  14. }

合並單元格:

//首先創建一個sheet

WritableSheet sheetWrite=writeWorkbook.createSheet("sheet的名稱",0);

//把 單元格(column, row)到單元格(column1, row1)進行合並

sheetWrite.mergeCells(column, row, column1, row1);

java 操作excel,jxl加邊框,jxl合並單元格,單元格的設置,單元

WritableCellFormat headerFormat = new WritableCellFormat(
HEADER_FONT_STYLE);
//水平居中對齊
headerFormat.setAlignment(Alignment.CENTRE);
//豎直方向居中對齊
headerFormat.setVerticalAlignment

(VerticalAlignment.CENTRE);

//建立標簽,參數依次為:列索引、行索引、內容、格式
Label seqLabel = new Label(0, 0, "序號", headerFormat);
//增加單元格
sheet.addCell(seqLabel);
//合並單元格,參數依次為:列索引、行索引、列索引+需要合並

的列的個數、行索引+需要合並的行的個數
sheet.mergeCells(0, 0, 0, 1);
//設置單元格寬度,以字符為單位
sheet.setColumnView(0, "序號".length() + 10);

Label basicInfoLabel = new Label(1, 0, "基本信息",

headerFormat);
sheet.addCell(basicInfoLabel);
sheet.mergeCells(1, 0, 3, 0);//合並垮了3行。

sheet.mergeCells(1, 1, 1, 3);//合並垮了3列。

label = new Label(0, 1, "蘋果”);
sheet.mergeCells(0,1, 0, 3- 1);//合並垮了3列。
WritableCellFormat cellFormat = new WritableCellFormat();
cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);

// 垂直居中
label.setCellFormat(cellFormat);
sheet.addCell(label);

註:再次使cellFormat時,需要重新NEW WritableCellFormat 。

轉:java 解析excel,帶合並單元的excel