我有一个需求,需要将多个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 可以让你访问每个形状的实际坐标,因此你可以实现更复杂、更智能的算法来确定要对哪些形状进行分组。恐怕实现这样的算法超出了技术支持的范围,也超出了我的能力范围。
非常感谢你的回复,我这边再尝试设计一下算法