Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

XWPFTable.java 47KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.xwpf.usermodel;
  16. import java.math.BigInteger;
  17. import java.util.ArrayList;
  18. import java.util.Collections;
  19. import java.util.EnumMap;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.function.Consumer;
  23. import java.util.function.Function;
  24. import org.apache.poi.ooxml.POIXMLDocumentPart;
  25. import org.apache.poi.ooxml.util.POIXMLUnits;
  26. import org.apache.poi.util.Internal;
  27. import org.apache.poi.util.Units;
  28. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;
  29. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
  30. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJcTable;
  31. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
  32. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
  33. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
  34. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
  35. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;
  36. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblCellMar;
  37. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
  38. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
  39. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
  40. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;
  41. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJcTable;
  42. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
  43. /**
  44. * <p>Sketch of XWPFTable class. Only table's text is being hold.</p>
  45. * <p>Specifies the contents of a table present in the document. A table is a set
  46. * of paragraphs (and other block-level content) arranged in rows and columns.</p>
  47. */
  48. @SuppressWarnings("WeakerAccess")
  49. public class XWPFTable implements IBodyElement, ISDTContents {
  50. public static final String REGEX_PERCENTAGE = "[0-9]+(\\.[0-9]+)?%";
  51. public static final String DEFAULT_PERCENTAGE_WIDTH = "100%";
  52. static final String NS_OOXML_WP_MAIN = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
  53. public static final String REGEX_WIDTH_VALUE = "auto|[0-9]+|" + REGEX_PERCENTAGE;
  54. // Create a map from this XWPF-level enum to the STBorder.Enum values
  55. public enum XWPFBorderType {
  56. NIL, NONE, SINGLE, THICK, DOUBLE, DOTTED, DASHED, DOT_DASH, DOT_DOT_DASH, TRIPLE,
  57. THIN_THICK_SMALL_GAP, THICK_THIN_SMALL_GAP, THIN_THICK_THIN_SMALL_GAP,
  58. THIN_THICK_MEDIUM_GAP, THICK_THIN_MEDIUM_GAP, THIN_THICK_THIN_MEDIUM_GAP,
  59. THIN_THICK_LARGE_GAP, THICK_THIN_LARGE_GAP, THIN_THICK_THIN_LARGE_GAP,
  60. WAVE, DOUBLE_WAVE, DASH_SMALL_GAP, DASH_DOT_STROKED, THREE_D_EMBOSS, THREE_D_ENGRAVE,
  61. OUTSET, INSET
  62. }
  63. private enum Border { INSIDE_V, INSIDE_H, LEFT, TOP, BOTTOM, RIGHT }
  64. private static final EnumMap<XWPFBorderType, STBorder.Enum> xwpfBorderTypeMap;
  65. // Create a map from the STBorder.Enum values to the XWPF-level enums
  66. private static final HashMap<Integer, XWPFBorderType> stBorderTypeMap;
  67. static {
  68. // populate enum maps
  69. xwpfBorderTypeMap = new EnumMap<>(XWPFBorderType.class);
  70. xwpfBorderTypeMap.put(XWPFBorderType.NIL, STBorder.Enum.forInt(STBorder.INT_NIL));
  71. xwpfBorderTypeMap.put(XWPFBorderType.NONE, STBorder.Enum.forInt(STBorder.INT_NONE));
  72. xwpfBorderTypeMap.put(XWPFBorderType.SINGLE, STBorder.Enum.forInt(STBorder.INT_SINGLE));
  73. xwpfBorderTypeMap.put(XWPFBorderType.THICK, STBorder.Enum.forInt(STBorder.INT_THICK));
  74. xwpfBorderTypeMap.put(XWPFBorderType.DOUBLE, STBorder.Enum.forInt(STBorder.INT_DOUBLE));
  75. xwpfBorderTypeMap.put(XWPFBorderType.DOTTED, STBorder.Enum.forInt(STBorder.INT_DOTTED));
  76. xwpfBorderTypeMap.put(XWPFBorderType.DASHED, STBorder.Enum.forInt(STBorder.INT_DASHED));
  77. xwpfBorderTypeMap.put(XWPFBorderType.DOT_DASH, STBorder.Enum.forInt(STBorder.INT_DOT_DASH));
  78. xwpfBorderTypeMap.put(XWPFBorderType.DOT_DOT_DASH, STBorder.Enum.forInt(STBorder.INT_DOT_DOT_DASH));
  79. xwpfBorderTypeMap.put(XWPFBorderType.TRIPLE, STBorder.Enum.forInt(STBorder.INT_TRIPLE));
  80. xwpfBorderTypeMap.put(XWPFBorderType.THIN_THICK_SMALL_GAP, STBorder.Enum.forInt(STBorder.INT_THIN_THICK_SMALL_GAP));
  81. xwpfBorderTypeMap.put(XWPFBorderType.THICK_THIN_SMALL_GAP, STBorder.Enum.forInt(STBorder.INT_THICK_THIN_SMALL_GAP));
  82. xwpfBorderTypeMap.put(XWPFBorderType.THIN_THICK_THIN_SMALL_GAP, STBorder.Enum.forInt(STBorder.INT_THIN_THICK_THIN_SMALL_GAP));
  83. xwpfBorderTypeMap.put(XWPFBorderType.THIN_THICK_MEDIUM_GAP, STBorder.Enum.forInt(STBorder.INT_THIN_THICK_MEDIUM_GAP));
  84. xwpfBorderTypeMap.put(XWPFBorderType.THICK_THIN_MEDIUM_GAP, STBorder.Enum.forInt(STBorder.INT_THICK_THIN_MEDIUM_GAP));
  85. xwpfBorderTypeMap.put(XWPFBorderType.THIN_THICK_THIN_MEDIUM_GAP, STBorder.Enum.forInt(STBorder.INT_THIN_THICK_THIN_MEDIUM_GAP));
  86. xwpfBorderTypeMap.put(XWPFBorderType.THIN_THICK_LARGE_GAP, STBorder.Enum.forInt(STBorder.INT_THIN_THICK_LARGE_GAP));
  87. xwpfBorderTypeMap.put(XWPFBorderType.THICK_THIN_LARGE_GAP, STBorder.Enum.forInt(STBorder.INT_THICK_THIN_LARGE_GAP));
  88. xwpfBorderTypeMap.put(XWPFBorderType.THIN_THICK_THIN_LARGE_GAP, STBorder.Enum.forInt(STBorder.INT_THIN_THICK_THIN_LARGE_GAP));
  89. xwpfBorderTypeMap.put(XWPFBorderType.WAVE, STBorder.Enum.forInt(STBorder.INT_WAVE));
  90. xwpfBorderTypeMap.put(XWPFBorderType.DOUBLE_WAVE, STBorder.Enum.forInt(STBorder.INT_DOUBLE_WAVE));
  91. xwpfBorderTypeMap.put(XWPFBorderType.DASH_SMALL_GAP, STBorder.Enum.forInt(STBorder.INT_DASH_SMALL_GAP));
  92. xwpfBorderTypeMap.put(XWPFBorderType.DASH_DOT_STROKED, STBorder.Enum.forInt(STBorder.INT_DASH_DOT_STROKED));
  93. xwpfBorderTypeMap.put(XWPFBorderType.THREE_D_EMBOSS, STBorder.Enum.forInt(STBorder.INT_THREE_D_EMBOSS));
  94. xwpfBorderTypeMap.put(XWPFBorderType.THREE_D_ENGRAVE, STBorder.Enum.forInt(STBorder.INT_THREE_D_ENGRAVE));
  95. xwpfBorderTypeMap.put(XWPFBorderType.OUTSET, STBorder.Enum.forInt(STBorder.INT_OUTSET));
  96. xwpfBorderTypeMap.put(XWPFBorderType.INSET, STBorder.Enum.forInt(STBorder.INT_INSET));
  97. stBorderTypeMap = new HashMap<>();
  98. stBorderTypeMap.put(STBorder.INT_NIL, XWPFBorderType.NIL);
  99. stBorderTypeMap.put(STBorder.INT_NONE, XWPFBorderType.NONE);
  100. stBorderTypeMap.put(STBorder.INT_SINGLE, XWPFBorderType.SINGLE);
  101. stBorderTypeMap.put(STBorder.INT_THICK, XWPFBorderType.THICK);
  102. stBorderTypeMap.put(STBorder.INT_DOUBLE, XWPFBorderType.DOUBLE);
  103. stBorderTypeMap.put(STBorder.INT_DOTTED, XWPFBorderType.DOTTED);
  104. stBorderTypeMap.put(STBorder.INT_DASHED, XWPFBorderType.DASHED);
  105. stBorderTypeMap.put(STBorder.INT_DOT_DASH, XWPFBorderType.DOT_DASH);
  106. stBorderTypeMap.put(STBorder.INT_DOT_DOT_DASH, XWPFBorderType.DOT_DOT_DASH);
  107. stBorderTypeMap.put(STBorder.INT_TRIPLE, XWPFBorderType.TRIPLE);
  108. stBorderTypeMap.put(STBorder.INT_THIN_THICK_SMALL_GAP, XWPFBorderType.THIN_THICK_SMALL_GAP);
  109. stBorderTypeMap.put(STBorder.INT_THICK_THIN_SMALL_GAP, XWPFBorderType.THICK_THIN_SMALL_GAP);
  110. stBorderTypeMap.put(STBorder.INT_THIN_THICK_THIN_SMALL_GAP, XWPFBorderType.THIN_THICK_THIN_SMALL_GAP);
  111. stBorderTypeMap.put(STBorder.INT_THIN_THICK_MEDIUM_GAP, XWPFBorderType.THIN_THICK_MEDIUM_GAP);
  112. stBorderTypeMap.put(STBorder.INT_THICK_THIN_MEDIUM_GAP, XWPFBorderType.THICK_THIN_MEDIUM_GAP);
  113. stBorderTypeMap.put(STBorder.INT_THIN_THICK_THIN_MEDIUM_GAP, XWPFBorderType.THIN_THICK_THIN_MEDIUM_GAP);
  114. stBorderTypeMap.put(STBorder.INT_THIN_THICK_LARGE_GAP, XWPFBorderType.THIN_THICK_LARGE_GAP);
  115. stBorderTypeMap.put(STBorder.INT_THICK_THIN_LARGE_GAP, XWPFBorderType.THICK_THIN_LARGE_GAP);
  116. stBorderTypeMap.put(STBorder.INT_THIN_THICK_THIN_LARGE_GAP, XWPFBorderType.THIN_THICK_THIN_LARGE_GAP);
  117. stBorderTypeMap.put(STBorder.INT_WAVE, XWPFBorderType.WAVE);
  118. stBorderTypeMap.put(STBorder.INT_DOUBLE_WAVE, XWPFBorderType.DOUBLE_WAVE);
  119. stBorderTypeMap.put(STBorder.INT_DASH_SMALL_GAP, XWPFBorderType.DASH_SMALL_GAP);
  120. stBorderTypeMap.put(STBorder.INT_DASH_DOT_STROKED, XWPFBorderType.DASH_DOT_STROKED);
  121. stBorderTypeMap.put(STBorder.INT_THREE_D_EMBOSS, XWPFBorderType.THREE_D_EMBOSS);
  122. stBorderTypeMap.put(STBorder.INT_THREE_D_ENGRAVE, XWPFBorderType.THREE_D_ENGRAVE);
  123. stBorderTypeMap.put(STBorder.INT_OUTSET, XWPFBorderType.OUTSET);
  124. stBorderTypeMap.put(STBorder.INT_INSET, XWPFBorderType.INSET);
  125. }
  126. protected StringBuilder text = new StringBuilder(64);
  127. protected final List<XWPFTableRow> tableRows = new ArrayList<>();
  128. // Unused: UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD
  129. //protected List<String> styleIDs;
  130. protected IBody part;
  131. private final CTTbl ctTbl;
  132. public XWPFTable(CTTbl table, IBody part, int row, int col) {
  133. this(table, part);
  134. for (int i = 0; i < row; i++) {
  135. XWPFTableRow tabRow = (getRow(i) == null) ? createRow() : getRow(i);
  136. for (int k = 0; k < col; k++) {
  137. if (tabRow.getCell(k) == null) {
  138. tabRow.createCell();
  139. }
  140. }
  141. }
  142. }
  143. public XWPFTable(CTTbl table, IBody part) {
  144. this.part = part;
  145. this.ctTbl = table;
  146. // is an empty table: I add one row and one column as default
  147. if (table.sizeOfTrArray() == 0) {
  148. createEmptyTable(table);
  149. }
  150. for (CTRow row : table.getTrList()) {
  151. StringBuilder rowText = new StringBuilder();
  152. XWPFTableRow tabRow = new XWPFTableRow(row, this);
  153. tableRows.add(tabRow);
  154. for (CTTc cell : row.getTcList()) {
  155. for (CTP ctp : cell.getPList()) {
  156. XWPFParagraph p = new XWPFParagraph(ctp, part);
  157. if (rowText.length() > 0) {
  158. rowText.append('\t');
  159. }
  160. rowText.append(p.getText());
  161. }
  162. }
  163. if (rowText.length() > 0) {
  164. this.text.append(rowText);
  165. this.text.append('\n');
  166. }
  167. }
  168. }
  169. private void createEmptyTable(CTTbl table) {
  170. // MINIMUM ELEMENTS FOR A TABLE
  171. table.addNewTr().addNewTc().addNewP();
  172. CTTblPr tblpro = table.addNewTblPr();
  173. tblpro.addNewTblW().setW(BigInteger.valueOf(0));
  174. tblpro.getTblW().setType(STTblWidth.AUTO);
  175. // layout
  176. // tblpro.addNewTblLayout().setType(STTblLayoutType.AUTOFIT);
  177. // borders
  178. CTTblBorders borders = tblpro.addNewTblBorders();
  179. borders.addNewBottom().setVal(STBorder.SINGLE);
  180. borders.addNewInsideH().setVal(STBorder.SINGLE);
  181. borders.addNewInsideV().setVal(STBorder.SINGLE);
  182. borders.addNewLeft().setVal(STBorder.SINGLE);
  183. borders.addNewRight().setVal(STBorder.SINGLE);
  184. borders.addNewTop().setVal(STBorder.SINGLE);
  185. /*
  186. * CTTblGrid tblgrid=table.addNewTblGrid();
  187. * tblgrid.addNewGridCol().setW(new BigInteger("2000"));
  188. */
  189. //getRows();
  190. }
  191. /**
  192. * @return ctTbl object
  193. */
  194. @Internal
  195. public CTTbl getCTTbl() {
  196. return ctTbl;
  197. }
  198. /**
  199. * Convenience method to extract text in cells. This
  200. * does not extract text recursively in cells, and it does not
  201. * currently include text in SDT (form) components.
  202. * <p>
  203. * To get all text within a table, see XWPFWordExtractor's appendTableText
  204. * as an example.
  205. *
  206. * @return text
  207. */
  208. public String getText() {
  209. return text.toString();
  210. }
  211. /**
  212. * Add a new cell at the end of each row in this table, creating a new column.
  213. * If rows have different numbers of columns, will still append a cell to each row.
  214. * Currently does not match the width of existing columns.
  215. */
  216. public void addNewCol() {
  217. if (tableRows.size() == 0) {
  218. createRow();
  219. }
  220. for (XWPFTableRow tableRow : tableRows) {
  221. tableRow.createCell();
  222. }
  223. }
  224. /**
  225. * create a new XWPFTableRow object with as many cells as the number of columns defined in that moment
  226. *
  227. * @return tableRow
  228. */
  229. public XWPFTableRow createRow() {
  230. int sizeCol = ctTbl.sizeOfTrArray() > 0 ? ctTbl.getTrArray(0)
  231. .sizeOfTcArray() : 0;
  232. XWPFTableRow tabRow = new XWPFTableRow(ctTbl.addNewTr(), this);
  233. addColumn(tabRow, sizeCol);
  234. tableRows.add(tabRow);
  235. return tabRow;
  236. }
  237. /**
  238. * @param pos - index of the row
  239. * @return the row at the position specified or null if no rows is defined or if the position is greather than the max size of rows array
  240. */
  241. public XWPFTableRow getRow(int pos) {
  242. if (pos >= 0 && pos < ctTbl.sizeOfTrArray()) {
  243. //return new XWPFTableRow(ctTbl.getTrArray(pos));
  244. return getRows().get(pos);
  245. }
  246. return null;
  247. }
  248. /**
  249. * Get the width value as an integer.
  250. * <p>If the width type is AUTO, DXA, or NIL, the value is 20ths of a point. If
  251. * the width type is PCT, the value is the percentage times 50 (e.g., 2500 for 50%).</p>
  252. * @return width value as an integer
  253. */
  254. public int getWidth() {
  255. CTTblPr tblPr = getTblPr();
  256. return tblPr.isSetTblW() ? (int)Units.toDXA(POIXMLUnits.parseLength(tblPr.getTblW().xgetW())) : -1;
  257. }
  258. /**
  259. * Set the width in 20ths of a point (twips).
  260. * @param width Width value (20ths of a point)
  261. */
  262. public void setWidth(int width) {
  263. CTTblPr tblPr = getTblPr();
  264. CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();
  265. tblWidth.setW(new BigInteger(Integer.toString(width)));
  266. tblWidth.setType(STTblWidth.DXA);
  267. }
  268. /**
  269. * @return number of rows in table
  270. */
  271. public int getNumberOfRows() {
  272. return ctTbl.sizeOfTrArray();
  273. }
  274. /**
  275. * Returns CTTblPr object for table. Creates it if it does not exist.
  276. */
  277. private CTTblPr getTblPr() {
  278. return getTblPr(true);
  279. }
  280. /**
  281. * Returns CTTblPr object for table. If force parameter is true, will
  282. * create the element if necessary. If force parameter is false, returns
  283. * null when CTTblPr element is missing.
  284. *
  285. * @param force - force creation of CTTblPr element if necessary
  286. */
  287. private CTTblPr getTblPr(boolean force) {
  288. return (ctTbl.getTblPr() != null) ? ctTbl.getTblPr()
  289. : (force ? ctTbl.addNewTblPr() : null);
  290. }
  291. /**
  292. * Return CTTblBorders object for table. If force parameter is true, will
  293. * create the element if necessary. If force parameter is false, returns
  294. * null when CTTblBorders element is missing.
  295. *
  296. * @param force - force creation of CTTblBorders element if necessary
  297. */
  298. private CTTblBorders getTblBorders(boolean force) {
  299. CTTblPr tblPr = getTblPr(force);
  300. return tblPr == null ? null
  301. : tblPr.isSetTblBorders() ? tblPr.getTblBorders()
  302. : force ? tblPr.addNewTblBorders()
  303. : null;
  304. }
  305. /**
  306. * Return CTBorder object for given border. If force parameter is true,
  307. * will create the element if necessary. If force parameter is false, returns
  308. * null when the border element is missing.
  309. *
  310. * @param force - force creation of border if necessary.
  311. */
  312. private CTBorder getTblBorder(boolean force, Border border) {
  313. final Function<CTTblBorders,Boolean> isSet;
  314. final Function<CTTblBorders,CTBorder> get;
  315. final Function<CTTblBorders,CTBorder> addNew;
  316. switch (border) {
  317. case INSIDE_V:
  318. isSet = CTTblBorders::isSetInsideV;
  319. get = CTTblBorders::getInsideV;
  320. addNew = CTTblBorders::addNewInsideV;
  321. break;
  322. case INSIDE_H:
  323. isSet = CTTblBorders::isSetInsideH;
  324. get = CTTblBorders::getInsideH;
  325. addNew = CTTblBorders::addNewInsideH;
  326. break;
  327. case LEFT:
  328. isSet = CTTblBorders::isSetLeft;
  329. get = CTTblBorders::getLeft;
  330. addNew = CTTblBorders::addNewLeft;
  331. break;
  332. case TOP:
  333. isSet = CTTblBorders::isSetTop;
  334. get = CTTblBorders::getTop;
  335. addNew = CTTblBorders::addNewTop;
  336. break;
  337. case RIGHT:
  338. isSet = CTTblBorders::isSetRight;
  339. get = CTTblBorders::getRight;
  340. addNew = CTTblBorders::addNewRight;
  341. break;
  342. case BOTTOM:
  343. isSet = CTTblBorders::isSetBottom;
  344. get = CTTblBorders::getBottom;
  345. addNew = CTTblBorders::addNewBottom;
  346. break;
  347. default:
  348. return null;
  349. }
  350. CTTblBorders ctb = getTblBorders(force);
  351. return ctb == null ? null
  352. : isSet.apply(ctb) ? get.apply(ctb)
  353. : force ? addNew.apply(ctb)
  354. : null;
  355. }
  356. /**
  357. * Returns the current table alignment or NULL
  358. *
  359. * @return Table Alignment as a {@link TableRowAlign} enum
  360. */
  361. public TableRowAlign getTableAlignment() {
  362. CTTblPr tPr = getTblPr(false);
  363. return tPr == null ? null
  364. : tPr.isSetJc() ? TableRowAlign.valueOf(tPr.getJc().getVal().intValue())
  365. : null;
  366. }
  367. /**
  368. * Set table alignment to specified {@link TableRowAlign}
  369. *
  370. * @param tra {@link TableRowAlign} to set
  371. */
  372. public void setTableAlignment(TableRowAlign tra) {
  373. CTTblPr tPr = getTblPr(true);
  374. CTJcTable jc = tPr.isSetJc() ? tPr.getJc() : tPr.addNewJc();
  375. jc.setVal(STJcTable.Enum.forInt(tra.getValue()));
  376. }
  377. /**
  378. * Removes the table alignment attribute from a table
  379. */
  380. public void removeTableAlignment() {
  381. CTTblPr tPr = getTblPr(false);
  382. if (tPr != null && tPr.isSetJc()) {
  383. tPr.unsetJc();
  384. }
  385. }
  386. private void addColumn(XWPFTableRow tabRow, int sizeCol) {
  387. if (sizeCol > 0) {
  388. for (int i = 0; i < sizeCol; i++) {
  389. tabRow.createCell();
  390. }
  391. }
  392. }
  393. /**
  394. * get the StyleID of the table
  395. *
  396. * @return style-ID of the table
  397. */
  398. public String getStyleID() {
  399. String styleId = null;
  400. CTTblPr tblPr = ctTbl.getTblPr();
  401. if (tblPr != null) {
  402. CTString styleStr = tblPr.getTblStyle();
  403. if (styleStr != null) {
  404. styleId = styleStr.getVal();
  405. }
  406. }
  407. return styleId;
  408. }
  409. /**
  410. * Set the table style. If the style is not defined in the document, MS Word
  411. * will set the table style to "Normal".
  412. *
  413. * @param styleName - the style name to apply to this table
  414. */
  415. public void setStyleID(String styleName) {
  416. CTTblPr tblPr = getTblPr();
  417. CTString styleStr = tblPr.getTblStyle();
  418. if (styleStr == null) {
  419. styleStr = tblPr.addNewTblStyle();
  420. }
  421. styleStr.setVal(styleName);
  422. }
  423. /**
  424. * Get inside horizontal border type
  425. *
  426. * @return {@link XWPFBorderType} of the inside horizontal borders or null if missing
  427. */
  428. public XWPFBorderType getInsideHBorderType() {
  429. return getBorderType(Border.INSIDE_H);
  430. }
  431. /**
  432. * Get inside horizontal border size
  433. *
  434. * @return The width of the Inside Horizontal borders in 1/8th points,
  435. * -1 if missing.
  436. */
  437. public int getInsideHBorderSize() {
  438. return getBorderSize(Border.INSIDE_H);
  439. }
  440. /**
  441. * Get inside horizontal border spacing
  442. *
  443. * @return The offset to the Inside Horizontal borders in points,
  444. * -1 if missing.
  445. */
  446. public int getInsideHBorderSpace() {
  447. return getBorderSpace(Border.INSIDE_H);
  448. }
  449. /**
  450. * Get inside horizontal border color
  451. *
  452. * @return The color of the Inside Horizontal borders, null if missing.
  453. */
  454. public String getInsideHBorderColor() {
  455. return getBorderColor(Border.INSIDE_H);
  456. }
  457. /**
  458. * Get inside vertical border type
  459. *
  460. * @return {@link XWPFBorderType} of the inside vertical borders or null if missing
  461. */
  462. public XWPFBorderType getInsideVBorderType() {
  463. return getBorderType(Border.INSIDE_V);
  464. }
  465. /**
  466. * Get inside vertical border size
  467. *
  468. * @return The width of the Inside vertical borders in 1/8th points,
  469. * -1 if missing.
  470. */
  471. public int getInsideVBorderSize() {
  472. return getBorderSize(Border.INSIDE_V);
  473. }
  474. /**
  475. * Get inside vertical border spacing
  476. *
  477. * @return The offset to the Inside vertical borders in points,
  478. * -1 if missing.
  479. */
  480. public int getInsideVBorderSpace() {
  481. return getBorderSpace(Border.INSIDE_V);
  482. }
  483. /**
  484. * Get inside vertical border color
  485. *
  486. * @return The color of the Inside vertical borders, null if missing.
  487. */
  488. public String getInsideVBorderColor() {
  489. return getBorderColor(Border.INSIDE_V);
  490. }
  491. /**
  492. * Get top border type
  493. *
  494. * @return {@link XWPFBorderType} of the top borders or null if missing
  495. */
  496. public XWPFBorderType getTopBorderType() {
  497. return getBorderType(Border.TOP);
  498. }
  499. /**
  500. * Get top border size
  501. *
  502. * @return The width of the top borders in 1/8th points,
  503. * -1 if missing.
  504. */
  505. public int getTopBorderSize() {
  506. return getBorderSize(Border.TOP);
  507. }
  508. /**
  509. * Get top border spacing
  510. *
  511. * @return The offset to the top borders in points,
  512. * -1 if missing.
  513. */
  514. public int getTopBorderSpace() {
  515. return getBorderSpace(Border.TOP);
  516. }
  517. /**
  518. * Get top border color
  519. *
  520. * @return The color of the top borders, null if missing.
  521. */
  522. public String getTopBorderColor() {
  523. return getBorderColor(Border.TOP);
  524. }
  525. /**
  526. * Get bottom border type
  527. *
  528. * @return {@link XWPFBorderType} of the bottom borders or null if missing
  529. */
  530. public XWPFBorderType getBottomBorderType() {
  531. return getBorderType(Border.BOTTOM);
  532. }
  533. /**
  534. * Get bottom border size
  535. *
  536. * @return The width of the bottom borders in 1/8th points,
  537. * -1 if missing.
  538. */
  539. public int getBottomBorderSize() {
  540. return getBorderSize(Border.BOTTOM);
  541. }
  542. /**
  543. * Get bottom border spacing
  544. *
  545. * @return The offset to the bottom borders in points,
  546. * -1 if missing.
  547. */
  548. public int getBottomBorderSpace() {
  549. return getBorderSpace(Border.BOTTOM);
  550. }
  551. /**
  552. * Get bottom border color
  553. *
  554. * @return The color of the bottom borders, null if missing.
  555. */
  556. public String getBottomBorderColor() {
  557. return getBorderColor(Border.BOTTOM);
  558. }
  559. /**
  560. * Get Left border type
  561. *
  562. * @return {@link XWPFBorderType} of the Left borders or null if missing
  563. */
  564. public XWPFBorderType getLeftBorderType() {
  565. return getBorderType(Border.LEFT);
  566. }
  567. /**
  568. * Get Left border size
  569. *
  570. * @return The width of the Left borders in 1/8th points,
  571. * -1 if missing.
  572. */
  573. public int getLeftBorderSize() {
  574. return getBorderSize(Border.LEFT);
  575. }
  576. /**
  577. * Get Left border spacing
  578. *
  579. * @return The offset to the Left borders in points,
  580. * -1 if missing.
  581. */
  582. public int getLeftBorderSpace() {
  583. return getBorderSpace(Border.LEFT);
  584. }
  585. /**
  586. * Get Left border color
  587. *
  588. * @return The color of the Left borders, null if missing.
  589. */
  590. public String getLeftBorderColor() {
  591. return getBorderColor(Border.LEFT);
  592. }
  593. /**
  594. * Get Right border type
  595. *
  596. * @return {@link XWPFBorderType} of the Right borders or null if missing
  597. */
  598. public XWPFBorderType getRightBorderType() {
  599. return getBorderType(Border.RIGHT);
  600. }
  601. /**
  602. * Get Right border size
  603. *
  604. * @return The width of the Right borders in 1/8th points,
  605. * -1 if missing.
  606. */
  607. public int getRightBorderSize() {
  608. return getBorderSize(Border.RIGHT);
  609. }
  610. /**
  611. * Get Right border spacing
  612. *
  613. * @return The offset to the Right borders in points,
  614. * -1 if missing.
  615. */
  616. public int getRightBorderSpace() {
  617. return getBorderSpace(Border.RIGHT);
  618. }
  619. /**
  620. * Get Right border color
  621. *
  622. * @return The color of the Right borders, null if missing.
  623. */
  624. public String getRightBorderColor() {
  625. return getBorderColor(Border.RIGHT);
  626. }
  627. private XWPFBorderType getBorderType(Border border) {
  628. final CTBorder b = getTblBorder(false, border);
  629. return (b != null) ? stBorderTypeMap.get(b.getVal().intValue()) : null;
  630. }
  631. private int getBorderSize(Border border) {
  632. final CTBorder b = getTblBorder(false, border);
  633. return (b != null)
  634. ? (b.isSetSz() ? b.getSz().intValue() : -1)
  635. : -1;
  636. }
  637. private int getBorderSpace(Border border) {
  638. final CTBorder b = getTblBorder(false, border);
  639. return (b != null)
  640. ? (b.isSetSpace() ? b.getSpace().intValue() : -1)
  641. : -1;
  642. }
  643. private String getBorderColor(Border border) {
  644. final CTBorder b = getTblBorder(false, border);
  645. return (b != null)
  646. ? (b.isSetColor() ? b.xgetColor().getStringValue() : null)
  647. : null;
  648. }
  649. public int getRowBandSize() {
  650. int size = 0;
  651. CTTblPr tblPr = getTblPr();
  652. if (tblPr.isSetTblStyleRowBandSize()) {
  653. CTDecimalNumber rowSize = tblPr.getTblStyleRowBandSize();
  654. size = rowSize.getVal().intValue();
  655. }
  656. return size;
  657. }
  658. public void setRowBandSize(int size) {
  659. CTTblPr tblPr = getTblPr();
  660. CTDecimalNumber rowSize = tblPr.isSetTblStyleRowBandSize() ? tblPr.getTblStyleRowBandSize() : tblPr.addNewTblStyleRowBandSize();
  661. rowSize.setVal(BigInteger.valueOf(size));
  662. }
  663. public int getColBandSize() {
  664. int size = 0;
  665. CTTblPr tblPr = getTblPr();
  666. if (tblPr.isSetTblStyleColBandSize()) {
  667. CTDecimalNumber colSize = tblPr.getTblStyleColBandSize();
  668. size = colSize.getVal().intValue();
  669. }
  670. return size;
  671. }
  672. public void setColBandSize(int size) {
  673. CTTblPr tblPr = getTblPr();
  674. CTDecimalNumber colSize = tblPr.isSetTblStyleColBandSize() ? tblPr.getTblStyleColBandSize() : tblPr.addNewTblStyleColBandSize();
  675. colSize.setVal(BigInteger.valueOf(size));
  676. }
  677. /**
  678. * Set Inside horizontal borders for a table
  679. *
  680. * @param type - {@link XWPFBorderType} e.g. single, double, thick
  681. * @param size - Specifies the width of the current border. The width of this border is
  682. * specified in measurements of eighths of a point, with a minimum value of two (onefourth
  683. * of a point) and a maximum value of 96 (twelve points). Any values outside this
  684. * range may be reassigned to a more appropriate value.
  685. * @param space - Specifies the spacing offset that shall be used to place this border on the table
  686. * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
  687. * or auto to allow a consumer to automatically determine the border color as appropriate.
  688. */
  689. public void setInsideHBorder(XWPFBorderType type, int size, int space, String rgbColor) {
  690. setBorder(Border.INSIDE_H, type, size, space, rgbColor);
  691. }
  692. /**
  693. * Set Inside Vertical borders for table
  694. *
  695. * @param type - {@link XWPFBorderType} e.g. single, double, thick
  696. * @param size - Specifies the width of the current border. The width of this border is
  697. * specified in measurements of eighths of a point, with a minimum value of two (onefourth
  698. * of a point) and a maximum value of 96 (twelve points). Any values outside this
  699. * range may be reassigned to a more appropriate value.
  700. * @param space - Specifies the spacing offset that shall be used to place this border on the table
  701. * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
  702. * or auto to allow a consumer to automatically determine the border color as appropriate.
  703. */
  704. public void setInsideVBorder(XWPFBorderType type, int size, int space, String rgbColor) {
  705. setBorder(Border.INSIDE_V, type, size, space, rgbColor);
  706. }
  707. /**
  708. * Set Top borders for table
  709. *
  710. * @param type - {@link XWPFBorderType} e.g. single, double, thick
  711. * @param size - Specifies the width of the current border. The width of this border is
  712. * specified in measurements of eighths of a point, with a minimum value of two (onefourth
  713. * of a point) and a maximum value of 96 (twelve points). Any values outside this
  714. * range may be reassigned to a more appropriate value.
  715. * @param space - Specifies the spacing offset that shall be used to place this border on the table
  716. * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
  717. * or auto to allow a consumer to automatically determine the border color as appropriate.
  718. */
  719. public void setTopBorder(XWPFBorderType type, int size, int space, String rgbColor) {
  720. setBorder(Border.TOP, type, size, space, rgbColor);
  721. }
  722. /**
  723. * Set Bottom borders for table
  724. *
  725. * @param type - {@link XWPFBorderType} e.g. single, double, thick
  726. * @param size - Specifies the width of the current border. The width of this border is
  727. * specified in measurements of eighths of a point, with a minimum value of two (onefourth
  728. * of a point) and a maximum value of 96 (twelve points). Any values outside this
  729. * range may be reassigned to a more appropriate value.
  730. * @param space - Specifies the spacing offset that shall be used to place this border on the table
  731. * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
  732. * or auto to allow a consumer to automatically determine the border color as appropriate.
  733. */
  734. public void setBottomBorder(XWPFBorderType type, int size, int space, String rgbColor) {
  735. setBorder(Border.BOTTOM, type, size, space, rgbColor);
  736. }
  737. /**
  738. * Set Left borders for table
  739. *
  740. * @param type - {@link XWPFBorderType} e.g. single, double, thick
  741. * @param size - Specifies the width of the current border. The width of this border is
  742. * specified in measurements of eighths of a point, with a minimum value of two (onefourth
  743. * of a point) and a maximum value of 96 (twelve points). Any values outside this
  744. * range may be reassigned to a more appropriate value.
  745. * @param space - Specifies the spacing offset that shall be used to place this border on the table
  746. * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
  747. * or auto to allow a consumer to automatically determine the border color as appropriate.
  748. */
  749. public void setLeftBorder(XWPFBorderType type, int size, int space, String rgbColor) {
  750. setBorder(Border.LEFT, type, size, space, rgbColor);
  751. }
  752. /**
  753. * Set Right borders for table
  754. *
  755. * @param type - {@link XWPFBorderType} e.g. single, double, thick
  756. * @param size - Specifies the width of the current border. The width of this border is
  757. * specified in measurements of eighths of a point, with a minimum value of two (onefourth
  758. * of a point) and a maximum value of 96 (twelve points). Any values outside this
  759. * range may be reassigned to a more appropriate value.
  760. * @param space - Specifies the spacing offset that shall be used to place this border on the table
  761. * @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
  762. * or auto to allow a consumer to automatically determine the border color as appropriate.
  763. */
  764. public void setRightBorder(XWPFBorderType type, int size, int space, String rgbColor) {
  765. setBorder(Border.RIGHT, type, size, space, rgbColor);
  766. }
  767. private void setBorder(Border border, XWPFBorderType type, int size, int space, String rgbColor) {
  768. final CTBorder b = getTblBorder(true, border);
  769. assert(b != null);
  770. b.setVal(xwpfBorderTypeMap.get(type));
  771. b.setSz(BigInteger.valueOf(size));
  772. b.setSpace(BigInteger.valueOf(space));
  773. b.setColor(rgbColor);
  774. }
  775. /**
  776. * Remove inside horizontal borders for table
  777. */
  778. public void removeInsideHBorder() {
  779. removeBorder(Border.INSIDE_H);
  780. }
  781. /**
  782. * Remove inside vertical borders for table
  783. */
  784. public void removeInsideVBorder() {
  785. removeBorder(Border.INSIDE_V);
  786. }
  787. /**
  788. * Remove top borders for table
  789. */
  790. public void removeTopBorder() {
  791. removeBorder(Border.TOP);
  792. }
  793. /**
  794. * Remove bottom borders for table
  795. */
  796. public void removeBottomBorder() {
  797. removeBorder(Border.BOTTOM);
  798. }
  799. /**
  800. * Remove left borders for table
  801. */
  802. public void removeLeftBorder() {
  803. removeBorder(Border.LEFT);
  804. }
  805. /**
  806. * Remove right borders for table
  807. */
  808. public void removeRightBorder() {
  809. removeBorder(Border.RIGHT);
  810. }
  811. /**
  812. * Remove all borders from table
  813. */
  814. public void removeBorders() {
  815. final CTTblPr pr = getTblPr(false);
  816. if (pr != null && pr.isSetTblBorders()) {
  817. pr.unsetTblBorders();
  818. }
  819. }
  820. private void removeBorder(final Border border) {
  821. final Function<CTTblBorders,Boolean> isSet;
  822. final Consumer<CTTblBorders> unSet;
  823. switch (border) {
  824. case INSIDE_H:
  825. isSet = CTTblBorders::isSetInsideH;
  826. unSet = CTTblBorders::unsetInsideH;
  827. break;
  828. case INSIDE_V:
  829. isSet = CTTblBorders::isSetInsideV;
  830. unSet = CTTblBorders::unsetInsideV;
  831. break;
  832. case LEFT:
  833. isSet = CTTblBorders::isSetLeft;
  834. unSet = CTTblBorders::unsetLeft;
  835. break;
  836. case TOP:
  837. isSet = CTTblBorders::isSetTop;
  838. unSet = CTTblBorders::unsetTop;
  839. break;
  840. case RIGHT:
  841. isSet = CTTblBorders::isSetRight;
  842. unSet = CTTblBorders::unsetRight;
  843. break;
  844. case BOTTOM:
  845. isSet = CTTblBorders::isSetBottom;
  846. unSet = CTTblBorders::unsetBottom;
  847. break;
  848. default:
  849. return;
  850. }
  851. final CTTblBorders tbl = getTblBorders(false);
  852. if (tbl != null && isSet.apply(tbl)) {
  853. unSet.accept(tbl);
  854. cleanupTblBorders();
  855. }
  856. }
  857. /**
  858. * removes the Borders node from Table properties if there are
  859. * no border elements
  860. */
  861. private void cleanupTblBorders() {
  862. final CTTblPr pr = getTblPr(false);
  863. if (pr != null && pr.isSetTblBorders()) {
  864. final CTTblBorders b = pr.getTblBorders();
  865. if (!(b.isSetInsideH() ||
  866. b.isSetInsideV() ||
  867. b.isSetTop() ||
  868. b.isSetBottom() ||
  869. b.isSetLeft() ||
  870. b.isSetRight())) {
  871. pr.unsetTblBorders();
  872. }
  873. }
  874. }
  875. public int getCellMarginTop() {
  876. return getCellMargin(CTTblCellMar::getTop);
  877. }
  878. public int getCellMarginLeft() {
  879. return getCellMargin(CTTblCellMar::getLeft);
  880. }
  881. public int getCellMarginBottom() {
  882. return getCellMargin(CTTblCellMar::getBottom);
  883. }
  884. public int getCellMarginRight() {
  885. return getCellMargin(CTTblCellMar::getRight);
  886. }
  887. private int getCellMargin(Function<CTTblCellMar,CTTblWidth> margin) {
  888. CTTblPr tblPr = getTblPr();
  889. CTTblCellMar tcm = tblPr.getTblCellMar();
  890. if (tcm != null) {
  891. CTTblWidth tw = margin.apply(tcm);
  892. if (tw != null) {
  893. return (int) Units.toDXA(POIXMLUnits.parseLength(tw.xgetW()));
  894. }
  895. }
  896. return 0;
  897. }
  898. public void setCellMargins(int top, int left, int bottom, int right) {
  899. CTTblPr tblPr = getTblPr();
  900. CTTblCellMar tcm = tblPr.isSetTblCellMar() ? tblPr.getTblCellMar() : tblPr.addNewTblCellMar();
  901. setCellMargin(tcm, CTTblCellMar::isSetTop, CTTblCellMar::getTop, CTTblCellMar::addNewTop, CTTblCellMar::unsetTop, top);
  902. setCellMargin(tcm, CTTblCellMar::isSetLeft, CTTblCellMar::getLeft, CTTblCellMar::addNewLeft, CTTblCellMar::unsetLeft, left);
  903. setCellMargin(tcm, CTTblCellMar::isSetBottom, CTTblCellMar::getBottom, CTTblCellMar::addNewBottom, CTTblCellMar::unsetBottom, bottom);
  904. setCellMargin(tcm, CTTblCellMar::isSetRight, CTTblCellMar::getRight, CTTblCellMar::addNewRight, CTTblCellMar::unsetRight, right);
  905. }
  906. private void setCellMargin(CTTblCellMar tcm, Function<CTTblCellMar,Boolean> isSet, Function<CTTblCellMar,CTTblWidth> get, Function<CTTblCellMar,CTTblWidth> addNew, Consumer<CTTblCellMar> unSet, int margin) {
  907. if (margin == 0) {
  908. if (isSet.apply(tcm)) {
  909. unSet.accept(tcm);
  910. }
  911. } else {
  912. CTTblWidth tw = (isSet.apply(tcm) ? get : addNew).apply(tcm);
  913. tw.setType(STTblWidth.DXA);
  914. tw.setW(BigInteger.valueOf(margin));
  915. }
  916. }
  917. /**
  918. * add a new Row to the table
  919. *
  920. * @param row the row which should be added
  921. */
  922. public void addRow(XWPFTableRow row) {
  923. ctTbl.addNewTr();
  924. ctTbl.setTrArray(getNumberOfRows() - 1, row.getCtRow());
  925. tableRows.add(row);
  926. }
  927. /**
  928. * add a new Row to the table
  929. * at position pos
  930. *
  931. * @param row the row which should be added
  932. */
  933. public boolean addRow(XWPFTableRow row, int pos) {
  934. if (pos >= 0 && pos <= tableRows.size()) {
  935. ctTbl.insertNewTr(pos);
  936. ctTbl.setTrArray(pos, row.getCtRow());
  937. tableRows.add(pos, row);
  938. return true;
  939. }
  940. return false;
  941. }
  942. /**
  943. * inserts a new tablerow
  944. *
  945. * @return the inserted row
  946. */
  947. public XWPFTableRow insertNewTableRow(int pos) {
  948. if (pos >= 0 && pos <= tableRows.size()) {
  949. CTRow row = ctTbl.insertNewTr(pos);
  950. XWPFTableRow tableRow = new XWPFTableRow(row, this);
  951. tableRows.add(pos, tableRow);
  952. return tableRow;
  953. }
  954. return null;
  955. }
  956. /**
  957. * Remove a row at position pos from the table
  958. *
  959. * @param pos position the Row in the Table
  960. */
  961. public boolean removeRow(int pos) throws IndexOutOfBoundsException {
  962. if (pos >= 0 && pos < tableRows.size()) {
  963. if (ctTbl.sizeOfTrArray() > 0) {
  964. ctTbl.removeTr(pos);
  965. }
  966. tableRows.remove(pos);
  967. return true;
  968. }
  969. return false;
  970. }
  971. public List<XWPFTableRow> getRows() {
  972. return Collections.unmodifiableList(tableRows);
  973. }
  974. /**
  975. * returns the type of the BodyElement Table
  976. */
  977. @Override
  978. public BodyElementType getElementType() {
  979. return BodyElementType.TABLE;
  980. }
  981. @Override
  982. public IBody getBody() {
  983. return part;
  984. }
  985. /**
  986. * returns the part of the bodyElement
  987. *
  988. * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
  989. */
  990. @Override
  991. public POIXMLDocumentPart getPart() {
  992. if (part != null) {
  993. return part.getPart();
  994. }
  995. return null;
  996. }
  997. /**
  998. * returns the partType of the bodyPart which owns the bodyElement
  999. *
  1000. * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
  1001. */
  1002. @Override
  1003. public BodyType getPartType() {
  1004. return part.getPartType();
  1005. }
  1006. /**
  1007. * returns the XWPFRow which belongs to the CTRow row
  1008. * if this row is not existing in the table null will be returned
  1009. */
  1010. public XWPFTableRow getRow(CTRow row) {
  1011. for (int i = 0; i < getRows().size(); i++) {
  1012. if (getRows().get(i).getCtRow() == row) {
  1013. return getRow(i);
  1014. }
  1015. }
  1016. return null;
  1017. }
  1018. /**
  1019. * Get the table width as a decimal value.
  1020. * <p>If the width type is DXA or AUTO, then the value will always have
  1021. * a fractional part of zero (because these values are really integers).
  1022. * If the with type is percentage, then value may have a non-zero fractional
  1023. * part.
  1024. *
  1025. * @return Width value as a double-precision decimal.
  1026. * @since 4.0.0
  1027. */
  1028. public double getWidthDecimal() {
  1029. return getWidthDecimal(getTblPr().getTblW());
  1030. }
  1031. /**
  1032. * Get the width as a decimal value.
  1033. * <p>This method is also used by table cells.
  1034. * @param ctWidth Width value to evaluate.
  1035. * @return Width value as a decimal
  1036. * @since 4.0.0
  1037. */
  1038. protected static double getWidthDecimal(CTTblWidth ctWidth) {
  1039. double result = 0.0;
  1040. STTblWidth.Enum typeValue = ctWidth.getType();
  1041. if (typeValue == STTblWidth.DXA
  1042. || typeValue == STTblWidth.AUTO
  1043. || typeValue == STTblWidth.NIL) {
  1044. result = 0.0 + Units.toDXA(POIXMLUnits.parseLength(ctWidth.xgetW()));
  1045. } else if (typeValue == STTblWidth.PCT) {
  1046. // Percentage values are stored as integers that are 50 times
  1047. // percentage.
  1048. result = Units.toDXA(POIXMLUnits.parseLength(ctWidth.xgetW())) / 50.0;
  1049. } else {
  1050. // Should never get here
  1051. }
  1052. return result;
  1053. }
  1054. /**
  1055. * Get the width type for the table, as an {@link STTblWidth.Enum} value.
  1056. * A table width can be specified as an absolute measurement (an integer
  1057. * number of twips), a percentage, or the value "AUTO".
  1058. *
  1059. * @return The width type.
  1060. * @since 4.0.0
  1061. */
  1062. public TableWidthType getWidthType() {
  1063. return getWidthType(getTblPr().getTblW());
  1064. }
  1065. /**
  1066. * Get the width type from the width value
  1067. * @param ctWidth CTTblWidth to evalute
  1068. * @return The table width type
  1069. * @since 4.0.0
  1070. */
  1071. protected static TableWidthType getWidthType(CTTblWidth ctWidth) {
  1072. STTblWidth.Enum typeValue = ctWidth.getType();
  1073. if (typeValue == null) {
  1074. typeValue = STTblWidth.NIL;
  1075. ctWidth.setType(typeValue);
  1076. }
  1077. switch (typeValue.intValue()) {
  1078. case STTblWidth.INT_NIL:
  1079. return TableWidthType.NIL;
  1080. case STTblWidth.INT_DXA:
  1081. return TableWidthType.DXA;
  1082. case STTblWidth.INT_PCT:
  1083. return TableWidthType.PCT;
  1084. default:
  1085. case STTblWidth.INT_AUTO:
  1086. return TableWidthType.AUTO;
  1087. }
  1088. }
  1089. /**
  1090. * Set the width to the value "auto", an integer value (20ths of a point), or a percentage ("nn.nn%").
  1091. *
  1092. * @param widthValue String matching one of "auto", [0-9]+, or [0-9]+(\.[0-9]+)%.
  1093. * @since 4.0.0
  1094. */
  1095. public void setWidth(String widthValue) {
  1096. setWidthValue(widthValue, getTblPr().getTblW());
  1097. }
  1098. /**
  1099. * Set the width value from a string
  1100. * @param widthValue The width value string
  1101. * @param ctWidth CTTblWidth to set the value on.
  1102. */
  1103. protected static void setWidthValue(String widthValue, CTTblWidth ctWidth) {
  1104. if (!widthValue.matches(REGEX_WIDTH_VALUE)) {
  1105. throw new RuntimeException("Table width value \"" + widthValue + "\" "
  1106. + "must match regular expression \"" + REGEX_WIDTH_VALUE + "\".");
  1107. }
  1108. if (widthValue.matches("auto")) {
  1109. ctWidth.setType(STTblWidth.AUTO);
  1110. ctWidth.setW(BigInteger.ZERO);
  1111. } else if (widthValue.matches(REGEX_PERCENTAGE)) {
  1112. setWidthPercentage(ctWidth, widthValue);
  1113. } else {
  1114. // Must be an integer
  1115. ctWidth.setW(new BigInteger(widthValue));
  1116. ctWidth.setType(STTblWidth.DXA);
  1117. }
  1118. }
  1119. /**
  1120. * Set the underlying table width value to a percentage value.
  1121. * @param ctWidth The CTTblWidth to set the value on
  1122. * @param widthValue String width value in form "33.3%" or an integer that is 50 times desired percentage value (e.g,
  1123. * 2500 for 50%)
  1124. * @since 4.0.0
  1125. */
  1126. protected static void setWidthPercentage(CTTblWidth ctWidth, String widthValue) {
  1127. ctWidth.setType(STTblWidth.PCT);
  1128. if (widthValue.matches(REGEX_PERCENTAGE)) {
  1129. String numberPart = widthValue.substring(0, widthValue.length() - 1);
  1130. double percentage = Double.parseDouble(numberPart) * 50;
  1131. long intValue = Math.round(percentage);
  1132. ctWidth.setW(BigInteger.valueOf(intValue));
  1133. } else if (widthValue.matches("[0-9]+")) {
  1134. ctWidth.setW(new BigInteger(widthValue));
  1135. } else {
  1136. throw new RuntimeException("setWidthPercentage(): Width value must be a percentage (\"33.3%\" or an integer, was \"" + widthValue + "\"");
  1137. }
  1138. }
  1139. /**
  1140. * Set the width value type for the table.
  1141. * <p>If the width type is changed from the current type and the currently-set value
  1142. * is not consistent with the new width type, the value is reset to the default value
  1143. * for the specified width type.</p>
  1144. *
  1145. * @param widthType Width type
  1146. * @since 4.0.0
  1147. */
  1148. public void setWidthType(TableWidthType widthType) {
  1149. setWidthType(widthType, getTblPr().getTblW());
  1150. }
  1151. /**
  1152. * Set the width type if different from current width type
  1153. * @param widthType The new width type
  1154. * @param ctWidth CTTblWidth to set the type on
  1155. * @since 4.0.0
  1156. */
  1157. protected static void setWidthType(TableWidthType widthType, CTTblWidth ctWidth) {
  1158. TableWidthType currentType = getWidthType(ctWidth);
  1159. if (!currentType.equals(widthType)) {
  1160. STTblWidth.Enum stWidthType = widthType.getStWidthType();
  1161. ctWidth.setType(stWidthType);
  1162. if (stWidthType.intValue() == STTblWidth.INT_PCT) {
  1163. setWidthPercentage(ctWidth, DEFAULT_PERCENTAGE_WIDTH);
  1164. } else {
  1165. ctWidth.setW(BigInteger.ZERO);
  1166. }
  1167. }
  1168. }
  1169. }