为您推荐:
精华内容
最热下载
问答
  • 3星
    38.36MB cc605523 2020-11-24 20:46:18
  • 5星
    4.45MB cc605523 2020-11-12 16:58:03
  • 5星
    487KB cc605523 2020-11-12 16:58:37
  • 5星
    466KB cc605523 2020-11-12 18:17:48
  • 5星
    386KB cc605523 2020-11-12 16:59:06
  • 5星
    7.27MB cc605523 2020-11-12 18:16:03
  • 5星
    226KB cc605523 2020-11-12 18:17:07
  • 9.38MB qq_34609712 2018-02-08 11:03:19
  • 展开全部本篇面向32313133353236313431303231363533e59b9ee7ad9431333264643066对象为Java的初学者,从下载必备软件到创建一个空白的POI工程,已经熟练掌握环境搭建的请跳过此文。开发环境为windowsXP-SP2,Eclipse...

    展开全部

    本篇面向32313133353236313431303231363533e59b9ee7ad9431333264643066对象为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具体做的事情就是向模板里写业务的数据,还是很方便快捷的。

    2Q==

    已赞过

    已踩过<

    你对这个回答的评价是?

    评论

    收起

    展开全文
    weixin_42131424 2021-02-12 23:18:32
  • 9.79MB qq_41955670 2019-12-27 15:46:08
  • 227KB lianghx0608 2017-10-23 11:10:54
  • 14.22MB newturing 2018-07-20 15:57:48
  • 12.53MB weixin_37721347 2018-04-22 23:10:00
  • 10.13MB daochuwenziyao 2017-09-15 22:47:56
  • 5星
    8.43MB lzc1993lzc 2018-11-01 16:20:56
  • 26.98MB weixin_39651041 2018-05-02 11:02:52
  • 17.73MB u014646662 2018-10-21 10:51:24
  • 9.95MB yeshushumemeda 2017-06-08 11:46:54
  • 4星
    11.02MB z_m_1 2018-06-06 10:52:00
  • 10.02MB qq_36772895 2018-01-18 10:52:58
  • 3星
    7.17MB u011208221 2016-09-25 22:21:53
  • 4KB as3966998 2018-11-02 17:46:25
  • 5星
    12KB evangel_z 2014-08-28 16:25:39
  • 3星
    69B axu_enfp 2019-01-10 16:03:42
  • 4星
    8.23MB lin9118 2013-12-14 16:07:58
  • 2.52MB yx1987kl 2018-06-12 21:35:43
  • 10KB qq_20512139 2020-03-20 16:55:01
  • 42KB weixin_38626080 2020-08-31 22:33:40
  • 103KB lkf728 2015-09-01 11:13:47
  • 14KB u012839498 2018-07-12 10:30:21
  • 可以参考我之前发的提问,可以参照看一下我的思考过程,根据IDEA或Eclipse的报错并不能解决问题,最后通过大量浏览其他人POI操作时发现可能是由于未导入5.0及以上版本POI的其他依赖commons.math3.jar导入...

    该问题我在初次导入5.0版本时遇到过,可以参考我之前发的提问,可以参照看一下我的思考过程,根据IDEA或Eclipse的报错并不能解决问题,最后通过大量浏览其他人POI操作时发现可能是由于未导入5.0及以上版本POI的其他依赖包commons.math3.jar包,导入该包后程序可以正常运行。希望可以帮助解决同样遇到这类问题的朋友。

    展开全文
    weixin_52026588 2021-11-24 12:43:19
  • 98KB weixin_38697063 2020-08-29 22:34:06
  • 最近有需求是导出和导入word,百度了好多,发现CSDN上并没有很合适的写法,所以写出这篇博客,希望帮助大家少走弯路,下面开干。 ### 导出word,推荐Poi-tl ,地址:https://github.com/Sayi/poi-tl,使用后你会...

    POI 导入word,支持doc、docx

    /**
    	 * 采用poi读取文件
    	 *
    	 * @param file 文件
    	 * @return map
    	 */
    	public static synchronized Map<String, String> readDocByPoiOnXcaj(MultipartFile file) {
    		Map<String, String> result;
    		String fileName = file.getOriginalFilename();
    		String prefix = fileName.substring(fileName.lastIndexOf("."));
    		if (".doc".equals(prefix)) {
    			result = importWordToDoc(file);
    		} else if (".docx".equals(prefix)) {
    			result = importWordToDocx(file);
    		} else {
    			throw new IllegalArgumentException("请联系管理员配合检查文档格式!");
    		}
    		return result;
    	}
    
    
    /**
    	 * 关闭输入流
    	 * @param is
    	 */
    	private static void close(InputStream is) {
    		if (is != null) {
    			try {
    				is.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    
    /**
    	 * 导入word (doc格式)
    	 */
    	public static Map<String,String> importWordToDoc (MultipartFile file) {
    		InputStream inputStream = null;
    		Map<String, String> result = new HashMap<>(30);
    		try {
    			//载入文档
    			inputStream = file.getInputStream();
    			HWPFDocument hwpf = new HWPFDocument(inputStream);
    			//得到文档的读取范围
    			Range range = hwpf.getRange();
    			TableIterator it = new TableIterator(range);
    			int index = 1;
    			String value = "";
    			String key = "";
    			// 迭代文档中的表格
    			while (it.hasNext()) {
    				Table tb = (Table) it.next();
    				for (int i = 0; i < tb.numRows(); i++) {
    					TableRow tr = tb.getRow(i);
    					StringBuffer stringBuffer = new StringBuffer();
    					for (int j = 0; j < tr.numCells(); j++) {
    						//取得单元格
    						TableCell td = tr.getCell(j);
    						//取得单元格的内容
    						for (int k = 0; k < td.numParagraphs(); k++) {
    							Paragraph para = td.getParagraph(k);
    							Optional<String> text1 = Optional.ofNullable(para.text());
    							String text = text1.orElse("");
    							text = text.replaceAll("\r", "");
    							text = text.replaceAll("\r\n", "");
    							text = text.replaceAll("\\u0007", "");
    							if (index % 2 != 0) {
    								key = text;
    							} else {
    								value = text;
    								stringBuffer.append(key).append(":").append(value);
    								result.put(key, value);
    							}
    							index++;
    						}
    					}
    					log.info("打印行" + stringBuffer.toString());
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			close(inputStream);
    		}
    		return result;
    	}
    
    
    	/**
    	 * 导入word (docx格式)
    	 */
    	public static Map<String,String> importWordToDocx (MultipartFile file) {
    		InputStream inputStream = null;
    		Map<String, String> result = new HashMap<>(30);
    		try {
    			InputStream inputStream1 = file.getInputStream();
    			XWPFDocument xdoc = new XWPFDocument(inputStream1);
    			List<XWPFParagraph> paras = xdoc.getParagraphs();
    			for (XWPFParagraph para : paras) {
    				//当前段落的属性
    				//       CTPPr pr = para.getCTP().getPPr();
    				System.out.println(para.getText());
    			}
    			//获取文档中所有的表格
    			List<XWPFTable> tables = xdoc.getTables();
    			List<XWPFTableRow> rows;
    			List<XWPFTableCell> cells;
    			int index = 1;
    			String value = "";
    			String key = "";
    			for (XWPFTable table : tables) {
    				//表格属性
    				//       CTTblPr pr = table.getCTTbl().getTblPr();
    				//获取表格对应的行
    				rows = table.getRows();
    				for (XWPFTableRow row : rows) {
    					//获取行对应的单元格
    					cells = row.getTableCells();
    					for (XWPFTableCell cell : cells) {
    						System.out.println(cell.getText());
    						String text = cell.getText();
    						text = text.replaceAll("\r", "");
    						text = text.replaceAll("\r\n", "");
    						text = text.replaceAll("\\u0007", "");
    						if (index % 2 != 0) {
    							key = text;
    						} else {
    							StringBuffer stringBuffer = new StringBuffer();
    							value = text;
    							stringBuffer.append(key).append(":").append(value);
    							result.put(key, value);
    						}
    						index++;
    					}
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			close(inputStream);
    		}
    		return result;
    	}

    到此结束,如果发现什么地方没有讲清楚可以在下方留言,谢谢大家!

    展开全文
    weixin_43069862 2019-08-30 16:27:10
  • 5星
    7.28MB yjaspire 2016-06-03 15:27:32
  • 4星
    42.8MB imnofeeling 2017-11-16 20:03:11
  • 前面说到下载模板后,对数据需要导入。 工具类 ImportExcelUtils :excel模板工具类 ...导入需要maven引入的jar(这里用的是poi) &amp;amp;amp;amp;lt;!-- https://mvnrepository.com/ar...
    前面说到下载模板后,对数据需要导入。

    工具类

    ImportExcelUtils :excel模板工具类
    FileUtils:文件上传工具类(这个工具类作用比较大,很多地方用的着,包括头像上传)
    ResponseData :对需要返回信息的一个封装工具类

    导入需要maven引入的jar包(这里用的是poi)
    pom.xml
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.10.1</version>
            </dependency>
    
            <dependency>
               <groupId>org.apache.poi</groupId>
               <artifactId>poi</artifactId>
               <version>3.6</version>
           </dependency>
    Excel导入的一个模板工具类

    导入包
    import java.io.IOException;
    import java.io.InputStream;
    import java.text.DecimalFormat;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.List;
    //
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    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.xssf.usermodel.XSSFWorkbook;

    public class ImportExcelUtils {
        private final static String excel2003L =".xls";    //2003- 版本的excel  
        private final static String excel2007U =".xlsx";   //2007+ 版本的excel  
    
        /** 
         * 描述:获取IO流中的数据,组装成List<List<Object>>对象 
         * @param in,fileName 
         * @return 
         * @throws IOException  
         */  
        public  List<List<Object>> getBankListByExcel(InputStream in,String fileName) throws Exception{  
            List<List<Object>> list = null;  
    
            //创建Excel工作薄  
            Workbook work = this.getWorkbook(in,fileName);  
            if(null == work){  
                throw new Exception("创建Excel工作薄为空!");  
            }  
            Sheet sheet = null;  
            Row row = null;  
            Cell cell = null;  
    
            list = new ArrayList<List<Object>>();  
            //遍历Excel中所有的sheet  
            for (int i = 0; i < work.getNumberOfSheets(); i++) {  
                sheet = work.getSheetAt(i);  
                if(sheet==null){continue;}  
    
                //遍历当前sheet中的所有行  
                for (int j = sheet.getFirstRowNum(); j <=sheet.getLastRowNum(); j++) {  
                    row = sheet.getRow(j); 
                    if(row==null||row.getFirstCellNum()==j){continue;}  
    
                    //遍历所有的列  
                    List<Object> li = new ArrayList<Object>();  
                    for (int k = row.getFirstCellNum(); k <row.getLastCellNum(); k++) {  
                        cell = row.getCell(k);
                        if(cell==null){continue;}  
    
                        li.add(this.getCellValue(cell));  
                    }  
                    list.add(li);  
                }  
            }  
            System.out.println(list);
            return list;  
    
            }
    
        /** 
         * 描述:根据文件后缀,自适应上传文件的版本  
         * @param inStr,fileName 
         * @return 
         * @throws Exception 
         */  
        public  Workbook getWorkbook(InputStream inStr,String fileName) throws Exception{  
            Workbook wb = null;  
            String fileType = fileName.substring(fileName.lastIndexOf("."));  
            if(excel2003L.equals(fileType)){  
                wb = new HSSFWorkbook(inStr);  //2003-  
            }else if(excel2007U.equals(fileType)){  
                wb = new XSSFWorkbook(inStr);  //2007+  
            }else{  
                throw new Exception("解析的文件格式有误!");  
            }  
            return wb;  
        }  
    
    
        /** 
         * 描述:对表格中数值进行格式化 
         * @param cell 
         * @return 
         */  
        public  Object getCellValue(Cell cell){  
            Object value = null;  
            DecimalFormat df = new DecimalFormat("0");  //格式化number String字符  
            SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd");  //日期格式化  
            DecimalFormat df2 = new DecimalFormat("0.00");  //格式化数字  
    
            switch (cell.getCellType()) {  
            case Cell.CELL_TYPE_STRING:  
                value = cell.getRichStringCellValue().getString();  
                break;  
            case Cell.CELL_TYPE_NUMERIC:  
                if("General".equals(cell.getCellStyle().getDataFormatString())){  
                    value = df.format(cell.getNumericCellValue());  
                }else if("m/d/yy".equals(cell.getCellStyle().getDataFormatString())){  
                    value = sdf.format(cell.getDateCellValue());  
                }else{  
                    value = df2.format(cell.getNumericCellValue());  
                }  
                break;  
            case Cell.CELL_TYPE_BOOLEAN:  
                value = cell.getBooleanCellValue();  
                break;  
            case Cell.CELL_TYPE_BLANK:  
                value = "";  
                break;  
            default:  
                break;  
            }  
            return value;  
        }      
    
    
    
    }

    这是Excel解析工具类,参考地址:https://blog.csdn.net/weixin_35751376/article/details/60139028
    大家也可以借鉴这位博主的这篇,地址:https://blog.csdn.net/xuanzhangran/article/details/70158995

    前端js

    一般上传,必须走form表单,需要对文件解析成流的方式进行上传。

    upload.jsp
     <form  id="importFrom" action="${request.getContextPath()}/example/upload.do" method="post" enctype="multipart/form-data" >      
        <button type="button"  onclick="uploadFile()">导入</button>
    
        <input type='file' id='fileUp' name='fileData' style="display: none" onchange="fu()" />
    </form>             

    隐藏一个file,通过点击按钮来触发上传

    以ajax方式对文件进行上传

    //excel导入
        function uploadFile(){       
            $("#fileUp").trigger("click");
        }
    
        function fu() {
             var files = document.getElementById('fileUp').files;  
             var fileSize = 0;
                if(files.length!=0){
                    fileSize = files[0].size;
                }
             $.ajaxFileUpload({
                url : '${request.getContextPath()}/example/upload.do',
                secureuri : false, //是否启用安全提交 默认为false
                fileElementId : 'fileUp', //file标签的id  
                dataType : 'jsonp',//返回数据的类型  
                success : function(data) {                
                    if(data=='null'){
                        alert("导入信息成功");
                        window.location.reload();
                    }else{
                        alert("导入信息以下部分异常,请重新导入失败部分:"+data);
                        window.location.reload();
                    }
                },
                error : function(data, status, e) {
                    alert(e);
                }
            });
        }
    

    上面回调的data是后台中对数据导入保存前验证不合格数据的返回。和一般我们新增数据做信息验证本质一样。
    $.ajaxFileUpload这样需要引入一个ajaxfileupload.js.以下是我的一个地址
    这里写图片描述
    下载地址:https://download.csdn.net/download/tt336798/10632016

    后台代码Controller
    导入方法(springmvc上传的方式)

    往下看借鉴后面的一个controller

      //@RequestParam("fileData") 对应页面中的name
      @RequestMapping(value="upload",method={RequestMethod.GET,RequestMethod.POST})
      public List  uploadExcel(@RequestParam("fileData") MultipartFile file,HttpServletRequest request,HttpServletResponse response) throws Exception {
    
                InputStream in =null;
                List<List<Object>> listob = null;
                if(file.isEmpty()){
                    throw new Exception("文件不存在!");
                }
                in = file.getInputStream();
                listob = new ImportExcelUtils().getBankListByExcel(in,file.getOriginalFilename());
                in.close();
    
                //一个个的取值放入到对应的属性setXX()中
               //声明变量,接受数据
                String empName=null;          
                List<String> errorList = new ArrayList<>();
                for (int i = 0; i < listob.size(); i++) {
                    List<Object> lo = listob.get(i);
    
                     StaffEntity sta=new StaffEntity();   //创建对象         
                    //姓名
                    empName=String.valueOf(lo.get(0)).trim();
                    if(empName==null){
                        String msg = "第" + (i + 2) + "行的姓名不能为空";
                        errorList.add(msg);
                    }
                  sta.setEmpName(empName);
                  //........
                 //后面调用保存的方法,将对象进行数据保存(前台我写的是json数据,后面记得要转json)
                 //.........
             }       
    
            return errorList;
    }           

    以上这样,需要在springMVC配置中做配置信息

    <!-- 文件上传解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"></property>
        <property name="maxUploadSize" value="10485760000"></property><!-- 最大上传文件大小 -->
        <property name="maxInMemorySize" value="10960"></property>
    </bean>

    后台另外一种,需要借助一个工具类(最后有两张图片详解)

    FileUtils工具类

    导入包

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.util.Date;
    //
    import javax.servlet.http.HttpServletRequest;
    //
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.multipart.MultipartHttpServletRequest;
    import org.springframework.web.multipart.commons.CommonsMultipartResolver;
    //
    import sun.misc.BASE64Decoder;

    public class FileUtils {
    
        public static String fileUpload(HttpServletRequest request,String fileRoot, String rootPath, String extArr) throws IOException {
    
            MultipartFile fileData = null;
            CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
            if (commonsMultipartResolver.isMultipart(request)) {
                MultipartHttpServletRequest multipartFile = commonsMultipartResolver
                        .resolveMultipart(request);
    
                fileData = multipartFile.getFile("fileData"); //页面中name
            }
            if (null == fileData || fileData.getSize() == 0) {
                System.out.println("fileData="+fileData);
                return null;
            }
            String fileName = fileData.getOriginalFilename();  //获得文件名字
            String ext = fileName.substring(fileName.indexOf("."));  //获取.xls
            File filePath = new File(rootPath + fileRoot);
    
            //文件不存在的时候创建新文件夹
            if (!filePath.exists()) {
                filePath.mkdirs();
            }
            if (ext != null && ext.length() > 1&& extArr.indexOf(ext.toLowerCase().substring(1)) > -1) {
                InputStream is = null;
                String tempName = new Date().getTime() + ext;  //产生新的文件名
                String url = rootPath + fileRoot + tempName;
                File file = new File(url);
                if (!file.exists()) {
                    file.createNewFile();
                }
                FileOutputStream out = new FileOutputStream(file);
                try {
                    is = fileData.getInputStream();
                    IOUtils.copy(is, out);
    
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                } finally {
                    if (out != null) {
                        out.close();
                    }
                    if (is != null) {
                        is.close();
                    }
                }
                return fileRoot + tempName;
            } else {
                throw new IOException("文件类型不匹配");
            }
    
        }
    
        public static String createFile(String rootPath, String childPath,
                String content, String fileName) throws IOException {
            try {
                File dir = new File(rootPath + childPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(rootPath + childPath + fileName);
                if (!file.exists()) {
                    file.createNewFile();
                }
                OutputStreamWriter oStreamWriter = new OutputStreamWriter(
                        new FileOutputStream(file), "utf-8");
                oStreamWriter.write(content);
                oStreamWriter.flush();
                oStreamWriter.close();
    
                // HtmlImageGenerator hig=new HtmlImageGenerator();
    
                // hig.loadHtml(content);
                // hig.saveAsImage(rootPath + childPath + imgName);
    
                return childPath + fileName;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * base64生成文件
         * 
         * @param rootPath
         * @param childPath
         * @param content
         * @param fileName
         * @return
         * @throws IOException
         */
        public static String createBase64File(String rootPath, String childPath,
                String content, String fileName) throws IOException {
            if (StringUtils.isBlank(content)) {
                return null;
            }
            try {
                File dir = new File(rootPath + childPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(rootPath + childPath + fileName);
                if (!file.exists()) {
                    file.createNewFile();
                }
    
                BASE64Decoder decoder = new BASE64Decoder();
    
                // Base64解码
                byte[] b = decoder.decodeBuffer(content);
                for (int i = 0; i < b.length; ++i) {
                    if (b[i] < 0) {// 调整异常数据
                        b[i] += 256;
                    }
                }
                // 生成jpeg图片
                OutputStream out = new FileOutputStream(file);
                out.write(b);
                out.flush();
                out.close();
                return childPath + fileName;
            } catch (Exception e) {
                e.printStackTrace();
    
            }
    
            return null;
        }
    
        public static String readFile(String rootPath, String childPath,
                String fileName) throws IOException {
            try {
    
                File file = new File(rootPath + childPath + fileName);
                FileInputStream in = new FileInputStream(file);
    
                int size = in.available();
    
                byte[] buffer = new byte[size];
    
                in.read(buffer);
    
                in.close();
    
                String str = new String(buffer, "utf-8");
                return str;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            return null;
        }
    
        public static String copyFile(String rootPath, String childPath,
                String srcFileName, String descFileName) throws IOException {
    
            FileInputStream in = new FileInputStream(rootPath + childPath + srcFileName);
            FileOutputStream out = new FileOutputStream(rootPath + childPath + descFileName);
            try {
    
                IOUtils.copy(in, out);
    
            } catch (IOException e) {
                return null;
            } finally {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            }
            return childPath + descFileName;
    
        }
    
    }

    maven需要导入(包本类需要的)

    pom.xml

    这里写图片描述

    后面自己写了个对错误信息封装的工具类

    返回值工具类
    public class ResponseData {
        public static final String ERRORS_KEY = "errors";
    
        private String message;
        private int code = 0;
        private Object data;
    
        public ResponseData() {
            this.code = 0;
        }
    
        public String getMessage() {
            return message;
        }
    
        public int getCode() {
            return code;
        }
    
        public Object getData() {
            return data;
        }
    
        public ResponseData putDataValue(Object value) {
            this.data = value;
            return this;
        }
        public ResponseData fail(String message) {
            return this.setResponseData(10003, message, null);
        }
    }

    好了,万事具备,这里开始展示后台信息controller

    后台Controller

    
    @Autowired
    private StaffServiceImpl staffServiceImpl;
    
    //@Value("${file.root.path}")
    private String rootPath="/D:";
    
    //@Value("${file.csv.path}")
    private String tempFile = "/MyWorkDoc";
    
    
    
    /**
         * 导入Excel
         * 
         * @param file
         * @param request
         * @param response
         * @param msgList 
         * @return
         * @throws Exception
         */
        @RequestMapping(value = "upload")
        @ResponseBody
    public ResponseData uploadExcel(HttpServletRequest request,
                HttpServletResponse response) throws Exception {
    
            System.out.println("开始导入.....");
            ResponseData responseData = new ResponseData();
            try {
                String url = FileUtils.fileUpload(request, tempFile, rootPath,".xls");
                if (StringUtils.isBlank(url)) {
                    responseData.fail("导入信息异常");
                }
                File file = new File(rootPath + url);
                if (!file.exists()) {
                    responseData.fail("导入信息异常");
                }
    
                List<List<Object>> listob = null;
    
                InputStream in = new FileInputStream(file);
                listob = new ImportExcelUtils().getBankListByExcel(in, url); //解析Excel
                in.close();
    
                // 声明变量,接受数据
                String empName = null;
                String idCard = null;
                String phoneCode = null;
                List<String> errorList = new ArrayList<>();
                for (int i = 0; i < listob.size(); i++) {
                    List<Object> lo = listob.get(i);
                    StaffEntity sta = new StaffEntity();
    
                    // 姓名
                    empName = String.valueOf(lo.get(0)).trim();
                    if (StringUtils.isBlank(empName)) {
                        String msg = "第" + (i + 2) + "行的姓名不能为空";
                        errorList.add(msg);
                        continue;
                    }
    
                    // 手机号
                    phoneCode = String.valueOf(lo.get(1));
                    if (StringUtils.isBlank(phoneCode)) {
                        errorList.add("第" + (i + 2) + "行: 手机号为空");
                        continue;
                    }
                    StaffEntity PhoneCordEntity = staffServiceImpl.findByStaffTel(phoneCode); //验证手机号码唯一
                    if (PhoneCordEntity != null) {
                        errorList.add("第" + (i + 2) + "行: 手机号已经存在");
                        continue;
                    }
    
                    // 身份证号
                    idCard = String.valueOf(lo.get(2));
                    if (StringUtils.isBlank(idCard)) {
                        errorList.add("第" + (i + 2) + "行: 身份证号为空");
                        continue;
                    }
                    StaffEntity idcardEntity = this.staffServiceImpl.findByStaffIdCard(idCard);//验证身份证号码唯一
                    if (idcardEntity != null) {
                        errorList.add("第" + (i + 2) + "行: 员工身份证号码已经存在");
                        continue;
                    }
    
    
                    sta.setStaffName(empName);          
                    sta.setStaffTel(phoneCode); // 手机号
                    sta.setStaffIdCard(idCard); // 身份证号
                    sta.setStaffBankCard(String.valueOf(lo.get(3))); // 银行卡
    
                    sta.setUpdateTime(new Date());
                    sta = this.staffServiceImpl.save(sta);
    
                }
                if (errorList != null && errorList.size() > 0) {
                    responseData.putDataValue(JSON.toJSONString(errorList));
                }
            } catch (Exception e) {
                e.printStackTrace();
                responseData.serverInternalError();
            }
            return responseData;
        }   

    回到前台JS页面(作稍微的更改)

    success : function(data) {  
                if(data.data=='null'){
                    alert("导入员工信息成功");
                    window.location.reload();
                }else{
                    alert("导入员工信息以下部分异常,请重新导入失败部分:"+data.data);
                    window.location.reload();
                }
    },

    最后这里上两张FileUtils的详解图,可以参考它的属性值
    这里写图片描述
    图中fileName是我要上传的文件名
    这里写图片描述
    使用了shiro框架,request会自动转换为ShiroHttpServletRequest,这是我们通常遇到的问题,在这个类中很好的避免了。
    会遇到的错误是:
    java.lang.ClassCastException: org.apache.shiro.web.servlet.ShiroHttpServletRequest cannot be cast to org.springframework.web.multipart.MultipartHttpServletRequest

    展开全文
    tt336798 2018-08-28 16:49:38
  • 4星
    37KB qq_30620793 2019-01-18 15:30:36

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,322
精华内容 8,928
关键字:

java导入poi包

java 订阅