Vba 将插入的EMF文件解组到Powerpoint时的失真

Vba 将插入的EMF文件解组到Powerpoint时的失真,vba,powerpoint,.emf,Vba,Powerpoint,.emf,背景:我是一个Powerpoint插件的开发人员,该插件在Powerpoint中包含LaTeX显示。IguanaTex可以生成矢量图形显示(Powerpoint形状,通常为自由形式),方法是将EMF文件插入幻灯片中,将其解组,然后进行一些清理(删除额外形状、进一步解组、删除行等)。这些EMF文件通常是使用外部引擎()从LaTeX或用户希望转换为可编辑形状的PDF文件生成的(与LaTeX没有真正的关系,但整个代码库都提供了该功能,所以我将其放在了其中) 问题:我最近注意到以编程方式取消EMF文件分

背景:我是一个Powerpoint插件的开发人员,该插件在Powerpoint中包含LaTeX显示。IguanaTex可以生成矢量图形显示(Powerpoint形状,通常为自由形式),方法是将EMF文件插入幻灯片中,将其解组,然后进行一些清理(删除额外形状、进一步解组、删除行等)。这些EMF文件通常是使用外部引擎()从LaTeX或用户希望转换为可编辑形状的PDF文件生成的(与LaTeX没有真正的关系,但整个代码库都提供了该功能,所以我将其放在了其中)

问题:我最近注意到以编程方式取消EMF文件分组时出现零星问题,而通过GUI取消同一文件分组不会导致错误。我已确认,这在运行Office 2010、Office 2016或Office 365的两台Windows 10计算机上发生

假设我们在Powerpoint中插入并获取以下图片对象:

使用插入同一文件会导致以下扭曲输出,其中“a”和“s”字母垂直拉长:

VBA代码基本上是:

  • 使用Shapes.AddPicture方法
  • 在ShapeRange中使用Shape.Ungroup方法(相当于在GUI中解组插入的EMF文件)
  • 再进行一次解组,移除额外的形状(在我们的例子中是1个自选图形和1个矩形),选择位于顶部的组(或自由形式,如果只有一个),移除剩余的矩形,并将每个形状的轮廓设置为不可见
  • 在调试模式下运行代码,我可以确定第一个Shape.Ungroup步骤中发生的失真,这在理论上应该再次等同于在GUI中执行Shift+Ctrl+G(当GUI在解组EMF文件时要求确认时,按Yes)。请注意,当我跨过解组线时,失真仍然会发生

    这个错误尤其令人沮丧的是,如果我在宏中放置与处理上述步骤2和步骤3完全相同的VBA代码(插入文件除外),然后在步骤1中插入文件后停止加载项代码,并使用宏运行其余代码,这通常不会导致任何失真。我通常说,因为这个bug不是100%可复制的:它有时会发生,有时不会。我发现复制它最可靠的方法是插入上面链接的EMF文件

    因此,代码本身似乎没有什么特别的问题,但是Powerpoint运行它的方式有问题。会有一些比赛条件吗?请注意,我还注意到,在分组/取消分组形状时,IguanaTex有时会在随机位置引发错误,重新运行通常可以解决该问题,这也可能指向某些竞争条件。然而,这在这里似乎不太可能,因为在调试模式下单步执行代码时仍然会出现失真问题

    因此,我的问题是:有人知道发生了什么事吗?我如何解决这个问题

    下面是前面提到的宏:

    公共子Emftoshape()
    将线设置为布尔值
    ConvertLines=False
    选择暗选
    设置Sel=Application.ActiveWindow.Selection
    '获取当前幻灯片,它将用于分组范围
    将sld变暗为幻灯片
    尺寸滑块索引与长度相同
    SlideIndex=ActiveWindow.View.Slide.SlideIndex
    设置sld=ActivePresentation.Slides(SlideIndex)
    将shp变暗为形状
    设置shp=选择形状(1)
    '将EMF图像转换为对象
    模糊Shr作为定形符
    设置Shr=shp.Ungroup
    Set Shr=Shr.Ungroup
    “清理
    第(1)项。删除
    Shr.项目(2).删除
    像形状一样暗淡的新闻形状
    如果Shr(3).GroupItems.count>2,则
    设置新闻形状=Shr(3)
    Else’只有一个自由形式,所以不是一个团体
    Set newShape=Shr(3)。GroupItems(2)
    如果结束
    Shr(3).分组项目(1).删除
    如果newShape.Type=msoGroup,则
    Dim arr_组()作为变量
    arr_group=GetAllShapeSingGroup(新形状)
    调用FullyUngroupShape(新闻形状)
    设置newShape=sld.Shapes.Range(arr\u group).group
    Dim emf_arr()作为变量“收集所有形状以便稍后重新组合”
    j_emf=0
    Dim delete_arr()作为变量“收集所有要在以后删除的形状”
    j_delete=0
    像形状一样变暗
    对于newShape.GroupItems中的每个s
    j_emf=j_emf+1
    ReDim保留emf_arr(1到j_emf)
    如果s.类型=msoLine,则
    如果转换线和(s.高度>0或s.宽度>0),则
    emf_arr(j_emf)=LineToFreeform(s)。名称
    j_delete=j_delete+1
    重拨保留删除(1到j_删除)
    delete_arr(j_delete)=s.name
    其他的
    emf_arr(j_emf)=s.name
    如果结束
    其他的
    emf_arr(j_emf)=s.name
    如果s.Fill.Visible=msoTrue,则
    s、 Line.Visible=msoFalse
    其他的
    s、 Line.Visible=msoTrue
    如果结束
    如果结束
    下一个
    新闻形态解组
    如果j_delete>0,则
    sld.Shapes.Range(删除)。删除
    如果结束
    设置newShape=sld.Shapes.Range(emf\u arr.Group)
    其他的
    如果newShape.Type=msoLine,则
    newShapeName=LineToFreeform(newShape).name
    新闻形状.删除
    设置newShape=sld.Shapes(newShapeName)
    其他的
    newShape.Line.Visible=msoFalse
    如果结束
    如果结束
    newShape.LockAspectRatio=msoTrue
    端接头
    私有子完整组形状(新形状作为形状)
    模糊Shr作为定形符
    像形状一样变暗
    如果newShape.Type=msoGroup,则
    Set Shr=newShape.Ungroup
    对于i=1到Shr.count
    集合s=Shr.项目(i)