将数据库的数据转换为excel文件下载到本地的方法中遇到的困难及解决方案

以下是将数据库的数据转换为excel文件下载到本地的方法

@Autowired
private BooksService booksService;
@RequestMapping("/downloadBooksExcel")
public void downstudents(HttpServletRequest request, HttpServletResponse response)throws IOException {

		String[] headers = { "序号", "作者", "出版社", "时间","项目编号","标题"};//导出的Excel头部,这个要根据自己项目改一下

		List<TBooks> dataset = booksService.findAll();//查询出来的数据,根据自己项目改一下

		for (TBooks books: dataset) {

		}
		//下面的完全不动就行了(Excel数据中不包含图片)

		// 声明一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 生成一个表格
		HSSFSheet sheet = workbook.createSheet();
		// 设置表格默认列宽度为15个字节
		sheet.setColumnWidth(5,8000);
		HSSFRow row = sheet.createRow(0);
		for (int i = 0; i < headers.length; i++) {
			HSSFCell cell = row.createCell(i);
			HSSFRichTextString text = new HSSFRichTextString(headers[i]);
			cell.setCellValue(text);
		}
		//遍历集合数据,产生数据行
		Iterator it = dataset.iterator();
		int index = 0;
		while (it.hasNext()) {
			index++;
			row = sheet.createRow(index);
			TBooks t = (TBooks) it.next();
			//利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
			Field[] fields = t.getClass().getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				String fieldName = field.getName();
				String getMethodName = "get"
						+ fieldName.substring(0, 1).toUpperCase()
						+ fieldName.substring(1);

				HSSFCell cell = row.createCell(i);

				try {
					Class tCls = t.getClass();
					Method getMethod = tCls.getMethod(getMethodName,
							new Class[]{});
					System.out.println(getMethodName);
					Object value = null;
					if (getMethodName.equals("getStatus")) {
						//sheet.removeMergedRegion(getMergedRegionIndex(sheet, 1, 1));
						continue;//相当于清空了是数据
					}
					if (getMethodName.equals("getResultId")) {
						continue;//相当于清空了是数据
					}

					//row.removeCell(cell);
					value = getMethod.invoke(t, new Object[]{});
					if (getMethodName.equals("getId")) {
						cell.setCellValue(i+1);//如果是id列的话,直接将序号设置进去
					}
					System.out.println(value);
					String textValue = null;


					if (value instanceof Date) {
						Date date = (Date) value;
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						textValue = sdf.format(date);
					} else {
						//其它数据类型都当作字符串简单处理
						textValue = value.toString();
					}

					HSSFRichTextString richString = new HSSFRichTextString(textValue);
					HSSFFont font3 = workbook.createFont();
					font3.setColor(HSSFColor.BLUE.index);//定义Excel数据颜色
					richString.applyFont(font3);
					cell.setCellValue(richString);


				} catch (SecurityException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

		}
		response.setContentType("application/octet-stream");
		response.setHeader("Content-disposition", "attachment;filename=createList.xls");//默认Excel名称
		response.flushBuffer();
		workbook.write(response.getOutputStream());
	}

今天在生成excel文件的时候遇到一个bug,那就是我们在查询数据库的时候得到一个集合,但是这个集合里面有一些字段不是我们需要的,比如id,status(状态)等信息,这些信息我们不需要生成excel表格,然后让客户下载下来。那么问题来了,我们就需要把把这些数据删掉。

if (getMethodName.equals("getStatus")) {
        						continue;//相当于清空了是数据
        					}
        					if (getMethodName.equals("getResultId")) {
        						continue;//相当于清空了是数据
        					}

然后我就把数据删掉了,但是这样的话还是会存在问题,因为数据虽然删掉了,但是生成的列还存在
在这里插入图片描述
就如上图一样,我们的项目编号是空的,因为if (getMethodName.equals(“getResultId”)) {
continue;//相当于清空了是数据
}清空了数据但是,没有删除列
然后我尝试了很多方法进行删除列
比如:sheet.removeMergedRegion(getMergedRegionIndex(sheet, 1, 1));
但是这个方法getMergedRegionIndex缺少依赖,无法正常使用
又尝试了另一种方法

//deleteColumn(sheet,0,1);
	private static void deleteColumn(HSSFSheet sheet, int columnStartIndex, int columnNum) {
		Util.shiftCellsLeft(sheet, 0, columnStartIndex + columnNum, sheet.getPhysicalNumberOfRows() - 1, sheet.getRow(0).getPhysicalNumberOfCells() - 1, columnNum, true);
		Util.shiftCellsLeft(sheet, 0, sheet.getRow(0).getPhysicalNumberOfCells(), sheet.getPhysicalNumberOfRows() - 1, sheet.getRow(0).getPhysicalNumberOfCells() + columnNum, columnNum, true);
}

这种方法是可以删除列的,但是本人比较笨,这个方法的源码有点不是很懂,源码如下:

public static void shiftCellsLeft(Sheet sheet, int startRow, int startCol, int endRow, int endCol, int shiftNumber, boolean removeSourceMergedRegion) {
        Set mergedRegions = new HashSet();

        for(int rowNum = startRow; rowNum <= endRow; ++rowNum) {
            boolean doSetWidth = true;
            Row row = sheet.getRow(rowNum);
            if (row != null) {
                for(int colNum = startCol; colNum <= endCol; ++colNum) {
                    Cell cell = row.getCell(colNum);
                    if (cell == null) {
                        cell = row.createCell(colNum);
                        doSetWidth = false;
                    }

                    int destColNum = colNum - shiftNumber;
                    Cell destCell = row.getCell(destColNum);
                    if (destCell == null) {
                        destCell = row.createCell(destColNum);
                    }

                    copyCell(cell, destCell, true);
                    updateMergedRegionInRow(sheet, mergedRegions, rowNum, colNum, destColNum, removeSourceMergedRegion);
                    if (doSetWidth) {
                        sheet.setColumnWidth(destCell.getColumnIndex(), getWidth(sheet, cell.getColumnIndex()));
                    }
                }
            }
        }

    }

最后数据是删除了,但是删除的结果不是我想要的,删除结果如下图
在这里插入图片描述
应该是参数的问题,或者是调用的方法放的位置不对
然后我想着既然我不能删除列,那我在创建列的时候不创建对应的列不就行了吗

HSSFCell cell = null;
				if(!getMethodName.equals("getStatus")||!getMethodName.equals("getResultId"){
					cell = row.createCell(i);
				}

但是事与愿违,它还是生成了对应的列,没有办法,我只能另寻出路了

最后我把实体类的顺序更改了一下,就完成了这个功能
更改前的顺序
更改前的顺序
更改后的顺序,把resultId(get/set方法也放在后面)放到最后了,虽然还会生成空的resultId的列,但是这是在后面,对我们的结果没有影响,这样虽然没有实现真正的删除列,但是我们得到了数据又有什么影响呢?
在这里插入图片描述
还有就是id那一列,通过一下方法,将数据存入进去就行了

value = getMethod.invoke(t, new Object[]{});
					if (getMethodName.equals("getId")) {
						cell.setCellValue(i+1);//如果是id列的话,直接将序号设置进去
					}

最后,访问网页http://localhost:8081/file/downloadBooksExcel就可以了
下载的数据如下图,大功告成
在这里插入图片描述

参考文献:https://blog.csdn.net/panpan96/article/details/76566475

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值