1. 程式人生 > >將資料庫的資料轉換為excel檔案下載到本地的方法中遇到的困難及解決方案

將資料庫的資料轉換為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就可以了
下載的資料如下圖,大功告成
在這裡插入圖片描述