java如何利用poi解析doc和docx中的數(shù)據(jù)
前言
這個(gè)功能是工作中遇到的一個(gè)需求,需要把上傳的word中的內(nèi)容解析出來(lái),其中包含段落字符串解析,和表格中的數(shù)據(jù)解析出來(lái),需要支持doc和docx格式的數(shù)據(jù)
Apache POI是Apache軟件基金會(huì)的開(kāi)源項(xiàng)目,POI提供API給Java程序?qū)icrosoft Office格式檔案讀和寫(xiě)的功能。 .NET的開(kāi)發(fā)人員則可以利用NPOI (POI for .NET) 來(lái)存取 Microsoft Office文檔的功能。
方法如下:
1、增加maven中的包
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>3.17</version> </dependency> <!--POI包 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency>
2、解析doc中的數(shù)據(jù)
獲取文件,把MultipartFile對(duì)象的數(shù)據(jù)轉(zhuǎn)成本地file
File file = new File(FileUtils.getUserDirectoryPath() + "/" + multipartFile.getOriginalFilename()); FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
String fileName = file.getName().toLowerCase(); FileInputStream in = new FileInputStream(file); if (fileName.endsWith(".doc")) { // 處理doc格式 即office2003版本 handlerDoc(in); } if (fileName.endsWith(".docx")) { handlerDocx(in); }
解析doc格式中的段落和第一個(gè)表格數(shù)據(jù)
/** * doc 格式解析 * * @param in * @throws IOException */ private void handlerDoc(FileInputStream in) throws IOException { POIFSFileSystem pfs = new POIFSFileSystem(in); HWPFDocument hwpf = new HWPFDocument(pfs); //得到文檔的讀取范圍 Range range = hwpf.getRange(); for (int i = 0; i < range.numParagraphs(); i++) { //段落 Paragraph p = range.getParagraph(i); //段落文本 String paragraphText = p.text().replace("\r", ""); log.info("paragraphText = {}", paragraphText ); if (paragraphText.contains(VALUE_YLYC)) { analyze = false; } } TableIterator it = new TableIterator(range); // 迭代文檔中的表格 // 如果有多個(gè)表格只讀取需要的一個(gè) set是設(shè)置需要讀取的第幾個(gè)表格,total是文件中表格的總數(shù) int set = 1, total = 1; int num = set; for (int i = 0; i < set - 1; i++) { it.hasNext(); it.next(); } while (it.hasNext()) { Map<String, List<String>> tabelText = DocUtils.getTabelDocText((Table) it.next()); log.info("tabelText = {}", tabelText); } // 過(guò)濾多余的表格 while (num < total) { it.hasNext(); it.next(); num += 1; } }
3、解析docx中數(shù)據(jù)
解析docx格式中的段落和第一個(gè)表格數(shù)據(jù)
/** * docx 格式解析 * * @param in * @throws IOException */ private void handlerDocx(FileInputStream in) throws IOException { XWPFDocument xwpf = new XWPFDocument(in); // 獲取word中的所有段落與表格 List<IBodyElement> elements = xwpf.getBodyElements(); // 解析表格后續(xù)不解析 for (IBodyElement element : elements) { // 段落 if (element instanceof XWPFParagraph) { String paragraphText = DocUtils.getParagraphText((XWPFParagraph) element); log.info("paragraphText = {}", paragraphText); } else if (element instanceof XWPFTable) { // 表格 Map<String, List<String>> tabelText = DocUtils.getTabelText((XWPFTable) element); log.info("tabelText = {}", tabelText); } else { log.info("其他內(nèi)容"); } } }
工具類
package com.hundsun.fais.innerreport.utils; import org.apache.poi.hwpf.usermodel.Paragraph; import org.apache.poi.hwpf.usermodel.Table; import org.apache.poi.hwpf.usermodel.TableCell; import org.apache.poi.hwpf.usermodel.TableRow; import org.apache.poi.xwpf.usermodel.*; import java.util.*; /** * @author lvbaolin * @date 2021/4/2 10:39 */ public class DocUtils { /** * docx 格式獲取表格內(nèi)容 * * @param table */ public static Map<String, List<String>> getTabelText(XWPFTable table) { Map<String, List<String>> result = new LinkedHashMap<>(); List<XWPFTableRow> rows = table.getRows(); for (XWPFTableRow row : rows) { String key = null; List<String> list = new ArrayList<>(16); int i = 0; List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { // 簡(jiǎn)單獲取內(nèi)容(簡(jiǎn)單方式是不能獲取字體對(duì)齊方式的) StringBuffer sb = new StringBuffer(); // 一個(gè)單元格可以理解為一個(gè)word文檔,單元格里也可以加段落與表格 List<XWPFParagraph> paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { sb.append(DocUtils.getParagraphText(paragraph)); } if (i == 0) { key = sb.toString(); } else { String value = sb.toString(); list.add(value == null || Objects.deepEquals(value, "") ? null : value.replace(",", "")); } i++; } result.put(key, list); } return result; } /** * docx 獲取段落字符串 * 獲取段落內(nèi)容 * * @param paragraph */ public static String getParagraphText(XWPFParagraph paragraph) { StringBuffer runText = new StringBuffer(); // 獲取段落中所有內(nèi)容 List<XWPFRun> runs = paragraph.getRuns(); if (runs.size() == 0) { return runText.toString(); } for (XWPFRun run : runs) { runText.append(run.text()); } return runText.toString(); } /** * doc 格式的字段解析表格 * @param tb * @return */ public static Map<String, List<String>> getTabelDocText(Table tb) { Map<String, List<String>> result = new HashMap<>(16); //迭代行,默認(rèn)從0開(kāi)始,可以依據(jù)需要設(shè)置i的值,改變起始行數(shù),也可設(shè)置讀取到那行,只需修改循環(huán)的判斷條件即可 for (int i = 0; i < tb.numRows(); i++) { List<String> list = new ArrayList<>(16); int x = 0; TableRow tr = tb.getRow(i); String key = null; //迭代列,默認(rèn)從0開(kāi)始 for (int j = 0; j < tr.numCells(); j++) { //取得單元格 TableCell td = tr.getCell(j); StringBuffer sb = new StringBuffer(); //取得單元格的內(nèi)容 for (int k = 0; k < td.numParagraphs(); k++) { Paragraph paragraph = td.getParagraph(k); String s = paragraph.text(); //去除后面的特殊符號(hào) if (null != s && !"".equals(s)) { s = s.substring(0, s.length() - 1); } sb.append(s); } if (x == 0) { key = sb.toString(); } else { String value = sb.toString(); list.add(value == null || Objects.deepEquals(value, "") ? null : value.replace(",", "")); } x++; } result.put(key, list); } return result; } }
總結(jié)
到此這篇關(guān)于java如何利用poi解析doc和docx中數(shù)據(jù)的文章就介紹到這了,更多相關(guān)java poi解析doc數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用JPA實(shí)現(xiàn)查詢部分字段
這篇文章主要介紹了SpringBoot使用JPA實(shí)現(xiàn)查詢部分字段方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java基于elasticsearch實(shí)現(xiàn)集群管理
這篇文章主要介紹了java基于elasticsearch實(shí)現(xiàn)集群管理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02使用JMX連接JVM實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了使用JMX連接JVM實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Mybatis報(bào)錯(cuò)mapkey is required問(wèn)題及解決
這篇文章主要介紹了Mybatis報(bào)錯(cuò)mapkey is required問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06java開(kāi)發(fā)Dubbo負(fù)載均衡與集群容錯(cuò)示例詳解
這篇文章主要為大家介紹了java開(kāi)發(fā)Dubbo負(fù)載均衡與集群容錯(cuò)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11