相信很多程序猿朋友碰到上传、读取Excel文件的问题,做个小结,权当是笔记收着吧。

之前做金融报表,是把Excel内嵌到页面中的,技术上采用ZK结合POI读取和插入Excel数据,后台方法比较死,比较程式化。

目前新需求是把Excel表格上传到服务器,读取到里边的数据做处理。

一、首先上传Excel

1、页面添加文件域

Java代码 
  1. <form id="uploadExcel" action="/auth/user/toHandleBatchRobotExcel.do"
  2. enctype="multipart/form- data" method="POST" >
  3. <input type="file" id="excel" name="excelFile"/>
  4. <input type="button" id="uploadExcel" />
  5. </form>

2、使用ajax提交表单(需导入jquery.form.js)

Java代码 
  1. var excel=$("#excel").val();
  2. var location=$('#excel').val();
  3. var point = location.lastIndexOf(".");
  4. var type = location.substr(point);
  5. //type是Excel表格的格式.xls\.xlsx
  6. $("#uploadExcel").ajaxSubmit({
  7. data:{ext:type},
  8. success:function(data){
  9. var dataJson = eval("("+data+")");
  10. console.log(data);
  11. if(dataJson.code==100){
  12. alert(dataJson.message);
  13. }else{
  14. alert("成功上传"+dataJson.attribute.robotNum+"条记录");
  15. }
  16. }
  17. });

二、后台读取

我尝试了两种方式来读取,jxl和poi。

1、jxl读取

jxl操作也是比较方便的,上代码吧。

Jar包:jxl-2.6.jar

读取Excel:

Java代码 
  1. @RequestMapping(value = UrlMappings.HANDLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
  2. @ResponseBody
  3. public void handleExcel(HttpServletResponse response,
  4. MultipartHttpServletRequest request, String ext) {
  5. logger.info("处理Excel表格");
  6. logger.info("开始解析...");
  7. logger.info(ext);
  8. MultipartFile fileFile = request.getFile("excelFile");
  9. InputStream in = fileFile.getInputStream();
  10. //获取Excel文件对象
  11. Workbook wb = Workbook.getWorkbook(in);
  12. //获取文件的指定工作表默认的第一个
  13. Sheet sheet = wb.getSheet(0);
  14. // 单元格
  15. Cell cell;
  16. //获取行数
  17. Int rows = sheet.getRows();
  18. Map<Integer, String> map = new HashMap<Integer, String>();
  19. List<UserInfoVo> list = new LinkedList<UserInfoVo>();
  20. if (rows.size() > 0 && rows!= null) {
  21. for (int i = 1; i < rows.size(); i++) {
  22. for (int j = 0; j < sheet.getColumns(); j++) {
  23. cell =sheet.getCell(j,i);
  24. map.put(j,cell.getContents());
  25. }
  26. //Excel数据对应的实体类,根据情况自己设定
  27. UserInfoVo userInfoVo = new UserInfoVo();
  28. userInfoVo.setNickName(map.get(1));
  29. userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
  30. userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
  31. userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
  32. .getTime());
  33. userInfoVo.setState(1);
  34. list.add(userInfoVo);
  35. }
  36. }
  37. }

这样读取到的list中就包括了excel表中的各行数据。

但是在使用过程中发现,有些用户上传2007版的Excel表格,这样的话就会出现读取错误的情况

jxl.read.biff.BiffException: Unable to recognize OLE stream,这是因为jxl久未更新,没法读取新版本的         Excel,就是.xlsx格式的文件。

于是,换种思路,使用兼容性更好的poi进行读取。

2、poi读取

poi是读取Excel最佳工具,功能丰富,对读取不同版本的excel都做了对应处理。

jar包:

poi-3.11.jar  针对03版excel,即后缀为.xls的文件。

poi-ooxml-3.11.jar  针对07版excel,即后缀为.xlsx的文件。

读取Excel:

Java代码 
  1. @RequestMapping(value = UrlMappings.HANDLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
  2. @ResponseBody
  3. public void handleExcel(HttpServletResponse response,
  4. MultipartHttpServletRequest request, String ext) {
  5. logger.info("处理Excel表格");
  6. logger.info("开始解析...");
  7. //excel格式 .xls\.xlsx
  8. logger.info(ext);
  9. // 得到上传的文件
  10. MultipartFile fileFile = request.getFile("excelFile");
  11. try {
  12. // 转换成输入流
  13. InputStream in = fileFile.getInputStream();
  14. // 单元格
  15. Cell cell;
  16. List<Row> rsRows = new ExcelUtils().readExcel(ext, in);
  17. // 实例化对象
  18. SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
  19. Map<Integer, String> map = new HashMap<Integer, String>();
  20. List<UserInfoVo> list = new LinkedList<UserInfoVo>();
  21. if (rsRows.size() > 0 && rsRows != null) {
  22. for (int i = 1; i < rsRows.size(); i++) {
  23. for (int j = 0; j < rsRows.get(i).getLastCellNum(); j++) {
  24. cell = rsRows.get(i).getCell(j);
  25. map.put(j, new ExcelUtils().getCellValue(cell));
  26. }
  27. UserInfoVo userInfoVo = new UserInfoVo();
  28. userInfoVo.setNickName(map.get(1));
  29. userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
  30. userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
  31. userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
  32. .getTime());
  33. userInfoVo.setState(1);
  34. list.add(userInfoVo);
  35. }
  36. }
  37. }

List中即是excel表中的数据。这其中要用到一个工具类ExcelUtils。

Java代码 
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.text.SimpleDateFormat;
  7. import java.util.ArrayList;
  8. import java.util.Date;
  9. import java.util.List;
  10. import org.apache.poi.hssf.usermodel.HSSFDateUtil;
  11. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  12. import org.apache.poi.ss.usermodel.Cell;
  13. import org.apache.poi.ss.usermodel.CellStyle;
  14. import org.apache.poi.ss.usermodel.Row;
  15. import org.apache.poi.ss.usermodel.Sheet;
  16. import org.apache.poi.ss.usermodel.Workbook;
  17. import org.apache.poi.ss.util.CellRangeAddress;
  18. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  19. public class ExcelUtils {
  20. // %%%%%%%%-------常量部分 开始----------%%%%%%%%%
  21. /**
  22. * 默认的开始读取的行位置为第一行(索引值为0)
  23. */
  24. private final static int READ_START_POS = 0;
  25. /**
  26. * 默认结束读取的行位置为最后一行(索引值=0,用负数来表示倒数第n行)
  27. */
  28. private final static int READ_END_POS = 0;
  29. /**
  30. * 默认Excel内容的开始比较列位置为第一列(索引值为0)
  31. */
  32. private final static int COMPARE_POS = 0;
  33. /**
  34. * 默认多文件合并的时需要做内容比较(相同的内容不重复出现)
  35. */
  36. private final static boolean NEED_COMPARE = true;
  37. /**
  38. * 默认多文件合并的新文件遇到名称重复时,进行覆盖
  39. */
  40. private final static boolean NEED_OVERWRITE = true;
  41. /**
  42. * 默认只操作一个sheet
  43. */
  44. private final static boolean ONLY_ONE_SHEET = true;
  45. /**
  46. * 默认读取第一个sheet中(只有当ONLY_ONE_SHEET = true时有效)
  47. */
  48. private final static int SELECTED_SHEET = 0;
  49. /**
  50. * 默认从第一个sheet开始读取(索引值为0)
  51. */
  52. private final static int READ_START_SHEET = 0;
  53. /**
  54. * 默认在最后一个sheet结束读取(索引值=0,用负数来表示倒数第n行)
  55. */
  56. private final static int READ_END_SHEET = 0;
  57. /**
  58. * 默认打印各种信息
  59. */
  60. private final static boolean PRINT_MSG = true;
  61. // %%%%%%%%-------常量部分 结束----------%%%%%%%%%
  62. // %%%%%%%%-------字段部分 开始----------%%%%%%%%%
  63. /**
  64. * Excel文件路径
  65. */
  66. private String excelPath = "data.xlsx";
  67. /**
  68. * 设定开始读取的位置,默认为0
  69. */
  70. private int startReadPos = READ_START_POS;
  71. /**
  72. * 设定结束读取的位置,默认为0,用负数来表示倒数第n行
  73. */
  74. private int endReadPos = READ_END_POS;
  75. /**
  76. * 设定开始比较的列位置,默认为0
  77. */
  78. private int comparePos = COMPARE_POS;
  79. /**
  80. * 设定汇总的文件是否需要替换,默认为true
  81. */
  82. private boolean isOverWrite = NEED_OVERWRITE;
  83. /**
  84. * 设定是否需要比较,默认为true(仅当不覆写目标内容是有效,即isOverWrite=false时有效)
  85. */
  86. private boolean isNeedCompare = NEED_COMPARE;
  87. /**
  88. * 设定是否只操作第一个sheet
  89. */
  90. private boolean onlyReadOneSheet = ONLY_ONE_SHEET;
  91. /**
  92. * 设定操作的sheet在索引值
  93. */
  94. private int selectedSheetIdx = SELECTED_SHEET;
  95. /**
  96. * 设定操作的sheet的名称
  97. */
  98. private String selectedSheetName = "";
  99. /**
  100. * 设定开始读取的sheet,默认为0
  101. */
  102. private int startSheetIdx = READ_START_SHEET;
  103. /**
  104. * 设定结束读取的sheet,默认为0,用负数来表示倒数第n行
  105. */
  106. private int endSheetIdx = READ_END_SHEET;
  107. /**
  108. * 设定是否打印消息
  109. */
  110. private boolean printMsg = PRINT_MSG;
  111. // %%%%%%%%-------字段部分 结束----------%%%%%%%%%
  112. public ExcelUtils() {
  113. }
  114. public ExcelUtils(String excelPath) {
  115. this.excelPath = excelPath;
  116. }
  117. /**
  118. * 还原设定(其实是重新new一个新的对象并返回)
  119. *
  120. * @return
  121. */
  122. public ExcelUtils RestoreSettings() {
  123. ExcelUtils instance = new ExcelUtils(this.excelPath);
  124. return instance;
  125. }
  126. /**
  127. * 自动根据文件扩展名,调用对应的读取方法
  128. *
  129. * @Title: writeExcel
  130. * @Date : 2014-9-11 下午01:50:38
  131. * @throws IOException
  132. */
  133. public List<Row> readExcel() throws IOException {
  134. return readExcel(this.excelPath);
  135. }
  136. /**
  137. * 自动根据文件扩展名,调用对应的读取方法
  138. *
  139. * @Title: writeExcel
  140. * @Date : 2014-9-11 下午01:50:38
  141. * @param xlsPath
  142. * @throws IOException
  143. */
  144. public List<Row> readExcel(String xlsPath) throws IOException {
  145. // 扩展名为空时,
  146. if (xlsPath.equals("")) {
  147. throw new IOException("文件路径不能为空!");
  148. } else {
  149. File file = new File(xlsPath);
  150. if (!file.exists()) {
  151. throw new IOException("文件不存在!");
  152. }
  153. }
  154. // 获取扩展名
  155. String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
  156. try {
  157. if ("xls".equals(ext)) { // 使用xls方式读取
  158. return readExcel_xls(xlsPath);
  159. } else if ("xlsx".equals(ext)) { // 使用xlsx方式读取
  160. return readExcel_xlsx(xlsPath);
  161. } else { // 依次尝试xls、xlsx方式读取
  162. out("您要操作的文件没有扩展名,正在尝试以xls方式读取...");
  163. try {
  164. return readExcel_xls(xlsPath);
  165. } catch (IOException e1) {
  166. out("尝试以xls方式读取,结果失败!,正在尝试以xlsx方式读取...");
  167. try {
  168. return readExcel_xlsx(xlsPath);
  169. } catch (IOException e2) {
  170. out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
  171. throw e2;
  172. }
  173. }
  174. }
  175. } catch (IOException e) {
  176. throw e;
  177. }
  178. }
  179. /**
  180. * 通过判断文件的扩展名,以不同的方式读取文件
  181. *
  182. * @author wufei 2016年9月19日 上午10:41:27
  183. * @Method: readExcel
  184. * @Description: TODO
  185. * @param @param ext
  186. * @param @param in
  187. * @param @return
  188. * @param @throws IOException
  189. * @return List<Row>
  190. * @throws
  191. */
  192. public List<Row> readExcel(String ext, InputStream in) {
  193. try {
  194. if (".xls".equals(ext)) { // 使用xls方式读取
  195. return readExcel_xlsAsStream(in);
  196. } else if (".xlsx".equals(ext)) { // 使用xlsx方式读取
  197. return readExcel_xlsxAsStream(in);
  198. } else { // 依次尝试xls、xlsx方式读取
  199. out("您要操作的文件没有扩展名,正在尝试以xlsx方式读取...");
  200. try {
  201. return readExcel_xlsxAsStream(in);
  202. } catch (Exception e1) {
  203. out("尝试以xlsx方式读取,结果失败!,正在尝试以xls方式读取...");
  204. try {
  205. return readExcel_xlsAsStream(in);
  206. } catch (IOException e2) {
  207. out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
  208. throw e2;
  209. }
  210. }
  211. }
  212. } catch (IOException e) {
  213. out(e.getMessage());
  214. return null;
  215. }
  216. }
  217. /**
  218. * 自动根据文件扩展名,调用对应的写入方法
  219. *
  220. * @Title: writeExcel
  221. * @Date : 2014-9-11 下午01:50:38
  222. * @param rowList
  223. * @throws IOException
  224. */
  225. public void writeExcel(List<Row> rowList) throws IOException {
  226. writeExcel(rowList, excelPath);
  227. }
  228. /**
  229. * 自动根据文件扩展名,调用对应的写入方法
  230. *
  231. * @Title: writeExcel
  232. * @Date : 2014-9-11 下午01:50:38
  233. * @param rowList
  234. * @param xlsPath
  235. * @throws IOException
  236. */
  237. public void writeExcel(List<Row> rowList, String xlsPath)
  238. throws IOException {
  239. // 扩展名为空时,
  240. if (xlsPath.equals("")) {
  241. throw new IOException("文件路径不能为空!");
  242. }
  243. // 获取扩展名
  244. String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
  245. try {
  246. if ("xls".equals(ext)) { // 使用xls方式写入
  247. writeExcel_xls(rowList, xlsPath);
  248. } else if ("xlsx".equals(ext)) { // 使用xlsx方式写入
  249. writeExcel_xlsx(rowList, xlsPath);
  250. } else { // 依次尝试xls、xlsx方式写入
  251. out("您要操作的文件没有扩展名,正在尝试以xls方式写入...");
  252. try {
  253. writeExcel_xls(rowList, xlsPath);
  254. } catch (IOException e1) {
  255. out("尝试以xls方式写入,结果失败!,正在尝试以xlsx方式读取...");
  256. try {
  257. writeExcel_xlsx(rowList, xlsPath);
  258. } catch (IOException e2) {
  259. out("尝试以xls方式写入,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
  260. throw e2;
  261. }
  262. }
  263. }
  264. } catch (IOException e) {
  265. throw e;
  266. }
  267. }
  268. /**
  269. * 修改Excel(97-03版,xls格式)
  270. *
  271. * @Title: writeExcel_xls
  272. * @Date : 2014-9-11 下午01:50:38
  273. * @param rowList
  274. * @param dist_xlsPath
  275. * @throws IOException
  276. */
  277. public void writeExcel_xls(List<Row> rowList, String dist_xlsPath)
  278. throws IOException {
  279. writeExcel_xls(rowList, excelPath, dist_xlsPath);
  280. }
  281. /**
  282. * 修改Excel(97-03版,xls格式)
  283. *
  284. * @Title: writeExcel_xls
  285. * @Date : 2014-9-11 下午01:50:38
  286. * @param rowList
  287. * @param src_xlsPath
  288. * @param dist_xlsPath
  289. * @throws IOException
  290. */
  291. public void writeExcel_xls(List<Row> rowList, String src_xlsPath,
  292. String dist_xlsPath) throws IOException {
  293. // 判断文件路径是否为空
  294. if (dist_xlsPath == null || dist_xlsPath.equals("")) {
  295. out("文件路径不能为空");
  296. throw new IOException("文件路径不能为空");
  297. }
  298. // 判断文件路径是否为空
  299. if (src_xlsPath == null || src_xlsPath.equals("")) {
  300. out("文件路径不能为空");
  301. throw new IOException("文件路径不能为空");
  302. }
  303. // 判断列表是否有数据,如果没有数据,则返回
  304. if (rowList == null || rowList.size() == 0) {
  305. out("文档为空");
  306. return;
  307. }
  308. try {
  309. HSSFWorkbook wb = null;
  310. // 判断文件是否存在
  311. File file = new File(dist_xlsPath);
  312. if (file.exists()) {
  313. // 如果复写,则删除后
  314. if (isOverWrite) {
  315. file.delete();
  316. // 如果文件不存在,则创建一个新的Excel
  317. // wb = new HSSFWorkbook();
  318. // wb.createSheet("Sheet1");
  319. wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
  320. } else {
  321. // 如果文件存在,则读取Excel
  322. wb = new HSSFWorkbook(new FileInputStream(file));
  323. }
  324. } else {
  325. // 如果文件不存在,则创建一个新的Excel
  326. // wb = new HSSFWorkbook();
  327. // wb.createSheet("Sheet1");
  328. wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
  329. }
  330. // 将rowlist的内容写到Excel中
  331. writeExcel(wb, rowList, dist_xlsPath);
  332. } catch (IOException e) {
  333. e.printStackTrace();
  334. }
  335. }
  336. /**
  337. * 修改Excel(97-03版,xls格式)
  338. *
  339. * @Title: writeExcel_xls
  340. * @Date : 2014-9-11 下午01:50:38
  341. * @param rowList
  342. * @param dist_xlsPath
  343. * @throws IOException
  344. */
  345. public void writeExcel_xlsx(List<Row> rowList, String dist_xlsPath)
  346. throws IOException {
  347. writeExcel_xls(rowList, excelPath, dist_xlsPath);
  348. }
  349. /**
  350. * 修改Excel(2007版,xlsx格式)
  351. *
  352. * @Title: writeExcel_xlsx
  353. * @Date : 2014-9-11 下午01:50:38
  354. * @param rowList
  355. * @throws IOException
  356. */
  357. public void writeExcel_xlsx(List<Row> rowList, String src_xlsPath,
  358. String dist_xlsPath) throws IOException {
  359. // 判断文件路径是否为空
  360. if (dist_xlsPath == null || dist_xlsPath.equals("")) {
  361. out("文件路径不能为空");
  362. throw new IOException("文件路径不能为空");
  363. }
  364. // 判断文件路径是否为空
  365. if (src_xlsPath == null || src_xlsPath.equals("")) {
  366. out("文件路径不能为空");
  367. throw new IOException("文件路径不能为空");
  368. }
  369. // 判断列表是否有数据,如果没有数据,则返回
  370. if (rowList == null || rowList.size() == 0) {
  371. out("文档为空");
  372. return;
  373. }
  374. try {
  375. // 读取文档
  376. HSSFWorkbook wb = null;
  377. // 判断文件是否存在
  378. File file = new File(dist_xlsPath);
  379. if (file.exists()) {
  380. // 如果复写,则删除后
  381. if (isOverWrite) {
  382. file.delete();
  383. // 如果文件不存在,则创建一个新的Excel
  384. // wb = new XSSFWorkbook();
  385. // wb.createSheet("Sheet1");
  386. wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
  387. } else {
  388. // 如果文件存在,则读取Excel
  389. wb = new HSSFWorkbook(new FileInputStream(file));
  390. }
  391. } else {
  392. // 如果文件不存在,则创建一个新的Excel
  393. // wb = new XSSFWorkbook();
  394. // wb.createSheet("Sheet1");
  395. wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
  396. }
  397. // 将rowlist的内容添加到Excel中
  398. writeExcel(wb, rowList, dist_xlsPath);
  399. } catch (IOException e) {
  400. e.printStackTrace();
  401. }
  402. }
  403. /**
  404. * //读取Excel 2007版,xlsx格式
  405. *
  406. * @Title: readExcel_xlsx
  407. * @Date : 2014-9-11 上午11:43:11
  408. * @return
  409. * @throws IOException
  410. */
  411. public List<Row> readExcel_xlsx() throws IOException {
  412. return readExcel_xlsx(excelPath);
  413. }
  414. /**
  415. * //读取Excel 2007版,xlsx格式
  416. *
  417. * @Title: readExcel_xlsx
  418. * @Date : 2014-9-11 上午11:43:11
  419. * @return
  420. * @throws Exception
  421. */
  422. public List<Row> readExcel_xlsx(String xlsPath) throws IOException {
  423. // 判断文件是否存在
  424. File file = new File(xlsPath);
  425. if (!file.exists()) {
  426. throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
  427. }
  428. XSSFWorkbook wb = null;
  429. List<Row> rowList = new ArrayList<Row>();
  430. try {
  431. FileInputStream fis = new FileInputStream(file);
  432. // 去读Excel
  433. wb = new XSSFWorkbook(fis);
  434. // 读取Excel 2007版,xlsx格式
  435. rowList = readExcel(wb);
  436. } catch (IOException e) {
  437. e.printStackTrace();
  438. }
  439. return rowList;
  440. }
  441. /**
  442. * 以流的形式读取excel文件 2007版xlsx
  443. *
  444. * @author wufei 2016年9月19日 上午10:35:40
  445. * @Method: readExcel_xlsxAsStream
  446. * @Description: TODO
  447. * @param @param in
  448. * @param @return
  449. * @param @throws IOException
  450. * @return List<Row>
  451. * @throws
  452. */
  453. public List<Row> readExcel_xlsxAsStream(InputStream in) throws IOException {
  454. XSSFWorkbook wb = null;
  455. List<Row> rowList = new ArrayList<Row>();
  456. try {
  457. // 去读Excel
  458. wb = new XSSFWorkbook(in);
  459. // 读取Excel 2007版,xlsx格式
  460. rowList = readExcel(wb);
  461. } catch (IOException e) {
  462. e.printStackTrace();
  463. }
  464. return rowList;
  465. }
  466. /***
  467. * 读取Excel(97-03版,xls格式)
  468. *
  469. * @throws IOException
  470. *
  471. * @Title: readExcel
  472. * @Date : 2014-9-11 上午09:53:21
  473. */
  474. public List<Row> readExcel_xls() throws IOException {
  475. return readExcel_xls(excelPath);
  476. }
  477. /***
  478. * 读取Excel(97-03版,xls格式)
  479. *
  480. * @throws Exception
  481. *
  482. * @Title: readExcel
  483. * @Date : 2014-9-11 上午09:53:21
  484. */
  485. public List<Row> readExcel_xls(String xlsPath) throws IOException {
  486. // 判断文件是否存在
  487. File file = new File(xlsPath);
  488. if (!file.exists()) {
  489. throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
  490. }
  491. HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
  492. List<Row> rowList = new ArrayList<Row>();
  493. try {
  494. // 读取Excel
  495. wb = new HSSFWorkbook(new FileInputStream(file));
  496. // 读取Excel 97-03版,xls格式
  497. rowList = readExcel(wb);
  498. } catch (IOException e) {
  499. e.printStackTrace();
  500. }
  501. return rowList;
  502. }
  503. /**
  504. * 以流的形式读取97-03版excel文件
  505. *
  506. * @author wufei 2016年9月19日 上午10:33:25
  507. * @Method: readExcel_xlsAsStream
  508. * @Description: TODO
  509. * @param @param in
  510. * @param @return
  511. * @param @throws IOException
  512. * @return List<Row>
  513. * @throws
  514. */
  515. public List<Row> readExcel_xlsAsStream(InputStream in) throws IOException {
  516. HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
  517. List<Row> rowList = new ArrayList<Row>();
  518. try {
  519. // 读取Excel
  520. wb = new HSSFWorkbook(in);
  521. // 读取Excel 97-03版,xls格式
  522. rowList = readExcel(wb);
  523. } catch (IOException e) {
  524. e.printStackTrace();
  525. }
  526. return rowList;
  527. }
  528. /***
  529. * 读取单元格的值
  530. *
  531. * @Title: getCellValue
  532. * @Date : 2014-9-11 上午10:52:07
  533. * @param cell
  534. * @return
  535. */
  536. public String getCellValue(Cell cell) {
  537. Object result = "";
  538. if (cell != null) {
  539. switch (cell.getCellType()) {
  540. case Cell.CELL_TYPE_STRING:
  541. result = cell.getStringCellValue();
  542. break;
  543. case Cell.CELL_TYPE_NUMERIC:
  544. // 判断是否为日期
  545. if (HSSFDateUtil.isCellDateFormatted(cell)) {
  546. SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
  547. Date date = HSSFDateUtil.getJavaDate(cell
  548. .getNumericCellValue());
  549. result = df.format(date);
  550. } else {
  551. result = cell.getNumericCellValue();
  552. }
  553. break;
  554. case Cell.CELL_TYPE_BOOLEAN:
  555. result = cell.getBooleanCellValue();
  556. break;
  557. case Cell.CELL_TYPE_FORMULA:
  558. result = cell.getCellFormula();
  559. break;
  560. case Cell.CELL_TYPE_ERROR:
  561. result = cell.getErrorCellValue();
  562. break;
  563. case Cell.CELL_TYPE_BLANK:
  564. break;
  565. default:
  566. break;
  567. }
  568. }
  569. return result.toString();
  570. }
  571. /**
  572. * 通用读取Excel
  573. *
  574. * @Title: readExcel
  575. * @Date : 2014-9-11 上午11:26:53
  576. * @param wb
  577. * @return
  578. */
  579. private List<Row> readExcel(Workbook wb) {
  580. List<Row> rowList = new ArrayList<Row>();
  581. int sheetCount = 1;// 需要操作的sheet数量
  582. Sheet sheet = null;
  583. if (onlyReadOneSheet) { // 只操作一个sheet
  584. // 获取设定操作的sheet(如果设定了名称,按名称查,否则按索引值查)
  585. sheet = selectedSheetName.equals("") ? wb
  586. .getSheetAt(selectedSheetIdx) : wb
  587. .getSheet(selectedSheetName);
  588. } else { // 操作多个sheet
  589. sheetCount = wb.getNumberOfSheets();// 获取可以操作的总数量
  590. }
  591. // 获取sheet数目
  592. for (int t = startSheetIdx; t < sheetCount + endSheetIdx; t++) {
  593. // 获取设定操作的sheet
  594. if (!onlyReadOneSheet) {
  595. sheet = wb.getSheetAt(t);
  596. }
  597. // 获取最后行号
  598. int lastRowNum = sheet.getLastRowNum();
  599. if (lastRowNum > 0) { // 如果>0,表示有数据
  600. out("\n开始读取名为【" + sheet.getSheetName() + "】的内容:");
  601. }
  602. Row row = null;
  603. // 循环读取
  604. for (int i = startReadPos; i <= lastRowNum + endReadPos; i++) {
  605. row = sheet.getRow(i);
  606. if (row != null) {
  607. rowList.add(row);
  608. out("第" + (i + 1) + "行:", false);
  609. // 获取每一单元格的值
  610. for (int j = 0; j < row.getLastCellNum(); j++) {
  611. String value = getCellValue(row.getCell(j));
  612. if (!value.equals("")) {
  613. out(value + " | ", false);
  614. }
  615. }
  616. out("");
  617. }
  618. }
  619. }
  620. return rowList;
  621. }
  622. /**
  623. * 修改Excel,并另存为
  624. *
  625. * @Title: WriteExcel
  626. * @Date : 2014-9-11 下午01:33:59
  627. * @param wb
  628. * @param rowList
  629. * @param xlsPath
  630. */
  631. private void writeExcel(Workbook wb, List<Row> rowList, String xlsPath) {
  632. if (wb == null) {
  633. out("操作文档不能为空!");
  634. return;
  635. }
  636. Sheet sheet = wb.getSheetAt(0);// 修改第一个sheet中的值
  637. // 如果每次重写,那么则从开始读取的位置写,否则果获取源文件最新的行。
  638. int lastRowNum = isOverWrite ? startReadPos : sheet.getLastRowNum() + 1;
  639. int t = 0;// 记录最新添加的行数
  640. out("要添加的数据总条数为:" + rowList.size());
  641. for (Row row : rowList) {
  642. if (row == null)
  643. continue;
  644. // 判断是否已经存在该数据
  645. int pos = findInExcel(sheet, row);
  646. Row r = null;// 如果数据行已经存在,则获取后重写,否则自动创建新行。
  647. if (pos >= 0) {
  648. sheet.removeRow(sheet.getRow(pos));
  649. r = sheet.createRow(pos);
  650. } else {
  651. r = sheet.createRow(lastRowNum + t++);
  652. }
  653. // 用于设定单元格样式
  654. CellStyle newstyle = wb.createCellStyle();
  655. // 循环为新行创建单元格
  656. for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
  657. Cell cell = r.createCell(i);// 获取数据类型
  658. cell.setCellValue(getCellValue(row.getCell(i)));// 复制单元格的值到新的单元格
  659. // cell.setCellStyle(row.getCell(i).getCellStyle());//出错
  660. if (row.getCell(i) == null)
  661. continue;
  662. copyCellStyle(row.getCell(i).getCellStyle(), newstyle); // 获取原来的单元格样式
  663. cell.setCellStyle(newstyle);// 设置样式
  664. // sheet.autoSizeColumn(i);//自动跳转列宽度
  665. }
  666. }
  667. out("其中检测到重复条数为:" + (rowList.size() - t) + " ,追加条数为:" + t);
  668. // 统一设定合并单元格
  669. setMergedRegion(sheet);
  670. try {
  671. // 重新将数据写入Excel中
  672. FileOutputStream outputStream = new FileOutputStream(xlsPath);
  673. wb.write(outputStream);
  674. outputStream.flush();
  675. outputStream.close();
  676. } catch (Exception e) {
  677. out("写入Excel时发生错误! ");
  678. e.printStackTrace();
  679. }
  680. }
  681. /**
  682. * 查找某行数据是否在Excel表中存在,返回行数。
  683. *
  684. * @Title: findInExcel
  685. * @Date : 2014-9-11 下午02:23:12
  686. * @param sheet
  687. * @param row
  688. * @return
  689. */
  690. private int findInExcel(Sheet sheet, Row row) {
  691. int pos = -1;
  692. try {
  693. // 如果覆写目标文件,或者不需要比较,则直接返回
  694. if (isOverWrite || !isNeedCompare) {
  695. return pos;
  696. }
  697. for (int i = startReadPos; i <= sheet.getLastRowNum() + endReadPos; i++) {
  698. Row r = sheet.getRow(i);
  699. if (r != null && row != null) {
  700. String v1 = getCellValue(r.getCell(comparePos));
  701. String v2 = getCellValue(row.getCell(comparePos));
  702. if (v1.equals(v2)) {
  703. pos = i;
  704. break;
  705. }
  706. }
  707. }
  708. } catch (Exception e) {
  709. e.printStackTrace();
  710. }
  711. return pos;
  712. }
  713. /**
  714. * 复制一个单元格样式到目的单元格样式
  715. *
  716. * @param fromStyle
  717. * @param toStyle
  718. */
  719. public static void copyCellStyle(CellStyle fromStyle, CellStyle toStyle) {
  720. toStyle.setAlignment(fromStyle.getAlignment());
  721. // 边框和边框颜色
  722. toStyle.setBorderBottom(fromStyle.getBorderBottom());
  723. toStyle.setBorderLeft(fromStyle.getBorderLeft());
  724. toStyle.setBorderRight(fromStyle.getBorderRight());
  725. toStyle.setBorderTop(fromStyle.getBorderTop());
  726. toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
  727. toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
  728. toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
  729. toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());
  730. // 背景和前景
  731. toStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor());
  732. toStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());
  733. // 数据格式
  734. toStyle.setDataFormat(fromStyle.getDataFormat());
  735. toStyle.setFillPattern(fromStyle.getFillPattern());
  736. // toStyle.setFont(fromStyle.getFont(null));
  737. toStyle.setHidden(fromStyle.getHidden());
  738. toStyle.setIndention(fromStyle.getIndention());// 首行缩进
  739. toStyle.setLocked(fromStyle.getLocked());
  740. toStyle.setRotation(fromStyle.getRotation());// 旋转
  741. toStyle.setVerticalAlignment(fromStyle.getVerticalAlignment());
  742. toStyle.setWrapText(fromStyle.getWrapText());
  743. }
  744. /**
  745. * 获取合并单元格的值
  746. *
  747. * @param sheet
  748. * @return
  749. */
  750. public void setMergedRegion(Sheet sheet) {
  751. int sheetMergeCount = sheet.getNumMergedRegions();
  752. for (int i = 0; i < sheetMergeCount; i++) {
  753. // 获取合并单元格位置
  754. CellRangeAddress ca = sheet.getMergedRegion(i);
  755. int firstRow = ca.getFirstRow();
  756. if (startReadPos - 1 > firstRow) {// 如果第一个合并单元格格式在正式数据的上面,则跳过。
  757. continue;
  758. }
  759. int lastRow = ca.getLastRow();
  760. int mergeRows = lastRow - firstRow;// 合并的行数
  761. int firstColumn = ca.getFirstColumn();
  762. int lastColumn = ca.getLastColumn();
  763. // 根据合并的单元格位置和大小,调整所有的数据行格式,
  764. for (int j = lastRow + 1; j <= sheet.getLastRowNum(); j++) {
  765. // 设定合并单元格
  766. sheet.addMergedRegion(new CellRangeAddress(j, j + mergeRows,
  767. firstColumn, lastColumn));
  768. j = j + mergeRows;// 跳过已合并的行
  769. }
  770. }
  771. }
  772. /**
  773. * 打印消息,
  774. *
  775. * @param msg
  776. *            消息内容 换行
  777. */
  778. private void out(String msg) {
  779. if (printMsg) {
  780. out(msg, true);
  781. }
  782. }
  783. /**
  784. * 打印消息,
  785. *
  786. * @param msg
  787. *            消息内容
  788. * @param tr
  789. *            换行
  790. */
  791. private void out(String msg, boolean tr) {
  792. if (printMsg) {
  793. System.out.print(msg + (tr ? "\n" : ""));
  794. }
  795. }
  796. public String getExcelPath() {
  797. return this.excelPath;
  798. }
  799. public void setExcelPath(String excelPath) {
  800. this.excelPath = excelPath;
  801. }
  802. public boolean isNeedCompare() {
  803. return isNeedCompare;
  804. }
  805. public void setNeedCompare(boolean isNeedCompare) {
  806. this.isNeedCompare = isNeedCompare;
  807. }
  808. public int getComparePos() {
  809. return comparePos;
  810. }
  811. public void setComparePos(int comparePos) {
  812. this.comparePos = comparePos;
  813. }
  814. public int getStartReadPos() {
  815. return startReadPos;
  816. }
  817. public void setStartReadPos(int startReadPos) {
  818. this.startReadPos = startReadPos;
  819. }
  820. public int getEndReadPos() {
  821. return endReadPos;
  822. }
  823. public void setEndReadPos(int endReadPos) {
  824. this.endReadPos = endReadPos;
  825. }
  826. public boolean isOverWrite() {
  827. return isOverWrite;
  828. }
  829. public void setOverWrite(boolean isOverWrite) {
  830. this.isOverWrite = isOverWrite;
  831. }
  832. public boolean isOnlyReadOneSheet() {
  833. return onlyReadOneSheet;
  834. }
  835. public void setOnlyReadOneSheet(boolean onlyReadOneSheet) {
  836. this.onlyReadOneSheet = onlyReadOneSheet;
  837. }
  838. public int getSelectedSheetIdx() {
  839. return selectedSheetIdx;
  840. }
  841. public void setSelectedSheetIdx(int selectedSheetIdx) {
  842. this.selectedSheetIdx = selectedSheetIdx;
  843. }
  844. public String getSelectedSheetName() {
  845. return selectedSheetName;
  846. }
  847. public void setSelectedSheetName(String selectedSheetName) {
  848. this.selectedSheetName = selectedSheetName;
  849. }
  850. public int getStartSheetIdx() {
  851. return startSheetIdx;
  852. }
  853. public void setStartSheetIdx(int startSheetIdx) {
  854. this.startSheetIdx = startSheetIdx;
  855. }
  856. public int getEndSheetIdx() {
  857. return endSheetIdx;
  858. }
  859. public void setEndSheetIdx(int endSheetIdx) {
  860. this.endSheetIdx = endSheetIdx;
  861. }
  862. public boolean isPrintMsg() {
  863. return printMsg;
  864. }
  865. public void setPrintMsg(boolean printMsg) {
  866. this.printMsg = printMsg;
  867. }
  868. }

至此,读取完毕。

Java读取Excel文件汇总相关推荐

  1. java读取jsp文件内容_使用Java读取Excel文件内容

    问题:我能用Java读取一个Excel文件吗?如果能,怎么做? 回答:是的,可以用Java读取Microsoft Excel文件.微软提供了一个Excel的ODBC驱动程序,因此我们就可以使用JDBC ...

  2. 【Apache POI】Java 读取Excel文件

    Excel内容如下: 封装Excel行列字段的Bean: public class Employee {private String name;private String gender;privat ...

  3. java 读取excel 文件 Unable to recognize OLE stream 错误

    使用 java 代码读取 excel 文件代码时报错如下: jxl.read.biff.BiffException: Unable to recognize OLE stream     at jxl ...

  4. java读取Excel文件,用JDBC导入数据到mysql

    本需求最重要的就是如何将Excel文件中的数据读取到java集合中.首先要知道Excel表格中的每行记录即为一个对象,我们可以使用操作Excel的org.apache.poi框架,对数据进行读取.首先 ...

  5. Java 读取excel文件内容插入到数据库

    Java读写Excel的包是Apache POI. JAVA EXCEL API:是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel ...

  6. Java读取Excel文件数据并将记录写入到新的文件中--POI技术实现

    1. apache poi包里有4个主要的类: Workbook----工作表,通过WorkbookFactory的create(FileInputStream fis)方法获取, Sheet---- ...

  7. java读取excel文件单元格英文出现乱码问题的解决方法

    小编今天测试读取excel文件,并且取其中的几个单元格作为文件名称的时候,发现文件名出现了乱码,毫无疑问,肯定就是读取excel的时候,取出来就出现了乱码,如图所示 excel原单元格数据,如图所示 ...

  8. Java 读取 Excel 文件内容, 根据 pdf 模板动态生成对应的 pdf 文件

    1. 下载 adobe acrobat https://www.cr173.com/soft/11135.html 2. 编辑 pdf 模板 1用 acrobat 打开 pdf 编辑模板 添加表单元素 ...

  9. Java 读取excel文件 兼容97-2013 V2.0

    注释里有struts的上传文件和Springmvc有些不一样.读写都是一样的 修复删除缓存文件占用的问题 package com.telling.cw.util.poi;import org.apac ...

最新文章

  1. LaTeX 使用 bib 管理参考文献时,引用网络资源 URL 导致排版难看的问题
  2. VC用MFC开发的圆形进度条控件
  3. 第一行冻结_EXCEL函数tips(4) 数据冻结和查找
  4. lucene快速入门_为Lucene选择快速唯一标识符(UUID)
  5. [渝粤教育] 广东-国家-开放大学 21秋期末考试计量经济学10551k1
  6. github 打不开_App更新不了? TF打不开? 试试这个
  7. KlayGE 3.10.0发布!
  8. 眼儿媚·迟迟春日弄轻柔 [宋] 朱淑真
  9. oracle组合索引最左原则,复合索引最左原则 -- 实战
  10. es文件浏览器怎么用_python爬虫入门:什么是爬虫,怎么玩爬虫?
  11. 正则表达式最后的/i是不区分大小写的意思
  12. linux硬件 软件raid,linux学习之路之磁盘阵列RAID及硬件RAID和软件RAID的区别
  13. 并发编程学习之ConcurrentHashMap扩容机制
  14. cadlisp点选面积标注_一个在CAD中标注坐标的LISP
  15. ubuntu18.04安装lua5.3.6和luarocks3.8
  16. Java基于WEB的商品库存管理系统
  17. win10更改无线网卡的MAC地址
  18. Spring项目启动时Error creating bean with name ‘xxxxxx‘: Bean with name ‘xxxxxx‘ has been injected into ot
  19. Android开发动态的监听网络状态的变化
  20. 怎么创建dllwenjian_怎样新建一个*.dll的文件?

热门文章

  1. 在Bootstrap模糊框中使用WebUploader的问题及解决方法
  2. Find the Winning Move
  3. Python使用Pillow包报错 ImportError: DLL load failed while importing _imaging: 找不到指定的程序。
  4. 1082. 射击比赛 (20)
  5. 欺骗的艺术(内容介绍)
  6. mysql修改为北京时间
  7. Unity3d嵌入web网页
  8. 计算机毕业设计Java乐居租房网的设计与实现(源码+系统+mysql数据库+lW文档)
  9. TinyP2P如何运行 How tinyp2p works!
  10. 如何使用即构JS SDK快速上线在线抓娃娃H5产品?