1. 程式人生 > >Java導入導出Excel和Word

Java導入導出Excel和Word

數據 自定義 cto pdf icc creat extends 代碼 鏈接

目的

實現Excel/Word導入導出,分以下步驟

  • 導入
    • 上傳文件
    • 解析Excel/Word裏面的內容
  • 導出
    • 生成Excel/Word文件
    • 文件下載

如何實現

  • 上傳文件----------Commons FileUpload上傳組件
  • Excel/Word-------Apache POI----Apache軟件基金會的開放源碼函式庫,POI提供API給Java程序對Microsoft Office格式檔案讀和寫的功能。
  • 下載文件----------ServletOutputStream直接輸出文件流

簡單的demo實現

首先需要這麽幾個jar包,紅色的部分是處理文件上傳需要的jar包

,藍色部分是JSTL標簽庫需要jar包,其他就是處理EXCEL/WORD的jar包

技術分享圖片

這裏插一段遇到的問題

IDEA將WEB-INF/lib目錄指定為jar目錄,並且將相應的jar包復制過去,但IDEA不提示相關類

解決方案:手動重新導入,更多操作方式看這個貼 https://blog.csdn.net/gdsgdh308227363/article/details/82930321

技術分享圖片

文件上傳demo

/*
 * @author MrPeng
 * @date 2019/1/29
 */
@WebServlet("/importExcel")
public class ImportExcelServlet extends
HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //表單上傳到這個Servlet中解析 //判斷表單提交是否存在enctype="multipart/form-data"屬性,也就是有文件流上傳,這種表單getParameter方式是拿不到值的 //需要導入commons-fileupload和commons-io這2個包
if (ServletFileUpload.isMultipartContent(request)){ //創建ServletFileUpload對象,默認配置即可 ServletFileUpload upload =new ServletFileUpload(new DiskFileItemFactory()); //設置編碼utf-8 upload.setHeaderEncoding("UTF-8"); try { //從請求中解析出各種表單控件 List<FileItem> fileItemList = upload.parseRequest(request); for (FileItem fileItem:fileItemList){ //判斷是普通表單 if (fileItem.isFormField()){ //獲取表單的name和value System.out.println(fileItem.getFieldName()+‘:‘+fileItem.getString("UTF-8")); }else{ //說明是個文件流 System.out.println(fileItem.getFieldName()); //直接寫到一個文件中--上傳成功 fileItem.write(new File("D:/JavaWeb/ExcelWord/web/upload/"+fileItem.getName())); } } } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }else{ //request.getParameter("") } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }

處理Excel解析/生成Demo

這裏需要理解一下POI中的類與EXCEL之間的關系

  • Excel對象本身對應------------POI中WorkBook類
  • Excel中sheet1/2/3對應-------POI中Sheet類
  • Excel中每一行對應------------POI中Row類
  • Excel中每一個單元格---------POI中Cell類
/**處理EXCEL的類
 * @author MrPeng
 * @date 2019/1/29
 */
public class ExcelServiceDemo {

    /**
     * 解析excel
     */
    public void impDemo(){
        try {
            //通過工廠方法創建excel對象
            Workbook workbook = WorkbookFactory.create(new File("D:/JavaWeb/ExcelWord/web/upload/import_03_excel.xls"));
            //處理第一個區域默認0開始
            Sheet sheet =workbook.getSheetAt(0);
            //獲取有效數據的最後行數,默認首行從0開始
            int rowNum = sheet.getLastRowNum();
            //循環遍歷每一行,從第2行開始,第一行是標題
            for (int i = 1; i <=rowNum ; i++) {
                Row row= sheet.getRow(i);
                //獲取每一行每個單元格的數據,默認也是從開始的,並解析成對應格式的數據
                System.out.println("姓名:"+row.getCell(0).getStringCellValue());
                System.out.println("年齡:"+row.getCell(1).getNumericCellValue());
                System.out.println("時間:"+row.getCell(2).getDateCellValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 導出excel
     * @param isXlsx 是否導出07版  03版後綴為xls ,07版為xlsx
     * @return
     */
    public void exportDemo(boolean isXlsx) {
        Workbook workbook = null;
        if (isXlsx) {
            //創建07版excel對象 ,07版有些新特性在這個類裏有實現
            workbook = new XSSFWorkbook();
        } else {
            //創建03版excel對象
            workbook = new HSSFWorkbook();
        }
        //創建工作區域sheet,自定義名字
        Sheet sheet = workbook.createSheet("My Sheet");
        //模擬假數據建一個getContent()方法獲取一個二維MAP數組
        List<List<String>> content = this.getContent();
        //外層循環控制行
        for (int i = 0; i < content.size(); i++) {
            //創建一行
            Row row = sheet.createRow(i);
            List<String> rowData = content.get(i);
            //內層循環控制每個單元格
            for (int j = 0; j < rowData.size(); j++) {
                //創建單元格,並設置值
                row.createCell(j).setCellValue(rowData.get(j));
            }
        }

        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream("D:\\JavaWeb\\ExcelWord\\web\\upload\\demo-07.xlsx");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //先將excel對象保存到文件輸出流--可以不保留文件
        //workbook.write(outputStream);//也就是直接寫入ServletOutputStream輸出流對象中
        try {
            workbook.write(fileOutputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                workbook.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

處理Word解析生成Demo

/**Word解析生成Demo
 * @author MrPeng
 * @date 2019/1/29
 */
public class WordServiceDemo {
    /**
     * 解析03Word, 由於03和07差異較大 實際處理策略是先用03的解析 在用07的解析
     */
    public void imp03() {
        HWPFDocument doc = null;
        //嘗試03版的解析
        try {
            //創建對象--文件流方式 如果需要保存文件,則可以使用File對象創建
            doc = new HWPFDocument(new FileInputStream("D:/JavaWeb/ExcelWord/web/upload/import_03_word.doc"));
            //直接獲取doc中的文本信息,如果是原樣一般是轉PDF
            String text = doc.getDocumentText();
            //替換成html中的換行
            text=text.replace("\r","<br/>");
            //輸出解析的文本
            System.out.println(text);
        } catch (OfficeXmlFileException oe) {
            //版本可能不對
            System.out.println("這可能是一個07版的Word");
        } catch (Exception e) {
            //解析錯誤
            e.printStackTrace();
        } finally {
            //釋放資源
            if(doc != null) {
                try {
                    doc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 解析07版
     */
    public void imp07()
    {
        XWPFDocument docx = null;
        try {
            //創建07版Word對象--文件流方式
            docx = new XWPFDocument(new FileInputStream("D:/JavaWeb/ExcelWord/web/upload/import_07_word.doc"));
            //從每一個段落取文本--當文字出現換行符認為是一個段落
            List<XWPFParagraph> paragraphList = docx.getParagraphs();
            StringBuilder content = new StringBuilder();
            for (int i = 0; i < paragraphList.size(); i++) {
                //換行處理
                if(i != 0) {
                    content.append("<br/>");
                }
                content.append(paragraphList.get(i).getText());
            }
            //輸出文本
            System.out.println(content.toString());
        } catch (IOException e) {
            //解析錯誤
            e.printStackTrace();
        } finally {
            if(docx != null) {
                try {
                    docx.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 導出03版Word
     * @param replaceContent--需要替換的東西k-v
     * @return
     */
    public HWPFDocument export03(Map<String,String> replaceContent) {
        HWPFDocument doc = null;
        try {
            //創建03Word對象
            doc = new HWPFDocument(new FileInputStream("D:\\JavaWeb\\ExcelWord\\web\\template\\template_03.doc"));
            //獲取Word文檔範圍
            Range range = doc.getRange();
            //替換模板中的變量
            for(Map.Entry<String,String> entry : replaceContent.entrySet()) {
                range.replaceText(entry.getKey(),entry.getValue());
            }
        } catch (Exception e) {
            //這裏不能有finally關閉doc,否則servlet不能將其寫入response響應流
            return null;
        }
        //返回doc對象,可以選擇像之前的excel導出處理 是否保留文件
        return doc;
    }

    /**
     * 導出07版Word
     * @param replaceContent--需要替換的東西k-v
     * @return
     */
    public XWPFDocument export07(Map<String,String> replaceContent) {
        XWPFDocument docx = null;
        try {
            //創建07版WORD對象
            docx = new XWPFDocument(new FileInputStream("D:\\JavaWeb\\ExcelWord\\web\\template\\template_07.docx"));
            //獲取每一個段落
            List<XWPFParagraph> paragraphList = docx.getParagraphs();
            for(XWPFParagraph paragraph : paragraphList) {
                //07版段落還不是最小單位,遇到不同樣式或者格式的文本也可能再拆分
                List<XWPFRun> runs = paragraph.getRuns();
                for(XWPFRun run : runs) {
                    //獲取最小單元的文本
                    String str = run.getText(run.getTextPosition());
                    //將key替換成value
                    for(Map.Entry<String,String> entry : replaceContent.entrySet()) {
                        str = str.replace(entry.getKey(),entry.getValue());
                    }
                    //直接賦值回去
                    run.setText(str,0);
                }
            }
        } catch (IOException e) {
            return null;
        }
        return docx;
    }
}

最後附上完整代碼

一個實現上訴操作的建議Web應用

鏈接:https://pan.baidu.com/s/1al8_ux3LF6SJtBfXz4Z4-Q
提取碼:u3a6

Java導入導出Excel和Word