excel導入是常用到的功能,若是文件數據量大的話仍是建議分割後導入,java經常使用的API是poi和jxl,我採用的是jxl,那麼讓咱們來看下怎麼用jxl來實現分割。java
<!--excel--> <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifactId>jxl</artifactId> <version>2.6.12</version> </dependency>
public class FileInfoModel { /** * 文件在數據庫中的Id */ private Long fileId; /** * 是否上傳 */ private boolean isUpload; /** * 存儲循環過程當中的索引值 */ private int forIndex; /** * 文件全名 xxx.xls */ private String fileFullName; /** * 文件名 xxx */ private String fileName; /** * 文件後綴 .xls */ private String fileSuffix; /** * 文件保存路徑 e:\\xx\xx */ private String filePath; /** * 文件的起始行號 */ private int beginRow; /** * 文件的末尾行號 */ private int endRow; public FileInfoModel() { super(); } public FileInfoModel(String fileFullName) { super(); this.fileFullName = fileFullName; } public FileInfoModel(String fileName, String fileFullName) { super(); this.fileName = fileName; this.fileFullName = fileFullName; } public FileInfoModel(String fileFullName, String fileName, String fileSuffix) { super(); this.fileFullName = fileFullName; this.fileName = fileName; this.fileSuffix = fileSuffix; } public FileInfoModel(String fileFullName, String fileName, String fileSuffix, String filePath) { super(); this.fileFullName = fileFullName; this.fileName = fileName; this.fileSuffix = fileSuffix; this.filePath = filePath; } public Long getFileId() { return fileId; } public void setFileId(Long fileId) { this.fileId = fileId; } public boolean isUpload() { return isUpload; } public void setUpload(boolean isUpload) { this.isUpload = isUpload; } public int getForIndex() { return forIndex; } public void setForIndex(int forIndex) { this.forIndex = forIndex; } public String getFileFullName() { return fileFullName; } public void setFileFullName(String fileFullName) { this.fileFullName = fileFullName; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileSuffix() { return fileSuffix; } public void setFileSuffix(String fileSuffix) { this.fileSuffix = fileSuffix; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public int getBeginRow() { return beginRow; } public void setBeginRow(int beginRow) { this.beginRow = beginRow; } public int getEndRow() { return endRow; } public void setEndRow(int endRow) { this.endRow = endRow; } }
public class ExcelModel { /*excel 文件路徑*/ private String excelFilePath; /*分割後的文件目錄*/ private String excelChildFileDir; /*excel 名稱*/ private String excelName; /*sheet 名稱*/ private String sheetName = "Sheet1"; /*excel 總記錄數*/ private int totalRows; /*分割文件後每一個文件的記錄數*/ private int fileSize = 3000; /*分割後的文件數*/ private int fileCount; /*分割後的文件集合*/ private List<FileInfoModel> files; /*計算總行數時是否去表頭*/ private boolean isRemoveHeader = true; /*是否去除重複數據*/ private boolean isCleareRepeat = false; /*導入文件過程當中是否出錯*/ private boolean isError; public boolean isError() { return isError; } public void setError(boolean isError) { this.isError = isError; } public String getExcelFilePath() { return excelFilePath; } public void setExcelFilePath(String excelFilePath) { this.excelFilePath = excelFilePath; } public boolean isCleareRepeat() { return isCleareRepeat; } public void setCleareRepeat(boolean isCleareRepeat) { this.isCleareRepeat = isCleareRepeat; } public String getExcelChildFileDir() { return excelChildFileDir; } public void setExcelChildFileDir(String excelChildFileDir) { this.excelChildFileDir = excelChildFileDir; } public boolean isRemoveHeader() { return isRemoveHeader; } public void setRemoveHeader(boolean isRemoveHeader) { this.isRemoveHeader = isRemoveHeader; } public int getFileCount() { //根據總記錄數及分割文件的行數計算文件數量 fileCount = (int) Math.ceil(this.totalRows / this.fileSize) + 1; return fileCount; } public String getExcelName() { return excelName; } public void setExcelName(String excelName) { this.excelName = excelName; } public String getSheetName() { return sheetName; } public void setSheetName(String sheetName) { this.sheetName = sheetName; } public int getTotalRows() { if (this.isRemoveHeader) { return totalRows - 1; } else { return totalRows; } } public void setTotalRows(int totalRows) { this.totalRows = totalRows; } public int getFileSize() { return fileSize; } public void setFileSize(int fileSize) { this.fileSize = fileSize; } public List<FileInfoModel> getFiles() { return files; } public void setFiles(List<FileInfoModel> files) { this.files = files; } }
public interface IExcelOperate { /** * 加載excel文件 * @param fileName */ void load(String fileName) throws Exception; /** * 讀取excel文件數據 * * @throws Exception */ public <T> List<T> readExcel() throws Exception; /** * 分割excel * * @throws Exception */ public void splitExcel() throws Exception; /** * 多線程分割excel */ public void splitExcelThread() throws Exception; /** * 關閉文件 */ void close(); }
public class ExcelUtil<T> implements IExcelOperate { protected final Log log = LogFactory.getLog(getClass()); private ExcelModel excelModel; private Class tClass; private Cell[] titleCell; private jxl.Workbook workBook; private Sheet sheet; public int getRows() { if (this.sheet != null) { return this.sheet.getRows(); } return 0; } public ExcelUtil() { super(); } public ExcelUtil(ExcelModel excelModel, Class tClass) { this.tClass = tClass; this.excelModel = excelModel; } public ExcelModel getExcelModel() { return excelModel; } public void setExcelModel(ExcelModel excelModel) { this.excelModel = excelModel; } @Override public void load(String fileName) throws Exception { try { File file = new File(fileName); workBook = Workbook.getWorkbook(file); this.excelModel.setFiles(new ArrayList<FileInfoModel>()); //默認讀取文件的路徑 String[] ary = file.getName().split("\\."); String suffix = ary[1]; this.excelModel.getFiles().add(new FileInfoModel(file.getName(), fileName, "." + suffix, file.getParent())); if (this.excelModel.isCleareRepeat()) { this.clearRepeat(file); workBook = Workbook.getWorkbook(file); } if (workBook == null) { throw new Exception("讀取excel文件出錯!"); } sheet = this.excelModel.getSheetName().trim() == "" ? workBook.getSheet(0) : workBook.getSheet(this.excelModel.getSheetName()); if (sheet == null) { sheet = workBook.getSheet(0); } if (sheet == null) { throw new Exception("讀取sheet出錯!"); } this.excelModel.setTotalRows(sheet.getRows()); // 用於存儲列標題 titleCell = new Cell[sheet.getColumns()]; // 將列標題存儲存到一個一維數組中 for (int i = 0; i < titleCell.length; i++) { titleCell[i] = sheet.getCell(i, 0); } } catch (IOException e) { workBook.close(); } } @Override public void splitExcel() throws Exception { //根據文件數分割 excel,重置文件集合 this.excelModel.setFiles(new ArrayList<FileInfoModel>()); //生成Guid做爲文件前綴 UUID uuid = UUID.randomUUID(); FileInfoModel fileInfoModel = new FileInfoModel(); for (int i = 1; i <= this.excelModel.getFileCount(); i++) { fileInfoModel = getFileInfoModelBySplit(i, uuid); this.excelModel.getFiles().add(this.split(fileInfoModel)); } } @Override public void splitExcelThread() throws Exception { //根據文件數分割 excel,重置文件集合 this.excelModel.setFiles(new ArrayList<FileInfoModel>()); //生成Guid做爲文件前綴 UUID uuid = UUID.randomUUID(); //根據文件數分割 excel,重置文件集合 this.excelModel.setFiles(new ArrayList<FileInfoModel>()); //工做線程 ExecutorService executorService = Executors.newFixedThreadPool(this.excelModel.getFileCount()); FileInfoModel fileInfoModel = new FileInfoModel(); for (int i = 1; i <= this.excelModel.getFileCount(); i++) { fileInfoModel = getFileInfoModelBySplit(i, uuid); ExcelThread thread = new ExcelThread(fileInfoModel); executorService.execute(thread); this.excelModel.getFiles().add(thread.getReturnFile()); } executorService.shutdown(); while (!executorService.isTerminated()) { //檢查全部線程都執行完成 } } /** * 分割excel時獲取文件信息 * * @param i * @return */ private FileInfoModel getFileInfoModelBySplit(int i, UUID uuid) { /*結束行*/ int endRow = i * this.excelModel.getFileSize(); /*起始行*/ int beginRow = (endRow - this.excelModel.getFileSize()) + 1; /*若是結束行超出總記錄數,結束行就等於總記錄數*/ if (endRow >= this.excelModel.getTotalRows()) { endRow = this.excelModel.getTotalRows(); } //獲取文件路徑 String filePath = MessageFormat.format("{0}/{1}_{2}.xls", this.excelModel.getExcelChildFileDir(), uuid, i); FileInfoModel fileInfoModel = new FileInfoModel(); fileInfoModel.setFilePath(filePath); fileInfoModel.setBeginRow(beginRow); fileInfoModel.setEndRow(endRow); fileInfoModel.setForIndex(i - 1); return fileInfoModel; } /** * 分割excel * * @param fileInfoModel * @return */ private FileInfoModel split(FileInfoModel fileInfoModel) { File file = new File(fileInfoModel.getFilePath()); try { jxl.write.WritableWorkbook ww = Workbook.createWorkbook(file); WritableSheet ws = ww.createSheet(this.excelModel.getSheetName(), 0); //添加表頭 for (int iColumn = 0; iColumn < this.titleCell.length; iColumn++) { ws.addCell(new Label(iColumn, 0, this.titleCell[iColumn].getContents())); } //添加數據到excel中 int rowIndex = 1; for (int iRow = fileInfoModel.getBeginRow(); iRow <= fileInfoModel.getEndRow(); iRow++, rowIndex++) { Cell[] cells = this.sheet.getRow(iRow); for (int iCell = 0; iCell < cells.length; iCell++) { Cell cell = cells[iCell]; //excel 行的索引須要計算 ws.addCell(new Label(iCell, rowIndex, cell.getContents())); } } ww.write(); ww.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (RowsExceededException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (WriteException e) { // TODO Auto-generated catch block e.printStackTrace(); } String[] ary = file.getName().split("\\."); String fileName = ary[0]; String suffix = ary[1]; fileInfoModel.setFileFullName(file.getName()); fileInfoModel.setFileName(fileName); fileInfoModel.setFileSuffix("." + suffix); return fileInfoModel; } class ExcelThread implements Runnable {// 任務接口 FileInfoModel returnFile; public FileInfoModel getReturnFile() { return returnFile; } ExcelThread(FileInfoModel fileInfoModel) { this.returnFile = fileInfoModel; } public void run() { long beginTime = System.currentTimeMillis(); this.returnFile = split(this.returnFile); System.out.println(MessageFormat.format("分割文件{0},執行耗時{1}秒", this.returnFile.getForIndex(), (System.currentTimeMillis() - beginTime) / 1000f)); } } }