Excel读写操作

Excel导入导出简单示例,希望可以帮助到你。如果你的业务更复杂一点的话,可以在此基础上稍作修改。实现的方式有很多,如果有时间可以自己再研究其他实现方式。

谈谈我的看法:主要理解工作薄、工作表、行、列(单元格)之间的关系;

项目结构截图:

Excel读写操作_第1张图片

pom.xml引入的依赖


  	
	
	    org.apache.poi
	    poi
	    4.1.2
	
	
	
	
	    org.apache.poi
	    poi-ooxml
	    4.1.2
	
	
	
	
	    joda-time
	    joda-time
	    2.10.5
	
  	
  

工具类:ExcelSuffix.java

public class ExcelSuffix {
	/**
	 * excel 03版本后缀
	 */
	public static final String EXCEL03PREFIX = ".xls";
	
	/**
	 * excel 07版本后缀
	 */
	public static final String EXCEL07PREFIX = ".xlsx";
	
	/**
	 * 文件路径
	 */
	public static final String PATH = "C:\\Desktop\\";
}

Excel读操作:

/**
 * Excel 读数据
 */
public class ExcelRead {

	/**
	 * 03版本的读取文件指定单元格内容
	 */
	@Test
	public void excelRead03V() throws Exception {
		FileInputStream fStream = new FileInputStream(ExcelSuffix.PATH + "excel03" + ExcelSuffix.EXCEL03PREFIX);
		Workbook workbook = new HSSFWorkbook(fStream);
		Sheet sheet = workbook.getSheetAt(0);
		Row row = sheet.getRow(0);
		Cell cell = row.getCell(0);
		String cellValue = cell.getStringCellValue();
		System.out.println("获取第一个单元格的内容 : " + cellValue);
		fStream.close();
	}

	/**
	 * 07版本的读取文件指定单元格内容
	 */
	@Test
	public void excelRead07V() throws Exception {
		FileInputStream fStream = new FileInputStream(ExcelSuffix.PATH + "excel07" + ExcelSuffix.EXCEL07PREFIX);
		Workbook workbook = new XSSFWorkbook(fStream);
		Sheet sheet = workbook.getSheetAt(0);
		Row row = sheet.getRow(0);
		Cell cell = row.getCell(0);
		String cellValue = cell.getStringCellValue();
		System.out.println("获取第一个单元格的内容 : " + cellValue);
		fStream.close();
	}

	/**
	 * 读取文件数据并判断类型
	 */
	@Test
	public void excelRead() throws Exception {
		// 加载文件数据
		FileInputStream inputStream = new FileInputStream(ExcelSuffix.PATH + "03明细" + ExcelSuffix.EXCEL03PREFIX);
		Workbook workbook = new HSSFWorkbook(inputStream);// 创建工作薄
		Sheet sheet = workbook.getSheetAt(0);// 获取工作表
		
		// 获取标题
		Row rowTitle = sheet.getRow(0);
		int cellCount = 0;
		if (rowTitle != null) {
			cellCount = rowTitle.getPhysicalNumberOfCells();//获取有多少列
			for (int cellNumi = 0; cellNumi < cellCount; cellNumi++) {
				Cell cell = rowTitle.getCell(cellNumi);//获取列
				if (cell != null) {
					String cellValue = cell.getStringCellValue();//获取单元格的值
					System.out.print(cellValue + " | ");
				}
			}
			System.out.println();
		}
		
		int rowCount = sheet.getPhysicalNumberOfRows();// 获取行数
		for (int rowNum = 1; rowNum < rowCount; rowNum++) {
			Row row = sheet.getRow(rowNum);
			if (row != null) {
				for (int i = 0; i < cellCount; i++) {
					Cell cell = row.getCell(i);
					if (cell != null) {
						CellType cellType = cell.getCellType();
						String cellValue = "";
						switch (cellType) {
						case STRING:// 字符串 
							cellValue = cell.getStringCellValue();
							System.out.print(cellValue + " | ");
							break;
						case NUMERIC:// 数字(日期、普通数字)
							if (DateUtil.isCellDateFormatted(cell)) {// true说明是日期 
								Date date = cell.getDateCellValue();
								cellValue = new DateTime(date).toString("yyyy-MM-dd");
							} else {//数字的话转字符串
								cell.setCellType(CellType.STRING);
								cellValue = cell.getStringCellValue();
							}
							System.out.print(cellValue + " | ");
							break;
						case BOOLEAN://布尔类型
							cellValue = String.valueOf(cell.getBooleanCellValue());
							System.out.println(cellValue);
							break;
						case BLANK://空
							break;
						default:
							break;
						}
					}
				}
			}
			System.out.println();
		}
	}
}

Excel写操作:

/**
 * excel 写操作的基本使用
 */
public class BaseExcelWrite {

	/**
	 * 03版本的excel的基本写操作示例
	 */
	@Test
	public void excel03V() throws Exception{
		Workbook workbook = new HSSFWorkbook();//创建工作薄
		Sheet sheet = workbook.createSheet("sheet03");//创建工作表
		Row row = sheet.createRow(0);//创建行
		Cell cell = row.createCell(0);//创建列
		cell.setCellValue("03版本cell1");//填写内容
		Cell cell2 = row.createCell(1);
		cell2.setCellValue("03版本cell2");
		//创建流
		FileOutputStream outputStream = new FileOutputStream(ExcelSuffix.PATH + "excel03" + ExcelSuffix.EXCEL03PREFIX);
		workbook.write(outputStream);//写操作
		//关闭流
		outputStream.close();
	}
	
	/**
	 * 07版本的excel的基本写操作示例
	 */
	@Test
	public void excel07V() throws Exception{
		Workbook workbook = new XSSFWorkbook();//创建工作薄
		Sheet sheet = workbook.createSheet("sheet07");//创建工作表
		Row row = sheet.createRow(0);//创建行
		Cell cell = row.createCell(0);//创建列
		cell.setCellValue("07版本cell1");//填写内容
		Cell cell2 = row.createCell(1);
		cell2.setCellValue("07版本cell2");
		//创建流
		FileOutputStream outputStream = new FileOutputStream(ExcelSuffix.PATH + "excel07" + ExcelSuffix.EXCEL07PREFIX);
		workbook.write(outputStream);//写操作
		//关闭流
		outputStream.close();
	}
}

---------------------------------我是分割线----------------------------------------------------
/**
 * excel 大数据量的操作
 */
public class BigExcelWrite {

	/**
	 * HSSF
* 缺点:最多只能处理65535行数据,否则会报如下异常: * java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535) * 优点:过程中写入缓存,不操作磁盘,最后一次性写入到文件中,速度相对较快 */ @Test public void excelWrite03V() throws Exception{ long beginTime = System.currentTimeMillis();//开始时间 Workbook workbook = new HSSFWorkbook();//创建工作薄 Sheet sheet = workbook.createSheet("03excel_bigdata");//创建工作表 for (int rowNum = 0; rowNum < 65536; rowNum++) { Row row = sheet.createRow(rowNum);//创建行 for (int cellNumj = 0; cellNumj < 10; cellNumj++) { Cell cell = row.createCell(cellNumj);//创建列 cell.setCellValue("data" + cellNumj);//填写内容 } } //创建流 FileOutputStream outputStream = new FileOutputStream(ExcelSuffix.PATH + "03bigdata" + ExcelSuffix.EXCEL03PREFIX); workbook.write(outputStream);//写操作 //关闭流 outputStream.close(); long endTime = System.currentTimeMillis(); System.out.println((double)(endTime - beginTime)/1000);//3.268 } /** * XSSF
* 缺点:写数据时,速度非常慢,非常耗内存,也会发生内存溢出,如100w条 * 优点:可以写较大的数据量,如20w条 */ @Test public void excelWrite07V() throws Exception{ long beginTime = System.currentTimeMillis();//开始时间 Workbook workbook = new XSSFWorkbook();//创建工作薄 Sheet sheet = workbook.createSheet("07excel_bigdata"); for (int rowNum = 0; rowNum < 65536; rowNum++) { Row row = sheet.createRow(rowNum);//创建行 for (int cellNumj = 0; cellNumj < 10; cellNumj++) { Cell cell = row.createCell(cellNumj);//创建列 cell.setCellValue("data" + cellNumj);//填写内容 } } //创建流 FileOutputStream outputStream = new FileOutputStream(ExcelSuffix.PATH + "07bigdata" + ExcelSuffix.EXCEL07PREFIX); workbook.write(outputStream);//写操作 //关闭流 outputStream.close(); long endTime = System.currentTimeMillis();//接收时间 System.out.println((double)(endTime - beginTime)/1000);//22.104 } /** * SXSSF
* 优点:可以写非常大的数据量,写数据速度快,占用更少的内存 * 注意:过程总会产生临时文件,需要清理临时文件;默认由100条记录被保存在内存中,如果超过这个数量,则最 * 前面的数据被写入临时文件,如果想要自定义内存中的数据的数量,可以使用new SXSSFWorkbook(数量) * 有些事情不是绝对的,也有可能占用大量内存 */ @Test public void excelWriteBigData() throws Exception { long beginTime = System.currentTimeMillis();//开始时间 Workbook workbook = new SXSSFWorkbook();//创建工作薄 Sheet sheet = workbook.createSheet("bigData");//创建工作表 for(int rowNum = 0;rowNum < 1000000; rowNum ++) { Row row = sheet.createRow(rowNum); for (int cellNum = 0; cellNum < 10; cellNum++) { Cell cell = row.createCell(cellNum); cell.setCellValue("bigData" + cellNum); } } //创建流 FileOutputStream fStream = new FileOutputStream(ExcelSuffix.PATH + "bigData" + ExcelSuffix.EXCEL07PREFIX); //写操作 workbook.write(fStream); //关闭流 fStream.close(); //清除临时文件 ((SXSSFWorkbook) workbook).dispose(); long endTime = System.currentTimeMillis(); System.out.println((double)(endTime-beginTime)/1000);//30.02 } }

Excel基本读取:

/**
 * Excel基本读取
 */
public class ReadExcel {
	
	public static void main(String[] args) throws Exception {
		
		FileInputStream fStream = new FileInputStream(ExcelSuffix.PATH + "03明细" + ExcelSuffix.EXCEL03PREFIX);
		Object object = excelReader(fStream,0);
	}

	/**
	 * Excel 读取方法
	 * @param fStream 文件流
	 * @param sheetIndex 工作表下标索引
	 */
	public static Object excelReader(FileInputStream fStream, int sheetIndex) throws IOException {
		Workbook wk = new HSSFWorkbook(fStream);// 创建工作薄并将文件流加载到内存中
		int sheets = wk.getNumberOfSheets();// 获取所有工作表的个数
		int sheetAt = 0;//工作表下标索引
		if(sheetIndex <= sheets) sheetAt = sheetIndex;//从第几个工作表开始
		for (; sheetAt < sheets; sheetAt++) {// 循环工作表
			Sheet sheet = wk.getSheetAt(sheetAt);// 获取具体的工作表
			int rows = sheet.getPhysicalNumberOfRows();// 获取工作表的行数
			for (int i = 0; i < rows; i++) {// 循环行
				Row row = sheet.getRow(i);// 获取具体的行
				if (row != null) {// 判断行对象是否为空
					int cells = row.getPhysicalNumberOfCells();// 获取行中的列(单元格)个数
					for (int j = 0; j < cells; j++) {// 循环单元格,准备获取内容了
						Cell cell = row.getCell(j);// 获取具体的单元格
						if (cell != null) {// 判断单元格是否为空
							//CellType cellType = cell.getCellType();// 获取单元格内容的类型
							String cellValue = handleValueByCellType(cell);
							System.out.println(cellValue);
							//TODO 在这里做"坏事"
						}
					}
				}
			}
		}

		return null;//TODO 这里需要返回结果
	}

	/**
	 * 根据单元格类型处理单元格内容
	 * @param cell 单元格对象
	 * @deprecated 如果case中类型没有,可自行添加上
	 */
	public static String handleValueByCellType(Cell cell) {
		String cellValue = "";
		CellType cellType = cell.getCellType();
		switch (cellType) {
		case STRING:
			cellValue = cell.getStringCellValue();
			break;
		case NUMERIC:// 数字(日期、普通数字)
			if (DateUtil.isCellDateFormatted(cell)) {// true说明是日期
				Date date = cell.getDateCellValue();
				cellValue = new DateTime(date).toString("yyyy-MM-dd");
			} else {// 数字的话转字符串
				cell.setCellType(CellType.STRING);
				cellValue = cell.getStringCellValue();
			}
			break;
		case BOOLEAN://布尔类型
			cellValue = String.valueOf(cell.getBooleanCellValue());
			break;
		case BLANK://空
			break;
		default:
			break;
		}
		return cellValue;
	}
}

Excel读取到封装对象:

public class ExcelReader {

	private long row;// 行

	private List cells = new ArrayList();//列

	public long getRow() {
		return row;
	}

	public void setRow(long row) {
		this.row = row;
	}

	public List getCells() {
		return cells;
	}

	public void setCells(Cell cell) {
		this.cells.add(cell);
	}

	@Override
	public String toString() {
		return "ExcelReader [row=" + row + ", cells=" + cells + "]\r\n";
	}
}
-------------------------------------------我是分割线---------------------------------------
/**
 * 读操作升级版
 */
public class ReadExcelPlus {

	@Test
	public void test() throws Exception {
		// 创建文件流
		FileInputStream fStream = new FileInputStream(ExcelSuffix.PATH + "03明细" + ExcelSuffix.EXCEL03PREFIX);
		// 调用读取表格的数据
		List> readExcel = ReadExcel(fStream, 0, 1);
		System.out.println(readExcel);// 输出打印
		// 关闭流
		fStream.close();
	}

	/**
	 * 读取excel
	 * 
	 * @param fiStream   文件流
	 * @param sheetIndex 工作表索引;从哪个工作表中开始读
	 * @param rowIndex   行索引;需要读取标题传0;不要标题传1
	 * @return
	 * @throws Exception
	 */
	public static List> ReadExcel(FileInputStream fiStream, int sheetIndex, 
			int rowIndex) throws Exception {
		List> excels = new ArrayList>();// 封装的对象
		Workbook wk = new HSSFWorkbook(fiStream);// 创建工作薄并将文件流加载到内存中
		int sheets = wk.getNumberOfSheets();// 获取所有工作表的个数
		int sheetAt = 0;// 工作表下标索引
		if (sheetIndex <= sheets)
			sheetAt = sheetIndex;// 从第几个工作表开始
		for (; sheetAt < sheets; sheetAt++) {// 循环工作表
			Sheet sheet = wk.getSheetAt(sheetAt);
			if (sheet.getPhysicalNumberOfRows() == 0)
				continue; // 工作表为空,跳过本次循环进入下一次循环
			List currentSheetExcels = new ArrayList();// 当前工作表的数据
			if (sheet != null) {// 这里也可以判断一下工作表是否为空
				int rows = sheet.getPhysicalNumberOfRows();// 获取行数获取工作表的行数
				int i = 0;
				if (rowIndex <= rows)
					i = rowIndex;// 从第几行开始读,如果标题不要,可以传1过来
				for (; i < rows; i++) {
					Row row = sheet.getRow(i);// 获取行
					int cells = row.getPhysicalNumberOfCells();// 获取当前行的所有列
					ExcelReader er = new ExcelReader();// 工作表读取对象
					er.setRow(i);// 设置行
					for (int j = 0; j < cells; j++) {
						Cell cell = row.getCell(j);// 获取每一个单元格
						if (cell != null)
							er.setCells(cell);// 设置列
					}
					if (er.getCells() != null && er.getCells().size() > 0) {// 判断列集合中是否有数据
						currentSheetExcels.add(er);// 将数据加入到当前工作表中
					}
				}
			}
			excels.add(currentSheetExcels);
		}
		return excels;
	}
}

Excel写操作:通过自定义注解和反射实现

/**
* @interface
* * @Target 表示我们的注解可以用在哪些地方 * ElementType.TYPE 类/接口 * ElementType.FIELD 字段声明 * ElementType.METHOD 方法声明 * ElementType.PACKAGE 包 * * @Retention 表示我们自定义的注解在什么阶段还有效 * RetentionPolicy.RUNTIME 运行级别 * RetentionPolicy.CLASS 字节码级别 * RetentionPolicy.SOURCE 源码级别 * * 运行级别: RUNTIME > CLASS > SOURCE */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelHead { String value(); int[] freeze() default {}; } ------------------------------------------------我是分割线----------------------------------------- @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelField { String value(); } ------------------------------------------------我是分割线----------------------------------------- /** * 学生类 */ @ExcelHead(value = "学生信息",freeze = {0,3}) public class Student { @ExcelField(value = "姓名") private String name; @ExcelField(value = "性别") private String gender; @ExcelField(value = "手机号码") private String tel; @ExcelField(value = "生日") private String birthday; @ExcelField(value = "年龄") private int age; @ExcelField(value = "地址") private String address; @ExcelField(value = "真假") private boolean flag; //构造方法、getter、setter、toString方法省略 } ------------------------------------------------我是分割线----------------------------------------- /** * 测试数据初始化以及测试 */ public class ExcelWrite { List list = Arrays.asList(new Student("王祖贤", "女", "18763372970", "1992-05-21", 18, "HK", false), new Student("陈乔恩", "女", "18763372768", "1991-05-21", 18, "TW", true), new Student("黄蓉", "女", "18863372970", "1990-05-21", 18, "HK", false)); @Test public void test() throws Exception { Class clazz = Student.class; String sheetName = clazz.getName(); ExcelHead excelHead = clazz.getAnnotation(ExcelHead.class); sheetName = excelHead.value(); Workbook wb = new XSSFWorkbook();// 创建工作薄 Sheet sheet = wb.createSheet(sheetName);// 创建工作表 Field[] fields = clazz.getDeclaredFields();// 获取类中声明的属性 Row titleRow = sheet.createRow(0);// 创建标题行 for (int i = 0; i < fields.length; i++) { ExcelField excelField = fields[i].getAnnotation(ExcelField.class);// 获取注解内容 Cell cell = titleRow.createCell(i);// 创建单元格 cell.setCellValue(excelField.value());// 设置值 } String fieldName = null; String getMethodName = null; Object value = null; for (int i = 0; i < list.size(); i++) { Row row = sheet.createRow(i + 1); for (int j = 0; j < fields.length; j++) { Cell cell = row.createCell(j); fieldName = fields[j].getName();//字段名称 getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Method getMethod = clazz.getMethod(getMethodName, new Class[]{}); value = getMethod.invoke(list.get(i), new Object[] {}); //判断类型,然后做相应的转换 if(value instanceof Boolean){ cell.setCellValue((Boolean)value); }else { cell.setCellValue(value.toString()); } } } FileOutputStream fis = new FileOutputStream(ExcelSuffix.PATH + sheetName + ExcelSuffix.EXCEL07PREFIX); wb.write(fis); fis.close(); } }

加油吧!

代码

你可能感兴趣的:(java,excel读写操作,poi操作excel文件,Excel读写操作,Poi操作Excel文件,Excel导入导出数据)