遇到一个小需求,公司写好了N个系统的设计方案(数据量比较大,不太适合收到复制粘贴这样搞),懂的都懂啊,N个系统的设计方案写在一个word文档中,现在要求将word文档将这N个系统设计方案中的标题以及描述提取出来,放到Excel中,方便进行分配任务。
如下图:
变成如下图
这样的话,就能更好地给开发人员分配任务。最终转换完成后是三千多行。代码如下:需要注意的是,标红的要根据自己的需求进行修改,主要包括word的路径以及excel的路径等,前提是创建一个excel表格用来接收数据。
使用以下代码的前提:一个word文档用来读取,一个excel文档用来输出!!!
package org.com.poi; import org.apache.commons.codec.binary.StringUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xwpf.usermodel.*; import java.io.*; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @Author * @Description 将word的内容进行格式化处理输出到Excel中 加强优化版 * @Date 2021-10-08 22:30 **/ public class PoiTest002 { private static Map<String,Map<String,Object>> orderMap =new HashMap<String, Map<String,Object>>(); private static final String EXCEL_XLS = "xls"; private static final String EXCEL_XLSX = "xlsx"; public static void main(String[] args) {
//以下标红的根据自己本地环境进行设置 String wordPath = "E:\\DawaFiles\\a.docx"; String excelPath = "E:\\DawaFiles\\a.xls"; String startStr = "项目管理系统"; String endStr = "应用支撑系统设计"; getWordOutExcel(wordPath,excelPath,startStr,endStr); } /** * @Author * @Description 获取word内容进行格式化并输出到Excel * @Date 2021-10-08 22:28 **/ public static void getWordOutExcel(String wordPath,String excelPath,String startStr,String endStr){ InputStream is = null; XWPFDocument doc=null; OutputStream out=null; try { is = new FileInputStream(wordPath); doc = new XWPFDocument(is); List<XWPFParagraph> paras=doc.getParagraphs(); //获取段落 String projectName = ""; String finalXlsxPath = excelPath; //写出到excel File finalXlsxFile = new File(finalXlsxPath); Workbook workBook = getWorkbok(finalXlsxFile); Sheet sheet = workBook.getSheetAt(0); //sheet 对应一个工作页 Row rowStart = sheet.createRow(0); //设置标题 setExcelTitile(rowStart); //设置excel标题 int num = 0; boolean start = false; //开启标识 for (XWPFParagraph para : paras){ String titleLvl = getTitleLvl(doc,para);//获取段落级别 String text = para.getParagraphText(); if (StringUtils.equals(startStr,text)){ //当读取内容为开始字符串时 将开启标识设置为true 开始将数据写出excel start = true; } if (StringUtils.equals(endStr,text)){ //当读取内容为结束字符串时 停止将数据写出excel,并跳出循环 break; } if (!start){ //判断开启标识是否为true 不为true不再继续执行 直接进行下一次循环 continue; } num ++; Row row = sheet.createRow(num); //创建新的一行 if (isTest(titleLvl)){ //当大纲等级为正文时 将描述内容放到上一行的第7列中 num -= 1; //将已经加1的num变量减1 从而达到将描述内容放到上一行中 row = sheet.getRow(num); } setTitleAndText(titleLvl,projectName,text,row); //打印输出 这里注意了啊 从这行打印就能看出来你想要提取内容的大纲等级 !!!! System.out.println(titleLvl+"===="+text); //按照等级和内容进行输出打印,可以通过这个打印输出调整正文以及标题等级的判断 } //创建文件输出流,准备输出电子表格:这个必须有,否则你在sheet上做的任何操作都不会有效 out = new FileOutputStream(finalXlsxPath); workBook.write(out); out.close(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(null!=out){ out.close(); } if(null!=is){ is.close(); } }catch (IOException e) { e.printStackTrace(); } } } /** * @Author * @Description 设置标题和内容 * @Date 2021-10-09 10:44 **/ public static void setTitleAndText(String titleLvl,String projectName,String text,Row row){ if ("2".equals(titleLvl)){ //如果等级为2 将项目名称保存下来 这一块需要注意 检查你想要的最高大纲等级是几,我这需要获取的最高大纲等级为2 projectName = text; Cell ling = row.createCell(0); //按照大纲等级,依次将数据对应该列进行填充 ling.setCellValue(projectName); }else if("3".equals(titleLvl)){ Cell first = row.createCell(1); //按照大纲等级,依次将数据对应该列进行填充 first.setCellValue(text); }else if ("4".equals(titleLvl)){ Cell first = row.createCell(2); //按照大纲等级,依次将数据对应该列进行填充 first.setCellValue(text); }else if ("5".equals(titleLvl)){ Cell first = row.createCell(3); first.setCellValue(text); }else if ("6".equals(titleLvl)){ Cell first = row.createCell(4); first.setCellValue(text); }else if ("7".equals(titleLvl)){ Cell first = row.createCell(5); first.setCellValue(text); }else if ("8".equals(titleLvl)){ Cell first = row.createCell(6); first.setCellValue(text); }else if (isTest(titleLvl)){ //判断是否为正文 Cell cell = row.getCell(7); //进行判断,获取当前行当前列是否已经有值 if (cell != null && cell.getStringCellValue() != null){ //如果当前列已存在,并且也存在值 String stringCellValue = cell.getStringCellValue(); //获取已经存在的值 stringCellValue += text; //将新值进行追加 cell.setCellValue(stringCellValue); //进行赋值 }else{ //如果当前行当前列不存在 Cell first = row.createCell(7); //新建该列 first.setCellValue(text); //进行赋值 } } } /** * @Author * @Description 设置Excel标题 * @Date 2021-10-09 10:39 **/ public static void setExcelTitile(Row row){ //菜单级别尽量设置多一点 防止文档中级别过高 String [] titleStr = {"项目名称","模块名称","二级菜单","三级菜单","四级菜单","五级菜单","六级菜单","功能描述"}; for (int k = 0; k < titleStr.length; k++) { //在一行内循环 Cell cell = row.createCell(k); cell.setCellValue(titleStr[k]); } } /** * Word中的大纲级别,可以通过getPPr().getOutlineLvl()直接提取,但需要注意,Word中段落级别,通过如下三种方式定义: * 1、直接对段落进行定义; * 2、对段落的样式进行定义; * 3、对段落样式的基础样式进行定义。 * 因此,在通过“getPPr().getOutlineLvl()”提取时,需要依次在如上三处读取。 * @param doc * @param para * @return */ private static String getTitleLvl(XWPFDocument doc, XWPFParagraph para) { String titleLvl = ""; try { //判断该段落是否设置了大纲级别 if (para.getCTP().getPPr().getOutlineLvl() != null) { return String.valueOf(para.getCTP().getPPr().getOutlineLvl().getVal()); } //判断该段落的样式是否设置了大纲级别 if (doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl() != null) { return String.valueOf(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal()); } //判断该段落的样式的基础样式是否设置了大纲级别 if (doc.getStyles().getStyle(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal()) .getCTStyle().getPPr().getOutlineLvl() != null) { String styleName = doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal(); return String.valueOf(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal()); } if(para.getStyleID()!=null){ return para.getStyleID(); } } catch (Exception e) { //这一块的异常建议别打开 很多空指针 上边的方法不想处理了 有兴趣的可以试着处理一下 //e.printStackTrace(); //注释不影响程序的 } return titleLvl; } /** * @Author 乔成强 * @Description 判断是否为正文,每个文档的正文大纲等级可能不一样, * 所以根据自己的文档进行调整,以下只是我个人的文档正文大纲等级, * 需要自己根据输出以及excel结果进行调整 * @Date 2021-10-08 21:25 **/ public static boolean isTest(String titleLvl){
//以下内容根据自己本地需求进行修改 if ("68".equals(titleLvl) || titleLvl == "" || titleLvl.equals("1309") || titleLvl.equals("1338") || titleLvl.equals("141") || titleLvl.equals("19") || titleLvl.equals("319") || titleLvl.equals("1308")){ return true; }else{ return false; } } /** * 判断Excel的版本,获取Workbook * @return * @throws IOException */ public static Workbook getWorkbok(File file) throws IOException{ Workbook wb = null; FileInputStream in = new FileInputStream(file); if(file.getName().endsWith(EXCEL_XLS)){ //Excel 2003 wb = new HSSFWorkbook(in); }else if(file.getName().endsWith(EXCEL_XLSX)){ // Excel 2007/2010 wb = new XSSFWorkbook(in); } return wb; } }