├── shili.png ├── expWordTest.docx ├── src └── main │ ├── resources │ ├── three.doc │ └── dbInfo.properties │ └── java │ ├── anno │ └── TableField.java │ ├── entity │ ├── Result.java │ └── TableDetail.java │ ├── util │ ├── ParagraphStyle.java │ ├── TextStyle.java │ ├── ExportWord.java │ ├── XWPFHelperTable.java │ └── XWPFHelper.java │ └── Main.java ├── README.md ├── .gitignore └── pom.xml /shili.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FFatTiger/ddl2threelinetable/HEAD/shili.png -------------------------------------------------------------------------------- /expWordTest.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FFatTiger/ddl2threelinetable/HEAD/expWordTest.docx -------------------------------------------------------------------------------- /src/main/resources/three.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FFatTiger/ddl2threelinetable/HEAD/src/main/resources/three.doc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ddl2threelinetable 2 | 3 | 数据库信息转三线表word 4 | 5 | 修改main函数databasename与dbinfo的数据库连接信息运行即可 6 | 7 | 导出结果示例 8 | ![](shili.png) 9 | -------------------------------------------------------------------------------- /src/main/resources/dbInfo.properties: -------------------------------------------------------------------------------- 1 | driver=com.mysql.cj.jdbc.Driver 2 | url=jdbc:mysql://:3306/smbms?serverTimezone=UTC&allowPublicKeyRetrieval=true 3 | username= 4 | pass= 5 | maxSize=100 6 | initSize=10 -------------------------------------------------------------------------------- /src/main/java/anno/TableField.java: -------------------------------------------------------------------------------- 1 | package anno; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author wzy 7 | * @date 2021/5/3 8 | */ 9 | @Documented 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target(ElementType.FIELD) 12 | public @interface TableField { 13 | 14 | String value() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | *.iml 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | hs_err_pid* 25 | /.idea/ 26 | /target/ 27 | -------------------------------------------------------------------------------- /src/main/java/entity/Result.java: -------------------------------------------------------------------------------- 1 | package entity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author wzy 8 | * @date 2021/5/2 9 | */ 10 | public class Result { 11 | 12 | private String tableSchema; 13 | private String tableName; 14 | 15 | private List tableDetails; 16 | 17 | public String getTableSchema() { 18 | return tableSchema; 19 | } 20 | 21 | public void setTableSchema(String tableSchema) { 22 | this.tableSchema = tableSchema; 23 | } 24 | 25 | public String getTableName() { 26 | return tableName; 27 | } 28 | 29 | public void setTableName(String tableName) { 30 | this.tableName = tableName; 31 | } 32 | 33 | public List getTableDetails() { 34 | if (tableDetails == null) { 35 | tableDetails = new ArrayList<>(); 36 | } 37 | return tableDetails; 38 | } 39 | 40 | public void setTableDetails(List tableDetails) { 41 | this.tableDetails = tableDetails; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "Result{" + 47 | "tableSchema='" + tableSchema + '\'' + 48 | ", tableName='" + tableName + '\'' + 49 | ", tableDetails=" + tableDetails + 50 | '}' + '\n'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | ddl2word 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | mysql 14 | mysql-connector-java 15 | 8.0.23 16 | 17 | 18 | org.springframework 19 | spring-jdbc 20 | 5.3.4 21 | 22 | 23 | com.alibaba 24 | druid 25 | 1.2.5 26 | 27 | 28 | 29 | org.apache.poi 30 | poi-ooxml 31 | 4.0.0 32 | 33 | 34 | 35 | org.apache.poi 36 | poi 37 | 4.0.0 38 | 39 | 40 | org.slf4j 41 | slf4j-api 42 | 1.7.30 43 | 44 | 45 | org.slf4j 46 | slf4j-nop 47 | 1.7.2 48 | 49 | 50 | 51 | 52 | 8 53 | 8 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/entity/TableDetail.java: -------------------------------------------------------------------------------- 1 | package entity; 2 | 3 | import anno.TableField; 4 | 5 | import java.lang.reflect.Field; 6 | import java.util.Arrays; 7 | 8 | /** 9 | * @author wzy 10 | * @date 2021/5/2 11 | */ 12 | public class TableDetail { 13 | @TableField("字段名") 14 | private String columnName; 15 | @TableField("类型") 16 | private String columnType; 17 | @TableField("是否为空") 18 | private String isNullable; 19 | @TableField("索引") 20 | private String columnKey; 21 | @TableField("默认值") 22 | private String columnDefault; 23 | @TableField("说明") 24 | private String columnComment; 25 | 26 | public static void main(String[] args) { 27 | Field declaredField = Arrays.stream(new TableDetail().getClass().getDeclaredFields()).iterator().next(); 28 | TableField annotation = declaredField.getAnnotation(TableField.class); 29 | System.out.println(annotation.value()); 30 | } 31 | 32 | public String getColumnName() { 33 | return columnName; 34 | } 35 | 36 | public void setColumnName(String columnName) { 37 | this.columnName = columnName; 38 | } 39 | 40 | public String getColumnType() { 41 | return columnType; 42 | } 43 | 44 | public void setColumnType(String columnType) { 45 | this.columnType = columnType; 46 | } 47 | 48 | public String getColumnKey() { 49 | return columnKey; 50 | } 51 | 52 | public void setColumnKey(String columnKey) { 53 | if ("".equals(columnKey) || columnKey == null) { 54 | this.columnKey = "无"; 55 | 56 | } else { 57 | this.columnKey = columnKey; 58 | } 59 | } 60 | 61 | public String getIsNullable() { 62 | return isNullable; 63 | } 64 | 65 | public void setIsNullable(String isNullable) { 66 | this.isNullable = isNullable; 67 | } 68 | 69 | public String getColumnDefault() { 70 | return columnDefault; 71 | } 72 | 73 | public void setColumnDefault(String columnDefault) { 74 | if ("".equals(columnDefault) || columnDefault == null) { 75 | this.columnDefault = "无"; 76 | 77 | } else { 78 | this.columnDefault = columnDefault; 79 | } 80 | } 81 | 82 | public String getColumnComment() { 83 | return columnComment; 84 | } 85 | 86 | public void setColumnComment(String columnComment) { 87 | this.columnComment = columnComment; 88 | } 89 | 90 | 91 | @Override 92 | public String toString() { 93 | return "TableDetail{" + 94 | "columnName='" + columnName + '\'' + 95 | ", columnType='" + columnType + '\'' + 96 | ", columnKey='" + columnKey + '\'' + 97 | ", isNullable='" + isNullable + '\'' + 98 | ", columnDefault='" + columnDefault + '\'' + 99 | ", columnComment='" + columnComment + '\'' + 100 | '}'; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/util/ParagraphStyle.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | /** 4 | * @Description 段落样式 5 | */ 6 | public class ParagraphStyle { 7 | 8 | private boolean isSpace; //是否缩进 9 | private String before; //段前磅数 10 | private String after; //段后磅数 11 | private String beforeLines; //段前行数 12 | private String afterLines; //段后行数 13 | private boolean isLine; //是否间距 14 | private String line; //间距距离 15 | //段落缩进信息 16 | private String firstLine; 17 | private String firstLineChar; 18 | private String hanging; 19 | private String hangingChar; 20 | private String right; 21 | private String rightChar; 22 | private String left; 23 | private String leftChar; 24 | 25 | //此处省略get/set方法... 26 | 27 | 28 | public boolean isSpace() { 29 | return isSpace; 30 | } 31 | 32 | public void setSpace(boolean space) { 33 | isSpace = space; 34 | } 35 | 36 | public String getBefore() { 37 | return before; 38 | } 39 | 40 | public void setBefore(String before) { 41 | this.before = before; 42 | } 43 | 44 | public String getAfter() { 45 | return after; 46 | } 47 | 48 | public void setAfter(String after) { 49 | this.after = after; 50 | } 51 | 52 | public String getBeforeLines() { 53 | return beforeLines; 54 | } 55 | 56 | public void setBeforeLines(String beforeLines) { 57 | this.beforeLines = beforeLines; 58 | } 59 | 60 | public String getAfterLines() { 61 | return afterLines; 62 | } 63 | 64 | public void setAfterLines(String afterLines) { 65 | this.afterLines = afterLines; 66 | } 67 | 68 | public boolean isLine() { 69 | return isLine; 70 | } 71 | 72 | public void setLine(boolean line) { 73 | isLine = line; 74 | } 75 | 76 | public String getLine() { 77 | return line; 78 | } 79 | 80 | public void setLine(String line) { 81 | this.line = line; 82 | } 83 | 84 | public String getFirstLine() { 85 | return firstLine; 86 | } 87 | 88 | public void setFirstLine(String firstLine) { 89 | this.firstLine = firstLine; 90 | } 91 | 92 | public String getFirstLineChar() { 93 | return firstLineChar; 94 | } 95 | 96 | public void setFirstLineChar(String firstLineChar) { 97 | this.firstLineChar = firstLineChar; 98 | } 99 | 100 | public String getHanging() { 101 | return hanging; 102 | } 103 | 104 | public void setHanging(String hanging) { 105 | this.hanging = hanging; 106 | } 107 | 108 | public String getHangingChar() { 109 | return hangingChar; 110 | } 111 | 112 | public void setHangingChar(String hangingChar) { 113 | this.hangingChar = hangingChar; 114 | } 115 | 116 | public String getRight() { 117 | return right; 118 | } 119 | 120 | public void setRight(String right) { 121 | this.right = right; 122 | } 123 | 124 | public String getRightChar() { 125 | return rightChar; 126 | } 127 | 128 | public void setRightChar(String rightChar) { 129 | this.rightChar = rightChar; 130 | } 131 | 132 | public String getLeft() { 133 | return left; 134 | } 135 | 136 | public void setLeft(String left) { 137 | this.left = left; 138 | } 139 | 140 | public String getLeftChar() { 141 | return leftChar; 142 | } 143 | 144 | public void setLeftChar(String leftChar) { 145 | this.leftChar = leftChar; 146 | } 147 | } -------------------------------------------------------------------------------- /src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import com.alibaba.druid.pool.DruidDataSource; 2 | import entity.Result; 3 | import entity.TableDetail; 4 | 5 | import org.apache.poi.xwpf.usermodel.XWPFDocument; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | import util.ExportWord; 8 | 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.util.*; 13 | import java.util.stream.Collectors; 14 | 15 | /** 16 | * @author wzy 17 | * @date 2021/5/2 18 | */ 19 | public class Main { 20 | 21 | private static final String SQL = "select table_schema,table_name,column_name,column_type,column_key,is_nullable,column_default,column_comment,character_set_name, EXTRA\n" + 22 | "\n" + 23 | "from information_schema.columns where table_schema=?\n" + 24 | "ORDER BY table_name,ORDINAL_POSITION\n" + 25 | ";"; 26 | 27 | public static void main(String[] args) throws Exception { 28 | ExportWord ew = new ExportWord(); 29 | Main main = new Main(); 30 | 31 | //修改此处数据库名 32 | String databaseName = "cczucampusforum"; 33 | List results = main.getTableDetails(databaseName); 34 | XWPFDocument document = ew.createXWPFDocument(results); 35 | ew.exportCheckWord(results, document, "expWordTest.docx"); 36 | System.out.println("文档生成成功"); 37 | } 38 | 39 | private List getTableDetails(String databaseName) throws IOException { 40 | InputStream resourceAsStream = Main.class.getClassLoader().getResourceAsStream("dbinfo.properties"); 41 | Properties pro = new Properties(); 42 | pro.load(resourceAsStream); 43 | 44 | DruidDataSource druidDataSource = new DruidDataSource(); 45 | druidDataSource.setUrl(pro.getProperty("url")); 46 | druidDataSource.setUsername(pro.getProperty("username")); 47 | druidDataSource.setPassword(pro.getProperty("pass")); 48 | druidDataSource.setDriverClassName(pro.getProperty("driver")); 49 | 50 | JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource); 51 | final HashMap tableMap = new HashMap<>(); 52 | 53 | 54 | return jdbcTemplate.query(SQL, (resultSet, rowNum) -> { 55 | String tableName = resultSet.getString("TABLE_NAME"); 56 | Result result = tableMap.get(tableName); 57 | if (result == null) { 58 | result = new Result(); 59 | tableMap.put(tableName, result); 60 | result.setTableSchema(resultSet.getString("TABLE_SCHEMA")); 61 | result.setTableName(tableName); 62 | List tableDetails = result.getTableDetails(); 63 | TableDetail tableDetail = new TableDetail(); 64 | tableDetail.setColumnName(resultSet.getString("COLUMN_NAME")); 65 | tableDetail.setColumnType(resultSet.getString("COLUMN_TYPE")); 66 | tableDetail.setColumnKey(resultSet.getString("COLUMN_KEY")); 67 | tableDetail.setIsNullable(resultSet.getString("IS_NULLABLE")); 68 | tableDetail.setColumnComment(resultSet.getString("COLUMN_COMMENT")); 69 | tableDetail.setColumnDefault(resultSet.getString("COLUMN_DEFAULT")); 70 | tableDetails.add(tableDetail); 71 | return result; 72 | } else { 73 | List tableDetails = result.getTableDetails(); 74 | TableDetail tableDetail = new TableDetail(); 75 | tableDetail.setColumnName(resultSet.getString("COLUMN_NAME")); 76 | tableDetail.setColumnType(resultSet.getString("COLUMN_TYPE")); 77 | tableDetail.setColumnKey(resultSet.getString("COLUMN_KEY")); 78 | tableDetail.setIsNullable(resultSet.getString("IS_NULLABLE")); 79 | tableDetail.setColumnComment(resultSet.getString("COLUMN_COMMENT")); 80 | tableDetail.setColumnDefault(resultSet.getString("COLUMN_DEFAULT")); 81 | tableDetails.add(tableDetail); 82 | 83 | return null; 84 | } 85 | }, databaseName).stream().filter(Objects::nonNull).collect(Collectors.toList()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/util/TextStyle.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | /** 4 | * @Description 文本样式 5 | */ 6 | public class TextStyle { 7 | 8 | private String url; // 超链接 9 | private String text; //文本内容 10 | private String fontFamily; //字体 11 | private String fontSize; //字体大小 12 | private String colorVal; //字体颜色 13 | private String shdColor; //底纹颜色 14 | private int position; //文本位置 15 | private int spacingValue; //间距 16 | private int indent; //缩进 17 | private boolean isBlod; //加粗 18 | private boolean isUnderLine; //下划线 19 | private boolean underLineColor; // 20 | private boolean isItalic; //倾斜 21 | private boolean isStrike; //删除线 22 | private boolean isDStrike; //双删除线 23 | private boolean isShadow; //阴影 24 | private boolean isVanish; //隐藏 25 | private boolean isEmboss; //阳文 26 | private boolean isImprint; //阴文 27 | private boolean isOutline; //空心 28 | private boolean isHightLight; //突出显示文本 29 | private boolean isShd; //底纹 30 | 31 | //此处省略get/set方法... 32 | 33 | public String getUrl() { 34 | return url; 35 | } 36 | 37 | public void setUrl(String url) { 38 | this.url = url; 39 | } 40 | 41 | public String getText() { 42 | return text; 43 | } 44 | 45 | public void setText(String text) { 46 | this.text = text; 47 | } 48 | 49 | public String getFontFamily() { 50 | return fontFamily; 51 | } 52 | 53 | public void setFontFamily(String fontFamily) { 54 | this.fontFamily = fontFamily; 55 | } 56 | 57 | public String getFontSize() { 58 | return fontSize; 59 | } 60 | 61 | public void setFontSize(String fontSize) { 62 | this.fontSize = fontSize; 63 | } 64 | 65 | public String getColorVal() { 66 | return colorVal; 67 | } 68 | 69 | public void setColorVal(String colorVal) { 70 | this.colorVal = colorVal; 71 | } 72 | 73 | public String getShdColor() { 74 | return shdColor; 75 | } 76 | 77 | public void setShdColor(String shdColor) { 78 | this.shdColor = shdColor; 79 | } 80 | 81 | public int getPosition() { 82 | return position; 83 | } 84 | 85 | public void setPosition(int position) { 86 | this.position = position; 87 | } 88 | 89 | public int getSpacingValue() { 90 | return spacingValue; 91 | } 92 | 93 | public void setSpacingValue(int spacingValue) { 94 | this.spacingValue = spacingValue; 95 | } 96 | 97 | public int getIndent() { 98 | return indent; 99 | } 100 | 101 | public void setIndent(int indent) { 102 | this.indent = indent; 103 | } 104 | 105 | public boolean isBlod() { 106 | return isBlod; 107 | } 108 | 109 | public void setBlod(boolean blod) { 110 | isBlod = blod; 111 | } 112 | 113 | public boolean isUnderLine() { 114 | return isUnderLine; 115 | } 116 | 117 | public void setUnderLine(boolean underLine) { 118 | isUnderLine = underLine; 119 | } 120 | 121 | public boolean isUnderLineColor() { 122 | return underLineColor; 123 | } 124 | 125 | public void setUnderLineColor(boolean underLineColor) { 126 | this.underLineColor = underLineColor; 127 | } 128 | 129 | public boolean isItalic() { 130 | return isItalic; 131 | } 132 | 133 | public void setItalic(boolean italic) { 134 | isItalic = italic; 135 | } 136 | 137 | public boolean isStrike() { 138 | return isStrike; 139 | } 140 | 141 | public void setStrike(boolean strike) { 142 | isStrike = strike; 143 | } 144 | 145 | public boolean isDStrike() { 146 | return isDStrike; 147 | } 148 | 149 | public void setDStrike(boolean DStrike) { 150 | isDStrike = DStrike; 151 | } 152 | 153 | public boolean isShadow() { 154 | return isShadow; 155 | } 156 | 157 | public void setShadow(boolean shadow) { 158 | isShadow = shadow; 159 | } 160 | 161 | public boolean isVanish() { 162 | return isVanish; 163 | } 164 | 165 | public void setVanish(boolean vanish) { 166 | isVanish = vanish; 167 | } 168 | 169 | public boolean isEmboss() { 170 | return isEmboss; 171 | } 172 | 173 | public void setEmboss(boolean emboss) { 174 | isEmboss = emboss; 175 | } 176 | 177 | public boolean isImprint() { 178 | return isImprint; 179 | } 180 | 181 | public void setImprint(boolean imprint) { 182 | isImprint = imprint; 183 | } 184 | 185 | public boolean isOutline() { 186 | return isOutline; 187 | } 188 | 189 | public void setOutline(boolean outline) { 190 | isOutline = outline; 191 | } 192 | 193 | public boolean isHightLight() { 194 | return isHightLight; 195 | } 196 | 197 | public void setHightLight(boolean hightLight) { 198 | isHightLight = hightLight; 199 | } 200 | 201 | public boolean isShd() { 202 | return isShd; 203 | } 204 | 205 | public void setShd(boolean shd) { 206 | isShd = shd; 207 | } 208 | } -------------------------------------------------------------------------------- /src/main/java/util/ExportWord.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.io.IOException; 4 | import java.lang.reflect.Field; 5 | import java.math.BigInteger; 6 | import java.util.Arrays; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import anno.TableField; 12 | import entity.Result; 13 | import entity.TableDetail; 14 | import org.apache.poi.xwpf.usermodel.*; 15 | import org.apache.xmlbeans.XmlCursor; 16 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; 17 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.impl.CTBorderImpl; 18 | import util.XWPFHelper; 19 | import util.XWPFHelperTable; 20 | 21 | 22 | /** 23 | * @Description 导出word文档 24 | */ 25 | public class ExportWord { 26 | private XWPFHelperTable xwpfHelperTable = null; 27 | private XWPFHelper xwpfHelper = null; 28 | public ExportWord() { 29 | xwpfHelperTable = new XWPFHelperTable(); 30 | xwpfHelper = new XWPFHelper(); 31 | } 32 | /** 33 | * 创建好文档的基本 标题,表格 段落等部分 34 | * @return 35 | */ 36 | public XWPFDocument createXWPFDocument(List results) { 37 | XWPFDocument doc = new XWPFDocument(); 38 | 39 | for (Result result : results) { 40 | int rows = result.getTableDetails().size(); 41 | int cols = TableDetail.class.getDeclaredFields().length; 42 | createTableParagraph(doc, rows + 1, cols); 43 | XWPFParagraph titleParagraph = doc.createParagraph(); //新建一个标题段落对象(就是一段文字) 44 | titleParagraph.setAlignment(ParagraphAlignment.CENTER);//样式居中 45 | XWPFRun titleFun = titleParagraph.createRun(); //创建文本对象 46 | titleFun.setText(result.getTableName()); 47 | titleFun.addBreak(); //换行 48 | titleFun.addBreak(); //换行 49 | } 50 | return doc; 51 | } 52 | 53 | /** 54 | * 设置表格 55 | * 56 | * @param tableDetailClass 57 | * @param document 58 | * @param rows 59 | * @param cols 60 | */ 61 | public void createTableParagraph( XWPFDocument document, int rows, int cols) { 62 | XWPFTable table = document.createTable(rows, cols); 63 | xwpfHelperTable.setTableWidthAndHAlign(table, "9072", STJc.CENTER); 64 | 65 | List rowList = table.getRows(); 66 | CTTblBorders borders=table.getCTTbl().getTblPr().addNewTblBorders(); 67 | CTBorder hBorder=borders.addNewInsideH(); 68 | hBorder.setVal(STBorder.Enum.forString("nil")); 69 | hBorder.setSz(new BigInteger("1")); 70 | 71 | CTBorder vBorder=borders.addNewInsideV(); 72 | vBorder.setVal(STBorder.Enum.forString("nil")); 73 | vBorder.setSz(new BigInteger("1")); 74 | 75 | CTBorder lBorder=borders.addNewLeft(); 76 | lBorder.setVal(STBorder.Enum.forString("nil")); 77 | lBorder.setSz(new BigInteger("1")); 78 | 79 | CTBorder rBorder=borders.addNewRight(); 80 | rBorder.setVal(STBorder.Enum.forString("nil")); 81 | rBorder.setSz(new BigInteger("1")); 82 | 83 | CTBorder tBorder=borders.addNewTop(); 84 | tBorder.setVal(STBorder.Enum.forString("thick")); 85 | tBorder.setSz(new BigInteger("10")); 86 | 87 | CTBorder bBorder=borders.addNewBottom(); 88 | bBorder.setVal(STBorder.Enum.forString("thick")); 89 | bBorder.setSz(new BigInteger("10")); 90 | 91 | CTTbl ttbl = table.getCTTbl(); 92 | CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr(); 93 | CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); 94 | CTJc cTJc=tblPr.addNewJc(); 95 | cTJc.setVal(STJc.Enum.forString("center")); 96 | tblWidth.setW(new BigInteger("8000")); 97 | tblWidth.setType(STTblWidth.DXA); 98 | 99 | //设置表头样式与标题 100 | List tableCells = rowList.get(0).getTableCells(); 101 | Iterator fieldIterator = Arrays.stream(TableDetail.class.getDeclaredFields()).iterator(); 102 | for (XWPFTableCell tableCell : tableCells) { 103 | Field field = fieldIterator.next(); 104 | TableField annotation = field.getAnnotation(TableField.class); 105 | String value = annotation.value(); 106 | CTTcBorders ctTcBorders = tableCell.getCTTc().addNewTcPr().addNewTcBorders(); 107 | CTBorder ctBorder = ctTcBorders.addNewBottom(); 108 | ctBorder.setVal(STBorder.Enum.forString("single")); 109 | ctBorder.setSz(new BigInteger("1")); 110 | setCellText(tableCell, value,"FFFFFF", 1600); 111 | } 112 | 113 | 114 | } 115 | 116 | /** 117 | * 往表格中填充数据 118 | * @param dataList 119 | * @param document 120 | * @throws IOException 121 | */ 122 | @SuppressWarnings("unchecked") 123 | public void exportCheckWord(List results, XWPFDocument document, String savePath) throws IOException, IllegalAccessException { 124 | 125 | Iterator tableIterator = document.getTables().iterator(); 126 | for (Result result : results) { 127 | XWPFTable table = tableIterator.next(); 128 | fillTableData(table, result.getTableDetails()); 129 | } 130 | 131 | xwpfHelper.saveDocument(document, savePath); 132 | } 133 | /** 134 | * 往表格中填充数据 135 | * @param table 136 | * @param tableData 137 | */ 138 | public void fillTableData(XWPFTable table, List tableDetails) throws IllegalAccessException { 139 | Iterator rowIterator = table.getRows().iterator(); 140 | rowIterator.next(); 141 | 142 | for (TableDetail tableDetail : tableDetails) { 143 | List tableCells = rowIterator.next().getTableCells(); 144 | Iterator fieldIterator = Arrays.stream(tableDetail.getClass().getDeclaredFields()).iterator(); 145 | 146 | for (XWPFTableCell tableCell : tableCells) { 147 | Field field = fieldIterator.next(); 148 | field.setAccessible(true); 149 | setCellText(tableCell, (String) field.get(tableDetail),"FFFFFF", 1600); 150 | 151 | } 152 | } 153 | } 154 | 155 | private void setCellText(XWPFTableCell cell,String text, String bgcolor, int width) { 156 | CTTc cttc = cell.getCTTc(); 157 | CTTcPr cellPr = cttc.addNewTcPr(); 158 | cellPr.addNewTcW().setW(BigInteger.valueOf(width)); 159 | //cell.setColor(bgcolor); 160 | CTTcPr ctPr = cttc.addNewTcPr(); 161 | CTShd ctshd = ctPr.addNewShd(); 162 | ctshd.setFill(bgcolor); 163 | ctPr.addNewVAlign().setVal(STVerticalJc.CENTER); 164 | cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER); 165 | cell.setText(text); 166 | } 167 | 168 | 169 | } -------------------------------------------------------------------------------- /src/main/java/util/XWPFHelperTable.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | /** 4 | * 5 | * @date 2021/5/2 6 | */ 7 | import java.math.BigInteger; 8 | import java.util.ArrayList; 9 | import java.util.Iterator; 10 | import java.util.List; 11 | 12 | import org.apache.poi.xwpf.usermodel.BodyElementType; 13 | import org.apache.poi.xwpf.usermodel.IBodyElement; 14 | import org.apache.poi.xwpf.usermodel.XWPFDocument; 15 | import org.apache.poi.xwpf.usermodel.XWPFParagraph; 16 | import org.apache.poi.xwpf.usermodel.XWPFRun; 17 | import org.apache.poi.xwpf.usermodel.XWPFTable; 18 | import org.apache.poi.xwpf.usermodel.XWPFTableCell; 19 | import org.apache.poi.xwpf.usermodel.XWPFTableRow; 20 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHMerge; 21 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHeight; 22 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc; 23 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; 24 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; 25 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol; 26 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; 27 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; 28 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; 29 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; 30 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr; 31 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge; 32 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc; 33 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; 34 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; 35 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; 36 | 37 | /** 38 | * @Description 操作word的基本工具类 39 | * 2018年12月3日 上午11:12:18 40 | * 41 | */ 42 | public class XWPFHelperTable { 43 | 44 | /** 45 | * 删除指定位置的表格,被删除表格后的索引位置 46 | * @param document 47 | * @param pos 48 | * 49 | */ 50 | public void deleteTableByIndex(XWPFDocument document, int pos) { 51 | Iterator bodyElement = document.getBodyElementsIterator(); 52 | int eIndex = 0, tableIndex = -1; 53 | while(bodyElement.hasNext()) { 54 | IBodyElement element = bodyElement.next(); 55 | BodyElementType elementType = element.getElementType(); 56 | if(elementType == BodyElementType.TABLE) { 57 | tableIndex++; 58 | if(tableIndex == pos) { 59 | break; 60 | } 61 | } 62 | eIndex++; 63 | } 64 | document.removeBodyElement(eIndex); 65 | } 66 | /** 67 | * 获得指定位置的表格 68 | * @param document 69 | * @param index 70 | * @return 71 | * 72 | */ 73 | public XWPFTable getTableByIndex(XWPFDocument document, int index) { 74 | List tableList = document.getTables(); 75 | if(tableList == null || index < 0 || index > tableList.size()) { 76 | return null; 77 | } 78 | return tableList.get(index); 79 | } 80 | /** 81 | * 得到表格的内容(第一次跨行单元格视为一个,第二次跳过跨行合并的单元格) 82 | * @param table 83 | * @return 84 | * 85 | */ 86 | public List> getTableRConten(XWPFTable table) { 87 | List> tableContextList = new ArrayList>(); 88 | for(int rowIndex = 0, rowLen = table.getNumberOfRows(); rowIndex < rowLen; rowIndex++) { 89 | XWPFTableRow row = table.getRow(rowIndex); 90 | List cellContentList = new ArrayList(); 91 | for(int colIndex = 0, colLen = row.getTableCells().size(); colIndex < colLen; colIndex++ ) { 92 | XWPFTableCell cell = row.getCell(colIndex); 93 | CTTc ctTc = cell.getCTTc(); 94 | if(ctTc.isSetTcPr()) { 95 | CTTcPr tcPr = ctTc.getTcPr(); 96 | if(tcPr.isSetHMerge()) { 97 | CTHMerge hMerge = tcPr.getHMerge(); 98 | if(STMerge.RESTART.equals(hMerge.getVal())) { 99 | cellContentList.add(getTableCellContent(cell)); 100 | } 101 | } else if(tcPr.isSetVMerge()) { 102 | CTVMerge vMerge = tcPr.getVMerge(); 103 | if(STMerge.RESTART.equals(vMerge.getVal())) { 104 | cellContentList.add(getTableCellContent(cell)); 105 | } 106 | } else { 107 | cellContentList.add(getTableCellContent(cell)); 108 | } 109 | } 110 | } 111 | tableContextList.add(cellContentList); 112 | } 113 | return tableContextList; 114 | } 115 | 116 | /** 117 | * 获得一个表格的单元格的内容 118 | * @param cell 119 | * @return 120 | * 121 | */ 122 | public String getTableCellContent(XWPFTableCell cell) { 123 | StringBuffer sb = new StringBuffer(); 124 | List cellParagList = cell.getParagraphs(); 125 | if(cellParagList != null && cellParagList.size() > 0) { 126 | for(XWPFParagraph xwpfPr: cellParagList) { 127 | List runs = xwpfPr.getRuns(); 128 | if(runs != null && runs.size() > 0) { 129 | for(XWPFRun xwpfRun : runs) { 130 | sb.append(xwpfRun.getText(0)); 131 | } 132 | } 133 | } 134 | } 135 | return sb.toString(); 136 | } 137 | /** 138 | * 得到表格内容,合并后的单元格视为一个单元格 139 | * @param table 140 | * @return 141 | * 142 | */ 143 | public List> getTableContent(XWPFTable table) { 144 | List> tableContentList = new ArrayList>(); 145 | for (int rowIndex = 0, rowLen = table.getNumberOfRows(); rowIndex < rowLen; rowIndex++) { 146 | XWPFTableRow row = table.getRow(rowIndex); 147 | List cellContentList = new ArrayList(); 148 | for (int colIndex = 0, colLen = row.getTableCells().size(); colIndex < colLen; colIndex++) { 149 | XWPFTableCell cell = row.getCell(colIndex); 150 | cellContentList.add(getTableCellContent(cell)); 151 | } 152 | tableContentList.add(cellContentList); 153 | } 154 | return tableContentList; 155 | } 156 | 157 | /** 158 | * 跨列合并 159 | * @param table 160 | * @param row 所合并的行 161 | * @param fromCell 起始列 162 | * @param toCell 终止列 163 | * @Description 164 | * 165 | */ 166 | public void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) { 167 | for(int cellIndex = fromCell; cellIndex <= toCell; cellIndex++ ) { 168 | XWPFTableCell cell = table.getRow(row).getCell(cellIndex); 169 | if(cellIndex == fromCell) { 170 | cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART); 171 | } else { 172 | cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE); 173 | } 174 | } 175 | } 176 | /** 177 | * 跨行合并 178 | * @param table 179 | * @param col 合并的列 180 | * @param fromRow 起始行 181 | * @param toRow 终止行 182 | * @Description 183 | * 184 | */ 185 | public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) { 186 | for(int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) { 187 | XWPFTableCell cell = table.getRow(rowIndex).getCell(col); 188 | //第一个合并单元格用重启合并值设置 189 | if(rowIndex == fromRow) { 190 | cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART); 191 | } else { 192 | //合并第一个单元格的单元被设置为“继续” 193 | cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE); 194 | } 195 | } 196 | } 197 | 198 | /** 199 | * @Description: 创建表格,创建后表格至少有1行1列,设置列宽 200 | */ 201 | public XWPFTable createTable(XWPFDocument xdoc, int rowSize, int cellSize, 202 | boolean isSetColWidth, int[] colWidths) { 203 | XWPFTable table = xdoc.createTable(rowSize, cellSize); 204 | if (isSetColWidth) { 205 | CTTbl ttbl = table.getCTTbl(); 206 | CTTblGrid tblGrid = ttbl.addNewTblGrid(); 207 | for (int j = 0, len = Math.min(cellSize, colWidths.length); j < len; j++) { 208 | CTTblGridCol gridCol = tblGrid.addNewGridCol(); 209 | gridCol.setW(new BigInteger(String.valueOf(colWidths[j]))); 210 | } 211 | } 212 | return table; 213 | } 214 | 215 | /** 216 | * @Description: 设置表格总宽度与水平对齐方式 217 | */ 218 | public void setTableWidthAndHAlign(XWPFTable table, String width, 219 | STJc.Enum enumValue) { 220 | CTTblPr tblPr = getTableCTTblPr(table); 221 | // 表格宽度 222 | CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); 223 | if (enumValue != null) { 224 | CTJc cTJc = tblPr.addNewJc(); 225 | cTJc.setVal(enumValue); 226 | } 227 | // 设置宽度 228 | tblWidth.setW(new BigInteger(width)); 229 | tblWidth.setType(STTblWidth.DXA); 230 | } 231 | 232 | /** 233 | * @Description: 得到Table的CTTblPr,不存在则新建 234 | */ 235 | public CTTblPr getTableCTTblPr(XWPFTable table) { 236 | CTTbl ttbl = table.getCTTbl(); 237 | // 表格属性 238 | CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr(); 239 | return tblPr; 240 | } 241 | 242 | /** 243 | * 设置表格行高 244 | * @param infoTable 245 | * @param heigth 高度 246 | * @param vertical 表格内容的显示方式:居中、靠右... 247 | * 248 | */ 249 | public void setTableHeight(XWPFTable infoTable, int heigth, STVerticalJc.Enum vertical) { 250 | List rows = infoTable.getRows(); 251 | for(XWPFTableRow row : rows) { 252 | CTTrPr trPr = row.getCtRow().addNewTrPr(); 253 | CTHeight ht = trPr.addNewTrHeight(); 254 | ht.setVal(BigInteger.valueOf(heigth)); 255 | List cells = row.getTableCells(); 256 | for(XWPFTableCell tableCell : cells ) { 257 | CTTcPr cttcpr = tableCell.getCTTc().addNewTcPr(); 258 | cttcpr.addNewVAlign().setVal(vertical); 259 | } 260 | } 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/util/XWPFHelper.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | /** 4 | * @author wzy 5 | * @date 2021/5/2 6 | */ 7 | 8 | import java.io.*; 9 | import java.math.BigInteger; 10 | import java.util.List; 11 | import java.util.logging.Level; 12 | import java.util.logging.Logger; 13 | 14 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 15 | import org.apache.poi.xwpf.usermodel.ParagraphAlignment; 16 | import org.apache.poi.xwpf.usermodel.TextAlignment; 17 | import org.apache.poi.xwpf.usermodel.XWPFDocument; 18 | import org.apache.poi.xwpf.usermodel.XWPFParagraph; 19 | import org.apache.poi.xwpf.usermodel.XWPFPicture; 20 | import org.apache.poi.xwpf.usermodel.XWPFPictureData; 21 | import org.apache.poi.xwpf.usermodel.XWPFRelation; 22 | import org.apache.poi.xwpf.usermodel.XWPFRun; 23 | import org.apache.poi.xwpf.usermodel.XWPFTable; 24 | import org.apache.poi.xwpf.usermodel.XWPFTableCell; 25 | import org.apache.poi.xwpf.usermodel.XWPFTableRow; 26 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; 27 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink; 28 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTInd; 29 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr; 30 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; 31 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; 32 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing; 33 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText; 34 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule; 35 | 36 | 37 | /** 38 | * @Description 设置docx文档的样式及一些操作 39 | * 基本概念说明:XWPFDocument代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档 40 | * XWPFParagraph代表文档、表格、标题等种的段落,由多个XWPFRun组成 41 | * XWPFRun代表具有同样风格的一段文本 42 | * XWPFTable代表一个表格 43 | * XWPFTableRow代表表格的一行 44 | * XWPFTableCell代表表格的一个单元格 45 | * XWPFChar 表示.docx文件中的图表 46 | * XWPFHyperlink 表示超链接 47 | * XWPFPicture 代表图片 48 | * 49 | * 注意:直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun。 50 | */ 51 | public class XWPFHelper { 52 | private static Logger logger = Logger.getLogger(XWPFHelper.class.toString()); 53 | 54 | /** 55 | * 创建一个word对象 56 | * @return 57 | */ 58 | public XWPFDocument createDocument() { 59 | XWPFDocument document = new XWPFDocument(); 60 | return document; 61 | } 62 | /** 63 | * 打开word文档 64 | * @param path 文档所在路径 65 | * @return 66 | * @throws IOException 67 | */ 68 | public XWPFDocument openDoc(String path) throws IOException { 69 | InputStream is = new FileInputStream(path); 70 | return new XWPFDocument(is); 71 | } 72 | /** 73 | * 保存word文档 74 | * @param document 文档对象 75 | * @param savePath 保存路径 76 | * @throws IOException 77 | */ 78 | public void saveDocument(XWPFDocument document, String savePath) throws IOException { 79 | File file = new File(savePath); 80 | if (!file.exists()) { 81 | file.createNewFile(); 82 | } 83 | OutputStream os = new FileOutputStream(file); 84 | document.write(os); 85 | os.close(); 86 | } 87 | /** 88 | * 设置段落文本样式 设置超链接及样式 89 | * @param paragraph 90 | * @param textStyle 91 | * @param url 92 | */ 93 | public void addParagraphTextHyperlink(XWPFParagraph paragraph, TextStyle textStyle) { 94 | String id = paragraph.getDocument().getPackagePart(). 95 | addExternalRelationship(textStyle.getUrl(), 96 | XWPFRelation.HYPERLINK.getRelation()).getId(); 97 | //追加链接并将其绑定到关系中 98 | CTHyperlink cLink = paragraph.getCTP().addNewHyperlink(); 99 | cLink.setId(id); 100 | //创建链接文本 101 | CTText ctText = CTText.Factory.newInstance(); 102 | ctText.setStringValue(textStyle.getText()); 103 | CTR ctr = CTR.Factory.newInstance(); 104 | CTRPr rpr = ctr.addNewRPr(); 105 | //以下设置各种样式 详情看TextStyle类 106 | if(textStyle.getFontFamily() != "" && textStyle.getFontFamily() != null ) { 107 | CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr.addNewRFonts(); 108 | fonts.setAscii(textStyle.getFontFamily()); 109 | //... 110 | } 111 | //设置字体大小 112 | } 113 | /** 114 | * 设置段落的基本样式 设置段落间距信息, 一行 = 100 一磅=20 115 | * @param paragraph 116 | * @param paragStyle 117 | */ 118 | public void setParagraphSpacingInfo(XWPFParagraph paragraph, ParagraphStyle paragStyle, STLineSpacingRule.Enum lineValue) { 119 | CTPPr pPPr = getParagraphCTPPr(paragraph); 120 | CTSpacing pSpacing = pPPr.getSpacing() != null ? pPPr.getSpacing() : pPPr.addNewSpacing(); 121 | if(paragStyle.isSpace()) { 122 | //段前磅数 123 | if(paragStyle.getBefore() != null) { 124 | pSpacing.setBefore(new BigInteger(paragStyle.getBefore())); 125 | } 126 | //段后磅数 127 | if(paragStyle.getAfter() != null) { 128 | pSpacing.setAfter(new BigInteger(paragStyle.getAfter())); 129 | } 130 | //依次设置段前行数、段后行数 131 | //... 132 | } 133 | //间距 134 | if(paragStyle.isLine()) { 135 | if(paragStyle.getLine() != null) { 136 | pSpacing.setLine(new BigInteger(paragStyle.getLine())); 137 | } 138 | if(lineValue != null) { 139 | pSpacing.setLineRule(lineValue); // 140 | } 141 | } 142 | } 143 | /** 144 | * 设置段落缩进信息 1厘米 约等于 567 145 | * @param paragraph 146 | * @param paragStyle 147 | */ 148 | public void setParagraphIndInfo(XWPFParagraph paragraph, ParagraphStyle paragStyle) { 149 | CTPPr pPPr = getParagraphCTPPr(paragraph); 150 | CTInd pInd = pPPr.getInd() != null ? pPPr.getInd() : pPPr.addNewInd(); 151 | if(paragStyle.getFirstLine() != null) { 152 | pInd.setFirstLine(new BigInteger(paragStyle.getFirstLine())); 153 | } 154 | //再进行其他设置 155 | //... 156 | } 157 | /** 158 | * 设置段落对齐 方式 159 | * @param paragraph 160 | * @param pAlign 161 | * @param valign 162 | */ 163 | public void setParagraphAlignInfo(XWPFParagraph paragraph, ParagraphAlignment pAlign, TextAlignment valign) { 164 | if(pAlign != null) { 165 | paragraph.setAlignment(pAlign); 166 | } 167 | if(valign != null) { 168 | paragraph.setVerticalAlignment(valign); 169 | } 170 | } 171 | /** 172 | * 得到段落的CTPPr 173 | * @param paragraph 174 | * @return 175 | */ 176 | public CTPPr getParagraphCTPPr(XWPFParagraph paragraph) { 177 | CTPPr pPPr = null; 178 | if(paragraph.getCTP() != null) { 179 | if(paragraph.getCTP().getPPr() != null) { 180 | pPPr = paragraph.getCTP().getPPr(); 181 | } else { 182 | pPPr = paragraph.getCTP().addNewPPr(); 183 | } 184 | } 185 | return pPPr; 186 | } 187 | /** 188 | * 得到XWPFRun的CTRPr 189 | * @param paragraph 190 | * @param pRun 191 | * @return 192 | */ 193 | public CTRPr getRunCTRPr(XWPFParagraph paragraph, XWPFRun pRun) { 194 | CTRPr ctrPr = null; 195 | if(pRun.getCTR() != null) { 196 | ctrPr = pRun.getCTR().getRPr(); 197 | if(ctrPr == null) { 198 | ctrPr = pRun.getCTR().addNewRPr(); 199 | } 200 | } else { 201 | ctrPr = paragraph.getCTP().addNewR().addNewRPr(); 202 | } 203 | return ctrPr; 204 | } 205 | 206 | 207 | /** 208 | * 复制表格 209 | * @param targetTable 210 | * @param sourceTable 211 | */ 212 | public void copyTable(XWPFTable targetTable, XWPFTable sourceTable) { 213 | //复制表格属性 214 | targetTable.getCTTbl().setTblPr(sourceTable.getCTTbl().getTblPr()); 215 | //复制行 216 | for(int i = 0; i < sourceTable.getRows().size(); i++) { 217 | XWPFTableRow targetRow = targetTable.getRow(i); 218 | XWPFTableRow sourceRow = sourceTable.getRow(i); 219 | if(targetRow == null) { 220 | targetTable.addRow(sourceRow); 221 | } else { 222 | copyTableRow(targetRow, sourceRow); 223 | } 224 | } 225 | } 226 | /** 227 | * 复制单元格 228 | * @param targetRow 229 | * @param sourceRow 230 | */ 231 | public void copyTableRow(XWPFTableRow targetRow, XWPFTableRow sourceRow) { 232 | //复制样式 233 | if(sourceRow != null) { 234 | targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr()); 235 | } 236 | //复制单元格 237 | for(int i = 0; i < sourceRow.getTableCells().size(); i++) { 238 | XWPFTableCell tCell = targetRow.getCell(i); 239 | XWPFTableCell sCell = sourceRow.getCell(i); 240 | if(tCell == sCell) { 241 | tCell = targetRow.addNewTableCell(); 242 | } 243 | copyTableCell(tCell, sCell); 244 | } 245 | } 246 | /** 247 | * 复制单元格(列) 从sourceCell到targetCell 248 | * @param targetCell 249 | * @param sourceCell 250 | */ 251 | public void copyTableCell(XWPFTableCell targetCell, XWPFTableCell sourceCell) { 252 | //表格属性 253 | if(sourceCell.getCTTc() != null) { 254 | targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr()); 255 | } 256 | //删除段落 257 | for(int pos = 0; pos < targetCell.getParagraphs().size(); pos++) { 258 | targetCell.removeParagraph(pos); 259 | } 260 | //添加段落 261 | for(XWPFParagraph sourceParag : sourceCell.getParagraphs()) { 262 | XWPFParagraph targetParag = targetCell.addParagraph(); 263 | copyParagraph(targetParag, sourceParag); 264 | } 265 | } 266 | /** 267 | * 复制段落,从sourceParag到targetParag 268 | * @param targetParag 269 | * @param sourceParag 270 | */ 271 | public void copyParagraph(XWPFParagraph targetParag, XWPFParagraph sourceParag) { 272 | targetParag.getCTP().setPPr(sourceParag.getCTP().getPPr()); //设置段落样式 273 | //移除所有的run 274 | for(int pos = targetParag.getRuns().size() - 1; pos >= 0; pos-- ) { 275 | targetParag.removeRun(pos); 276 | } 277 | //copy新的run 278 | for(XWPFRun sRun : sourceParag.getRuns()) { 279 | XWPFRun tarRun = targetParag.createRun(); 280 | copyRun(tarRun, sRun); 281 | } 282 | } 283 | /** 284 | * 复制XWPFRun 从sourceRun到targetRun 285 | * @param targetRun 286 | * @param sourceRun 287 | */ 288 | public void copyRun(XWPFRun targetRun, XWPFRun sourceRun) { 289 | //设置targetRun属性 290 | targetRun.getCTR().setRPr(sourceRun.getCTR().getRPr()); 291 | targetRun.setText(sourceRun.text());//设置文本 292 | //处理图片 293 | List pictures = sourceRun.getEmbeddedPictures(); 294 | for(XWPFPicture picture : pictures) { 295 | try { 296 | copyPicture(targetRun, picture); 297 | } catch (InvalidFormatException e) { 298 | e.printStackTrace(); 299 | logger.log(Level.WARNING, "copyRun", e); 300 | } catch (IOException e) { 301 | e.printStackTrace(); 302 | logger.log(Level.WARNING, "copyRun", e); 303 | } 304 | } 305 | } 306 | /** 307 | * 复制图片从sourcePicture到 targetRun(XWPFPicture --> XWPFRun) 308 | * @param targetRun 309 | * @param source 310 | * @throws IOException 311 | * @throws InvalidFormatException 312 | */ 313 | public void copyPicture(XWPFRun targetRun, XWPFPicture sourcePicture) throws InvalidFormatException, IOException { 314 | XWPFPictureData picData = sourcePicture.getPictureData(); 315 | String fileName = picData.getFileName(); //图片的名称 316 | InputStream picInIsData = new ByteArrayInputStream(picData.getData()); 317 | int picType = picData.getPictureType(); 318 | int width = (int) sourcePicture.getCTPicture().getSpPr().getXfrm().getExt().getCx(); 319 | int height = (int) sourcePicture.getCTPicture().getSpPr().getXfrm().getExt().getCy(); 320 | targetRun.addPicture(picInIsData, picType, fileName, width, height); 321 | // targetRun.addBreak();//分行 322 | } 323 | } --------------------------------------------------------------------------------