1. 程式人生 > >jxl實現excel匯入匯出的完整demo

jxl實現excel匯入匯出的完整demo

@RequestMapping("/pointsImport.do")
public void StructureImport(HttpServletRequest request, HttpServletResponse response, Long driveId) {
    String msg = null;
    try {
        response.setContentType("text/html;charset=utf-8");
        MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
        MultipartFile fileM = re.getFile("upFile"
); CommonsMultipartFile cf = (CommonsMultipartFile) fileM; InputStream inputStream = cf.getInputStream(); if (inputStream != null) { Workbook workbook = null; try { workbook = Workbook.getWorkbook(inputStream); processData(workbook, response, driveId); } catch
(Exception e) { logger.error("上傳檔案錯誤:" + e); } } } catch (Exception e) { logger.error("上傳檔案錯誤:" + e); } }

也可以用path來獲取檔案,可path大多時候,獲取的是相對路徑,具體為什麼我也不清楚…..

            response.setContentType("text/html;charset=utf-8");
            MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
            CommonsMultipartFile file = (CommonsMultipartFile) re.getFile("upFile"
); DiskFileItem dfi = (DiskFileItem) file.getFileItem(); String path = dfi.getStoreLocation().getPath().toString(); File toFile = new File(path); if (toFile != null) { //file.transferTo(toFile); Workbook workbook = null; try { // excel檔案上傳 workbook = Workbook.getWorkbook(toFile); //處理資料,如果需要userid的話,這裡可以追加 processData(workbook, response); } catch (Exception e) { msg = "上傳檔案錯誤!"; } } } catch (Exception e) { msg = "上傳檔案錯誤!"; }

上傳控制元件:

<form id="edit_form" action="<%=basePath%>tpManagerDownLoad/pointsImport.do" method="post" class="data-form" enctype="multipart/form-data">
    <input type="hidden" name="deviceStoreId" value="${deviceStoreId }" />
    <input type="hidden" name="id" value="${driveId}" />
    <input type="hidden" id="document" name="document" value="${document }" />
    <table width="100%">
        <tbody>
        <tr>
            <td class="field-lable"><label>驅動檔案:</label></td>
            <td><input type="file" title="請選擇檔案" id="upFile"  name="upFile" onselect="getFileName()" onchange="getFileName()"/></td>
        </tr>
        </tbody>
    </table>
    <table class="btn-ct">
        <tbody><tr>
            <td>
                <button type="submit" id="save">確定</button>
            </td>
        </tr>
        </tbody></table>
    </div>
</form>

也可以這麼寫:

               <div class="panel-top-banner">
                        <form action="StructureExIm/StructureImport.do" id="form" method="post" enctype="multipart/form-data">
                            上傳:
                            <input id="upFile" name="upFile" type="file" />
                            <input type="submit" value="提交"/>
                            <br/>
                        </form>
                </div>

所有上傳和下載的程式碼demo:

package com.tdenergys.platform.web.controller;

import com.tdenergys.platform.core.model.Project;
import com.tdenergys.platform.core.model.Structure;
import com.tdenergys.platform.core.service.IProjectService;
import com.tdenergys.platform.core.service.IStructureService;
import jxl.*;
import jxl.format.Colour;
import jxl.format.UnderlineStyle;
import jxl.write.*;
import jxl.write.biff.RowsExceededException;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.lang.Boolean;
import java.util.*;
import java.util.regex.Matcher;

/**
* 結構匯入
* Created by Jerry.ZR on 15-3-4.
*/
@Controller
@RequestMapping("/StructureExIm")
public class StructureExImController {

    @Resource(name = "structureService")
    private IStructureService structureService;

    @Resource(name = "projectService")
    private IProjectService projectService;


    private static final String IMPORT_TEMP_FILE_NAME = "Structure_import_temp.xls";

    private static final String[] STORE_HOUSE_IMPORT_TEMP_FILE_TITLE =
            {"專案名稱", "父親名稱", "結構名稱", "結構編號"};

    private static final String[] STORE_HOUSE_IMPORT_TEMP_FILE_TITLE_ID =
            {"project_id", "parent_id", "name", "code"};

    public static final String STORE_HOUSE_FAIL = "失敗";

    public static final String STORE_HOUSE_SUCCESS = "成功";

    private static final String IMPORT_TEMP_RESULT_NAME = "Structure_import_result";

    //資料字典頁的表頭
    private static final String[] STORE_HOUSE_DICTIONARY_TITLE = {"專案名稱"};
    //與資料字典表頭對應的id號
    private static final String STORE_HOUSE_DICTIONARY_ID = "projectName";

    /**
     * 裝置匯入 模版下載
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/StructureDownload.do")
    public void StructureDownload(HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        response.setContentType("aplication/msexcel;charset=utf-8"); // 設定檔案型別
        response.setHeader("Content-disposition", "attachment; filename=" + IMPORT_TEMP_FILE_NAME);

        WritableWorkbook workbook = null;
        String[] titles = STORE_HOUSE_IMPORT_TEMP_FILE_TITLE;
        String[] titleIds = STORE_HOUSE_IMPORT_TEMP_FILE_TITLE_ID;

        try {
            // 建立工作簿
            workbook = Workbook.createWorkbook(response.getOutputStream());
            // 建立匯入資料頁
            WritableSheet sheet0 = workbook.createSheet("匯入資料", 0);

            CellView cellView = new CellView();
            // 設定自動大小
            cellView.setAutosize(true);
            // 設定字型 普通格式
            WritableFont font = new WritableFont(WritableFont.ARIAL, 10);
            WritableCellFormat cellFormat = new WritableCellFormat(font);
            // 設定背景顏色;
            cellFormat.setBackground(Colour.YELLOW);

            // 設定必填欄位為紅色字型 特殊字型
            WritableFont fontRed = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.RED);
            WritableCellFormat cellFormatRed = new WritableCellFormat(fontRed);
            // 設定背景色為黃色
            cellFormatRed.setBackground(Colour.YELLOW);

            // 定義單元格為文字樣式
            WritableCellFormat wcf = new WritableCellFormat(NumberFormats.TEXT);
            // 定義一個列顯示樣式
            CellView cv = new CellView();
            // 把定義的單元格格式初始化進去
            cv.setFormat(wcf);
            // 設定列寬度(不設定的話是0,不會顯示)
            cv.setSize(10 * 265);

            //excel寫上註釋
            WritableCellFeatures projectNameWCF = new WritableCellFeatures();
            projectNameWCF.setComment("專案名稱不能為空");

            WritableCellFeatures structureNameWCF = new WritableCellFeatures();
            structureNameWCF.setComment("結構名稱不能為空");


            if (titles != null) {

                for (int i = 0; i < titles.length; i++) {
                    // 將所有列設定為文字格式,且寬度為10 * 265
                    sheet0.setColumnView(i, cv);

                    String title = titles[i];
                    String titleId = titleIds[i];
                    if (StringUtils.isNotBlank(title)) {
                        // 列名
                        Label label = null;
                        // 設定必填欄位為紅色字型
                        if (i == 0 || i == 2) {
                            // Label(列,行,標題)
                            label = new Label(i, 0, titles[i], cellFormatRed);
                        } else {
                            label = new Label(i, 0, titles[i], cellFormat);
                        }
                        //編寫excel註釋
                        if ("project_id".equals(titleId)) {
                            label.setCellFeatures(projectNameWCF);
                        }
                        if ("name".equals(titleId)) {
                            label.setCellFeatures(structureNameWCF);
                        }
                        sheet0.addCell(label);
                    }
                }
            }

            // 建立資料辭典頁
            WritableSheet sheet1 = workbook.createSheet("資料辭典", 1);

            Map<String, Object> result2 = new HashMap<String, Object>();

            Project p = new Project();
            List<Project> list = projectService.selectEntitys(p);
            result2.put("projectName", list);

            List<Object> listProject = new ArrayList<Object>();


            //將多個list的資料放入一個Map中
            if (list.size() != 0) {
                List<Project> valueProject = (List<Project>) result2.get("projectName");
                for (int j = 0; j < valueProject.size(); j++) {
                    listProject.add(valueProject.get(j).getName());
                }
            }

            Map<String, Object> result = new HashMap<String, Object>();
            result.put("projectName", listProject);

            String[] DataDictionary = STORE_HOUSE_DICTIONARY_ID.split(",");
            String[] dictionaryTitles = STORE_HOUSE_DICTIONARY_TITLE;

            //對應sheet0中的第幾列
            int[] dictionaryId = {0};
            String key = "";
            String dictionaryTitle = "";
            int columnNum;

            //每列都執行
            for (int i = 0; i < DataDictionary.length; i++) {
                //key為第i列的列名id
                key = DataDictionary[i];
                //對應sheet0中的第幾列
                columnNum = dictionaryId[i];
                //value接收的是result中第一列的值
                List<Object> value = (List<Object>) result.get(key);

                List<String> codeList = new ArrayList<String>();
                //獲取第I列的文字資訊
                dictionaryTitle = dictionaryTitles[i];
                //給第一列命名
                if (StringUtils.isNotBlank(dictionaryTitle)) {
                    Label label = new Label(i, 0, dictionaryTitles[i], cellFormat);
                    sheet1.addCell(label);
                }

                if (value != null) {
                    for (int j = 0; j < value.size(); j++) {
                        String manufactureValue = "";
                        Object manufactureValueMap = value.get(j);
                        manufactureValue = manufactureValueMap.toString();
                        Label label = new Label(i, j + 1, manufactureValue);
                        sheet1.addCell(label);
                        codeList.add(manufactureValue);
                    }

                    // 設定資料有效性,預設設定1000行
                    int[] target = new int[2];
                    int[] current = new int[2];
                    //將列表框的資料隱藏在22行附近,這個列數可以隨意改,只要比當前列數大就行
                    int defultColumn = 22;
                    Label label = new Label(defultColumn + i, 0, dictionaryTitles[i]);
                    //從第幾行開始展現下拉框
                    for (int j = 1; j < 1000; j++) {
                        //行
                        target[0] = columnNum;
                        target[1] = j;
                        //列
                        current[0] = defultColumn + i;
                        current[1] = 1;

                        buildDataValidationCell(sheet0, target, current, codeList);
                    }

                }

            }


            workbook.write();
            workbook.close();
        } catch (Exception e) {
            e.printStackTrace();
//            logger.error("匯出excel檔案錯誤!" + e);
        }
    }

    /**
     * 建立excel的資料有效性
     *
     * @param sheet
     * @param target  要設定資料驗證性的單元格位置
     * @param current 要存放驗證性資料的單元格位置
     * @param data
     * @return
     */
    private int[] buildDataValidationCell(WritableSheet sheet, int[] target, int[] current, List<String> data) {
        try {
            //data儲存的是下拉框中的資訊
            if (data.size() == 0)
                return current;
            //strings去掉data中空的資料
            List<String> strings = new ArrayList<String>();
            for (String d : data) {
                if (d != null && !"".equals(d.trim()))
                    strings.add(d);
            }
            //如果有65535行資料,那麼報錯
            if (strings.size() > 65535)
                throw new RuntimeException("excel2003單列上限,資料驗證只能使用單列或單行");
            // excel2003上限是65535,所以隱藏的行數超過5w就換另外一列,
            // 列上限是255。暫時不考慮行列都到上限的情況
            if (current[1] > 50000 || (current[1] > 50000 && strings.size() > 15535)) {
                current[0] = current[0] + 1;
                current[1] = 0;
            }
            // 構建下拉資料範圍
            buildDataValidationRange(sheet, target, current, strings);
            // 設定隱藏
            CellView cv = new CellView();
            cv.setHidden(true);
            sheet.setColumnView(current[0], cv);
            // 填充資料
            for (String s : strings) {
                Label b = new Label(current[0], current[1], s);
                sheet.addCell(b);
                current[1] += 1;
            }
        } catch (RowsExceededException e) {
            e.printStackTrace();
        } catch (WriteException e) {
            e.printStackTrace();
        }
        return current;

    }

    /**
     * 構建下拉資料範圍
     *
     * @param sheet
     * @param target  要設定資料驗證性的單元格位置
     * @param current 要存放驗證性資料的單元格位置
     * @param strings
     * @throws WriteException
     * @throws RowsExceededException
     */
    private void buildDataValidationRange(WritableSheet sheet, int[] target, int[] current, List<String> strings) throws WriteException, RowsExceededException {

        WritableCellFeatures wcf = null;
        // 資料驗證初始cell值,預設為空
        Label targetCell = new Label(target[0], target[1], "");
        wcf = new WritableCellFeatures();
        // 資料驗證範圍
        StringBuffer buff = new StringBuffer();
        // 起點
        CellReferenceHelper.getCellReference(current[0], true, current[1], true, buff);
        buff.append(":");
        // 終點
        CellReferenceHelper.getCellReference(current[0], true, current[1] + strings.size() - 1, true, buff);
        // 設定資料驗證性
        wcf.setDataValidationRange(buff.toString());
        targetCell.setCellFeatures(wcf);
        sheet.addCell(targetCell);
    }


    /**
     * 對匯入模版excel進行解析並插入資料庫
     *
     * @param request
     * @param response
     * @return
     */

    @RequestMapping("/StructureImport.do")
    public void StructureImport(HttpServletRequest request, HttpServletResponse response) {
        String msg = null;
        try {
這裡還可以用inputStream
===========================================================================================================
@RequestMapping("/pointsImport.do")
public void StructureImport(HttpServletRequest request, HttpServletResponse response, Long driveId) {
    String msg = null;
    try {
        response.setContentType("text/html;charset=utf-8");
        MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
        MultipartFile fileM = re.getFile("upFile");
        CommonsMultipartFile cf = (CommonsMultipartFile) fileM;
        InputStream inputStream = cf.getInputStream();

        if (inputStream != null) {
            Workbook workbook = null;
            try {
                workbook = Workbook.getWorkbook(inputStream);
                //處理資料,如果需要userId的話,這裡可以追加
                processData(workbook, response, driveId);
            } catch (Exception e) {
                logger.error("上傳檔案錯誤:" + e);
            }
        }
    } catch (Exception e) {
        logger.error("上傳檔案錯誤:" + e);
    }

}
=============================================================



            response.setContentType("text/html;charset=utf-8");
            MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
            CommonsMultipartFile file = (CommonsMultipartFile) re.getFile("upFile");
            DiskFileItem dfi = (DiskFileItem) file.getFileItem();
            String path = dfi.getStoreLocation().getPath().toString();
            File toFile = new File(path);

            if (toFile != null) {

                //file.transferTo(toFile);
                Workbook workbook = null;
                try {
                    // excel檔案上傳
                    workbook = Workbook.getWorkbook(toFile);
                    //處理資料,如果需要userid的話,這裡可以追加
                    processData(workbook, response);
                } catch (Exception e) {
                    msg = "上傳檔案錯誤!";
                }
            }
        } catch (Exception e) {
            msg = "上傳檔案錯誤!";
        }

        // return null;
    }


    private String processData(Workbook workbook, final HttpServletResponse response) {
        String msg = null;
        try {            // 獲取第一頁
            Sheet sheet = workbook.getSheet(0);
            // 獲取行數
            int rows = sheet.getRows();
            if (rows > 1) {
                // 獲取有多少列
                int columns = sheet.getColumns();
                int titleLength = STORE_HOUSE_IMPORT_TEMP_FILE_TITLE.length;
                // 比較title數量與sheet實際列數,切掉多餘列
                if (columns > titleLength)
                    columns = titleLength;

                List<List<String>> resultList = new ArrayList<List<String>>();
                List<List<String>> successResultList = new ArrayList<List<String>>();
                //儲存excel中所有行的資料,用來辨別找不到父親的記錄
                List<String[]> allDatas = getAllExcelData(rows, sheet);
                //檢驗excel中是否存在重複
                List<List<String>> checkResultList = new ArrayList<List<String>>();
//=========================================================
                //取出資料表中的所有記錄,放入記憶體
                Structure a = new Structure();
                List<Structure> list = structureService.selectEntitys(a);
//=========================================================


                boolean checkAllSuccess = true;
                // 從第1行開始遍歷,i=0時候是標題行
                for (int i = 1; i < rows; i++) {
                    // data儲存每一行的所有資料(所有列)
                    String[] datas = new String[titleLength + 2];
                    // 如果名稱(第一列)為空則不校驗此行資料
                    if (StringUtils.isBlank(sheet.getCell(0, i).getContents()) && StringUtils.isBlank(sheet.getCell(2, i).getContents())) {
                        continue;
                    }
                    for (int j = 0; j < columns; j++) {
                        Cell cell = sheet.getCell(j, i);
                        if (StringUtils.isNotBlank(cell.getContents())) {
                            datas[j] = cell.getContents().trim();
                        } else {
                            datas[j] = "";
                        }
                    }

                    String[] datasClon = datas.clone();
                    if (columns == titleLength) {
                        //校驗資料
                        String result = checkData(datas, datasClon, list);
                        //檢驗excel中是否有重複資料
                        result += isExistInExcel(checkResultList, datasClon);
                        checkResultList.add(Arrays.asList(datasClon));
                        //檢測有沒有找不到父親的記錄
                        result += findFather(datasClon, allDatas);


                        int leng = titleLength + 2;
                        if (StringUtils.isNotBlank(result)) {
                            datas[leng - 2] = STORE_HOUSE_FAIL;
                            datas[leng - 1] = result;
                            checkAllSuccess = false;
                        } else {
                            datas[leng - 2] = STORE_HOUSE_SUCCESS;
                            successResultList.add(Arrays.asList(datasClon));
                        }
                    }
                    resultList.add(Arrays.asList(datas));
                }

                // 只有所有的資料都校驗成功後,再進行批量儲存資料
                if (checkAllSuccess) {

                    cleanData(successResultList);

                }
                // 將結果資料匯出
                if (resultList.size() > 0) {
                    String[] titles = new String[columns + 2];
                    for (int i = 0; i < columns; i++) {
                        titles[i] = null;
                    }
                    int leng = titleLength + 2;
                    titles[leng - 2] = "處理結果";
                    titles[leng - 1] = "原因";
                    //如果出錯的話,返回一個excel。
                    commonExportExcel(IMPORT_TEMP_RESULT_NAME, titles, resultList, workbook, response);
                } else {
                    msg = "處理成功!";
                }
            } else {
                msg = "上傳檔案沒有內容資訊!";
            }
        } catch (Exception e) {
            msg = "讀取excel異常!";
        } finally {
            if (workbook != null) {
                workbook.close();
            }
        }


        return msg;
    }


    private String checkData(String[] datas, String[] datasClon, List<Structure> list) {
        String error = "";

//        //檢驗資料是否重複
        error += isExistInDBBySelectAll(datasClon, list);
//
//        // 校驗不能為空的欄位:名稱      編號
        int[] checkIsBlankId = {2};
        error += checkDataIsBlank(datasClon, checkIsBlankId, STORE_HOUSE_IMPORT_TEMP_FILE_TITLE);
//
//        // 校驗期數字段為正整數,長度暫定為15,
//        // 2是地區編號 4是郵編 7是電話 8是oldId
//        int[] checkBatchNo = {4, 7};
//        for (int i = 0; i < checkBatchNo.length; i++) {
//            if (!StringUtils.isBlank(datas[i]))
//                error += checkNumber(datasClon, checkBatchNo[0], STORE_HOUSE_IMPORT_TEMP_FILE_TITLE, "+", 15);
//        }
        return error;
    }


    /**
     * 校驗不能為空的欄位
     *
     * @param datas      需要校驗的資料
     * @param titleId    需要校驗的欄位在資料陣列中的位置
     * @param titleNames 需要校驗的資料的所有欄位的中文名稱
     * @return
     */
    private String checkDataIsBlank(String[] datas, int[] titleId, String[] titleNames) {
        String error = "";
        if (titleId != null && datas != null && titleNames != null) {
            for (int i = 0; i < titleId.length; i++) {
                int checkId = titleId[i];
                String checkValue = datas[checkId];
                if (StringUtils.isBlank(checkValue)) {
                    error += titleNames[checkId] + "為空,";
                }
            }
        }
        return error;
    }

    /**
     * @param datas      需要校驗的資料
     * @param titleId    需要校驗的欄位在資料陣列中的位置
     * @param titleNames 需要校驗的資料的所有欄位的中文名稱
     * @param type       "0+":非負整數 "+":正整數 "-0":非正整數 "-":負整數 "":整數
     * @param MaxLength  數字的最大位數
     * @return
     */
    private String checkNumber(String[] datas, int titleId, String[] titleNames, String type, int MaxLength) {
        String error = "";
        String eL = "";
        String value = "";
        if (type.equals("0+")) {
            eL = "^\\d+$";// 非負整數
            value = "非負整數";
        } else if (type.equals("+")) {
            eL = "^\\d*[1-9]\\d*$";// 正整數
            value = "正整數";
        } else if (type.equals("-0")) {
            eL = "^((-\\d+)|(0+))$";// 非正整數
            value = "非正整數";
        } else if (type.equals("-")) {
            eL = "^-\\d*[1-9]\\d*$";// 負整數
            value = "負整數";
        } else {
            eL = "^-?\\d+$";// 整數
            value = "整數";
        }

        if (datas != null && titleNames != null) {
            String checkValue = datas[titleId];
            java.util.regex.Pattern p = java.util.regex.Pattern.compile(eL);
            Matcher m = p.matcher(checkValue);
            boolean b = m.matches();
            if (!b) {
                error += titleNames[titleId] + "不是" + value;
            } else {
                int length = checkValue.length();
                if (length > 2 && "-".equals(checkValue.substring(0, 1))) {
                    length = length - 1;
                }
                if (length > MaxLength) {
                    error += titleNames[titleId] + "大於" + MaxLength + "位的" + value;
                }
            }

        }

        return error;
    }


    /**
     * 匯出excel檔案
     *
     * @param name     檔名
     * @param titles   標題
     * @param dataList 內容資料
     * @param response
     */
    public void commonExportExcel(String name, String[] titles, List<List<String>> dataList, Workbook workbook, HttpServletResponse response) {
        try {

            response.setCharacterEncoding("utf-8");
            response.setContentType("aplication/msexcel;charset=utf-8"); // 設定檔案型別
            response.setHeader("Content-disposition", "attachment; filename=" + name + ".xls");

            WritableWorkbook book = null;
            WritableSheet sheet = null;

            WorkbookSettings settings = new WorkbookSettings();
            settings.setWriteAccess(null);


            if (workbook != null) {
                book = Workbook.createWorkbook(response.getOutputStream(), workbook, settings); // 建立檔案
                sheet = book.getSheet(0);
            } else {
                book = Workbook.createWorkbook(response.getOutputStream());
                sheet = book.createSheet("sheet", 0);
            }

            if (titles != null) {
                Cell cell = sheet.getCell(0, 0);
                for (int i = 0; i < titles.length; i++) {
                    String title = titles[i];
                    if (StringUtils.isNotBlank(title)) {
                        Label label = new Label(i, 0, titles[i]);
                        label.setCellFormat(cell.getCellFormat());
                        sheet.addCell(label);
                    }
                }
            }

            for (int i = 0; i < dataList.size(); i++) {
                List<String> list = dataList.get(i);
                for (int j = 0; j < list.size(); j++) {
                    Label label = new Label(j, i + 1, list.get(j));
                    sheet.addCell(label);
                }
            }
            book.write();
            book.close();
        } catch (Exception e) {

        }
    }

    /**
     * 判斷excel中是否有重複資料
     *
     * @param datas
     * @param current
     * @return
     */
    private String isExistInExcel(List<List<String>> datas, String[] current) {
        String error = "";
        for (int i = 0; i < datas.size(); i++) {
            Boolean check = true;
            for (int j = 0; j < datas.get(i).size() - 2; j++) {
                if (!current[j].equals(datas.get(i).get(j))) {
                    check = false;
                    break;
                }
            }
            if (check) {
                error += "與excel第" + (i + 1) + "行重複;";
            }
        }
        return error;
    }

    /**
     * 判斷此記錄資料庫中是否已經存在,目前是根據裝置所屬專案,裝置名稱,兩個來確定一條記錄
     * <p/>
     * 這種方式是先將資料表中所有資料都取出來放入記憶體中,然後每一條資料都到這個list中進行匹配,這樣
     * 只訪問一次資料庫,其他全在記憶體中操作,速度會非常快,但有可能會消耗大量記憶體,目前沒有觀察到記憶體方面都壓力
     *
     * @param datas
     * @return
     */

    private String isExistInDBBySelectAll(String[] datas, List<Structure> list) {
        String error = "";
        Long projectId = new Long(-1);
        //
        if (StringUtils.isNotBlank(datas[0])) {
            projectId = selectProjectName(datas[0]).getId();
        }

        //迴圈從記憶體中取出結果
        for (int i = 0; i < list.size(); i++) {
            Structure structure = new Structure();
            structure = list.get(i);

            if ( structure.getProjectId()==projectId
                    && datas[2].equals(structure.getName())) {
                error += "此條記錄資料庫已存在;";
                break;
            }
            }

        return error;
    }

    /**
     * 根據project名稱名稱取id
     *
     * @param
     * @return
     */
    private Project selectProjectName(String projectName) {
        Project project = new Project();
        project.setName(projectName);
        return projectService.selectEntity(project);
    }

    /**
     * 根據parentName取ID
     *
     */
    private Structure selectStructureParentId(String ParentName) {
        Structure structure = new Structure();
        structure.setName(ParentName);
        return structureService.selectEntity(structure);
    }

    /**
     * 儲存資料
     *
     * 這裡的儲存資料比較特殊,必須按層級來儲存,先儲存祖先,再儲存第二輩祖先
     * 保證有祖先的都能在資料庫裡面找到id號,而且能走到這一步的資料,都是肯定能找到祖先的
     *
     * @param dataList 入庫資料
     */
    private void saveData(List<List<String>> dataList) {

        List<Structure> structures = new ArrayList<Structure>();

        for (List<String> data : dataList) {
            Structure structure = new Structure();
            Long projectId = null;
            Long structureId = null;
            //專案id,專案名稱不為空時候,用它去取對應的id
            if (StringUtils.isNotBlank(data.get(0)))
                projectId = selectProjectName(data.get(0)).getId();
            //parentId
            if (StringUtils.isNotBlank(data.get(1)))
               structureId = selectStructureParentId(data.get(1)).getId();

            structure.setProjectId(projectId);
            structure.setParentId(structureId);
            structure.setName(data.get(2));
            structure.setCode(data.get(3));

            structures.add(structure);
        }
        structureService.insertBatch(structures);
    }

    /**
     * 整理資料,把資料分層
     */
    private List<List<String>> cleanData(List<List<String>> dataList){
        Map<String,Object> a = new HashMap<String, Object>();
        //先把父親為空的放進去
        a = findRoot(dataList);
        List<List<String>> paixu = (List<List<String>>) a.get("root");
        dataList = (List<List<String>>) a.get("dataList");
        a.clear();
        saveData(paixu);
        //遞迴,一級級走下去
        while (dataList.size()!=0){
        //再把第二級放進去
        a = findNextRoot(dataList,paixu);
        List<List<String>> paixuN = (List<List<String>>) a.get("root");
        dataList = (List<List<String>>) a.get("dataList");
        a.clear();
        saveData(paixuN);
        paixu=paixuN;
        }
        return null;
    }

    /**
     * 尋找第一層的祖先
     */
    private Map<String,Object> findRoot(List<List<String>> dataList){
        List<List<String>> root = new ArrayList<List<String>>();
        Map<String,Object> a = new HashMap<String, Object>();
        //祖先加入root
        for (List<String> data : dataList) {
            if (!StringUtils.isNotBlank(data.get(1))){
                root.add(data);
            }
        }
        //祖先加完後,從總資料中移除
        for(List<String> data : root){
            dataList.remove(data);
        }
        a.put("root",root);
        a.put("dataList",dataList);
        return a;
    }
    /**
     * 尋找第二級祖先,
     */
    private Map<String,Object> findNextRoot(List<List<String>> dataList,List<List<String>> paixu){
        List<List<String>> root = new ArrayList<List<String>>();
        Map<String,Object> a = new HashMap<String, Object>();
        for (List<String> data : dataList) {
            for (List<String> dataCompare : paixu){
                if (data.get(1).equals(dataCompare.get(2))){
                    root.add(data);
                    break;
                }
            }
        }

        //祖先加完後,從總資料中移除
        for(List<String> data : root){
            dataList.remove(data);
        }

        a.put("root",root);
        a.put("dataList"