scanny / python-pptx

Create Open XML PowerPoint documents in Python
MIT License
2.4k stars 519 forks source link

Shape of group type has incorrect size #925

Open YuMingtao0503 opened 11 months ago

YuMingtao0503 commented 11 months ago

n some cases, the position and size of group type shapes are incorrect, but I have found that even if they are in the wrong position, their relative positions are still relatively accurate. Therefore, there is a way to convert them

prs = Presentation("your_ppt.pptx")
slide = prs.slides[13]
for m,shape in enumerate(slide.shapes):  
    if shape.shape_type == 6:
        # true size and xy
        group_top_left_x = shape.left
        group_top_left_y = shape.top
        group_width = shape.width
        group_height = shape.height
        # false size and xy
        shape_top_left_x = min([ sp.left for sp in shape.shapes])
        shape_top_left_y = min([ sp.top for sp in shape.shapes])
        shape_width = max([sp.left + sp.width for sp in shape.shapes]) - shape_top_left_x
        shape_height = max([sp.top + sp.height for sp in shape.shapes]) - shape_top_left_y
        # scale xy
        px = group_width/shape_width
        py = group_height/shape_height
        group_shape_xy = []
        for n,sp in enumerate(shape.shapes):
            group_shape_left = (sp.left - shape_top_left_x) * group_width /shape_width + group_top_left_x
            group_shape_top = (sp.top - shape_top_left_y) * group_height /shape_height + group_top_left_y
            group_shape_width = sp.width * group_width / shape_width
            group_shape_height = sp.height * group_height/shape_height
            group_shape_xy.append([int(group_shape_left),int(group_shape_top),int(group_shape_width),int(group_shape_height)])

then group_shape_xysaved relatively real location information

devotedtaylor commented 9 months ago

I also met the same problem, and this solution solves my problem. Thank u very much.

AliMamed commented 4 months ago

@YuMingtao0503 thanks a lot. Solves my problem

Force1ess commented 1 month ago

@YuMingtao0503

Hi, thank you for your solution—it's been really helpful!

However, I've encountered a "divide by zero" issue when implementing it in my code.

Here's my code:

def parse_groupshape(groupshape: GroupShape):
    assert isinstance(groupshape, GroupShape)
    group_top_left_x = groupshape.left
    group_top_left_y = groupshape.top
    group_width = groupshape.width
    group_height = groupshape.height

    # Calculate false size and position
    shape_top_left_x = min([sp.left for sp in groupshape.shapes])
    shape_top_left_y = min([sp.top for sp in groupshape.shapes])
    shape_width = (
        max([sp.left + sp.width for sp in groupshape.shapes]) - shape_top_left_x
    )
    shape_height = (
        max([sp.top + sp.height for sp in groupshape.shapes]) - shape_top_left_y
    )

    # Scale position and size
    group_shape_xy = []
    for sp in groupshape.shapes:
        group_shape_left = (
            (sp.left - shape_top_left_x) * group_width / shape_width + group_top_left_x
        )
        group_shape_top = (
            (sp.top - shape_top_left_y) * group_height / shape_height + group_top_left_y
        )
        group_shape_width = sp.width * group_width / shape_width
        group_shape_height = sp.height * group_height / shape_height
        group_shape_xy.append(
            {
                "left": Length(group_shape_left),
                "top": Length(group_shape_top),
                "width": Length(group_shape_width),
                "height": Length(group_shape_height),
            }
        )
    return group_shape_xy

Does anyone have any suggestions on how to resolve this "divide by zero" problem?

Force1ess commented 4 weeks ago

Not only divide by zero, some time it will give a error position when parse nested group shape