Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
     Licensed to Plutext Pty Ltd under one or more contributor license agreements.  
   *  This file is part of docx4j.
      docx4j is licensed under the Apache License, Version 2.0 (the "License"); 
      you may not use this file except in compliance with the License. 
      You may obtain a copy of the License at 
     Unless required by applicable law or agreed to in writing, software 
     distributed under the License is distributed on an "AS IS" BASIS, 
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     See the License for the specific language governing permissions and 
     limitations under the License.
 package org.docx4j.convert.out.common.writer;
There are different ways to represent a table with possibly merged cells.
  • In html, both vertically and horizontally merged cells are represented by one cell only that has a colspan and rowspan attribute. No dummy cells are used.
  • In docx, horizontally merged cells are represented by one cell with a gridSpan attribute; while vertically merged cells are represented as a top cell containing the actual content and a series of dummy cells having a vMerge tag with "continue" attribute.
  • This table is a regular matrix, dummy cells are added for both merge directions.
The algorithm is as follows,
  • When a cell is added, its colspan is set. Even a dummy cell can have a colspan, the same value as its upper has.
  • When a new cell has a colspan greater than 1, the required extra dummy cells are also added
  • When a docx dummy cell is encountered (one with a vMerge continue attribute), the rowspan is incremented in its upper neighbors until a real cell is found.

Adam Schmideg
A cell in the table holding its own content, too
 public class AbstractTableWriterModelCell {
 	private final static Logger logger = LoggerFactory.getLogger(AbstractTableWriterModelCell.class);
 	private int row;
 	private int col;
 	protected int rowspan = 0;
 	protected int colspan = 0;
If this is a real cell or only a placeholder. Vertically merged cells are represented as a real cell on the top and dummy cell(s) below
 	protected boolean dummy = false;
 	protected Node content = null;
 	public TcPr getTcPr() {
 		return ;

Create a dummy cell without content
 	public AbstractTableWriterModelCell(AbstractTableWriterModel tableint rowint col) {
 		this. = table;
 		this. = row;
 		this. = col;
 		this. = true;
 	public AbstractTableWriterModelCell(AbstractTableWriterModel tableint rowint colTc tcNode content) {
 		 = false;
 		this. = content;
 		 = tc.getTcPr();
 		if (content==null) {
 			.error("No content for row " + row + ", col " + col + "\n" 
 							+ XmlUtils.marshaltoString(tctruetrue));
 		} else {
			.debug("Cell content: " + XmlUtils.w3CDomNodeToString(content));
		/* xhtmlTc.appendChild(
		   document.importNode(tcDoc, true) );
		   org.w3c.dom.DOMException: NOT_SUPPORTED_ERR: The implementation does not support the requested type of object or operation
		// rowspan
		try {
			String vm = tc.getTcPr().getVMerge().getVal();
			if (vm == null || vm.equals("continue"))
				 = true;
			// dummy cells propagate this call upwards until a real cell is found
catch (NullPointerException ne) {
			// no vMerge
		if () {
			// set its colspan to the same value as its upper neighbor,
			// so dummy cells will be created to the right if colspan>1
			 = table.getCell(row - 1, col).;
else {
			// real cell
			// colspan
			try {
				int gridSpan = tc.getTcPr().getGridSpan().getVal().intValue();
				 = gridSpan;
catch (NullPointerException ne) {
				// no gridSpan

How many columns are merged into this cell

0 if none merged; 1 if two cells are merged so there is one extra; etc. A dummy cell has the same extraCols value as its upper neighbor.
	public int getExtraCols() {
		if ( < 2)
			return 0;
			return  - 1;
	public int getExtraRows() {
		if ( > 1)
			return  - 1;
			return 0;
	public boolean isDummy() {
		return ;
	public Node getContent() {
		return ;
	public int getColumn() {
		return ;

If this is a real cell, increment rowspan; if this is a dummy, propagate the call to the cell upwards
	protected void incrementRowSpan() {
		if ()
	public String debugStr() {
		String s = null;
		if ()
			s = "d";
			s = "r";
		s += "(" +  + "," +  + ")";
		s += ;
		s += ;
		return s + " ";
	 * @since 3.0.0
	public boolean isVMerged() {
		return ( != null) && 
			   (.getVMerge() != null);
New to GrepCode? Check out our FAQ X