POI詳解---使用poi操作excel文件

上一篇博客中給大家講解了maven工具的安裝和配置,下面我們就來使用maven來構建一個項目,首先來說一下我們的項目功能,這次我們要做的功能是將excel格式的數據表格中的數據導入到數據庫中,使用的技術主要就是前面給大家講解的Spring框架,同時還有一個操作excel表格的工具包poi,poi也是apache的一個項目,該項目主要是爲Java提供操作微軟的office文件的一套解決方案,也就是說poi框架的功能不光是操作excel,包括word和PowerPoint等等office辦公常用格式的文件。好了,我們先來看看怎麼使用poi來操作excel。

再囉嗦一句,不管我們學習什麼技術,最好的辦法就是閱讀官方提供的文檔,既然我們要學習poi的是使用那麼我們首先就是去看看他的官網了,好了,打開http://poi.apache.org/,我們來到poi官網:

我們選擇javadocs,可以看到不同版本的文檔信息,這裏我們選擇最新的4.0版本,查看官網的在線文檔, 

進入文檔後如下圖所示:

和我們的JavaAPI文檔類似,這裏我們可以看到poi框架的全部的api的是使用方法, 這裏我們主要關注操作excel的方法,首先打開org.apache.poi.hssf.usemodel這個包。找到HSSFWorkBook這個類,這個類的作用就是創建一個工作表對象,也就是對應於excel中的一個sheet,HSSFCell這個類的作用是創建一個單元格,如下圖所示:

 

 找到了這三個類我們就可以完成一個操作excel文件的基本的程序了。下面就來看看具體的用法,

首先打開eclipse ,創建一個maven工程,如下圖所示:

這裏我們需要將Create a simple project 勾選上,這個選項的作用是快速的創建一個簡單的maven項目,不需要選擇原型模板,這樣的好處就是可以快速的創建項目。接着選擇next 

第一個Group Id 意思是組織的id,也就是對應於公司域名,也就是項目裏邊的一級包名,第二個Artifact Id 對應於項目名,這兩個id在maven項目裏邊稱爲座標,當我們發佈項目的時候,就會將這兩個值作爲我們項目的唯一標識,相當於地址。選擇finish

打開我們創建好的項目,項目結構如上圖所示,其中我們的代碼是寫在Java目錄下,配置文件放在resources目錄下,測試的代碼放在test目錄下。這裏需要介紹一下的是pom.xml這個文件,這個文件就是maven工程裏邊的管理依賴用的以及管理各種插件,首先我們打開該文件,

其中dependences標籤就是用來管理依賴的,所謂的依賴就是指的這個項目依賴於那些jar包,大家應該都知道一個項目會依賴很多jar包,如果把所有的jar包都導入項目裏,那麼項目就顯得很笨重,所以我們就需要maven來管理這些jar包,首先大家在pom.xml文件中添加dependences標籤,並且在該標籤中添加以下的依賴,

    <dependency>
	    <groupId>org.apache.poi</groupId>
	    <artifactId>poi</artifactId>
	    <version>4.0.0</version>
	</dependency>

這就是poi工具的依賴,從上邊的依賴中可以看到poi 是apache的一個項目,因此他的groupId也就是組織id就是apache的poi項目的域名 org.apache.poi,artifactId對應的項目名就是poi,version就不用說了,指的是版本號,  好了,這個步驟叫做導入依賴的座標。導入之後我們打開項目,創建包結構如下圖所示:

其中bean包下是User是實體類,用來封裝數據的。controller層中的是試圖層,這裏只是模擬一下正規的項目結構,在下一篇博客中將會把這個項目改造成使用spring框架來構建。service包下放的是service接口和實現類,utils包下放的是項目需要使用到的工具類,好了,一個傳統的單體應用的項目結構一般就是這樣了。你可能注意到了Maven Dependencies這個包,其實這個包下就是我們剛剛導入的poi依賴,打開這個包我們可以發現裏邊存放的是jar包。

我們在pom.xml文件中導入我們需要使用的jar包的座標,maven就會幫助我們下載該座標對應的jar包,存放在我們本地磁盤上的一個路徑,這個路徑在maven的安裝目錄中的 conf文件夾下的setting.xml文件中配置,具體的路徑如下圖所示:

由於該文件中有示例這裏便不再演示。好了,項目的環境準備到此結束。下面就進入了具體的編碼了。

首先我們需要編寫實體類User的代碼,該類主要模擬一下一個用戶,我們在程序裏爲該用戶封裝數據,然後寫入到本地的excel文件中。 User類中的代碼如下圖所示:

public class User {
	
	private Long id;
	
	private String userName;
	
	private String password;
	
	private String sign;
	
	private Date birthDay;
	
	private Integer age;
	
	private Double salary;
	

	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

	public User(Long id, String userName, String password, String sign, Date birthDay, Integer age, Double salary) {
		super();
		this.id = id;
		this.userName = userName;
		this.password = password;
		this.sign = sign;
		this.birthDay = birthDay;
		this.age = age;
		this.salary = salary;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getSign() {
		return sign;
	}

	public void setSign(String sign) {
		this.sign = sign;
	}

	public Date getBirthDay() {
		return birthDay;
	}

	public void setBirthDay(Date birthDay) {
		this.birthDay = birthDay;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public Double getSalary() {
		return salary;
	}

	public void setSalary(Double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", userName=" + userName + ", password=" + password + ", sign=" + sign + ", birthDay="
				+ birthDay + ", age=" + age + ", salary=" + salary + "]";
	}
	
	
}

這裏爲了給大家演示不同的數據類型的處理,分別使用了Long、Integer、String、Date類型的數據,這些數據一般是最常見的,好了,我們有了User類之後我們就要分裝數據進去了,首先我們來service接口中,在該接口中添加一個方法,該接口中的方法如下所示:

import java.util.List;

import com.wcan.poi.bean.User;

public interface UserService {
	
	public List<User> add();
}

 這個方法就是用來添加數據的,接下來我們需要將該方法實現,代碼如下:

public class UserServiceImpl implements UserService{

	/**
	 * 	添加用戶
	 * 
	 */
	@Override
	public List<User> add() {
		// TODO Auto-generated method stub
		List<User>  list = new ArrayList<User>();
		for(int i=0;i<100;i++) {
			User user = new User();
			user.setId(Long.valueOf(i));
			user.setUserName(Integer.valueOf(i+(i+1)*99).toString());
			user.setPassword(UUID.randomUUID().toString().substring(0, 5));
			user.setSign("我是第"+i+"個用戶,我很高興!");
			user.setBirthDay(new Date());
			user.setAge((i+1)*10+i);
			user.setSalary(Double.valueOf((i+1)*500));
			list.add(user);
		}
		return list;
	}
}

這裏我們使用循環,快速的生成100條數據,用戶id就是循環的次數,userName我們通過處理每次循環的次數來生成,這裏只是爲了快速的演示效果,如果你有更好的辦法也可以。密碼我們採用UUID來生成,截取 前面5位。剩下的只是爲了演示效果,就不解釋了。當我們生成完了這些數據後就將這些數據封裝進User對象。封裝完了就把該對象放入list集合中。返回這個list集合。

好了,這裏我們來到controller層,創建UserController層的代碼如下:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.Test;

import com.wcan.poi.bean.User;
import com.wcan.poi.service.UserService;
import com.wcan.poi.service.UserServiceImpl;
import com.wcan.poi.utils.PoiUtils;

public class UserController {

	private UserService userService;
	
	@Test
	public void creatExcel() {

		userService = new UserServiceImpl();

		List<User> list = userService.add();
		
		HSSFWorkbook workBook = PoiUtils.getWorkBook(list);
		FileOutputStream fileOutputStream = null;
		try {
			fileOutputStream = new FileOutputStream(new File("E://demo.xls"));
			workBook.write(fileOutputStream);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				fileOutputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
	
	@Test
	public void readExcel() {
		String filePath = "E://demo.xls";
		List<User> readExcel = PoiUtils.readExcel(filePath);
		for (User user : readExcel) {
			System.out.println(user);
		}
	}
	
	

}

z在這個controller中有兩個方法每一個是將對象中的數據寫入excel文件,一個是將excel文件中的數據讀取出來,並且存入到對象之中。好了現在就來講解怎麼實現excel文件的讀寫了。

這裏我們來到PoiUtils類中,這個類就是我們這個項目的工具類,這裏我將實現excel文件的讀寫功能都封裝在這個類種,該類的代碼如下所示:

/**
 * 	工具類
 * 
 * @author wcan
 * @date 2018-11-10
 *
 */
public class PoiUtils {

	/**
	 * 
	 * 	讀取文件
	 * 
	 */
	public static List<User> readExcel(String filePath) {
		//創建集合存放數據
		List<User> list = new ArrayList<User>();
		POIFSFileSystem fs = null;
		 try {
			 fs=new POIFSFileSystem(new FileInputStream(filePath));
			 HSSFWorkbook wb = new HSSFWorkbook(fs); 
			//讀取第第張表格
			 HSSFSheet sheet = wb.getSheetAt(0); 
			 //獲取行
			 for(int i= 1;i<sheet.getLastRowNum();i++) {
				 HSSFRow row = sheet.getRow(i); 
				 String[] str = new String[row.getLastCellNum()];			 
				 for (int j=0;j<=row.getLastCellNum();j++) {
					str[j]=row.getCell(j).toString();
				}
				User user = new User();
				user.setId(Long.valueOf(str[0]));
				user.setUserName(str[1]);
				user.setPassword(str[2]);
				user.setBirthDay(PoiUtils.stringToDate(str[3]));
				user.setSign(str[4]);
				user.setAge(Integer.valueOf(str[5]));
				user.setSalary(Double.valueOf(str[6]));
				list.add(user);
				// System.out.println("添加了第: "+i+" 個對象");
			 }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				fs.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		 System.out.println("返回了一個存放了 "+list.size()+" 個對象的集合");
		 
		 return list;
	}

	/**
	 * 將對象中封裝的數據存放到HSSFWorkbook對象中
	 * 
	 * @param list
	 * @return workbook
	 */
	public static HSSFWorkbook getWorkBook(List<User> list) {
		for (User user : list) {
			System.out.println(user);
		}
		// 創建工作表對象
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 在對象中創建一個表
		HSSFSheet sheet = workbook.createSheet("sheet0");
		// 獲取表頭
		String[] header = PoiUtils.getTabHeader();
		for (int i = 0; i < list.size() + 1; i++) {
			// 創建第i行
			HSSFRow row = sheet.createRow(i);
			// 設置表頭
			if (i == 0) {
				for (int j = 0; j < header.length; j++) {
					row.createCell(j).setCellValue(header[j]);
				}
			}
			// 將內容寫入excel表格
			else {
				// 獲取對象屬性值
				String[] userMsg = getUserMsg(list.get(i - 1));
				for (int j = 0; j < userMsg.length; j++) {
					row.createCell(j).setCellValue(userMsg[j]);
				}
			}

		}
		return workbook;
	}

	/**
	 * 將對象屬性值存入到string數組中
	 * 
	 * @param user
	 * @return
	 */
	public static String[] getUserMsg(User user) {
		String[] usersMsg = {

				user.getId() != null ? user.getId().toString() : null, user.getUserName(), user.getPassword(),
				PoiUtils.dateToString(user.getBirthDay()), user.getSign(), user.getAge().toString(),
				user.getSalary().toString()

		};
		return usersMsg;

	}

	/**
	 * 提供表頭
	 * 
	 * @return
	 */
	public static String[] getTabHeader() {

		String[] tabHeader = { "用戶ID", "用戶名", "密碼", "個性簽名", "生日", "年齡", "工資" };
		return tabHeader;

	}

	/**
	 * 將日期類型的數據轉成字符串
	 * 
	 * @param date
	 * @return date
	 */
	public static String dateToString(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		return sdf.format(date);

	}

	/**
	 * 將字符串類型的數據轉成日期
	 * 
	 * @param date
	 * @return date
	 */
	public static Date stringToDate(String str) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		try {
			return sdf.parse(str);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw new RuntimeException("轉換失敗");
		}

	}
}

給大家解釋一下,由於數據類型的不同,這裏可以將所有的數據都轉換成字符串,放在一個字符串數組中,飯後遍歷該字符串數組,將值一次放入到表格中,最終表格中的數據都是以字符串的形式寫入到excel 文件中。需要注意的是Date類型的數據轉成字符串的時候需要日期格式化的一個工具類,在構造器中指定要轉換的格式即可。

同理,讀取excel文件的中的數據存入到對象中的時候我們讀取出來的數據也是字符串類型的,因此也需要處理。其實poi中有自帶的數據處理的功能,但是我個人覺得來麻煩了,每次用的時候都要加入判斷的方法,嚴重的影響了程序的執行效率。所以這裏採用了統一轉換的方式來進行處理。

好了,我們回到controller層,測試一下creatExcel這個方法,結果如下圖所示:

可以看到,我們成功的將數據封裝到了對象中,同時我們打開D盤,就可以發現在D盤下已經生成了一個demo.xls的文件。打開該文件,如下所示:

好了,使用poi生成excel文件的的功能 實現了,接下來我們來讀取這個生成的excel文件。運行readExcel方法,結果如下圖所示:

好了,這次的poi使用的教程就到此爲止了,後面的要做的項目就是把數據知道導入到數據庫中,也就是後臺的上傳excel文件,然後解析excel文件,經該文件的數據導入到數據庫中,同時還要不實現將數據庫中的數據寫入到excel文件中,並且從服務器上下載下來。好了,今天就到這裏了,希望這篇博客對大家有幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章