PDFsharp & MigraDoc Foundation
https://forum.pdfsharp.net/

Table Row - Get Height
https://forum.pdfsharp.net/viewtopic.php?f=2&t=892
Page 1 of 1

Author:  mikesowerbutts [ Wed Sep 30, 2009 12:50 pm ]
Post subject:  Table Row - Get Height

Hi All,

I am building a function to allow me to get the X/Y position of a particular cell in a particular table in my pdf document, so I can then use PdfSharp's drawing functions to "draw into" the cell as if I had added an image file to it.

I originally started on this topic a few months ago under the topic "Position PdfSharp graphics in a MigraDoc table" or something like that. This what I am encountering isnt really the same problem, more a "bug" in how the row heights are calculated.

I basically have the function working, but it is behaving slightly strangely when it comes to the Y position. I Apply the following settings to each "Row" object i create:
Code:
Row _row = _table.AddRow();
_row.Height = rowHeight; // This is a parameter i pass into my buildTable function
_row.HeightRule = RowHeightRule.AtLeast;


As the table's rows are of varying height (they word wrap) I would expect the height to also vary when I get it back - but instead it always comes back as the "rowHeight" variable's value i set it to originally, and not the height which it actually is (if there is more than one line of text in one of that row's cells - as the rowHeight variable only accounts for 1 line of text).

This subsequently means that unless all the rows in my table are all exactly the same height - the positions I am trying to draw my graphics at are incorrect.

Here is the function I use to get the rendered table objects (which allows me to get their formatting information such as row height and column width):
Code:
public List<RenderedTable> getRenderedTables()
        {
            List<RenderedTable> _objs = new List<RenderedTable>();
            MigraDoc.DocumentObjectModel.Document _document = document.Clone();
            DocumentRenderer _renderer = new DocumentRenderer(_document);
            _renderer.PrepareDocument();
            int pageCount = _renderer.FormattedDocument.PageCount;
            for (int idx = 1; idx <= pageCount; idx++)
            {
                RenderInfo[] _renderInfo = _renderer.GetRenderInfoFromPage(idx);
                _renderer.PrepareDocument();
                MigraDoc.DocumentObjectModel.Tables.Table _tbl = null;
                if (_renderInfo != null && _renderInfo.Length > 0)
                {
                    for (int g = 0; g < _renderInfo.Length; g++)
                    {
                        if (_renderInfo[g].DocumentObject.GetType() == typeof(MigraDoc.DocumentObjectModel.Tables.Table))
                        {
                            List<List<int>> _colsWidth = new List<List<int>>();
                            List<int> _rowsHeight = new List<int>();
                            _tbl = (MigraDoc.DocumentObjectModel.Tables.Table)_renderInfo[g].DocumentObject;
                            if (_tbl.Tag != null)
                            {
                                for (int r = 0; r < _tbl.Rows.Count; r++)
                                {
                                    _colsWidth.Add(new List<int>());
                                    Row _row = _tbl.Rows[r];
                                    for (int c = 0; c < _row.Cells.Count; c++)
                                    {
                                        try
                                        {
                                            _colsWidth[r].Add((int)_row.Cells[c].Column.Width);
                                        }
                                        catch
                                        {

                                        }
                                    }
                                    // This is the line which is causing problems as it is not getting the actual row height once text is added
                                    _rowsHeight.Add(((int)_tbl.Rows[r].Height));
                                }
                            }
                            if (_colsWidth.Count > 0 && _rowsHeight.Count > 0)
                            {
                                _objs.Add(new RenderedTable(_colsWidth, _rowsHeight, (int)_renderInfo[g].LayoutInfo.ContentArea.Height, (float)_renderInfo[g].LayoutInfo.ContentArea.X.Point, (float)_renderInfo[g].LayoutInfo.ContentArea.Y.Point, _tbl));
                            }
                        }
                    }
                }
            }
            return _objs;
        }

I dont know if the ability to do what I am doing here is included with the newest release of PdfSharp/MigraDoc, but Thomas Hoevel was kind enough to help me out a lot in the topic I mentioned earlier to "unlock" this functionality from the existing 1.2 release.

And this is the function I then use to find the position of the appropriate cell in the table:
Code:
public static System.Drawing.RectangleF GetContainerCellPosition(List<RenderedTable> renderedTables, string identifier)
        {
            System.Drawing.RectangleF _rect = new System.Drawing.RectangleF();
            foreach (RenderedTable rt in renderedTables)
            {
                float _x = rt.x + rt.table.LeftPadding;
                float _y = rt.y + rt.table.TopPadding;
                if (_x > -1 && _y > -1)
                {
                    for (int r = 0; r < rt.rowHeights.Count; r++)
                    {
                        for (int c = 0; c < rt.colWidths[r].Count; c++)
                        {
                            CellContainer _cellContainer = null;
                            try
                            {
                                _cellContainer = (CellContainer)rt.table[r, c].Elements[0].Tag;
                            }
                            catch
                            {

                            }
                            if (_cellContainer != null)
                            {
                                if (_cellContainer.type == identifier)
                                {
                                    _rect.X = (float)Math.Floor(_x);
                                    _rect.Y = (float)Math.Floor(_y);
                                    _rect.Width = rt.table[r, c].Column.Width;
                                    _rect.Height = rt.table[r, c].Row.Height;
                                }
                            }
                            _x += rt.colWidths[r][c];
                        }
                        if (r == 0)
                        {
                            _y += rt.rowHeights[r];
                        }
                        else
                        {
                            _y += rt.rowHeights[r] + 1;
                        }
                        _x = 0;
                    }
                }
            }
            return _rect;
        }

All I am doing it creating a List of all the row heights in the first function, then using a loop - adding those list values together until I have found the appropriate cell which should give me the height - and it kind of is, but as I said the heights are all what I originally set it to, rather than the "expanded" height becuase some text in one of the row's cells is on multiple lines.

Does anyone know how I can get the "true" height of the row once text has been added and wrapped etc.etc.?

Thanks,

Mike

Author:  Thomas Hoevel [ Wed Sep 30, 2009 1:03 pm ]
Post subject:  Re: Table Row - Get Height

mikesowerbutts wrote:
As the table's rows are of varying height (they word wrap) I would expect the height to also vary when I get it back - but instead it always comes back as the "rowHeight" variable's value i set it to originally, and not the height which it actually is (if there is more than one line of text in one of that row's cells - as the rowHeight variable only accounts for 1 line of text).

This is by design.

Don't query rowHeight (it will never change), take the height from the RenderInfo (this is the height calculated during rendering).
viewtopic.php?p=1960#p1960

Author:  mikesowerbutts [ Fri Oct 02, 2009 9:07 am ]
Post subject:  Re: Table Row - Get Height

Hi,

I am unsure of how to the the RenderInfo for a individual row/column in a table - I can get the Table as a DocumentObject object using RenderInfo[idx].DocumentObject. I then cast the DocumentObject to a table to access it's rows/columns, but this then gives me the widths etc. as I am currently getting them - Can I get the RenderInfo for indivudual cells etc.? As this seems the only way to get the true height.

Mike

Author:  herbatnik9 [ Tue May 16, 2017 9:24 am ]
Post subject:  Re: Table Row - Get Height

Just forget about everything and use below code after rendering page and iterating over all rows summing result of realRowHeight (below) until you find desired row.
Code:
var formattedCellProperties = typeof(FormattedCell).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).ToArray();
var formattedCellInnerWidth = formattedCellProperties.FirstOrDefault(p => p.Name == "InnerWidth");
var formattedCellInnerHeight = formattedCellProperties.FirstOrDefault(p => p.Name == "InnerHeight");
Func<MigraDocTables.Row, TableFormatInfo, Unit> realRowHeight = (row, formatInfo) =>
{
    XUnit maxHeight = 0;
    foreach (MigraDocTables.Cell cell in row.Cells)
    {
        var formattedCell = formatInfo.FormattedCells[cell];
        var cellInnerHeight = (XUnit)formattedCellInnerHeight.GetValue(formattedCell);
        cellInnerHeight += XUnit.FromPoint(cell.Borders.Top.Width.Point);
        cellInnerHeight += XUnit.FromPoint(cell.Borders.Bottom.Width.Point);
        maxHeight = Math.Max(cellInnerHeight, maxHeight);
    }
    return Unit.FromPoint(maxHeight.Point);
};


works for 1.50

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/