当前位置: 首页 > wzjs >正文

太仓网站建设有限公司网站兼容代码

太仓网站建设有限公司,网站兼容代码,2023年生鲜电商交易规模超6000亿,asp.net建网站项目背景: 当我们对一些word文档(该文档包含很多的标题比如 1.1 ,1.2 , 1.2.1.1, 1.2.2.3)当我们删除其中一项或者几项时,需要手动的对后续的进行补充。该功能主要是对标题进行自动的补充。 具…

项目背景:

当我们对一些word文档(该文档包含很多的标题比如 1.1 ,1.2 , 1.2.1.1, 1.2.2.3)当我们删除其中一项或者几项时,需要手动的对后续的进行补充。该功能主要是对标题进行自动的补充。

具体步骤:

导入依赖:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>

官网网址:(觉得麻烦不可也许)

Apache Poi 官方链接 可以看官方文档,其实更方便的可以直接导入依赖后,下载源代码,直接看源码的注释也许

跑一下代码熟悉一下

首先把下面的代码复制到编译器跑一下,看看是否正常运行,顺便了解基本使用

package codeByZyc;import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;
import java.io.IOException;public class rederWordTest {public static void main(String[] args) throws IOException {FileInputStream file = new FileInputStream("输入你的word文档地址");XWPFDocument document = new XWPFDocument(file);// 获取word中的段落,无法获取表格System.out.println("获取到的段落");for (XWPFParagraph paragraph : document.getParagraphs()) {System.out.println(paragraph.getText());}//  这是只能获取word中的表格System.out.println("获取到的表给内容");for (XWPFTable table : document.getTables()) {for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {System.out.print(cell.getText() + " \t");}System.out.println();}}document.close();file.close();}}

api说明

通过上面的代码,我们可以知道poi是用过XWPFDocument这个类去获取的word内容。 下面从段落和表格两部分进行代码说明

段落api说明

对于word中的段落他的操作如下:

XWPFDocument(最大的模块).getParagraphs->Paragraph(负责每一个段落).getRuns->Run(这是最小处理的元素)

下面是进行调式的图片,配合图片更好理解:

XWPFDocument:就是最大的那个模块 信息很大

在这里插入图片描述

Paragraphs:这是所有的段落集合

在这里插入图片描述

Paragraph:存放的就是每一段了 里面的runs 是按照格式进行分割的

在这里插入图片描述

Runs run的集合

具体看下面

Run(最基础的元素)

这是最重要的那个元素,他是构成所有段落和表格的最小单位。
一个段落他是如何划分成几个run的?
他是按照每个字的前后 是否同一个格式(字体,加粗否,大小等)必须完全一样才能分到一个run里面。具体分割还得调式看

下图是一些run的切割:
在这里插入图片描述
这个就是特殊的符号会被划开
在这里插入图片描述
这个更离谱 注意 1.3.1后面的空格没有 ,这个的空格是被划开的。是因为空格的格式和标题不一样
在这里插入图片描述

段落代码(直接看结尾的整合代码,写得更详细注释更全面):里面有注释 应该算比较清楚了 有问题可以下面评论

文件路径自己填写一下

package codeByZyc;import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class word {// 匹配数字开头,小数点隔开 空格后接内容static Pattern headerPattern = Pattern.compile("^(\\d+(?:\\.\\d+)*)(\\s+.*)");//用于计算层级static ArrayList<Integer> headerlist= new ArrayList();//用于存放段落开头有单个特殊符号的static ArrayList<String> kaitou =new ArrayList<>();// 匹配中文括号列表项(如 (1))
//   static Pattern listItemPattern = Pattern.compile("^((\\d+))(.*)$");public static void main(String[] args) {String path="文件路径";//初始化计算器for (int i = 0; i < 10; i++) {headerlist.add(0);}//初始化开头特殊字符kaitou.add("★");kaitou.add("*");//执行代码updateWord(path);}public static void updateWord(String path){try {// 1. 读取 .docx 文件FileInputStream fis = new FileInputStream(path);XWPFDocument document = new XWPFDocument(fis);//获取word每一个段落元素(不包含表格的)List<XWPFParagraph> paragraphs = document.getParagraphs();//  //一个段落一个段落的处理for (int i = 0; i < paragraphs.size(); i++) {wordDuanluo(paragraphs.get(i));}//开始村存回去FileOutputStream out = new FileOutputStream("文件路径代码生成.docx");document.write(out);// 4. 关闭流document.close();fis.close();out.close();} catch (Exception e) {e.printStackTrace();}}//处理段落private static void wordDuanluo(XWPFParagraph paragraph) {//每个段落下面还有更小的元素,叫run 所以处理runList<XWPFRun> runs = paragraph.getRuns();//直接匹配第一个 是那就是标题 不是那就是正文if (runs.size()==1){wordRun(runs.get(0));}else if (runs.size()==2){//只有两个识别开头是不是包含特殊  时走一个通道 不是走二通道//标志是否匹配boolean flagkaitou= false;for (int i = 0; i < kaitou.size(); i++) {if (kaitou.get(i).equals(runs.get(0).text())){flagkaitou=true;break;}}if (flagkaitou==true){//证明开头匹配走一同到wordRun(runs.get(1));}else {//不匹配wordRun(runs.get(0),runs.get(1));}}else if (runs.size()>2){//数量在三个及以上//标志是否匹配boolean flagkaitou= false;for (int i = 0; i < kaitou.size(); i++) {if (kaitou.get(i).equals(runs.get(0).text())){flagkaitou=true;break;}}if (flagkaitou==true){//证明开头匹配wordRun(runs.get(1),runs.get(2));}else {//不匹配wordRun(runs.get(0),runs.get(1));}}}// 处理非常特殊的 标题后面跟的空格字体和标题不一样分开了 进行拼接private static void wordRun(XWPFRun run1, XWPFRun run2) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run1.text()+run2.text());if (matcher.find()) {//匹配成功//保存序号后面的文章用于拼接String contex = matcher.group(2);//按照.进行切割String[] originalParts = matcher.group(1).split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);//序号放到run1  空格+正文放到run2run1.setText(result.toString(),0);run2.setText(contex,0);}}private static void wordRun(XWPFRun run) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run.text());if (matcher.find()) {//匹配成功//保存序号后面的文章用于拼接String contex = matcher.group(2);//按照.进行切割String[] originalParts = matcher.group(1).split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);result.append(contex);//将内容替换到runrun.setText(result.toString(),0);}}}
表格api说明 基本上和段落一样 有一点点不一样
XWPFDocument(最大的模块).getTables->XWPFTable(负责每一个表格).getRows->Row(代表一行).getTableCells->XWPFTableCell(每一格子)[由于cell无法更改具体看下图] 需要深入到 run

注意,我原来以为在cell就可以更改他的文本
在这里插入图片描述
但是看源码可以知道 他是在尾部追加并不是覆盖,所以还是只能追到run去覆盖。

表格代码:(直接看结尾的整合代码,写得更详细注释更全面)
import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class TestWord {// 匹配表格的 结尾开头是数字 空格几个都行static  Pattern tablePattern = Pattern.compile("^(\\d+)(\\s*)$");static  Integer tableCount=0;//用于存放段落开头有单个特殊符号的static ArrayList<String> kaitou =new ArrayList<>();public static void main(String[] args) {String path="测试table.docx";//初始化开头特殊字符kaitou.add("★");kaitou.add("*");readWord(path);}public static void readWord(String filePath){try {// 1. 读取 .docx 文件FileInputStream fis = new FileInputStream(filePath);XWPFDocument document = new XWPFDocument(fis);//直接一层一层找一下找到 run  试过在cell进行修改 但是cell的修改是 原来的基础上进行了新的增加 不能进行替换 直接找到run进行替换for (XWPFTable table : document.getTables()) {//一个table 清除一次计数器tableCount=0;for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {for (XWPFParagraph paragraph : cell.getParagraphs()) {List<XWPFRun> runs = paragraph.getRuns();//直接匹配第一行if (runs.size()==1){tableup(runs.get(0));}else if (runs.size()>1){//这边就是 考虑到前面有个特殊符号的情况 就需要判断了XWPFRun run1 = runs.get(0);//第一个不是特殊那就直接走第一通道boolean flag=false;for (int i = 0; i < kaitou.size(); i++) {if (kaitou.get(i).equals(run1.text())){flag=true;break;}}if (flag){tableup(runs.get(1));}else {tableup(run1);}}}}}}System.out.println("测试完成");FileOutputStream out = new FileOutputStream("生成的table.docx");document.write(out);// 4. 关闭流document.close();fis.close();out.close();} catch (Exception e) {e.printStackTrace();}}public  static void  tableup(XWPFRun run){Matcher matcher = tablePattern.matcher(run.text());if (matcher.find()){//匹配成功  开始更换层级String content = matcher.group(2);String originalParts = matcher.group(1);//开始覆盖掉序号 并拼接后面的内容tableCount++;StringBuffer result=new StringBuffer();result.append(tableCount+content);//写入run.setText(result.toString(),0);}}
}

总结

整合代码:

package codeByZyc;import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;public class Upword {// 匹配数字开头,小数点隔开 空格后接内容static Pattern headerPattern = Pattern.compile("^(\\D?)(\\d+(?:\\.\\d+)*)(\\s+)");//用于段落计算层级static ArrayList<Integer> headerlist= new ArrayList();//用于存放段落开头有单个特殊符号的// 匹配表格的 结尾开头是数字 空格几个都行static  Pattern tablePattern = Pattern.compile("^(\\D?)(\\d+)(\\s*)$");//匹配表格的层级static  Integer tableCount=0;// 匹配中文括号列表项(如 (1))
//   static Pattern listItemPattern = Pattern.compile("^((\\d+))(.*)$");public static void main(String[] args) {String path="测试专用删除部分标题.docx";//初始化段落层级计算器for (int i = 0; i < 10; i++) {headerlist.add(0);}//执行代码updateWord(path);}public static void updateWord(String path){try {// 1. 读取 .docx 文件FileInputStream fis = new FileInputStream(path);XWPFDocument document = new XWPFDocument(fis);//获取word每一个段落元素(不包含表格的)List<XWPFParagraph> paragraphs = document.getParagraphs();//  //一个段落一个段落的处理for (int i = 0; i < paragraphs.size(); i++) {wordDuanluo(paragraphs.get(i));}//获取word的表格
//            直接一层一层找一下找到 run  试过在cell进行修改 但是cell的修改是 原来的基础上进行了新的增加 不能进行替换 直接找到run进行替换for (XWPFTable table : document.getTables()) {wordtable(table);}//开始村存回去FileOutputStream out = new FileOutputStream("代码生成.docx");document.write(out);// 4. 关闭流document.close();fis.close();out.close();} catch (Exception e) {e.printStackTrace();}}//处理表格private static void wordtable(XWPFTable table){//一个table 清除一次计数器tableCount=0;for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {for (XWPFParagraph paragraph : cell.getParagraphs()) {List<XWPFRun> runs = paragraph.getRuns();//直接匹配第一行if (runs.size()==1){wordTableRun(runs.get(0));}else if (runs.size()==2){wordTableRun(runs.get(0),runs.get(1));}}}}}//处理段落private static void wordDuanluo(XWPFParagraph paragraph) {//每个段落下面还有更小的元素,叫run 所以处理runList<XWPFRun> runs = paragraph.getRuns();/* 这里需要注意一下因为我的测试文档的需求标题是这样的 *1.2.1 背景展望   像这个 要是格式不一样会被划分成 三个部分  *    1.2.1   还有一个空格  。 但是要是格式一样 就直接化成一个了主要是我的测试文档是有些一样 有些不一样所以需要考虑的比较多。*/if (runs.size()==1){//针对只划分一个的  那没得说 直接走第一个wordRun(runs.get(0));}else if (runs.size()==2){//这就是两个 那可能是两种情况:  *1.2.1  空格   或者 *   1.2.1空格   就是两种了wordRun(runs.get(0),runs.get(1));}else if (runs.size()>2){//数量在三个及以上//这种 就是我上面说的 三个格式都不一样wordRun(runs.get(0),runs.get(1),runs.get(2));}}private static void wordRun(XWPFRun run) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run.text());if (matcher.find()) {//匹配成功String  oldxuaho=matcher.group(2);//按照.进行切割String[] originalParts =oldxuaho.split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//拼接正确的序号//把序号前面的放进来result.append(matcher.group(1));for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);//替换if(run.text().contains(oldxuaho)){//进行替换String s = run.text();s.replace(oldxuaho,result.toString());run.setText(s,0);}}}// 处理非常特殊的 标题后面跟的空格字体和标题不一样分开了 进行拼接private static void wordRun(XWPFRun run1, XWPFRun run2) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run1.text()+run2.text());if (matcher.find()) {//匹配成功String  oldxuaho=matcher.group(2);//按照.进行切割String[] originalParts =oldxuaho.split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//把前面的放进来result.append(matcher.group(1));//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);//查找替换 具体思路看一看下面的if(run1.text().contains(oldxuaho)){//进行替换String s = run1.text();s.replace(oldxuaho,result.toString());run1.setText(s,0);}else if (run2.text().contains(oldxuaho)){String s = run2.text();s.replace(oldxuaho,result.toString());run2.setText(s,0);}}}private static void wordRun(XWPFRun run1, XWPFRun run2,XWPFRun run3) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run1.text()+run2.text()+run3.text());if (matcher.find()) {//匹配成功String oldxuaho=matcher.group(2);//按照.进行切割String[] originalParts = oldxuaho.split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//直接将他们拼起来result.append(matcher.group(1));//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);/*下面就需要考虑 run1 2 3 如何划分了因为我的matcher.group 把他们三个合并的 拆分成了 三部分  (数字标题前面的部分) (数字标题) 空格内容(内容可能有可能无)* 情况1:  最开始说到的  *       1.2.1    空格内容(内容可能有可能无)* 情况2:  也有可能是: *1.2.1   空格内容(内容可能有可能无)     内容情况3:  也有可能是: *      1.2.1空格内容(内容可能有可能无)   内容情况4:  *1.2.1空格内容(内容可能有可能无)  内容  内容解决思路: group(2)匹配的序号 只需要 挨个便利 看看 哪个run包含 进行替换就行其他的保持不变。* *///查找if(run1.text().contains(oldxuaho)){//进行替换String s = run1.text();s.replace(oldxuaho,result.toString());run1.setText(s,0);}else if (run2.text().contains(oldxuaho)){String s = run2.text();s.replace(oldxuaho,result.toString());run2.setText(s,0);}else {String s = run3.text();s.replace(oldxuaho,result.toString());run3.setText(s,0);}}}//处理表格的单元格private static void wordTableRun(XWPFRun run){Matcher matcher = tablePattern.matcher(run.text());if (matcher.find()){//匹配成功  开始更换层级String oldxuhao  = matcher.group(2);//开始覆盖掉序号 并拼接后面的内容tableCount++;String s = run.text();s.replace(oldxuhao,tableCount.toString());//写入run.setText(s,0);}}private static void wordTableRun(XWPFRun run1,XWPFRun run2){Matcher matcher = tablePattern.matcher(run1.text()+run2.text());if (matcher.find()){String oldxuhao=matcher.group(2);//开始覆盖掉序号 并拼接后面的内容tableCount++;String s;if (run1.text().contains(oldxuhao)){s=run1.text();s.replace(oldxuhao,tableCount.toString());run1.setText(s,0);}else if (run2.text().contains(oldxuhao)){s=run2.text();s.replace(oldxuhao,tableCount.toString());run2.setText(s,0);}}}}

难点:

我感觉最大的难点就是对Api的熟悉,需要看看源码或者文档。以及利用正则表达式对标题进行匹配


文章转载自:

http://gY3Wu2Cg.pjphg.cn
http://Vn3aQVib.pjphg.cn
http://MLFeNoe9.pjphg.cn
http://BCR9aWzK.pjphg.cn
http://5e4yeJKr.pjphg.cn
http://NkkpvU4z.pjphg.cn
http://amftEZT1.pjphg.cn
http://O1E21ILl.pjphg.cn
http://YIlJkeLy.pjphg.cn
http://g3goHmjS.pjphg.cn
http://Z5GqMOJu.pjphg.cn
http://C5Cl3gyw.pjphg.cn
http://VVvhRVVR.pjphg.cn
http://w77Arui3.pjphg.cn
http://XFx8Ok3r.pjphg.cn
http://TS2XO2yl.pjphg.cn
http://Wfd5mAMM.pjphg.cn
http://j8kNkCPe.pjphg.cn
http://8juAezgT.pjphg.cn
http://gSYP0iqU.pjphg.cn
http://wP8UqVot.pjphg.cn
http://ezz0hNTa.pjphg.cn
http://mLLN4XoK.pjphg.cn
http://7Q69CNjj.pjphg.cn
http://x4RiExeG.pjphg.cn
http://zth4JeMZ.pjphg.cn
http://FcvffC5K.pjphg.cn
http://hWa1lpNS.pjphg.cn
http://Fpy7Aekx.pjphg.cn
http://cHzj7r4Z.pjphg.cn
http://www.dtcms.com/wzjs/646667.html

相关文章:

  • 电子商务网站功能特点如何做网站霸屏
  • 做网站用什么系统网站建设明细费用
  • 安装php和mysql网站网站建设员招聘
  • 网站建设与管理读书心得东莞本地生活网
  • 洋洋点建站简单网页制作源代码
  • 烟台网站建设团队企业网站模板免费版
  • wordpress网站缓存安装浏览器网页游戏
  • 横岗网站建设多少钱重庆最新情况 最新消息
  • 周口市住房和城乡建设局网站最好的互联网公司
  • 最好建站网站公共资源交易中心主任级别
  • 没网站怎么做二维码扫描连接做公司网站需要什么资料
  • 网站服务器安全配置保健品网站源码
  • 外贸公司手机网站中国乐清网
  • 网站后台账号密码忘记了怎么办门窗网站制作宣传语
  • 触摸屏网站建设网站地域分站怎么做
  • 旅游网官方网站建设网站对企业的重要性
  • 那些网站是php做的碑林网站制作
  • 广州物流网站建设专业做数据的网站有哪些方面
  • 公众号免费模板网站唐河做网站
  • 网站远程图片做电子商城网站
  • 哪些公司做外贸网站有源码个人网站怎么建立
  • 如何进行网站的seo怎么让百度收录自己的网站
  • aspnet网站开发源码房地产开发公司招聘
  • 网站开发的著作权归谁本科自考
  • 区块链开源平台网站关键词优化方法
  • 网站页面上的悬浮窗怎么做建设银行鞍山网站
  • 国外网页网站设计wordpress 表单js改变
  • wordpress打赏积分功能知乎seo排名的搜软件
  • 主播网站怎么建立搜索seo神器
  • 商城类网站建设的服务器选择深圳vi设计哪家好