Merging of cells

Hi,

I need to achieve simple merging of cells as in the following example. What is not clear to me from the description in the documentation is how this left-right etc. applies while selecting the cells.

From this:

Value1 Value2 Value3 Value4_1
Value1 Value2 Value3 Value4_2

 

To get this:

Value1 Value2 Value3 Value4_1
Value4_2


This is basically to merge all rows that have the same values in each column except the last one.

Thank you in advance,



6 Replies 1 reply marked as answer

DM Dhanasekar Mohanraj Syncfusion Team September 21, 2022 03:18 PM UTC

Hi Biljana,

Your requirement to merge cells depends on the content is achievable by using SfDataGrid.ItemsSourceChanged, SfDataGrid.QueryCoveredRange events. Please refer the below user guide documentation for more information,

UG Link: https://help.syncfusion.com/wpf/datagrid/merge-cells#merging-cells-based-on-the-content

We have prepared the sample based on your scenario. Please find the sample in the attachment and let us know if you have any concerns in this.


Regards,

Dhanasekar M.


If this post is helpful, please consider Accepting it as the solution so that other members can locate it more quickly.


Attachment: Sample_9640e27.zip


BI Biljana September 22, 2022 07:51 AM UTC

Hello,

Thank you for the answer. Actually I know of this sample, but it doesn`t do what is requested. It merges per column.

That is, from this:

Value1 Value2_1 Value3 Value4_1
Value1 Value2_1 Value3 Value4_2
Value1 Value2_2 Value3 Value4_1
Value1 Value2_2 Value3 Value4_1


it gets this:

Value1 Value2_1 Value3 Value4_1
Value2_2 Value4_2


While the request is to get this:

Value1 Value2_1 Value3 Value4_1
Value4_2
Value1 Value2_2 Value3 Value4_1
Value4_1


i.e. merge only the rows which have the same value in each column until the last one.

Nevertheless, I will be using a different solution. as this one is a bit complex for me.

Kind Regards,



DM Dhanasekar Mohanraj Syncfusion Team September 23, 2022 03:08 PM UTC

Hi Biljana,

We are a little unclear about your scenario. By default, the cell merging is applied depending on the given range or the content present in the cell. We have checked the provided illustration, in this, you mentioned that the cell gets merged when all columns have the same value, but in your illustration the last column does not merge even though all data have the same value shown below,

And the provided illustrations are different from both scenarios (Range and content). Like the complex merging (combining both) like merging the cell based on the index. If we misunderstood your requirement, can you please provide more information related to your requirement based on that we will proceed with this further.

Regards,
Dhanasekar M.



BI Biljana September 27, 2022 02:36 PM UTC

Hi,

That which you marked was my mistake. In the initial message is 4_1; 4_2.

The request was to get this

Value1Value2_1Value3Value4_1
Value4_2
Value1Value2_2Value3Value4_1
Value4_2


merge the columns only if all columns of a row except the last one in this case, have the same value.


Kind Regards,







DM Dhanasekar Mohanraj Syncfusion Team September 29, 2022 05:49 AM UTC

Hi Biljana,


Currently, we are checking the feasibility to achieve your requirement on our end. We will check and update you with further details on September 30, 2022.

We appreciate your patience until then.

Regards,
Dhanasekar M.



DM Dhanasekar Mohanraj Syncfusion Team September 30, 2022 06:43 PM UTC

Hi Biljana,

Your requirement can be achieved by customizing the GetRange method and QueryCoveredRange event in SfDataGridPlease refer to the below code snippet, 


void OnQueryCoveredRange(object sender, GridQueryCoveredRangeEventArgs e)

{

    // here skip the merging for particular columns in SfDataGrid.

    // Skipped the last column as you required.

    if (e.GridColumn.MappingName == "Col4")

        return;

 

    var range = GetRange(e.GridColumn, e.RowColumnIndex.RowIndex, e.RowColumnIndex.ColumnIndex, e.Record);

 

    if (range == null)

        return;

 

    // You can know that the range is already exist in Covered Cells by IsInRange method.

 

    if (!dataGrid.CoveredCells.IsInRange(range))

    {

        e.Range = range;

        e.Handled = true;

    }

 

    //If the calculated range is already existed in CoveredCells, you can get the range using SfDataGrid.GetConflictRange (CoveredCellInfo coveredCellInfo) extension method.

}






private
CoveredCellInfo GetRange(GridColumn column, int rowIndex, int columnIndex, object rowData)

{

    var range = new CoveredCellInfo(columnIndex, columnIndex, rowIndex, rowIndex);

    object data = reflector.GetFormattedValue(rowData, column.MappingName);

 

    GridColumn leftColumn = null;

    GridColumn rightColumn = null;

 

    // total rows count.

    int recordsCount = this.dataGrid.GroupColumnDescriptions.Count != 0 ?

    (this.dataGrid.View.TopLevelGroup.DisplayElements.Count + this.dataGrid.TableSummaryRows.Count + this.dataGrid.UnBoundRows.Count + (this.dataGrid.AddNewRowPosition == AddNewRowPosition.Top ? +1 : 0)) :

    (this.dataGrid.View.Records.Count + this.dataGrid.TableSummaryRows.Count + this.dataGrid.UnBoundRows.Count + (this.dataGrid.AddNewRowPosition == AddNewRowPosition.Top ? +1 : 0));

 

    // Merge Horizontally

 

    // compare right column               

 

    for (int i = dataGrid.Columns.IndexOf(column); i < this.dataGrid.Columns.Count - 1; i++)

    {

        var compareData = reflector.GetFormattedValue(rowData, dataGrid.Columns[i + 1].MappingName);

 

        if (compareData == null)

            break;

 

        if (!compareData.Equals(data))

            break;

        rightColumn = dataGrid.Columns[i + 1];

    }

 

    // compare left column.

 

    for (int i = dataGrid.Columns.IndexOf(column); i > 0; i--)

    {

        var compareData = reflector.GetFormattedValue(rowData, dataGrid.Columns[i - 1].MappingName);

 

        if (compareData == null)

            break;

 

        if (!compareData.Equals(data))

            break;

        leftColumn = dataGrid.Columns[i - 1];

    }

 

    if (leftColumn != null || rightColumn != null)

    {

 

        // set left index

 

        if (leftColumn != null)

        {

            var leftColumnIndex = this.dataGrid.ResolveToScrollColumnIndex(this.dataGrid.Columns.IndexOf(leftColumn));

            range = new CoveredCellInfo(leftColumnIndex, range.Right, range.Top, range.Bottom);

        }

 

        // set right index

 

        if (rightColumn != null)

        {

            var rightColumnIndex = this.dataGrid.ResolveToScrollColumnIndex(this.dataGrid.Columns.IndexOf(rightColumn));

            range = new CoveredCellInfo(range.Left, rightColumnIndex, range.Top, range.Bottom);

        }

        return range;

    }

 

    // Merge Vertically from the row index.

 

    int previousRowIndex = -1;

    int nextRowIndex = -1;

 

    // Get previous row data.               

    var startIndex = dataGrid.ResolveStartIndexBasedOnPosition();

 

    for (int i = rowIndex - 1; i >= startIndex; i--)

    {

        var previousData = this.dataGrid.GetRecordEntryAtRowIndex(i);

 

        if (previousData == null || !previousData.IsRecords)

            break;

        var compareData = reflector.GetFormattedValue((previousData as RecordEntry).Data, column.MappingName);

 

        if (compareData == null)

            break;

 

        //here skip the merging when different values contains on the Col2

        var previousCol2 = reflector.GetFormattedValue((previousData as RecordEntry).Data, "Col2");

 

        object rowDataCol2 = reflector.GetFormattedValue(rowData, "Col2");

 

        if (!compareData.Equals(data) || !previousCol2.Equals(rowDataCol2))

            break;

 

        previousRowIndex = i;

    }

 

    // get next row data.

 

    for (int i = rowIndex + 1; i < recordsCount + 1; i++)

    {

        var nextData = this.dataGrid.GetRecordEntryAtRowIndex(i);

 

        if (nextData == null || !nextData.IsRecords)

            break;

        var compareData = reflector.GetFormattedValue((nextData as RecordEntry).Data, column.MappingName);

 

        if (compareData == null)

            break;

 

        //here skip the merging when different Col2 contains record

        var nextDataCol2 = reflector.GetFormattedValue((nextData as RecordEntry).Data, "Col2");

        object rowDataCol2 = reflector.GetFormattedValue(rowData, "Col2");

 

        if (!compareData.Equals(data) || !nextDataCol2.Equals(rowDataCol2))

            break;

 

        nextRowIndex = i;

    }

 

    if (previousRowIndex != -1 || nextRowIndex != -1)

    {

 

        if (previousRowIndex != -1)

            range = new CoveredCellInfo(range.Left, range.Right, previousRowIndex, range.Bottom);

 

        if (nextRowIndex != -1)

            range = new CoveredCellInfo(range.Left, range.Right, range.Top, nextRowIndex);

        return range;

    }

    return null;

}


Output screenshot:

Here we have prepared the sample based on your scenario. Please have a look at this and revert us if you have any concerns about this.


Regards,
Dhanasekar M.

If this post is helpful, please consider Accepting it as the solution so that other members can locate it more quickly.


Attachment: Sample__7131776.zip

Marked as answer
Loader.
Up arrow icon