Programmatically find the exact top and bottom of a shape or a table comparing to page top and page bottom

Hello,
I have got one of my tasks in hand to identify all the objects (mainly shapes and tables) which are in document body but they are overlapping header or footer. How can I find the exact top and bottom position of a shape or a table comparing to page top and page bottom, regardless of its relative positioning programmatically in C#?

My final goal is to find the distance top and bottom to find out if its overlapping header/footer or not.

Thanks,
Varun

@varun.arora,

The following C# code of Aspose.Words for .NET API will calculate the Top and Bottom positions of of any Table in Word document and you can build logic on this code to get the desired output:

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

Table table = doc.FirstSection.Body.Tables[0];

LayoutCollector layoutCollector = new LayoutCollector(doc);
LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);

double minTop = double.MaxValue;
double maxBottom = 0;
foreach (Node node in table.GetChildNodes(NodeType.Any, true))
{
    try
    {
        layoutEnumerator.Current = layoutCollector.GetEntity(node);

        if (layoutEnumerator.Rectangle.Bottom > maxBottom)
            maxBottom = layoutEnumerator.Rectangle.Bottom;

        if (layoutEnumerator.Rectangle.Top < minTop)
            minTop = layoutEnumerator.Rectangle.Top;
    }
    catch { }
}

double pageWidth = ((Section)table.GetAncestor(NodeType.Section)).PageSetup.PageWidth;

DocumentBuilder builder = new DocumentBuilder(doc);

builder.MoveTo(table.PreviousSibling); // just to anchor shape to            
DrawLine(builder, minTop, pageWidth, Color.Blue);

builder.MoveTo(table.NextSibling);
DrawLine(builder, maxBottom, pageWidth, Color.Red);

doc.Save("C:\\Temp\\21.2.docx");

public static void DrawLine(DocumentBuilder builder, double top, double width, Color color)
{
    Shape line = new Shape(builder.Document, ShapeType.Line);
    line.StrokeColor = color;
    line.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
    line.RelativeVerticalPosition = RelativeVerticalPosition.Page;
    line.WrapType = WrapType.None;
    line.Left = 0;
    line.Top = top;
    line.Width = width;

    builder.InsertNode(line);
}

Thank you so much, it’s working for all my tables I have so far.

I did tweak a little for shapes as nothing was coming as child node for shapes and I applied layout logic directly on shape instead of loop.

            LayoutCollector layoutCollector = new LayoutCollector(document);
            LayoutEnumerator layoutEnumerator = new LayoutEnumerator(document);

            double minTop = double.MaxValue;
            double maxBottom = 0;

            layoutEnumerator.Current = layoutCollector.GetEntity(shape);

            if (layoutEnumerator.Rectangle.Bottom > maxBottom)
                maxBottom = layoutEnumerator.Rectangle.Bottom;

            if (layoutEnumerator.Rectangle.Top < minTop)
                minTop = layoutEnumerator.Rectangle.Top;

It’s working for most of the shapes I have so far, but breaking for one of the shape that has image on the below line:
layoutEnumerator.Current = layoutCollector.GetEntity(shape);

Error Message:
System.ArgumentNullException
HResult=0x80004003
Message=Value cannot be null.
Parameter name: value
Source=Aspose.Words
StackTrace:
at Aspose.Words.Layout.LayoutEnumerator.set_Current(Object value)

Can you please help?

[Edit]
Another issue is for ShapeType CustomShape the layoutEnumerator.Rectangle.Top is always 0.

Thanks,
Varun

@varun.arora,

Please ZIP and upload your source Word document containing the Shape(s) that you are getting this problem with here for testing. We will then investigate the issue on our end and provide you more information.

OverlappedHeadersFooters.zip (69.1 KB)
It has some shapes that are throwing error as I mentioned earlier.

GroupShapes.zip (37.7 KB)
It has custom shapes where layoutEnumerator.Rectangle.Top is always 0.

Thanks,
Varun

@varun.arora,

To determine Top and Bottom positions of Shapes and GroupShapes, please use the following code respectively:

Document doc = new Document("C:\\temp\\OverlappedHeadersFooters\\OverlappedHeadersFooters.docx");

LayoutCollector layoutCollector = new LayoutCollector(doc);
LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);

foreach (Shape shape in doc.GetChildNodes(NodeType.Shape, true))
{
    layoutEnumerator.Current = layoutCollector.GetEntity(shape);
    Console.WriteLine("Top: " + layoutEnumerator.Rectangle.Top + " Bottom: " + layoutEnumerator.Rectangle.Bottom);
}

Document doc = new Document("C:\\temp\\OverlappedHeadersFooters\\GroupShapes.docx");

LayoutCollector layoutCollector = new LayoutCollector(doc);
LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);

foreach (GroupShape groupShape in doc.GetChildNodes(NodeType.GroupShape, true))
{
    layoutEnumerator.Current = layoutCollector.GetEntity(groupShape);
    Console.WriteLine("Top: " + layoutEnumerator.Rectangle.Top + " Bottom: " + layoutEnumerator.Rectangle.Bottom);
}