Finding grouped shape constituents

I have a requirement to identify the individual shapes that are part of a grouped shape in Excel.
I am using Aspose.Cells for Java 18.5.0

I went through the GroupShape class and found that its javadoc description matched exacty what I wanted: “Represents the individual shapes within a grouped shape.”

In my attached test file, I have two shapes “Cloud shape” and “Lightning shape”, that constitute a group shape called “Cloud and Lightning”.

When I tried
shape instanceof GroupShape
I got FALSE for the shapes “Cloud shape” and “Lightning shape”.

Since that did not work as per the documentation, I tried the Shape.isGroup() method, which returned FALSE for the individual “Cloud shape” and “Lighning shape”, and TRUE for “Cloud and Lightning”. However I have a problem using the FALSE evaluation, because then I cannot distinguish the constituent shapes from any non-grouped shapes such as the “Right arrow” (which also returns FALSE).

Here is my code snippet.

for (final Shape shape : (Iterable<Shape>) worksheet.getShapes())
    String shpTxt = shape.getAlternativeText();
    System.out.println();
    System.out.println("Shape alt text is: " + shpTxt);

    System.out.println("instance of: " + (shape instanceof GroupShape));
    System.out.println("isGroup(): " + shape.isGroup());
}

The output is:

Shape alt text is: Cloud and Lightning grouped together.
instance of: true
isGroup(): true

Shape alt text is: Cloud shape grouped with Lightning.
instance of: false
isGroup(): false

Shape alt text is: Lightning shape grouped with Cloud.
instance of: false
isGroup(): false

Shape alt text is: Right arrow shape.
instance of: false
isGroup(): false

Shape alt text is: Curved Left shape.
instance of: false
isGroup(): false

What is the right way to iterate (in a single loop) over all shapes in the sheet and return ONLY “Cloud shape” and “Lightning shape” (constituents), and ignore “Cloud and Lightning” (group container) and the non-grouped arrows?

Thanks.
GroupShape.zip (10.4 KB)

@oraspose

Thanks for using Aspose APIs.

Please use the GroupShape.getGroupedShapes() method for your needs. Please see the following sample code and its console output for your reference.

Java

Workbook wb = new Workbook(dirPath + "GroupShape.xlsx");

Worksheet ws = wb.getWorksheets().get(0);

Shape sh = ws.getShapes().get(0);

if(sh instanceof GroupShape)
{
	GroupShape gsh = (GroupShape)sh;
	
	Shape[] shps = gsh.getGroupedShapes();
	
	System.out.println(shps.length);
	System.out.println(shps[0].getName());
	System.out.println(shps[1].getName());
}

Console Output:

2
Cloud
Lightning Bolt 20

Thanks, I see that your example satisfies the requirement I stated of identifying the group constituents. I realize I did not describe my requirement in the right way.

I need to iterate (preferably in a single loop) over ALL shapes in the sheet and segregate the group constituent shapes from the rest of the shapes. So ideally, in the example you gave, there should be a loop and IF-ELSE blocks. How can we achieve that?

@oraspose

If some shape is a part of group shape, then its Group property will not be null and you can then use the following code to get all other constituent shapes from that shape.

Java

Shape[] shps = sh1.getGroup().getGroupedShapes();

Can you clarify that the Group property does not represent the same property in
shape.getGroup()
and
shape.isGroup()?

For Cloud shape and Lightning shape,isGroup() is FALSE, but getGroup() is NOT NULL.
For “Cloud and Lightning” shape,isGroup() is TRUE, but getGroup() is NULL.

I wanted to confirm that for my requirement, while I can use shape.getGoup() != null, I should NOT use shape.isGroup() because the “Group” property represents the group container shape, and not the group constituent shapes.

@oraspose

Group shapes can be identified easily because they are of type GroupShape. Other shapes may have different types.

Please see this screenshot. It shows, only one shape is GroupShape while all other shapes are of type CellsDrawing.

Please also check the post#4 above for more help.

Screenshot:

Thanks, I will use the shape.getGoup() != null condition to distinguish the individual group constituents from other shapes.

Also please confirm that the javadoc for the GroupShape class is misleading, as I pointed out in my first post. It says: “Represents the individual shapes within a grouped shape.”, whereas in your screenshot above Cloud shape and Lightning shape are NOT GroupShape instances.

@oraspose

Thanks for your posting and using Aspose APIs.

We have logged this issue as follows so that we change its description both for .NET and Java documentation.

Because GroupShape class represents group shape not the individual shape inside the group shape.

  • CELLSNET-46171 - GroupShape definition is misleading

The issues you have found earlier (filed as CELLSNET-46171) have been fixed in Aspose.Cells for .NET 18.6. Please also check the document/article for your reference: Install Aspose Cells through NuGet|Documentation