- 浏览: 32223 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
wabiaozia:
wabiaozia 写道谁能分享一份附件。。。。。。。。今天又 ...
大数据量的excel文件读取——excel2007 -
wabiaozia:
谁能分享一份附件。。。。。。。。
大数据量的excel文件读取——excel2007 -
wabiaozia:
附件怎么下载不下来,谁分享一份。。。。。。。。
大数据量的excel文件读取——excel2007 -
hao00zzb:
dasfads
大数据量的excel文件读取——2003及之前版本 -
jiaoxianli:
写得好!太感谢你了,请问能遍历指定的SHEET名称的SHEET ...
大数据量的excel文件读取——excel2007
目前公司接的项目都有很多功能的数据都要依靠excel导入,因此对excel中数据的验证必不可少。
先来看一下目前存在的问题:
一:在每处导入的程序中都会包括excel读取、数据验证、错误数据的导出或错误的输出,每次都是拷贝、粘帖、修改,本来不同的地方只有验证部分,但由于格式、验证的不同,在修改过程中还要对excel的读取、错误的导出进行修改、调试,造成工作效率的降低和时间的浪费。
二:由于人员更替频繁,每个人的风格都不一样,对于错误的显示和输出都不一样,客户看到的结果是每处导入的地方返回的错误结果也不一样,有的只是提醒一句成功、失败,有的则会把错误的记录导出excel供客户下载修改。客户对此也有很多抱怨。
解决思路:
在excel导入中我们关心的(也是唯一不同的)是数据的验证、保存,对于读取、错误记录导出并不关心,那就该把这两部分分离出来,这样的好处有:1.导入时不再关心excel的读取和错误信息的导出,编码及调试时不再为这部分付出时间和精力,加快开发效率。2.降低耦合度,目前对excel的操作使用的是jxl,如果以后改为poi那只需要需改excel操作的实现即可。3.统一,所有的导入使用相同的excel操作实现,如果excel读取操作有bug则只需修改一处(写此代码的起因就是一个同事出现的一个bug引起的),而且对错误记录的输出也有统一的输出。
解决办法:
限于本人的表达能力,要想讲清楚太费时间和篇幅了,在这里就直接上代码了
首先是抽象类 ImportDataMultiSheet,包括excel读取、错误记录导出的实现,支持多sheet及合并单元格的处理
import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import org.gaosheng.util.exception.EntityException; import jxl.Cell; import jxl.CellType; import jxl.DateCell; import jxl.NumberCell; import jxl.Range; import jxl.Sheet; import jxl.Workbook; import jxl.format.Colour; import jxl.write.Label; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; /** * jxl导入excel类,继承类实现验证方法 * * @author gaosheng * */ public abstract class ImportDataMultiSheet { private int startRow = 1; private int startColumn = 0; private int minRows = 1; private int minColumns = 1; private int maxRows = -1; private int maxColumns = -1; private Map<Integer, Method> methodMap; private Map<Integer, List<String>> holdColumns; private List<String>[] titiles ; private List<MeregRange> meregRangeList ; private Cell curCell; private Cell[] curRowCells; private int successcount = 0; private String[] columnMethods = null; private int[] needHoldColumns = null; private File importExcel; private File errorExcel; private boolean hasError = false; private List<String> errors = new ArrayList<String>(); /** * 启动导入 * * @return boolean * @throws SecurityException * @throws NoSuchMethodException * @throws EntityException */ public boolean execute() throws SecurityException, NoSuchMethodException, EntityException { setMethodMap(); setHoldColumns(); Workbook work = null; try { work = Workbook.getWorkbook(importExcel); } catch (Exception e) { throw new EntityException("Excel表格读取异常!批量导入失败!<br/>"); } //数据总行数 int totalRows = 0; Sheet sheet = null; WritableWorkbook writew = null; WritableSheet writes = null; int sheet_num = work.getNumberOfSheets(); // 全局验证 if (!this.validGlobal(work.getSheets())) { throw new EntityException("导入文件格式错误"); } try { for (int sheet_index = 0; sheet_index < sheet_num ;sheet_index++) { sheet = work.getSheet(sheet_index); meregRangeList = new ArrayList<MeregRange>(); int columns = sheet.getColumns(); int rows = sheet.getRows(); totalRows += rows; for (Range range : sheet.getMergedCells()) { Cell topleft = range.getTopLeft(); Cell bottomRight = range.getBottomRight(); meregRangeList.add(new MeregRange(topleft.getRow(),topleft.getColumn(),bottomRight.getRow(),bottomRight.getColumn(),getCellValue(topleft))); } writew = Workbook.createWorkbook(errorExcel); writes = writew.createSheet("ErrorReport", 0); Label label; WritableCellFormat wcf; titiles = new List[startRow]; List<String> list = null; for (int i = 0; i < startRow; i++) { list = new ArrayList<String>(); for (int j = 0; j < columns; j++) { label = new Label(j, i, getCellValue(sheet.getCell(j, i))); writes.addCell(label); list.add(getValue(sheet.getCell(j, i))); } titiles[i] = list; } label = new Label(columns, startRow - 1, "错误详细"); WritableFont wf0 = new WritableFont(WritableFont.TIMES, 12); wcf = new WritableCellFormat(wf0); label.setCellFormat(wcf); writes.addCell(label); int wi = startRow; // ------------------------- StringBuffer info_temp = null; String result = null; Method method = null; for (int i = startRow; i < rows; i++) { curRowCells = sheet.getRow(i); if (curRowCells == null || curRowCells.length < minColumns) { continue; } boolean[] wj = new boolean[columns]; info_temp = new StringBuffer(); for (int j = startColumn; j < columns; j++) { curCell = sheet.getCell(j, i); // System.out.print(String.format("%-30.30s", this.getValue(curCell))+" "); result = everyCell(); if (result != null) { method = methodMap.get(j); if (method == null) { continue; } result = (String) method.invoke(this, null); } if (result != null) { info_temp.append(result); info_temp.append(" "); wj[j] = true; } if (holdColumns.get(j) != null) { holdColumns.get(j).add(this.getValue(curCell)); } if (info_temp.length() > 0) { errors.add("sheet "+sheet.getName()+" 中第 " + (i + 1) + " 行 :" + info_temp.toString()); } } // System.out.println(); if (info_temp.length() > 1) { for (int ii = startColumn; ii < columns; ii++) { Cell c_temp = sheet.getCell(ii, i); label = new Label(ii, wi, c_temp.getContents().trim()); wcf = new WritableCellFormat(); if (wj[ii]) wcf.setBackground(Colour.RED); label.setCellFormat(wcf); writes.addCell(label); } label = new Label(columns, wi, info_temp.toString()); WritableFont wf = new WritableFont(WritableFont.TIMES, 12); wf.setColour(Colour.RED); wcf = new WritableCellFormat(wf); label.setCellFormat(wcf); writes.addCell(label); wi++; } else { this.save(); successcount ++; } } } } catch (Exception e) { e.printStackTrace(); this.hasError = true; errors.add("sheet "+sheet.getName()+" 第"+this.curCell.getRow() +" 行 第 "+ this.curCell.getColumn()+" 列 :"+this.getCurCell().getContents()+" 遇到错误"); return false; } finally { try { writew.write(); writew.close(); work.close(); } catch (IOException e) { e.printStackTrace(); } } if (successcount < totalRows - sheet_num*startRow) { this.hasError = true; } return true; } /** * 全局验证,验证对行数和列数的要求 * * @return */ public boolean validGlobal(Sheet[] sheets) { for (int i = 0; i < sheets.length; i++) { if (minRows != -1 && sheets[i].getRows() < minRows) { return false; } else if (minColumns != -1 && sheets[i].getColumns() < minColumns) { return false; } else if (maxRows != -1 && sheets[i].getRows() > maxRows) { return false; } else if (maxColumns != -1 && sheets[i].getColumns() > maxColumns) { return false; } } return true; } /** * 一行数据验证成功后保存 * @return boolean */ public abstract boolean save(); /** * 对每一个单元格进行的操作 * @return boolean */ public abstract String everyCell(); /** * 初始化存储验证列方法的Map * * @throws SecurityException * @throws NoSuchMethodException */ @SuppressWarnings("unchecked") private void setMethodMap() throws SecurityException, NoSuchMethodException { methodMap = new HashMap<Integer, Method>(); if (columnMethods == null) { Method[] methods = this.getClass().getMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().startsWith("validColumn_")) { String column = methods[i].getName().substring( methods[i].getName().indexOf("_") + 1); try { methodMap.put(Integer.parseInt(column), methods[i]); } catch (Exception e) { throw new NumberFormatException("默认列明必须为数字"); } } } } else { Class<ImportDataMultiSheet> class1 = (Class<ImportDataMultiSheet>) this.getClass(); for (int i = 0; i < columnMethods.length; i++) { methodMap.put(i, class1.getMethod(columnMethods[i], null)); } } } /** * 初始化存储保留列的Map,保留列用于验证某些列值时需引用其他列的情况 */ private void setHoldColumns() { holdColumns = new HashMap<Integer, List<String>>(); if (needHoldColumns == null) { return; } for (int i = 0; i < needHoldColumns.length; i++) { holdColumns.put(needHoldColumns[i], new ArrayList<String>()); } } /** * 获得给定单元格的实际值,对于时间会返回 'yyyy-MM-dd HH:mm:ss' 格式的字符串 * * @param cell * @return String */ public static String getCellValue(Cell cell) { if (cell.getType().equals(CellType.NUMBER)) { return Double.toString(((NumberCell) cell).getValue()); } else if (cell.getType().equals(CellType.DATE)) { TimeZone gmt = TimeZone.getTimeZone("GMT"); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); dateFormat.setTimeZone(gmt); return dateFormat.format(((DateCell) cell).getDate()); } else if (cell.getType().equals(CellType.EMPTY)) { return null; } else { return cell.getContents().trim(); } } public String getValue(Cell cell){ String value = getCellValue(cell); if (value == null || getCellValue(cell).equals("")) { for(MeregRange meregRange:meregRangeList){ if (meregRange.isInRange(cell.getRow(), cell.getColumn())) { return meregRange.getValue(); } } return value; }else { return value; } } /** * 防止空指针 * * @param object * @return String */ public String fixNull(Object object) { return object == null ? "" : object.toString(); } public int getMinRows() { return minRows; } public void setMinRows(int minRows) { this.minRows = minRows; } public int getMinColumns() { return minColumns; } public void setMinColumns(int minColumns) { this.minColumns = minColumns; } public int getMaxRows() { return maxRows; } public void setMaxRows(int maxRows) { this.maxRows = maxRows; } public int getMaxColumns() { return maxColumns; } public void setMaxColumns(int maxColumns) { this.maxColumns = maxColumns; } public String[] getColumnMethods() { return columnMethods; } public void setColumnMethods(String[] columnMethods) { this.columnMethods = columnMethods; } public File getImportExcel() { return importExcel; } public void setImportExcel(File importExcel) { this.importExcel = importExcel; } public File getErrorExcel() { return errorExcel; } public void setErrorExcel(File errorExcel) { this.errorExcel = errorExcel; } public boolean isHasError() { return hasError; } public int[] getNeedHoldColumns() { return needHoldColumns; } public void setNeedHoldColumns(int[] needHoldColumns) { this.needHoldColumns = needHoldColumns; } public Map<Integer, List<String>> getHoldColumns() { return holdColumns; } public int getStartRow() { return startRow; } public void setStartRow(int startRow) { this.startRow = startRow; } public int getStartColumn() { return startColumn; } public void setStartColumn(int startColumn) { this.startColumn = startColumn; } public Cell getCurCell() { return curCell; } public List<String> getErrors() { return errors; } public Cell[] getCurRowCells() { return curRowCells; } public List<String>[] getTitiles() { return titiles; } public int getSuccesscount() { return successcount; } }
下面是一个实现类的范例:
import java.io.File; import java.util.List; import jxl.Cell; import org.gaosheng.util.exception.EntityException; import org.gaosheng.util.xls.ImportDataMultiSheet; public class ImportDatemultiImp extends ImportDataMultiSheet { public static void main(String[] args) throws SecurityException, NoSuchMethodException, EntityException { File importFile = new File("F:/test.xls"); File errorFile = new File("F:/error.xls"); ImportDatemultiImp importDateImp = new ImportDatemultiImp(); importDateImp.setImportExcel(importFile); importDateImp.setErrorExcel(errorFile); importDateImp.setStartRow(1); importDateImp.execute(); importDateImp.getErrorExcel(); for (String error : importDateImp.getErrors()) { System.out.println(error); } } //对每一个单元格的执行的统一操作,返回值为错误信息,没有错误则返回null public String everyCell() { Cell cell = this.getCurCell(); List<String> semList = this.getTitiles()[2]; List<String> courseList = this.getTitiles()[3]; if (cell.getRow() > 3 && cell.getColumn() > 3) { String cellvalue = this.getValue(cell); String course_name = courseList.get(cell.getColumn()); String reg_no = this.getValue(this.getCurRowCells()[1]); String stuname = this.getValue(this.getCurRowCells()[2]); if (cellvalue != null && !cellvalue.equals("") && course_name !=null && !course_name.equals("") && reg_no != null && !reg_no.equals("")) { }else { return "无效成绩"; } } return null; } //定义每一列的验证,默认方法名是validColumn_+列索引,也可以用setColumnMethods(String[] columnMethods)指定列的验证方法 返回值为错误信息,没有错误则返回null public String validColumn_1(){ if (!this.getCurCell().getContents().equals("name")) { return "姓名错误"; } return null; } public String validColumn_2(){ if (!this.getCurCell().getContents().equals("passwd")) { return "密码错误"; } return null; } public String validColumn_3(){ return null; } //验证成功后保存记录 public boolean save() { return false; } }
评论
7 楼
yylovelei
2012-03-19
gaosheng08 写道
yylovelei 写道
gaosheng08 写道
yylovelei 写道
import org.gaosheng.util.exception.EntityException;
博主能把这个包贴出来吗?
谢谢了
博主能把这个包贴出来吗?
谢谢了
这个是自定义的异常,随便实现就行
才看到你这个是jxl
对excel2007以上版本是不就不通用了??
对博主后来所写的excel2007
http://gaosheng08.iteye.com/blog/624758
是不就用不了了?
恩,是的,2007以上的一直没有写。
唉,水平有限啊,这下是判断不了了。
6 楼
gaosheng08
2012-03-18
yylovelei 写道
gaosheng08 写道
yylovelei 写道
import org.gaosheng.util.exception.EntityException;
博主能把这个包贴出来吗?
谢谢了
博主能把这个包贴出来吗?
谢谢了
这个是自定义的异常,随便实现就行
才看到你这个是jxl
对excel2007以上版本是不就不通用了??
对博主后来所写的excel2007
http://gaosheng08.iteye.com/blog/624758
是不就用不了了?
恩,是的,2007以上的一直没有写。
5 楼
yylovelei
2012-03-18
gaosheng08 写道
yylovelei 写道
import org.gaosheng.util.exception.EntityException;
博主能把这个包贴出来吗?
谢谢了
博主能把这个包贴出来吗?
谢谢了
这个是自定义的异常,随便实现就行
才看到你这个是jxl
对excel2007以上版本是不就不通用了??
对博主后来所写的excel2007
http://gaosheng08.iteye.com/blog/624758
是不就用不了了?
4 楼
gaosheng08
2012-03-18
yylovelei 写道
import org.gaosheng.util.exception.EntityException;
博主能把这个包贴出来吗?
谢谢了
博主能把这个包贴出来吗?
谢谢了
这个是自定义的异常,随便实现就行
3 楼
yylovelei
2012-03-16
import org.gaosheng.util.exception.EntityException;
博主能把这个包贴出来吗?
谢谢了
博主能把这个包贴出来吗?
谢谢了
2 楼
gaosheng08
2011-08-03
fengmengcy 写道
请问这个类是MergeRange 是什么类
忘了贴了,是合并单元格的范围类
package org.gaosheng.util.xls.valid; public class MeregRange { private int topleft_row ; private int topleft_column ; private int bottomRight_row ; private int bottomRight_column; private String value ; public MeregRange() { super(); } public MeregRange(int topleft_row, int topleft_column, int bottomRight_row,int bottomRight_column){ this(topleft_row, topleft_column, bottomRight_row, bottomRight_column, null); } public MeregRange(int topleft_row, int topleft_column, int bottomRight_row,int bottomRight_column,String value) { super(); this.topleft_row = topleft_row; this.topleft_column = topleft_column; this.bottomRight_row = bottomRight_row; this.bottomRight_column = bottomRight_column; this.value = value; } public boolean isInRange(int row,int column) { if (row >= topleft_row && column >= topleft_column && row <= bottomRight_row && column <= bottomRight_column) { return true; } return false; } public int getTopleft_row() { return topleft_row; } public void setTopleft_row(int topleft_row) { this.topleft_row = topleft_row; } public int getTopleft_column() { return topleft_column; } public void setTopleft_column(int topleft_column) { this.topleft_column = topleft_column; } public int getBottomRight_row() { return bottomRight_row; } public void setBottomRight_row(int bottomRight_row) { this.bottomRight_row = bottomRight_row; } public int getBottomRight_column() { return bottomRight_column; } public void setBottomRight_column(int bottomRight_column) { this.bottomRight_column = bottomRight_column; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
1 楼
fengmengcy
2011-08-03
请问这个类是MergeRange 是什么类
相关推荐
总结来说,结合JXL库和反射原理,我们可以实现高效且灵活的Excel导入导出功能,不仅能够方便地读写Excel文件,还能进行动态内容验证,确保数据的质量和一致性。这对于企业级应用中的数据处理和交互具有很大的价值。...
本话题主要探讨如何使用C#编程语言来验证Excel导入模板是否符合预设的标准,包括文件名、工作表名和字段名称的验证。 首先,我们需要理解验证的目标。一个标准的Excel导入模板应具有明确的命名规则,例如文件名可能...
在本项目中,我们结合了POI库和XML技术来实现Excel数据的验证与导入数据库。 首先,Apache POI提供了HSSF和XSSF两个API,分别用于处理老版本的BIFF8格式(.xls)和新版本的OOXML格式(.xlsx)。在这个案例中,我们...
本文将深入探讨如何结合EasyExcel和Validation实现高效且准确的Excel导入导出与数据校验。 EasyExcel的优势在于其简洁的API设计和对内存的高效利用。它无需预先加载整个Excel文件到内存,而是采用流式读写,降低了...
本文将详细探讨"Excel导入动态校验,自定义注解动态校验"这一主题,旨在帮助你理解和掌握如何在处理Excel数据时进行有效的验证和校验。 首先,Excel导入动态校验是指在将Excel数据导入到系统或数据库时,对数据进行...
本文将深入解析这一操作的具体步骤、注意事项以及潜在的错误处理机制,为IT专业人士提供一个全面的PB9 Excel导入指南。 ### 一、PB9与Excel交互原理 在PB9中实现Excel文件导入主要依赖于OLE (Object Linking and ...
在.NET框架中,处理Excel数据是一项常见的任务,特别是在构建企业级Web应用时,用户可能需要上传Excel文件...根据项目的具体需求选择合适的库,并确保处理好数据的读取、验证和存储,以提供高效且安全的Excel导入功能。
总的来说,C#中实现Excel导入SQLite的过程涉及文件I/O、数据库操作、异常处理和UI交互等多个方面,这些知识点对于C#开发者来说都是基础且重要的技能。通过以上介绍,你应该能够理解如何在自己的项目中实现类似的功能...
"我的导入校验项目excel导入校验"这个标题揭示了一个专注于使用Excel文件进行数据导入,并对数据进行复杂校验的项目。在这个过程中,用户或系统会将Excel表格中的数据提取出来,经过一系列验证规则的检查,然后将...
VS2012创建项目,这个是使用C#语言npoi2.1.3.0导入excel到数据库中,同时使用了xml对excel的每个单元格数据进行了非空验证。经测试,导入成功。数据库写入部分请自己完成。有问题请留言。已经在项目中运中复杂多表头...
"通过Excel导入QC"是QC提供的一种功能,允许用户批量导入需求和测试用例数据,从而提高工作效率。本文将深入探讨如何利用Excel与QC进行数据交互,以及这一过程中的关键步骤和注意事项。 首先,我们需要了解Excel在...
在前端开发中,Web Excel导入是一项常见的需求,它允许用户在网页上直接上传Excel文件,以便进行数据的读取、处理或展示。这项技术对于数据分析、报表制作等场景尤为重要。以下将详细介绍实现Web Excel导入涉及的...
1. **Excel导入原理**: Jeecg框架提供了对Excel数据导入的支持,其工作原理通常是读取Excel文件中的数据,然后按照预定义的映射规则,将这些数据存储到数据库中。这一过程涉及到了文件读取、数据解析、数据验证...
* 此代码是完成从excel导入电话号码,将正确的电话号码保存到set集合中,因为set集合对于重复的值会覆盖,所以达到了去重复的值的用例,并累计了不正确的电话号码的个数,对电话号码进行了验证有效性。所需要的 dom4...
Excel导入SQL工具是一种实用软件,主要用于将Excel表格数据高效、便捷地导入到SQL数据库中。这类工具极大地简化了数据管理过程,特别是在处理大量结构化数据时,能够避免手动输入的繁琐工作,提高工作效率。 首先,...
"Excel导入导出"这一主题涵盖了如何将数据从外部源引入Excel以及如何将Excel数据导出到其他应用程序或格式。以下是对这一主题的详细解释: 1. **Excel导入**: - **CSV文件导入**:CSV(Comma Separated Values)...
在"普元导入导出 EOS 用于Excel导入导出"的场景下,我们可以探讨以下几个关键知识点: 1. **数据导入导出**: 这是系统与用户间交互的重要方式,允许用户通过Excel这样的工具来编辑和管理数据,然后将这些更改同步到...
2. **Excel导入**:导入Excel则是将用户填写的数据读取并存入数据库。在这个过程中,数据校验至关重要,以确保输入的数据符合业务规则。配置文件可以定义校验规则,如不能为空、必须是数字、日期格式正确等。当读取...
三、Excel导入 1. 使用PHPExcel导入Excel文件,首先需要创建一个PHPExcel对象,然后加载文件并读取数据: ```php use PHPExcel_IOFactory; $filePath = 'path/to/your/file.xlsx'; $inputFileType = PHPExcel_...