PageRenderTime 121ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparties-extension/org.apache.poi.xwpf.converter.core/src/main/java/org/apache/poi/xwpf/converter/core/utils/XWPFTableUtil.java

https://github.com/minstrelsy/xdocreport
Java | 438 lines | 329 code | 45 blank | 64 comment | 62 complexity | a478f187fe2341e51a7f5e2902591fe7 MD5 | raw file
  1. /**
  2. * Copyright (C) 2011-2012 The XDocReport Team <xdocreport@googlegroups.com>
  3. *
  4. * All rights reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. package org.apache.poi.xwpf.converter.core.utils;
  26. import static org.apache.poi.xwpf.converter.core.utils.DxaUtil.dxa2points;
  27. import java.awt.Color;
  28. import java.math.BigInteger;
  29. import java.util.ArrayList;
  30. import java.util.Collection;
  31. import java.util.List;
  32. import org.apache.poi.xwpf.converter.core.TableCellBorder;
  33. import org.apache.poi.xwpf.converter.core.TableWidth;
  34. import org.apache.poi.xwpf.usermodel.XWPFTable;
  35. import org.apache.poi.xwpf.usermodel.XWPFTableCell;
  36. import org.apache.poi.xwpf.usermodel.XWPFTableRow;
  37. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;
  38. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
  39. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShortHexNumber;
  40. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
  41. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;
  42. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblCellMar;
  43. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid;
  44. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol;
  45. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
  46. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
  47. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
  48. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr;
  49. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;
  50. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
  51. import org.w3c.dom.Attr;
  52. import org.w3c.dom.Node;
  53. public class XWPFTableUtil
  54. {
  55. private static final String MAIN_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
  56. // Hexa Bitmask for tblLook.
  57. public static final int DEFAULT_TBLLOOK = 0x0000;
  58. public static final int APPLY_FIRST_ROW_CONDITIONNAL_FORMATTING = 0x0020; // Apply first row conditional formatting
  59. public static final int APPLY_LAST_ROW_CONDITIONNAL_FORMATTING = 0x0040; // Apply last row conditional formatting
  60. public static final int APPLY_FIRST_COLUMN_CONDITIONNAL_FORMATTING = 0x0080; // Apply first column conditional
  61. // formatting
  62. public static final int APPLY_LAST_COLUMN_CONDITIONNAL_FORMATTING = 0x0100; // Apply last column conditional
  63. // formatting
  64. public static final int DO_NOT_APPLY_ROW_BANDING_CONDITIONNAL_FORMATTING = 0x0200; // Do not apply row banding
  65. // conditional formatting
  66. public static final int DO_NOT_APPLY_COLUMN_BANDING_CONDITIONNAL_FORMATTING = 0x0400; // Do not apply column banding
  67. // conditional formatting
  68. /**
  69. * Compute column widths of the XWPF table.
  70. *
  71. * @param table
  72. * @return
  73. */
  74. public static float[] computeColWidths( XWPFTable table )
  75. {
  76. XWPFTableRow firstRow = getFirstRow( table );
  77. float[] colWidths;
  78. // Get first row to know if there is cell which have gridSpan to compute
  79. // columns number.
  80. int nbCols = getNumberOfColumns( firstRow );
  81. // Compare nbCols computed with number of grid colList
  82. CTTblGrid grid = table.getCTTbl().getTblGrid();
  83. List<CTTblGridCol> cols = grid.getGridColList();
  84. if ( nbCols > cols.size() )
  85. {
  86. Collection<Float> maxColWidths = null;
  87. Collection<Float> currentColWidths = null;
  88. // nbCols computed is not equals to number of grid colList
  89. // columns width must be computed by looping for each row/cells
  90. List<XWPFTableRow> rows = table.getRows();
  91. for ( XWPFTableRow row : rows )
  92. {
  93. currentColWidths = computeColWidths( row );
  94. if ( maxColWidths == null )
  95. {
  96. maxColWidths = currentColWidths;
  97. }
  98. else
  99. {
  100. if ( currentColWidths.size() > maxColWidths.size() )
  101. {
  102. maxColWidths = currentColWidths;
  103. }
  104. }
  105. }
  106. colWidths = new float[maxColWidths.size()];
  107. int i = 0;
  108. for ( Float colWidth : maxColWidths )
  109. {
  110. colWidths[i++] = colWidth;
  111. }
  112. return colWidths;
  113. }
  114. else
  115. {
  116. // If w:gridAfter is defined, ignore the last columns defined on the gridColumn
  117. int nbColumnsToIgnoreBefore = getNbColumnsToIgnore( firstRow, true );
  118. int nbColumnsToIgnoreAfter = getNbColumnsToIgnore( firstRow, false );
  119. int nbColumns = cols.size() - nbColumnsToIgnoreBefore - nbColumnsToIgnoreAfter;
  120. // nbCols computed is equals to number of grid colList
  121. // columns width can be computed by using the grid colList
  122. colWidths = new float[nbColumns];
  123. float colWidth = -1;
  124. for ( int i = nbColumnsToIgnoreBefore; i < colWidths.length; i++ )
  125. {
  126. CTTblGridCol tblGridCol = cols.get( i );
  127. colWidth = tblGridCol.getW().floatValue();
  128. colWidths[i] = dxa2points( colWidth );
  129. }
  130. }
  131. return colWidths;
  132. }
  133. private static int getNbColumnsToIgnore( XWPFTableRow row, boolean before )
  134. {
  135. CTTrPr trPr = row.getCtRow().getTrPr();
  136. if ( trPr == null )
  137. {
  138. return 0;
  139. }
  140. List<CTDecimalNumber> gridBeforeAfters = before ? trPr.getGridBeforeList() : trPr.getGridAfterList();
  141. if ( gridBeforeAfters == null || gridBeforeAfters.size() < 1 )
  142. {
  143. return 0;
  144. }
  145. int nbColumns = 0;
  146. BigInteger val = null;
  147. for ( CTDecimalNumber gridBeforeAfter : gridBeforeAfters )
  148. {
  149. val = gridBeforeAfter.getVal();
  150. if ( val != null )
  151. {
  152. nbColumns += val.intValue();
  153. }
  154. }
  155. return nbColumns;
  156. }
  157. /**
  158. * Returns number of column if the XWPF table by using the declared cell (which can declare gridSpan) from the first
  159. * row.
  160. *
  161. * @param table
  162. * @return
  163. */
  164. public static int getNumberOfColumns( XWPFTableRow row )
  165. {
  166. if ( row == null )
  167. {
  168. return 0;
  169. }
  170. // Get first row to know if there is cell which have gridSpan to compute
  171. // columns number.
  172. int nbCols = 0;
  173. List<XWPFTableCell> tableCellsOffFirstRow = row.getTableCells();
  174. for ( XWPFTableCell tableCellOffFirstRow : tableCellsOffFirstRow )
  175. {
  176. CTDecimalNumber gridSpan = getGridSpan( tableCellOffFirstRow );
  177. if ( gridSpan != null )
  178. {
  179. nbCols += gridSpan.getVal().intValue();
  180. }
  181. else
  182. {
  183. nbCols += 1;
  184. }
  185. }
  186. return nbCols;
  187. }
  188. public static XWPFTableRow getFirstRow( XWPFTable table )
  189. {
  190. int numberOfRows = table.getNumberOfRows();
  191. if ( numberOfRows > 0 )
  192. {
  193. return table.getRow( 0 );
  194. }
  195. return null;
  196. }
  197. public static CTDecimalNumber getGridSpan( XWPFTableCell cell )
  198. {
  199. if ( cell.getCTTc().getTcPr() != null )
  200. return cell.getCTTc().getTcPr().getGridSpan();
  201. return null;
  202. }
  203. public static CTTblWidth getWidth( XWPFTableCell cell )
  204. {
  205. return cell.getCTTc().getTcPr().getTcW();
  206. }
  207. private static Collection<Float> computeColWidths( XWPFTableRow row )
  208. {
  209. List<Float> colWidths = new ArrayList<Float>();
  210. List<XWPFTableCell> cells = row.getTableCells();
  211. for ( XWPFTableCell cell : cells )
  212. {
  213. // Width
  214. CTTblWidth width = getWidth( cell );
  215. if ( width != null )
  216. {
  217. int nb = 1;
  218. CTDecimalNumber gridSpan = getGridSpan( cell );
  219. TableWidth tableCellWidth = getTableWidth( cell );
  220. if ( gridSpan != null )
  221. {
  222. nb = gridSpan.getVal().intValue();
  223. }
  224. for ( int i = 0; i < nb; i++ )
  225. {
  226. colWidths.add( tableCellWidth.width / nb );
  227. }
  228. }
  229. }
  230. return colWidths;
  231. }
  232. /**
  233. * Returns table width of teh XWPF table.
  234. *
  235. * @param table
  236. * @return
  237. */
  238. public static TableWidth getTableWidth( XWPFTable table )
  239. {
  240. float width = 0;
  241. boolean percentUnit = false;
  242. CTTblPr tblPr = table.getCTTbl().getTblPr();
  243. if ( tblPr.isSetTblW() )
  244. {
  245. CTTblWidth tblWidth = tblPr.getTblW();
  246. return getTableWidth( tblWidth );
  247. }
  248. return new TableWidth( width, percentUnit );
  249. }
  250. public static TableWidth getTableWidth( XWPFTableCell cell )
  251. {
  252. float width = 0;
  253. boolean percentUnit = false;
  254. CTTcPr tblPr = cell.getCTTc().getTcPr();
  255. if ( tblPr.isSetTcW() )
  256. {
  257. CTTblWidth tblWidth = tblPr.getTcW();
  258. return getTableWidth( tblWidth );
  259. }
  260. return new TableWidth( width, percentUnit );
  261. }
  262. public static TableWidth getTableWidth( CTTblWidth tblWidth )
  263. {
  264. float width = tblWidth.getW().intValue();
  265. boolean percentUnit = ( STTblWidth.INT_PCT == tblWidth.getType().intValue() );
  266. if ( percentUnit )
  267. {
  268. width = width / 100f;
  269. }
  270. else
  271. {
  272. width = dxa2points( width );
  273. }
  274. return new TableWidth( width, percentUnit );
  275. }
  276. public static CTTblPr getTblPr( XWPFTable table )
  277. {
  278. CTTbl tbl = table.getCTTbl();
  279. if ( tbl != null )
  280. {
  281. return tbl.getTblPr();
  282. }
  283. return null;
  284. }
  285. public static CTTblBorders getTblBorders( XWPFTable table )
  286. {
  287. CTTblPr tblPr = getTblPr( table );
  288. if ( tblPr != null )
  289. {
  290. return tblPr.getTblBorders();
  291. }
  292. return null;
  293. }
  294. public static CTTblCellMar getTblCellMar( XWPFTable table )
  295. {
  296. CTTblPr tblPr = getTblPr( table );
  297. if ( tblPr != null )
  298. {
  299. return tblPr.getTblCellMar();
  300. }
  301. return null;
  302. }
  303. public static TableCellBorder getTableCellBorder( CTBorder border, boolean fromTableCell )
  304. {
  305. if ( border != null )
  306. {
  307. boolean noBorder = ( STBorder.NONE == border.getVal() || STBorder.NIL == border.getVal() );
  308. if ( noBorder )
  309. {
  310. return new TableCellBorder( !noBorder, fromTableCell );
  311. }
  312. Float borderSize = null;
  313. BigInteger size = border.getSz();
  314. if ( size != null )
  315. {
  316. // http://officeopenxml.com/WPtableBorders.php
  317. // if w:sz="4" => 1/4 points
  318. borderSize = size.floatValue() / 8f;
  319. }
  320. Color borderColor = ColorHelper.getBorderColor( border );
  321. return new TableCellBorder( borderSize, borderColor, fromTableCell );
  322. }
  323. return null;
  324. }
  325. public static Color getBorderColor( CTBorder border )
  326. {
  327. if ( border == null )
  328. {
  329. return null;
  330. }
  331. // border.getColor returns object???, use attribute w:color to get
  332. // the color.
  333. Node colorAttr = border.getDomNode().getAttributes().getNamedItemNS( MAIN_NAMESPACE, "color" );
  334. if ( colorAttr != null )
  335. {
  336. Object val = border.getVal();
  337. return ColorHelper.getColor( ( (Attr) colorAttr ).getValue(), val, false );
  338. }
  339. return null;
  340. }
  341. public static CTShortHexNumber getTblLook( XWPFTable table )
  342. {
  343. CTTblPr tblPr = getTblPr( table );
  344. if ( tblPr != null )
  345. {
  346. return tblPr.getTblLook();
  347. }
  348. return null;
  349. }
  350. public static int getTblLookVal( XWPFTable table )
  351. {
  352. int tblLook = DEFAULT_TBLLOOK;
  353. CTShortHexNumber hexNumber = getTblLook( table );
  354. if ( hexNumber != null && !hexNumber.isNil() )
  355. {
  356. // CTShortHexNumber#getVal() returns byte[] and not byte, use attr value ???
  357. Attr attr = (Attr) hexNumber.getDomNode().getAttributes().getNamedItemNS( MAIN_NAMESPACE, "val" );
  358. if ( attr != null )
  359. {
  360. String value = attr.getValue();
  361. try
  362. {
  363. tblLook = Integer.parseInt( value, 16 );
  364. }
  365. catch ( Throwable e )
  366. {
  367. e.printStackTrace();
  368. }
  369. }
  370. }
  371. return tblLook;
  372. }
  373. public static boolean canApplyFirstRow( int tblLookVal )
  374. {
  375. int mask = APPLY_FIRST_ROW_CONDITIONNAL_FORMATTING;
  376. return ( tblLookVal & mask ) == mask;
  377. }
  378. public static boolean canApplyLastRow( int tblLookVal )
  379. {
  380. int mask = APPLY_LAST_ROW_CONDITIONNAL_FORMATTING;
  381. return ( tblLookVal & mask ) == mask;
  382. }
  383. public static boolean canApplyFirstCol( int tblLookVal )
  384. {
  385. int mask = APPLY_FIRST_COLUMN_CONDITIONNAL_FORMATTING;
  386. return ( tblLookVal & mask ) == mask;
  387. }
  388. public static boolean canApplyLastCol( int tblLookVal )
  389. {
  390. int mask = APPLY_LAST_COLUMN_CONDITIONNAL_FORMATTING;
  391. return ( tblLookVal & mask ) == mask;
  392. }
  393. }