需求:在实际J2EE项目中,经常遇到需要导入导出excel文件的情况;
解决方案: 利用java的annotation,自定义一个annotation ,在声明pojo的时候对需要操作字段的属性进行声明,
然后通用的处理类运行时,读取annotation 相关信息进行解析。
对于导入,读入是一个excel文件,输出一个list<pojo> ,如果你用hibernate操作的话相当方便。
对于导出,你需要组织一个List<pojo>传入,将得到一个excel。
1、页面效果如下图所示:
2、自定义的Exel的annotation如下图所示:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Excel { //导入时,对应数据库的字段 主要是用户区分每个字段,不能有annocation重名的 //导出时的列名 导出排序跟定义了annotation的字段的顺序有关 public String exportName(); //导出时在excel中每个列的宽 单位为字符,一个汉字=2个字符 //如 以列名列内容中较合适的长度 例如姓名列6 【姓名一般三个字】 性别列4【男女占1,但是列标题两个汉字】 //限制1-255 public int exportFieldWidth(); //导出时是否进行字段转换 例如 性别用int存储,导出时可能转换为男,女 //若是sign为1,则需要在pojo中加入一个方法 get字段名Convert() //例如,字段sex ,需要加入 public String getSexConvert() 返回值为string //若是sign为0,则不必管 public int exportConvertSign(); //导入数据是否需要转化 及 对已有的excel,是否需要将字段转为对应的数据 //若是sign为1,则需要在pojo中加入 void set字段名Convert(String text) public int importConvertSign(); }
3、model类如下图所示:
@Entity @Table(name = "JEECG_TUSER", schema = "") public class Tuser implements java.io.Serializable { // Fields private String cid; @Excel(exportName="真实姓名", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String realname; @Excel(exportName="所属部门", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String org; @Excel(exportName="邮箱", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String mail; @Excel(exportName="手机", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String mobile; @Excel(exportName="用户类型", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String usertype; @Excel(exportName="状态", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String status; @Excel(exportName="创建时间", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private Date ccreatedatetime; @Excel(exportName="修改时间", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private Date cmodifydatetime; @Excel(exportName="用户名", exportConvertSign = 0, exportFieldWidth = 10, importConvertSign = 0) private String cname; @Excel(exportName="密码", exportConvertSign = 0, exportFieldWidth = 30, importConvertSign = 0) private String cpwd; }
4、jsp页面如下图所示:
<head> <jsp:include page="/inc.jsp"></jsp:include> <script> function exportExcel(){ window.location.href="demoAction!exportExcel.action"; } function importExcel(){ $('#excelForm').form({ success : function(result) { try { var r = $.parseJSON(result); $.messager.show({ title : '提示', msg : r.msg }); } catch (e) { $.messager.alert('提示', result); } } }); if($('#excelForm').form('validate')){ $('#excelForm').submit(); } } </script> </head> <body> <div style="margin:10px 0;"></div> <div class="easyui-panel" title="用户信息" style="width:400px"> <div style="padding:10px 0 10px 60px"> <form id="excelForm" method="post" enctype="multipart/form-data" action="demoAction!importExcel.action"> <table> <tr> <td>文件路径</td> <td><input name="filedata" class="easyui-validatebox" required="true" type="file" missingMessage="请选择上传文件" /></td> </tr> </table> </form> </div> <div style="text-align:center;padding:5px"> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="importExcel()">导入excel</a> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="exportExcel()">导出excel</a> </div> </div> </body>
5、action处理如下图所示:
注意:
<input type="file" name="upload"> 这个name对应后台的 private File upload; 约定, <s:file/>标志不仅仅是绑定到upload,
还有uploadContentType(上传文件的MIME类型)和 uploadFileName(上传文件的文件名,该文件名不包括文件的路径)。
因此,<s:file name="xxx" />对应Action类里面的xxx、xxxContentType和xxxFileName三个属性。
/** * 跳转到excel导入导出页面 * @return * */ public String goExcelOpt(){ return "excel-opt"; } //供浏览器读取的信息 private String fileName; private InputStream inputStream; private String filedataFileName; public String getFiledataFileName() { return filedataFileName; } public void setFiledataFileName(String filedataFileName) { this.filedataFileName = filedataFileName; } public InputStream getInputStream() { return inputStream; } public void setInputStream(InputStream inputStream) { this.inputStream = inputStream; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } /** * 导出Excel * @return * */ public String exportExcel(){ fileName = "导出信息.xls"; try { fileName = new String(fileName.getBytes(), "ISO8859-1"); inputStream = demoService.exportExcel(); } catch (Exception e) { e.printStackTrace(); logger.error(ExceptionUtil.getExceptionMessage(e)); } return "export"; } /** * 导入Excel * @return * */ public void importExcel(){ Json j = new Json(); try { demoService.importExcel(filedataFileName, filedata); j.setSuccess(true); j.setMsg("文件导入成功!"); } catch (Exception e) { j.setSuccess(false); j.setMsg("文件导入失败!"); logger.error(ExceptionUtil.getExceptionMessage(e)); } writeJson(j); }
6、service如下图所示:
/** * 导出excel */ @Override public InputStream exportExcel() throws Exception{ //获取数据 String hql = "from Tuser t where 1=1 "; List<Object> values = new ArrayList<Object>(); List<Tuser> listUser = userDao.find(hql, values); File file = new File(new Date(0).getTime()+".xls"); OutputStream outputStream = new FileOutputStream(file); ExcelExportUtil.exportExcel("导出信息", Tuser.class, listUser, outputStream); InputStream is = new BufferedInputStream(new FileInputStream(file.getPath())); file.delete(); return is; } /** * 导入excel * * @param fileName 文件名称 * @param excelFile 文件 * @return */ public void importExcel(String fileName,File excelFile){ List<Tuser> listUsers = (List<Tuser>)ExcelUtil.importExcel(excelFile, Tuser.class); for(Tuser user : listUsers){ user.setCid(UUID.randomUUID().toString()); userDao.saveOrUpdate(user); } }
7、util的工具类如下图所示:
【导出工具类】
/** * * @param title Sheet名字 * @param pojoClass Excel对象Class * @param dataSet Excel对象数据List * @param out 输出流 */ public static void exportExcel(String title, Class<?> pojoClass, Collection<?> dataSet, OutputStream out) { // 使用userModel模式实现的,当excel文档出现10万级别的大数据文件可能导致OOM内存溢出 exportExcelInUserModel(title, pojoClass, dataSet, out); // 使用eventModel实现,可以一边读一边处理,效率较高,但是实现复杂,暂时未实现 } private static void exportExcelInUserModel(String title, Class<?> pojoClass, Collection<?> dataSet, OutputStream out) { try { // 首先检查数据看是否是正确的 if (dataSet == null || dataSet.size() == 0) { throw new Exception("导出数据为空!"); } if (title == null || out == null || pojoClass == null) { throw new Exception("传入参数不能为空!"); } // 声明一个工作薄 Workbook workbook = new HSSFWorkbook(); // 生成一个表格 Sheet sheet = workbook.createSheet(title); // 标题 List<String> exportFieldTitle = new ArrayList<String>(); List<Integer> exportFieldWidth = new ArrayList<Integer>(); // 拿到所有列名,以及导出的字段的get方法 List<Method> methodObj = new ArrayList<Method>(); Map<String, Method> convertMethod = new HashMap<String, Method>(); // 得到所有字段 Field fileds[] = pojoClass.getDeclaredFields(); // 遍历整个filed for (int i = 0; i < fileds.length; i++) { Field field = fileds[i]; Excel excel = field.getAnnotation(Excel.class); // 如果设置了annottion if (excel != null) { // 添加到标题 exportFieldTitle.add(excel.exportName()); // 添加标题的列宽 exportFieldWidth.add(excel.exportFieldWidth()); // 添加到需要导出的字段的方法 String fieldname = field.getName(); // System.out.println(i+"列宽"+excel.exportName()+" "+excel.exportFieldWidth()); StringBuffer getMethodName = new StringBuffer("get"); getMethodName.append(fieldname.substring(0, 1) .toUpperCase()); getMethodName.append(fieldname.substring(1)); Method getMethod = pojoClass.getMethod(getMethodName .toString(), new Class[] {}); methodObj.add(getMethod); if (excel.exportConvertSign() == 1) { StringBuffer getConvertMethodName = new StringBuffer( "get"); getConvertMethodName.append(fieldname.substring(0, 1) .toUpperCase()); getConvertMethodName.append(fieldname.substring(1)); getConvertMethodName.append("Convert"); // System.out.println("convert: "+getConvertMethodName.toString()); Method getConvertMethod = pojoClass .getMethod(getConvertMethodName.toString(), new Class[] {}); convertMethod.put(getMethodName.toString(), getConvertMethod); } } } int index = 0; // 产生表格标题行 Row row = sheet.createRow(index); for (int i = 0, exportFieldTitleSize = exportFieldTitle.size(); i < exportFieldTitleSize; i++) { Cell cell = row.createCell(i); // cell.setCellStyle(style); RichTextString text = new HSSFRichTextString(exportFieldTitle .get(i)); cell.setCellValue(text); } // 设置每行的列宽 for (int i = 0; i < exportFieldWidth.size(); i++) { // 256=65280/255 sheet.setColumnWidth(i, 256 * exportFieldWidth.get(i)); } Iterator its = dataSet.iterator(); // 循环插入剩下的集合 while (its.hasNext()) { // 从第二行开始写,第一行是标题 index++; row = sheet.createRow(index); Object t = its.next(); for (int k = 0, methodObjSize = methodObj.size(); k < methodObjSize; k++) { Cell cell = row.createCell(k); Method getMethod = methodObj.get(k); Object value = null; if (convertMethod.containsKey(getMethod.getName())) { Method cm = convertMethod.get(getMethod.getName()); value = cm.invoke(t, new Object[] {}); } else { value = getMethod.invoke(t, new Object[] {}); } cell.setCellValue(value == null ? "" : value.toString()); } } workbook.write(out); } catch (Exception e) { e.printStackTrace(); } }
【导入工具类】
注意:
//先设置Cell的类型,然后就可以把纯数字作为String类型读进来了:
cell.setCellType(Cell.CELL_TYPE_STRING);
/** * 导入 excel * @param file * @param pojoClass * @param pattern * @return */ public static Collection importExcel(File file ,Class pojoClass) { Collection dist = new ArrayList<Object>(); try { // 得到目标目标类的所有的字段列表 Field filed[] = pojoClass.getDeclaredFields(); // 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中 Map<String,Method> fieldSetMap = new HashMap<String,Method>(); Map<String,Method> fieldSetConvertMap = new HashMap<String,Method>(); // 循环读取所有字段 for (int i = 0; i < filed.length; i++) { Field f = filed[i]; // 得到单个字段上的Annotation Excel excel = f.getAnnotation(Excel.class); // 如果标识了Annotationd的话 if (excel != null) { // 构造设置了Annotation的字段的Setter方法 String fieldname = f.getName(); String setMethodName = "set" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1); // 构造调用的method, Method setMethod = pojoClass.getMethod(setMethodName, new Class[] { f.getType() }); // 将这个method以Annotaion的名字为key来存入。 //对于重名将导致 覆盖 失败,对于此处的限制需要 fieldSetMap.put(excel.exportName(), setMethod); if(excel.importConvertSign()==1) { StringBuffer setConvertMethodName = new StringBuffer("set"); setConvertMethodName.append(fieldname.substring(0, 1) .toUpperCase()); setConvertMethodName.append(fieldname.substring(1)); setConvertMethodName.append("Convert"); Method getConvertMethod = pojoClass.getMethod(setConvertMethodName.toString(), new Class[] {String.class}); fieldSetConvertMap.put(excel.exportName(), getConvertMethod); } } } // 将传入的File构造为FileInputStream; FileInputStream in = new FileInputStream(file); // // 得到工作表 HSSFWorkbook book = new HSSFWorkbook(in); // // 得到第一页 HSSFSheet sheet = book.getSheetAt(0); // // 得到第一面的所有行 Iterator<Row> row = sheet.rowIterator(); // 得到第一行,也就是标题行 Row title = row.next(); // 得到第一行的所有列 Iterator<Cell> cellTitle = title.cellIterator(); // 将标题的文字内容放入到一个map中。 Map titlemap = new HashMap(); // 从标题第一列开始 int i = 0; // 循环标题所有的列 while (cellTitle.hasNext()) { Cell cell = cellTitle.next(); String value = cell.getStringCellValue(); titlemap.put(i, value); i = i + 1; } //用来格式化日期的DateFormat SimpleDateFormat sf; while (row.hasNext()) { // 标题下的第一行 Row rown = row.next(); // 行的所有列 Iterator<Cell> cellbody = rown.cellIterator(); // 得到传入类的实例 Object tObject = pojoClass.newInstance(); int k = 0; // 遍历一行的列 while (cellbody.hasNext()) { Cell cell = cellbody.next(); // 这里得到此列的对应的标题 String titleString = (String) titlemap.get(k); // 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值 if (fieldSetMap.containsKey(titleString)) { Method setMethod = (Method) fieldSetMap.get(titleString); //得到setter方法的参数 Type[] ts = setMethod.getGenericParameterTypes(); //只要一个参数 String xclass = ts[0].toString(); //判断参数类型 if (fieldSetConvertMap.containsKey(titleString)) { fieldSetConvertMap.get(titleString).invoke(tObject, cell.getStringCellValue()); } else { if (xclass.equals("class java.lang.String")) { //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了: cell.setCellType(Cell.CELL_TYPE_STRING); setMethod.invoke(tObject, cell .getStringCellValue()); } else if (xclass.equals("class java.util.Date")) { try{ setMethod.invoke(tObject, cell .getDateCellValue()); }catch(Exception e){ } } else if (xclass.equals("class java.lang.Boolean")) { setMethod.invoke(tObject, cell .getBooleanCellValue()); } else if (xclass.equals("class java.lang.Integer")) { setMethod.invoke(tObject, new Integer(cell .getStringCellValue())); }else if(xclass. equals("class java.lang.Long")) { setMethod.invoke(tObject,new Long( cell.getStringCellValue())); } } } // 下一列 k = k + 1; } dist.add(tObject); } } catch (Exception e) { e.printStackTrace(); return null; } return dist; }
相关推荐
通用数据库导入导出excel.pdf
Jeecg提供了相应的API或服务,开发者可以通过这些接口指定模板文件的位置,并指定导出的数据源,如数据库查询结果或内存中的数据对象。 在实际应用中,导出过程会根据数据填充模板。Jeecg会遍历数据源,将每一条...
- 数据校验:在将Excel数据导入数据库前,进行数据格式和完整性检查。 - 错误处理:捕获并处理可能出现的异常,如文件读取错误、数据库连接失败等。 - 性能优化:大量数据导入时,可以使用批处理操作,减少与数据库...
描述中提到的“程序可以完成从 数据库 生成 Excel 或者从Excel导入数据库”,这涉及到两个主要操作:导出和导入。导出是从数据库中提取数据并将其格式化为Excel文件,而导入则是反过来,将Excel文件的数据加载到...
标题中的“一个通用从数据库导出excel、excel导入数据库组件所用到的jar包”指的是一个Java开发的工具,主要用于数据的导入导出操作。这个工具可以方便地将数据库中的数据导出为Excel格式,同时也可以将Excel文件中...
本工具是一款基于Java编写的桌面应用程序,专为Oracle数据库的导入导出提供便利。 1. **Oracle数据库导入导出的重要性** - 数据迁移:当需要将数据从一个Oracle实例迁移到另一个实例时,导入导出工具是关键。 - ...
SQL Server 数据库导入导出的方法 SQL Server 数据库导入导出是数据库管理员和开发者常用的操作,目的是将数据库备份到本地或网络存储设备中,以便在需要时恢复数据库或将数据库迁移到其他服务器上。下面将详细介绍...
MYSQL 数据库导入导出命令 MySQL 数据库导入导出命令是数据库管理员和开发者经常使用的命令,用于将 MySQL 数据库导出到文件中,以便备份、还原或迁移到其他服务器。下面将详细介绍 MySQL 数据库导入导出的命令和...
总结来说,“数据库结构导出Excel”是一项实用的技巧,它能够帮助我们更方便地管理和交流数据库的信息。通过选择合适的工具和方法,我们可以将复杂的数据库结构转化为直观易懂的Excel文件,从而提高工作效率和协作...
DB2 数据库导入导出 DB2 数据库导入导出的操作方法是指将用户的 DB2 数据库导出并导入到自己的 DB2 数据库上。由于 DB2 没有直接的数据库导出功能,因此需要导出表结构、表数据,然后在导入。 一、导出表结构 在 ...
然而,在实际应用中,我们经常需要将数据库中的数据导出到Excel文件中进行查看或者编辑,反之亦然。本文将详细介绍如何在Linux环境下通过命令行操作SQLite数据库,实现数据的导入导出功能。 #### 二、准备工作 在...
总的来说,熟练掌握数据库和Excel之间的导入导出技巧,对于数据工作者来说是至关重要的技能。这不仅可以提高工作效率,还能在各种数据处理和分析场景中发挥关键作用。通过不断学习和实践,我们可以更好地应对日益...
标题中的“通用从数据库导出excel、excel导入数据库组件”是指一种软件工具或技术,它允许用户方便地将数据从数据库导出到Excel电子表格格式,并能将Excel数据反向导入回数据库。这样的组件通常在数据迁移、数据分析...
以往的易程序导出excel太慢了,特别是数据比较多的时候,本程序写excel模板的方法极速导入导出excel或者数据库,1万条数据不用一秒钟的时间,速度杠杠的,大家可以试试效果。本例子是用超级列表框做例子,如有需要...
在本项目中,"spring boot+mybatis plus+easy poi实现数据库导出成excel和excel导入到数据库",开发者利用了Spring Boot、MyBatis Plus和EasyPoi库来实现了一个功能强大的数据交互系统,允许用户将数据库中的数据...
### 不同类型数据库导入导出详解 在信息技术领域中,数据迁移是一项常见且重要的任务,尤其是在不同的数据库系统间进行数据转换时。本文将基于提供的部分代码样例,深入探讨Access、Visual FoxPro(VFP)、SQL等...
利用NPOI组件,将数据库中表,或查询结果导出Excel以及将Excel中数据导入到数据库中
功能:DataPie可以把EXCEL2007的数据导入SQL server2008或者ACCESS 2007数据库中,也可以把数据库中的表导出到excel2007,同时可以通过该工具运算数据库中的存储过程。 更新 V1.0,2012年2月3日 支持sql server导入...
数据库导入导出是数据库管理中的重要环节,尤其在数据迁移、备份、恢复和系统整合时显得尤为关键。这里我们主要讨论的是针对ORACLE数据库的导入导出工具,它能够帮助用户方便地处理大量数据的传输。 Oracle数据库...