关于多个shape拼接成一个整体图的问题。

我有一个需求,需要将多个shape拼接成一个组合,然后渲染保存为图片。请问是否可以做到?
下方是word文件。
test-shape.docx (47.9 KB)

@Calvin95 您可以尝试使用以下代码:

Document doc = new Document(@"C:\Temp\in.docx");

LayoutCollector collector = new LayoutCollector(doc);
LayoutEnumerator enumerator = new LayoutEnumerator(doc);

// Get top-level shapes in the first paragraph.
ShapeBase[] shapesToGroup = doc.FirstSection.Body.GetChildNodes(NodeType.Any, true)
    .Where(n => n is ShapeBase).Cast<ShapeBase>().Where(s => s.IsTopLevel)
    .ToArray();

// Set absolute position of the top level shapes to make grouping work as expected.
foreach (ShapeBase s in shapesToGroup)
{
    enumerator.Current = collector.GetEntity(s);
    s.WrapType = WrapType.None;
    s.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
    s.RelativeVerticalPosition = RelativeVerticalPosition.Page;
    s.Left = enumerator.Rectangle.Left;
    s.Top = enumerator.Rectangle.Top;
}

DocumentBuilder builder = new DocumentBuilder(doc);
builder.MoveToDocumentEnd();
GroupShape g = builder.InsertGroupShape(shapesToGroup.ToArray());
// Required to update page layout since currently layout is cached after using LayoutCollector and LayoutEnumerator.
doc.UpdatePageLayout();

g.GetShapeRenderer().Save(@"C:\Temp\out.png", new ImageSaveOptions(SaveFormat.Png));

以下是生成的输出结果:out.png (2.0 KB)

非常感谢您的回复,我尝试了你提供的示例代码,可以正常存为图片。
但是整份的完整文档中,存在很多的shape,如果沿用上述代码,会把其他shape也拼接到一起。
是否有方法判断该不该进行拼接?
如下是完整文档
test_all.docx (161.7 KB)

@Calvin95 您可以实现按页面分组。例如:

Document doc = new Document(@"C:\Temp\in.docx");

LayoutCollector collector = new LayoutCollector(doc);
LayoutEnumerator enumerator = new LayoutEnumerator(doc);

// Get top-level shapes in the first paragraph.
ShapeBase[] shapesToGroup = doc.FirstSection.Body.GetChildNodes(NodeType.Any, true)
    .Where(n => n is ShapeBase).Cast<ShapeBase>().Where(s => s.IsTopLevel)
    .ToArray();

// Group shapes on each page separately.
List<ShapeBase[]> pagesShapes = new List<ShapeBase[]>();
// VML and DML shapes cannot be grouped. So collect them in separate collections.
List<ShapeBase> currentPageShapesVML = null;
List<ShapeBase> currentPageShapesDML = null;
int currentPage = -1;
foreach (ShapeBase s in shapesToGroup)
{
    // Set absolute position of the top level shapes to make grouping work as expected.
    enumerator.Current = collector.GetEntity(s);
    s.WrapType = WrapType.None;
    s.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
    s.RelativeVerticalPosition = RelativeVerticalPosition.Page;
    s.Left = enumerator.Rectangle.Left;
    s.Top = enumerator.Rectangle.Top;

    if (enumerator.PageIndex != currentPage)
    {
        currentPage = enumerator.PageIndex;
        if (currentPageShapesVML != null && currentPageShapesVML.Count > 0)
            pagesShapes.Add(currentPageShapesVML.ToArray());
        if (currentPageShapesDML != null && currentPageShapesDML.Count > 0)
            pagesShapes.Add(currentPageShapesDML.ToArray());

        currentPageShapesVML = new List<ShapeBase>();
        currentPageShapesDML = new List<ShapeBase>();
    }
    if(s.MarkupLanguage == ShapeMarkupLanguage.Vml)
        currentPageShapesVML.Add(s);
    if (s.MarkupLanguage == ShapeMarkupLanguage.Dml)
        currentPageShapesDML.Add(s);
}
if (currentPageShapesVML != null && currentPageShapesVML.Count > 0)
    pagesShapes.Add(currentPageShapesVML.ToArray());
if (currentPageShapesDML != null && currentPageShapesDML.Count > 0)
    pagesShapes.Add(currentPageShapesDML.ToArray());

DocumentBuilder builder = new DocumentBuilder(doc);
for (int i = 0; i < pagesShapes.Count; i++)
{
    ShapeBase[] shapes = pagesShapes[i];

    if (shapes.Length == 1)
    {
        shapes[0].GetShapeRenderer().Save($@"C:\Temp\out_{i}.png", new ImageSaveOptions(SaveFormat.Png));
    }
    else
    {
        builder.MoveToDocumentEnd();
        GroupShape g = builder.InsertGroupShape(shapes.ToArray());
        // Required to update page layout since currently layout is cached after using LayoutCollector and LayoutEnumerator.
        doc.UpdatePageLayout();

        g.GetShapeRenderer().Save($@"C:\Temp\out_{i}.png", new ImageSaveOptions(SaveFormat.Png));
    }
}

LayoutEnumerator 可以让你访问每个形状的实际坐标,因此你可以实现更复杂、更智能的算法来确定要对哪些形状进行分组。恐怕实现这样的算法超出了技术支持的范围,也超出了我的能力范围。

非常感谢你的回复,我这边再尝试设计一下算法