Hiding table column and adjusting other columns

13 posts, 0 answers
  1. Aaron
    Aaron avatar
    7 posts
    Member since:
    Aug 2012

    Posted 11 Dec 2012 Link to this post

    I have a table that has a column that may or not be visible. When it isn't visible I then need to adjust the proceeding 2 columns, one to put in the now invisible column's space and the second to increase its width. I have been able to get the column to be invisible via formatting but am not sure how to move and adjust the other columns. I had the same issue with rows and had to create a table for each row and keep track of the visibility and location of each row myself.
  2. Elian
    Admin
    Elian avatar
    435 posts

    Posted 14 Dec 2012 Link to this post

    Hi Aaron,

    Telerik Reporting is a data driven solution. Thus to hide certain table columns our suggestion is to use a group filter. To explore the table groups, please open the group explorer in extended mode. When hiding a column with filters the rest of the columns will automatically move to the left and take the space that the hidden column should have occupied. 

    As to the spacing - you can manually adjust the columns widths only before the table is processed. This can be done by changing the definition of the table. You should shrink the following items:
    1. The table itself 
    2. The table's body column
    3. All the items contained inside the corresponding column
    Refer to the following sample code:
    private void table1_ItemDataBound(object sender, EventArgs e)
    {
        //adjust the overall width
        this.table1.Width = this.table.Width - ...
        //adjust the body column
        this.table1.Body.Columns(2).Width = <new_size>;
        //...
        //adjust all the items in the corresponding column
        this.textBox4.Width = <new_size>;
        //...
        //and so on...
    }

    Regards,
    Elian
    the Telerik team

    HAPPY WITH REPORTING? Do you feel that it is fantastic? Or easy to use? Or better than Crystal Reports? Tell the world, and help fellow developers! Write a short review about Telerik Reporting and Telerik Report Designer in Visual Studio Gallery today!

  3. DevCraft banner
  4. Aaron
    Aaron avatar
    7 posts
    Member since:
    Aug 2012

    Posted 04 Feb 2013 Link to this post

    This works great when deleting a row with only one column, but how would you go about removing a row with multiple columns? Setting all textboxes' height to 0 does not do the job and the entire row remains visible. Does the column and row grouping have anything to do with this?

    Thanks.
  5. Steven
    Steven avatar
    81 posts
    Member since:
    Dec 2011

    Posted 04 Feb 2013 Link to this post

    Just create an iterator that loops the table cells and then set the Height or Width to your desired measurement.

    If you are adjusting a column, then you need to adjust the Column Width, Table Width and then every cell in that index, even those columns that span the target index.

    You can merge these extension methods into a single helper method to do what you need, but these are a part of my extension library that has a bunch of Telerik tweeks.

    MODERATOR - Are there any community driven open source Telerik extensions?


    /// <summary>
    /// ItemDataBinding, Remove columns by settings its width to Zero
    /// </summary>
    /// <param name="tableDef"></param>
    /// <param name="columnIndexes"></param>
    public static void CollapseColumns(this Telerik.Reporting.Table tableDef, params int[] columnIndexes)
    {
        var cells = tableDef.Body.Where(x => x.ReportItem != null).ToList();
        int columnLength = tableDef.Body.Columns.Count;
     
        for (var i=0; i < columnLength; i++)
        {
            if (columnIndexes.Contains(i))
            {
                var column = tableDef.Body.Columns[i];               
                cells.FindByColumn(i).AdjustWidth(column.Width, false);
                tableDef.Width = tableDef.Width.Subtract(column.Width);
                column.Width = zero;
            }
        }
    }
     
     
     
    /// <summary>
    /// ItemDataBinding, Get cells for matching column or in colSpan
    /// </summary>
    /// <param name="tableDef"></param>
    /// <param name="columns"></param>
    public static IEnumerable<Telerik.Reporting.TableCell> FindByColumn(this IEnumerable<Telerik.Reporting.TableCell> cells, params int[] columnIndexes)
    {
        foreach (int index in columnIndexes)
            foreach (var cell in cells.Where(x => x.ColumnIndex <= index && (x.ColumnIndex + x.ColumnSpan - 1) >= index))
                yield return cell;
    }
     
    public static void AdjustWidth(this IEnumerable<Telerik.Reporting.TableCell> cells, Telerik.Reporting.Drawing.Unit unit, bool add = true)
    {
        UnitFunc unitFunc = x => (add) ? x.Add(unit) : x.Subtract(unit);
     
        foreach (var cell in cells.Where(x => x.ReportItem != null).ToArray())
        {
            var newWidth = unitFunc(cell.ReportItem.Width);
            if (newWidth.Value <= almostZero)
                newWidth = zero;
     
            if (newWidth.Value < cell.ReportItem.Width.Value && cell.ReportItem is Telerik.Reporting.TextItemBase)
                ((Telerik.Reporting.TextItemBase)cell.ReportItem).CanGrow = false; // value is still populated
     
            cell.ReportItem.Width = newWidth;
        }
    }


    Same logic would be applied to Row Height but you have to use reflection to set the Row Height in Millimeters


    private static PropertyInfo RowHeightProperty = typeof(Telerik.Reporting.Processing.TableRow).GetProperty("Height", BindingFlags.Instance | BindingFlags.NonPublic);
     
            
    /// <summary>
    /// Collapse Rows that matches predicate
    /// </summary>
    /// <param name="table"></param>
    /// <param name="cellCheck"></param>
    public static void CollapseRows(this Telerik.Reporting.Processing.Table table, Func<Telerik.Reporting.Processing.ITableCell, bool> cellCheck = null)
    {
        Telerik.Reporting.Processing.ITableCell cell;
     
        if (cellCheck == null) cellCheck = x => true;
        int cLen = table.Columns.Count;
        int rLen = table.Rows.Count;
        Telerik.Reporting.Drawing.Unit height;
                 
        for (var r=0; r < rLen; r++)
        {
            var row = table.Rows[r];
     
            cell = null;
            for(int c = 0; c < cLen; c += cell.ColumnSpan)
            {
                cell = row.GetCell(c);
                if (cell.RowIndex == r && cellCheck(cell))
                {
                    height = Telerik.Reporting.Drawing.Unit.Mm(RowHeightProperty.GetValue(row, null).ChangeType<double>());
     
                    cell = null;
                    for (int i = 0; i < cLen; i += cell.ColumnSpan)
                    {
                        cell = row.GetCell(i);
                        if (cell.RowIndex == r)
                        {
                            cell.Item.Visible = false;
                        }
                        // else
                        // {
                        //     cell.Item.Height = cell.Item.Height.Subtract(height);
                        // }
                    }
     
                    RowHeightProperty.SetValue(row, 0D, null);
                             
                    break;
                }
            }
        }                      
    }
  6. Massimiliano Bassili
    Massimiliano Bassili avatar
    323 posts
    Member since:
    May 2006

    Posted 05 Feb 2013 Link to this post

    Steven, you can use the code library section (http://www.telerik.com/community/code-library/reporting/general.aspx) to post extensions/projects that the community can benefit from.

    Cheers!
  7. Aaron
    Aaron avatar
    7 posts
    Member since:
    Aug 2012

    Posted 05 Feb 2013 Link to this post

    Your code did not work for me...

    So if the following code works for a row with one column, why wouldn't it work for multiple columns?

     public static void RemoveTableRow(Table table, int rowIndex, params ReportItem[] textBoxesToRemove)
            {
                Unit height = textBoxesToRemove[0].Height;
                foreach (var textBox in textBoxesToRemove)
                {
                    textBox.Height = new Unit(0, UnitType.Inch);
                }
                table.Body.Rows[rowIndex].Height = new Unit(0, UnitType.Inch);
                table.Height -= height;
            }
  8. Hadib Ahmabi
    Hadib Ahmabi avatar
    181 posts
    Member since:
    Nov 2011

    Posted 08 Feb 2013 Link to this post

    Why would you need to remove rows? That's what filters are for.
  9. Aaron
    Aaron avatar
    7 posts
    Member since:
    Aug 2012

    Posted 08 Feb 2013 Link to this post

    Ok, so without using filters. If I can remove a row that has one column using that logic why can I not remove a row with multiple columns?

    Using Steven's code does not remove the row and then causes a few more issues.
  10. Steven
    Steven avatar
    81 posts
    Member since:
    Dec 2011

    Posted 08 Feb 2013 Link to this post

    It depends on what stage of the report lifecycle your in.

    Within the Reports ItemDataBinding event you can load your data and manually set the visibility of static rows and static columns.

    While the table rows are binding, you'll have to use the table filters

    After the table is bound, you could provide cleanup by collapsing the row and textboxes within the row cells.

    Within the bound event it already has populated the table cells with data and changing visibility at this stage will cause the rendering extensions to crash.


    The code I provided was to Collapse the row after its data has been populated because sometime you just don't have the data available to determine where to suppress the row during its binding event since you only have access to Static Methods and the Binding DataObject.

    If I have a static row and a horizontal group, I may need to hide a row if all the row values are zero,
    I can set the rows visibility within the Reports ItemDataBinding event if I manually get my data before the table binds, but if I can't then I can just cleanup after the tables bound.

    The table becomes the definition for the processing element, so updating fields after the processing object has been generated won't work and blows up if you change visibility.


    I also use this in a report that has a dozen different configuration settings and I collapse certain rows and resize others to take up the slack.   These reports also have very complex logic on how a value should be formatted, rounded, precision and whether zeros should be suppressed.    You can apply this in a Binding or Bound event to every cell, but I find it easier to iterate that table within its ItemDataBound event.


    I'm not providing you a finished solution for your problem, I'm providing ideas on how you can tweak the report outside of the existing logic points.

    Use the debugger and JustCode to see what properties you can adjust out of cycle.
  11. Robert
    Robert avatar
    4 posts
    Member since:
    Dec 2011

    Posted 15 Jan in reply to Elian Link to this post

    I realize this is an old post.  I have not used these forums before, so I'm not sure if I should expect a response.

    I have a very similar situation where I wish to conditionally remove a column and have the other columns re-size. You (Admin) seem to suggest that by filtering the column group using the extended group editor functionality, the columns will re-size themselves to some extent. However, you mention that the filtered column will cause the columns to the right to move to the left. I need the opposite: I need to conditionally hide the last column on the right in my table, and have the column to the left grow horizontally to take up the space of the filtered column. Is this possible without resorting to writing code to adjust the widths? 

  12. Nasko
    Admin
    Nasko avatar
    909 posts

    Posted 19 Jan Link to this post

    Hello Robert,

    The Table item does not offer an option to reclaim space from hidden columns automatically. However, it is possible to assign a binding to another column, which sets the Width property of the whole column to a larger than the current value.

    Regards,
    Nasko
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  13. Robert
    Robert avatar
    4 posts
    Member since:
    Dec 2011

    Posted 19 Jan in reply to Nasko Link to this post

    Thank you. Is it better to use the forums when asking questions like these? Or is it better to use your Ticket System?

    Will a member of the support team answer forum in quires? 

  14. Nasko
    Admin
    Nasko avatar
    909 posts

    Posted 20 Jan Link to this post

    Hello Robert,

    We recommend to avoid posting the same question multiple times, in order not to split information between threads and handle your question more precisely.
    If it is an emergency use our support ticketing system as this is the best way to reach our support staff - the support system assigns a response time for all of your questions, depending on your license and ensures that all questions will reach the respective developers if needed.
    You can post your questions in the forums when you don't need an urgent answer and you want to help the community as well. The forums are community driven and as such we do not guarantee that a support team member will always be there to answer all of the queries.

    Regards,
    Nasko
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
DevCraft banner