/// <summary> /// Get cell width, this should be called after ParseTable(). /// </summary> /// <param name="cellId"></param> /// <returns></returns> public float GetCellWidth(TableHelperCell cell) { float ret = 0f; if (cell != null) { for (int i = 0; i < cell.ColSpan; i++) { ret += this.TableColumnsWidth[cell.colId + i]; } } return(ret); }
private void adjustTableColumnsWidth() { if (this.table == null) { return; } // Get table total width float totalWidth = -1f; bool autoWidth = false; Word.TableWidth tableWidth = this.styleHelper.GetAppliedElement <Word.TableWidth>(this.table); if (tableWidth != null && tableWidth.Type != null) { switch (tableWidth.Type.Value) { case Word.TableWidthUnitValues.Nil: case Word.TableWidthUnitValues.Auto: // fits the contents default: autoWidth = true; break; case Word.TableWidthUnitValues.Dxa: if (tableWidth.Width != null) { totalWidth = Tools.ConvertToPoint(tableWidth.Width.Value, Tools.SizeEnum.TwentiethsOfPoint, -1f); } break; case Word.TableWidthUnitValues.Pct: if (tableWidth.Width != null) { totalWidth = this.styleHelper.PrintablePageWidth * Tools.Percentage(tableWidth.Width.Value); //if (table.Parent.GetType() == typeof(Word.Body)) // totalWidth = (float)((pdfDoc.PageSize.Width - pdfDoc.LeftMargin - pdfDoc.RightMargin) * percentage(tableWidth.Width.Value)); //else // totalWidth = this.getCellWidth(table.Parent as Word.TableCell) * percentage(tableWidth.Width.Value); } break; } } Console.WriteLine("Table total width: " + totalWidth); if (!autoWidth) { scaleTableColumnsWidth(ref this.tableColumnsWidth, totalWidth); } else { totalWidth = this.tableColumnsWidth.Sum(); } for (int i = 0; i < this.RowLength; i++) { // Get all cells in this row List <TableHelperCell> cellsInRow = this.cells.FindAll(c => c.rowId == i); if (cellsInRow.Count <= 0) { continue; } // Get if any gridBefore & gridAfter int skipGridsBefore = 0, skipGridsAfter = 0; float skipGridsBeforeWidth = 0f, skipGridsAfterWidth = 0f; TableHelperCell head = cellsInRow.FirstOrDefault(c => c.rowStart); if (head != null) { if (head.row.TableRowProperties != null) { // w:gridBefore var tmpGridBefore = head.row.TableRowProperties.Elements <Word.GridBefore>().FirstOrDefault(); if (tmpGridBefore != null && tmpGridBefore.Val != null) { skipGridsBefore = tmpGridBefore.Val.Value; } // w:wBefore var tmpGridBeforeWidth = head.row.TableRowProperties.Elements <Word.WidthBeforeTableRow>().FirstOrDefault(); if (tmpGridBeforeWidth != null && tmpGridBeforeWidth.Width != null) { skipGridsBeforeWidth = Tools.ConvertToPoint(Convert.ToInt32(tmpGridBeforeWidth.Width.Value), Tools.SizeEnum.TwentiethsOfPoint, -1f); } // w:gridAfter var tmpGridAfter = head.row.TableRowProperties.Elements <Word.GridAfter>().FirstOrDefault(); if (tmpGridAfter != null && tmpGridAfter.Val != null) { skipGridsAfter = tmpGridAfter.Val.Value; } // w:wAfter var tmpGridAfterWidth = head.row.TableRowProperties.Elements <Word.WidthAfterTableRow>().FirstOrDefault(); if (tmpGridAfterWidth != null && tmpGridAfterWidth.Width != null) { skipGridsAfterWidth = Tools.ConvertToPoint(Convert.ToInt32(tmpGridAfterWidth.Width.Value), Tools.SizeEnum.TwentiethsOfPoint, -1f); } } } int j = 0; int edgeEnd = 0; // ------- // gridBefore edgeEnd = skipGridsBefore; for (; j < edgeEnd; j++) { // deduce specific columns width from required width skipGridsBeforeWidth -= this.tableColumnsWidth[j]; } if (skipGridsBeforeWidth > 0f) { // if required width is larger than the total width of specific columns, // the remaining required width adds to the last specific column this.tableColumnsWidth[edgeEnd - 1] += skipGridsBeforeWidth; } // ------ // cells while (j < (cellsInRow.Count - skipGridsAfter)) { float reqCellWidth = 0f; Word.TableCellWidth cellWidth = this.styleHelper.GetAppliedElement <Word.TableCellWidth>(cellsInRow[j].cell); if (cellWidth != null && cellWidth.Type != null) { switch (cellWidth.Type.Value) { case Word.TableWidthUnitValues.Auto: //// TODO: calculate the items width //if (cellsInRow[j].elements.Count > 0) //{ // iTSText.IElement element = cellsInRow[j].elements[0]; //} break; case Word.TableWidthUnitValues.Nil: default: break; case Word.TableWidthUnitValues.Dxa: if (cellWidth.Width != null) { reqCellWidth = Tools.ConvertToPoint(cellWidth.Width.Value, Tools.SizeEnum.TwentiethsOfPoint, -1f); } break; case Word.TableWidthUnitValues.Pct: if (cellWidth.Width != null) { reqCellWidth = Tools.Percentage(cellWidth.Width.Value) * totalWidth; } break; } } // check row span int spanCount = 1; if (cellsInRow[j].cell != null) { Word.TableCell tmpCell = cellsInRow[j].cell; if (tmpCell.TableCellProperties != null) { Word.GridSpan span = tmpCell.TableCellProperties.Elements <Word.GridSpan>().FirstOrDefault(); spanCount = (span != null && span.Val != null) ? span.Val.Value : 1; } } edgeEnd = j + spanCount; for (; j < edgeEnd; j++) { // deduce specific columns width from required width reqCellWidth -= this.tableColumnsWidth[j]; } if (reqCellWidth > 0f) { // if required width is larger than the total width of specific columns, // the remaining required width adds to the last specific column this.tableColumnsWidth[edgeEnd - 1] += reqCellWidth; } } // ------ // gridAfter edgeEnd = j + skipGridsAfter; for (; j < edgeEnd; j++) { // deduce specific columns width from required width skipGridsAfterWidth -= this.tableColumnsWidth[j]; } if (skipGridsAfterWidth > 0f) { // if required width is larger than the total width of specific columns, // the remaining required width adds to the last specific column this.tableColumnsWidth[edgeEnd - 1] += skipGridsAfterWidth; } if (!autoWidth) // fixed table width, adjust width to fit in { scaleTableColumnsWidth(ref this.tableColumnsWidth, totalWidth); } else // auto table width { totalWidth = this.tableColumnsWidth.Sum(); } } }
// TODO: get row height (not total row height): http://kuujinbo.info/iTextSharp/rowHeights.aspx public void ParseTable(Word.Table t) { if (t == null) { return; } this.table = t; this.tableColumnsWidth = this.getTableGridCols(this.table); this.colLen = this.tableColumnsWidth.Count(); int cellId = 0; int rowId = 0; foreach (Word.TableRow row in table.Elements <Word.TableRow>()) { bool rowStart = true; // w:gridBefore Word.GridBefore tmpGridBefore = (Word.GridBefore)StHelper.GetAppliedElement <Word.GridBefore>(row); int skipGridsBefore = (tmpGridBefore != null && tmpGridBefore.Val != null) ? tmpGridBefore.Val.Value : 0; // w:gridAfter Word.GridAfter tmpGridAfter = (Word.GridAfter)StHelper.GetAppliedElement <Word.GridAfter>(row); int skipGridsAfter = (tmpGridAfter != null && tmpGridAfter.Val != null) ? tmpGridAfter.Val.Value : 0; int colId = 0; // gridBefore (with same cellId and set as blank) if (skipGridsBefore > 0) { for (int i = 0; i < skipGridsBefore; i++) { cells.Add(new TableHelperCell(this, cellId, rowId, colId)); colId++; // increase for each cells.Add() Debug.Write(String.Format("{0:X} ", cellId)); } cellId++; } foreach (Word.TableCell col in row.Elements <Word.TableCell>()) { int _cellId = cellId; int _cellcount = 1; TableHelperCell basecell = new TableHelperCell(this, _cellId, rowId, colId); if (rowStart) { basecell.rowStart = true; rowStart = false; } basecell.row = row; basecell.cell = col; // process rowspan and colspan if (col.TableCellProperties != null) { // colspan if (col.TableCellProperties.GridSpan != null) { _cellcount = col.TableCellProperties.GridSpan.Val; } // rowspan if (col.TableCellProperties.VerticalMerge != null) { // "continue": get cellId from (rowId-1):(colId) if (col.TableCellProperties.VerticalMerge.Val == null || col.TableCellProperties.VerticalMerge.Val == "continue") { _cellId = cells[(this.ColumnLength * (rowId - 1)) + colId].cellId; } // "restart": the begin of rowspan else { _cellId = cellId; } } } basecell.cellId = _cellId; cells.Add(basecell); colId++; // increase for each cells.Add() Debug.Write(String.Format("{0:X} ", _cellId)); for (int i = 1; i < _cellcount; i++) { // Add spanned cells cells.Add(new TableHelperCell(this, _cellId, rowId, colId)); colId++; // increase for each cells.Add() Debug.Write(String.Format("{0:X} ", _cellId)); } // The latest cellId was used, then we must increase it for future usage if (cellId == _cellId) { cellId++; } } int rowEndIndex = cells.Count - 1; int rowEndCellId = cells[rowEndIndex].cellId; while (rowEndIndex > 0 && cells[rowEndIndex - 1].cellId == rowEndCellId) { rowEndIndex--; } cells[rowEndIndex].rowEnd = true; // gridAfter (with same cellId and set as blank) if (skipGridsAfter > 0 && colId < this.ColumnLength) { for (int i = 0; i < skipGridsAfter; i++) { cells.Add(new TableHelperCell(this, cellId, rowId, colId)); colId++; // increase for each cells.Add() Debug.Write(String.Format("{0:X} ", cellId)); } cellId++; } rowId++; Debug.Write("\n"); } this.rowLen = rowId; // ====== Adjust table columns width by their content ====== this.adjustTableColumnsWidth(); // ====== Resolve cell border conflict ====== // prepare table conditional formatting (border), which will be used in // applyCellBorders() so must be called before applyCellBorders() this.rollingUpTableBorders(); for (int r = 0; r < this.RowLength; r++) { // The following handles the situation where // if table innerV is set, and cnd format for first row specifies nill border, then nil border wins. // if table innerH is set, and cnd format for first columns specifies nil border, then table innerH wins. //// TODO: if row's cellspacing is not zero then bypass this row //Word.TableCellSpacing tcspacing = _CvrtCell.GetTableRow(cells, r).TableRowProperties.Descendants<Word.TableCellSpacing>().FirstOrDefault(); //if (tcspacing.Type.Value != Word.TableWidthUnitValues.Nil) // continue; for (int c = 0; c < this.ColumnLength; c++) { TableHelperCell me = this.GetCell(r, c); if (me.Blank) { continue; } if (me.Borders == null) { me.Borders = this.applyCellBorders(me.cell.Descendants <Word.TableCellBorders>().FirstOrDefault(), (me.colId == 0) | me.rowStart, (me.colId + this.GetColSpan(me.cellId) == this.ColumnLength) | me.rowEnd, (me.rowId == 0), (me.rowId + this.GetRowSpan(me.cellId) == this.RowLength) ); } int colspan = this.GetColSpan(me.cellId); int rowspan = this.GetRowSpan(me.cellId); // Process the cells at the right side of me // Can bypass column-spanned cells because they never exist if ((c + (colspan - 1) + 1) < this.ColumnLength) // not last column { List <TableHelperCell> rights = new List <TableHelperCell>(); for (int i = 0; i < rowspan; i++) { TableHelperCell tmp = this.GetCell(r + i, c + (colspan - 1) + 1); if (tmp != null && !tmp.Blank) { rights.Add(tmp); } } if (rights.Count > 0) { foreach (TableHelperCell right in rights) { if (right.Borders == null) { right.Borders = this.applyCellBorders(right.cell.Descendants <Word.TableCellBorders>().FirstOrDefault(), (right.colId == 0) | right.rowStart, (right.colId + this.GetColSpan(right.cellId) == this.ColumnLength) | right.rowEnd, (right.rowId == 0), (right.rowId + this.GetRowSpan(right.cellId) == this.RowLength) ); } bool meWin = compareBorder(me.Borders, right.Borders, compareDirection.Horizontal); if (meWin) { StyleHelper.CopyAttributes(right.Borders.LeftBorder, me.Borders.RightBorder); } } me.Borders.RightBorder.ClearAllAttributes(); } } // Process the cells below me // Can't bypass row-spanned cells because they still have tcBorders property if ((r + 1) < this.RowLength) // not last row { List <TableHelperCell> bottoms = new List <TableHelperCell>(); for (int i = 0; i < colspan; i++) { TableHelperCell tmp = this.GetCell(r + 1, c + i); if (tmp != null && !tmp.Blank) { bottoms.Add(tmp); } } foreach (TableHelperCell bottom in bottoms) { if (bottom.Borders == null) { bottom.Borders = this.applyCellBorders(bottom.cell.Descendants <Word.TableCellBorders>().FirstOrDefault(), (bottom.colId == 0) | bottom.rowStart, (bottom.colId + this.GetColSpan(bottom.cellId) == this.ColumnLength) | bottom.rowEnd, (bottom.rowId == 0), (bottom.rowId + this.GetRowSpan(bottom.cellId) == this.RowLength) ); } bool meWin = compareBorder(me.Borders, bottom.Borders, compareDirection.Vertical); if (meWin) { StyleHelper.CopyAttributes(bottom.Borders.TopBorder, me.Borders.BottomBorder); } } } } } if (this.cells.Count > 0) { // re-process each cell's border conflict with its bottom cell for (int i = 0; i < this.cells[this.cells.Count - 1].cellId; i++) { TableHelperCell me = this.GetCellByCellId(i); if (me.Blank) // ignore gridBefore/gridAfter cells { continue; } if (me.RowSpan > 1) { // merge bottom border from the last cell of row-spanned cells TableHelperCell meRowEnd = this.GetCell(me.rowId + (me.RowSpan - 1), me.colId); if (meRowEnd != null && meRowEnd.Borders != null && meRowEnd.Borders.BottomBorder != null) { StyleHelper.CopyAttributes(me.Borders.BottomBorder, meRowEnd.Borders.BottomBorder); } } if (me.rowId + me.RowSpan < this.RowLength) { // if me is not at the last row, compare the border with the cell below it TableHelperCell bottom = this.GetCellByCellId(this.GetCell(me.rowId + me.RowSpan, me.colId).cellId); bool meWin = compareBorder(me.Borders, bottom.Borders, compareDirection.Vertical); if (!meWin) { me.Borders.BottomBorder.ClearAllAttributes(); } } } } }