Failed to Retrieve Hyperlinks in C# in the Same Visual Order as Available in PPT File

@lpappachen,
You can get text and hyperlinks from text portions like this:

foreach (var paragraph in autoShape.TextFrame.Paragraphs)
{
    foreach (var portion in paragraph.Portions)
    {
        var text = portion.Text;
        var url = portion.PortionFormat.HyperlinkClick.ExternalUrl;

        //...
    }
}

Documents: Manage Hyperlinks

Please let us know if you have some difficulties with this.

The above code is working fine for few scenarios ,how ever its not working for few special cases (attaching a sample document for one of such) like when we have combination of text regions and content.
Result.zip (93.2 KB)

below is the full code we are using and the attaching the output screenshot as well.

Please suggest what can we do here to retrieve the links and names in visual order .

public static Dictionary<string, string> ExtractHTMlLink(string PPTFilePath)
{
    Presentation pptxPresentation = new Presentation(PPTFilePath);

    Dictionary<string, string> HypLinks = new Dictionary<string, string>();

    for (int slideNo = 0; slideNo < pptxPresentation.Slides.Count; slideNo++)
    {
        var slide = pptxPresentation.Slides[slideNo];

        // A collection for shapes with text to be sorted.
        var textShapes = new List<IShape>();

        foreach (var shape in slide.Shapes)
        {
            if (shape is IAutoShape)
            {
                textShapes.Add(shape);
            }
        }

        textShapes.Sort(new ShapeComparer());
        textShapes.Reverse();

        foreach (var shape in textShapes)
        {
            if (shape is IAutoShape autoShape)
            {
                foreach (var paragraph in autoShape.TextFrame.Paragraphs)
                {
                    foreach (var port in paragraph.Portions)
                    {
                        if (port.PortionFormat.AsIHyperlinkContainer.HyperlinkClick != null
                            && port.PortionFormat.AsIHyperlinkContainer.HyperlinkClick.ExternalUrl != null)
                        {
                            {
                                if (!string.IsNullOrEmpty(port.Text.Trim()))
                                {
                                    HypLinks.Add(port.Text?.Trim(), port.PortionFormat.AsIHyperlinkContainer.HyperlinkClick.ExternalUrl);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return HypLinks;
}

@lpappachen,
Thank you for the case description. I am working on the issue and will get back to you soon.

@lpappachen,
Please try using the following code examples:

using var presentation = new Presentation("QA testing links PPT.pptx");

// Collect all hyperlinks in shapes.
var allHyperlinks = new List<Tuple<IShape, IPortion>>();
foreach (var slide in presentation.Slides)
{
    var slideHyperlinks = ExtractHyperlinks(slide);
    slideHyperlinks.Sort(new PortionComparer());
    allHyperlinks.AddRange(slideHyperlinks);
}

// The sorted list of portions with hyperlinks.
var portionList = allHyperlinks.Select(tuple => tuple.Item2).ToList();

// Print all hyperlinks.
foreach (var portion in portionList)
{
    var text = portion.Text.Trim();
    var url = portion.PortionFormat.HyperlinkClick.ExternalUrl;

    Console.WriteLine("Text: " + text);
    Console.WriteLine("URL: " + url + "\r\n");
}
private static List<Tuple<IShape, IPortion>> ExtractHyperlinks(ISlide slide)
{
    var hyperlinks = new List<Tuple<IShape, IPortion>>();

    foreach (var shape in slide.Shapes)
    {
        if (shape is IAutoShape autoShape)
        {
            foreach (var paragraph in autoShape.TextFrame.Paragraphs)
            {
                foreach (var portion in paragraph.Portions)
                {
                    var hyperlink = portion.PortionFormat.HyperlinkClick;
                    if (hyperlink != null && hyperlink.ExternalUrl != null)
                    {
                        var text = portion.Text.Trim();
                        if (!string.IsNullOrEmpty(text))
                        {
                            hyperlinks.Add(Tuple.Create(shape, portion));
                        }
                    }
                }
            }
        }
    }

    return hyperlinks;
}
private class PortionComparer : IComparer<Tuple<IShape, IPortion>>
{
    public int Compare(Tuple<IShape, IPortion> pair1, Tuple<IShape, IPortion> pair2)
    {
        var rect1 = pair1.Item2.GetCoordinates();
        var rect2 = pair2.Item2.GetCoordinates();

        // Сoordinates of the first portion relative to the slide.
        var x1 = rect1.X + pair1.Item1.X;
        var y1 = rect1.Y + pair1.Item1.Y;

        // Сoordinates of the second portion relative to the slide.
        var x2 = rect2.X + pair2.Item1.X;
        var y2 = rect2.Y + pair2.Item1.Y;

        // Who is higher, the earlier.
        if (y1 < y2) return -1;

        // Who is lower, the later.
        if (y1 > y2) return 1;

        // Who is to the left, the earlier.
        if (x1 < x2) return -1;

        // Who is to the right, the later.
        if (x1 > x2) return 1;

        // The portions are in the same position.
        return 0;
    }
}

Output:

Text: Link1
URL: https://forum.aspose.com/t/read-hyperlinks/97484/2

Text: Link2
URL: https://forum.aspose.com/t/read-hyperlinks/97484/2

Text: Link3
URL: https://forum.aspose.com/t/read-hyperlinks/97484/2

Text: Link4
URL: https://forum.aspose.com/t/read-hyperlinks/97484/2

Text: Link5
URL: https://forum.aspose.com/t/read-hyperlinks/97484/2

Thanks for the work around .This solution is working fine for some of our use cases. How ever it is failing when the hyperlink is wrapped around text (its not even identifying as hyper link and getting ignored). I have attached the sample document with which we have issues.
Do we have a permanent fix / function ,which can give us the visual order ?QA testing links PPT.zip (59.2 KB)

We are using Aspose.Slides 23.7 version. Is the issue going to be fixed as part of future release ?

@lpappachen,
I am working on your question and will get back to you as soon as possible.

@lpappachen,

This happened because the link was placed in the table. The code example I provided handles only autoshapes in the ExtractHyperlinks method:

if (shape is IAutoShape autoShape)
{
    // ...
}

You can add code that parses tables in a similar manner as well.