How to inline images with text by using aspose.words for .NET

I am not allowed to use this.
Document doc = new Document(@“D:\TestOutput\test.docx”);

Do you have any method to get the saved document??? Because I think It’s only working with saved word document. Do you have any suggestions?

@nethmi Thank you for additional information. The suggested method should be used together with the approach suggested earlier. First you should change the appropriate shapes WrapType and then process the document with the code that uses LayoutCollector and LayoutEnumerator.
Also, it is not required to use Document doc = new Document(@"D:\TestOutput\test.docx");. This line of code is used for demonstration purposes to check the output produced by the code.

You code should look like this:

public List<byte[]> Convert(ContentsDto content, IDictionary<string, string> options, System.Func<DependentContent, Task<ContentsDto>> GetDependency = null)
{
    License htmlLicense1 = new License();
    htmlLicense1.SetLicense("Aspose.Words.NET.lic");

    HtmlDocument htmlDocument = new HtmlDocument();
    using (var htmlStream = new MemoryStream(content.Data))
    {
        htmlDocument.Load(htmlStream);
    }

    var byteArray = new List<byte[]>();

    using (var dataStream = new MemoryStream(content.Data))
    {
        HtmlLoadOptions docOptions = new HtmlLoadOptions();

        docOptions.ResourceLoadingCallback = new AsposeWordsAuthHandler(_settingsProvider, _authSettings, _logger);

        var document = new Aspose.Words.Document(dataStream, docOptions);

        using (var outputStream = new MemoryStream())
        {
            using (var htmlStream = new MemoryStream(content.Data))
            {
                htmlDocument.Load(htmlStream);
            }

            ApplyImageFormatting(document, htmlDocument);
            FormatOutput(GetDependency, document, htmlDocument);
            
            // Here overlap issue is fixed by layout code.
            OverlapIssue(document);

            document.Save(outputStream, SaveFormat.Docx);
            byteArray.Add(outputStream.ToArray());
        }
    }
    return byteArray;
}

done. still getting the same issue.

@nethmi Could you please crate a simple console application and attach it here, so I can run it on my side and debug it? I will check what is going wrong and provide you more information.
Also, please modify OverlapIssue method like this:

//Method , which adjust the overlap issue
 private static void OverlapIssue(Document doc)
        {
            LayoutCollector collector = new LayoutCollector(doc);
            LayoutEnumerator enumerator = new LayoutEnumerator(doc);

            NodeCollection shapes = doc.GetChildNodes(NodeType.Shape, true);
            foreach (Shape s in shapes)
            {
                // LayoutCollector and LayoutEnumerator do not work with nodes in header and footer.
                // Skip them.
                if (s.GetAncestor(NodeType.HeaderFooter) != null)
                    continue;

                PageSetup ps = ((Section)s.GetAncestor(NodeType.Section)).PageSetup;
                // Rectangle inside page margin.
                double top = ps.TopMargin + ps.HeaderDistance;
                double bottom = ps.BottomMargin + ps.FooterDistance;
                float width = (float)(ps.PageWidth - ps.LeftMargin - ps.RightMargin);
                float height = (float)(ps.PageHeight - top - bottom);
                RectangleF rect = new RectangleF((float)ps.LeftMargin, (float)top, width, height);

                // Get shape rectangle on the page.
                enumerator.Current = collector.GetEntity(s);
                RectangleF shapeRect = enumerator.Rectangle;

                // Update shape position to place it inside page margins.
                if (shapeRect.Left < rect.Left)
                    s.Left += (rect.Left - shapeRect.Left);

                if (shapeRect.Right > rect.Right)
                    s.Left -= (shapeRect.Right - rect.Right);

                if (shapeRect.Top < rect.Top)
                    s.Top += (rect.Top - shapeRect.Top);

                if (shapeRect.Bottom > rect.Bottom)
                    s.Top -= (shapeRect.Bottom - rect.Bottom);
            } 
    }

sure I will.
Could you please try OverlapIssue(Document doc) method, with these two word documents???

If you can see a difference please let me know. I think both overlap images in the two documents run under same if condition. I think, That’s why we can’t get correct output for one document.

sample1.docx (29.6 KB)

sample2.docx (30.0 KB)

any update??

@nethmi Thank you for additional information. I have modified the code a bit more and now it gives better result. But please note that fonts used in the document must be available on the machine where code is used, because layout code requires fonts to build layout properly. Could you please check on your side:

private static void OverlapIssue(Document doc)
{
    LayoutCollector collector = new LayoutCollector(doc);
    LayoutEnumerator enumerator = new LayoutEnumerator(doc);

    NodeCollection shapes = doc.GetChildNodes(NodeType.Shape, true);
    foreach (Shape s in shapes)
    {
        // LayoutCollector and LayoutEnumerator do not work with nodes in header and footer.
        // Skip them.
        if (s.GetAncestor(NodeType.HeaderFooter) != null || !s.IsTopLevel)
            continue;

        PageSetup ps = ((Section)s.GetAncestor(NodeType.Section)).PageSetup;
        // Rectangle inside page margin.
        float width = (float)(ps.PageWidth - ps.LeftMargin - ps.RightMargin);
        float height = (float)(ps.PageHeight - ps.TopMargin - ps.BottomMargin);
        RectangleF rect = new RectangleF((float)ps.LeftMargin, (float)ps.TopMargin, width, height);

        // Get shape rectangle on the page.
        enumerator.Current = collector.GetEntity(s);
        RectangleF shapeRect = enumerator.Rectangle;

        double left = 0;
        double top = 0;

        // Update shape position to place it inside page margins.
        if (shapeRect.Left < rect.Left)
            left = rect.Left;

        if (shapeRect.Right > rect.Right)
            left = rect.Right - shapeRect.Width;

        if (shapeRect.Top < rect.Top)
            top = rect.Top;

        if (shapeRect.Bottom > rect.Bottom)
            top = rect.Bottom - shapeRect.Height;

        if (!IsZero(left) || !IsZero(top))
        {
            // Set relative shape position to page.
            s.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
            s.RelativeVerticalPosition = RelativeVerticalPosition.Page;
            s.Top = Math.Max(top, rect.Top);
            s.Left = Math.Max(left, rect.Left);
            doc.UpdatePageLayout();
        }
    }
}

public static bool IsZero(double value)
{
    return (Math.Abs(value) < Double.Epsilon);
}
1 Like

Hii

This is working. I checked several scenarios with this code. It’s working. Thank you very much for your support and effort. I really appreciate it. :slightly_smiling_face:

1 Like

A post was split to a new topic: How to change image wrap type using Aspose.Pdf?

Hii

I am using below code to wrap my images.

private static void SetImageLayout(Document document, HtmlDocument htmlDocument)
    {
        HtmlNodeCollection images = htmlDocument.DocumentNode.SelectNodes("//img");
        NodeCollection shapes = document.GetChildNodes(NodeType.Shape, true);

        if (images != null)
        {
            var imgIndex = 0;
            foreach (Shape shape in shapes)
            {
                var image = images.ElementAt(imgIndex);

                if (image.HasClass("fr-fil"))
                {
                    shape.WrapType = WrapType.Square;
                    shape.Top += shape.Height + 10;
                
                }
                else
                {
                    shape.HorizontalAlignment = HorizontalAlignment.Center;
                }
                shape.AllowOverlap = false;
                imgIndex++;
            }
        }
    }

but sometimes it doesn’t give the expected outcome.( When I reduce content between two images -you can understand this problem by using my expected and current outcomes. It has two wrapped images.)

Expected outcome expected.PNG.jpg (163.7 KB)

current outcome(this is happening when I reduce paragraph length between images.)current.PNG.jpg (161.8 KB)

HTML.zip (2.9 KB)

I can’t provide exact information because of the privacy reasons. So I have sent you a dummy HTML . My HTML is like that. You can check my issue with this HTML by changing paragraph length between those two images. images are in the third page.

Could you please help me to solve this issue?

@nethmi I am checking the issue and get back to you soon.

1 Like

@nethmi I have checked your HTML and code on my side and unfortunately, I cannot reproduce the same output document you have shared. Could you please attach your output DOCX document with the problem?
I suspect the shapes are anchored to the same paragraph and as a solution you can check whether the shapes are in the same paragraph and placed on the same page, if so you can adjust position of such shapes and place them one above another. However, this in only my guess. Once I have your real problematic document I can analyze the issue closer.

ok i’ll send you

1 Like

Hiii

HTML MYHTML.zip (2.1 KB)
word document document.docx (17.5 KB)
used Image picture.jpg (5.7 KB)

In the 3rd page you can see the two wrapped images.
current outcomecurrent.PNG.jpg (135.9 KB)

expected outcome expected.PNG.jpg (163.7 KB)

shapes are in different paragraphs

@nethmi Thank you for additional information. I have create a code example that demonstrates the basic technique of adjusting shapes positions to get the required output. But note, the code demonstrates only the basic technique and does not guaranty to work with more complicated cases. For more complicated cases, you have to implement more complicated logic to adjust positions of shapes on the page. Implementation of such logic is out of Aspose.Words scope.

Document doc = new Document(@"C:\Temp\in.docx");
CorrectShapesPosition(doc);
doc.Save(@"C:\Temp\out.docx");
private static void CorrectShapesPosition(Document doc)
{
    LayoutCollector collector = new LayoutCollector(doc);
    LayoutEnumerator enumerator = new LayoutEnumerator(doc);

    // Get all shapes in the document.
    NodeCollection shapes = doc.GetChildNodes(NodeType.Shape, true);

    // Collect shapes per page.
    Dictionary<int, List<ShapeRect>> shapesPerPage = new Dictionary<int, List<ShapeRect>>();
    foreach (Shape s in shapes)
    {
        enumerator.Current = collector.GetEntity(s);
        if (!shapesPerPage.ContainsKey(enumerator.PageIndex))
            shapesPerPage.Add(enumerator.PageIndex, new List<ShapeRect>());

        shapesPerPage[enumerator.PageIndex].Add(new ShapeRect(s, enumerator.Rectangle));
    }

    foreach (int page in shapesPerPage.Keys)
    {
        List<ShapeRect> shapesOnPage = shapesPerPage[page];
        // If there is only one shape on the page no actiona is required.
        if (shapesOnPage.Count == 1)
            continue;

        // Adjust vertical position of shapes to avoid overlapping.
        // The code demonstrates the basic technique and does not guaranly to work in all case.
        // More complicated cases requires implemeting core complicated logic.
        for (int i = 0; i < shapesOnPage.Count - 1; i++)
        {
            ShapeRect current = shapesOnPage[i];
            ShapeRect next = shapesOnPage[i + 1];
            if (current.Rectangle.Bottom > next.Rectangle.Top)
                current.Shape.Top -= current.Rectangle.Bottom - next.Rectangle.Top;
        }
    }
}

private class ShapeRect
{
    public ShapeRect(Shape shape, RectangleF rect)
    {
        mShape = shape;
        mRect = rect;
    }

    public Shape Shape { get { return mShape; } }
    public RectangleF Rectangle { get { return mRect; } }

    private Shape mShape;
    private RectangleF mRect;
}

here is the output document produced on my side: out.docx (17.5 KB)

1 Like

got it. Thank you very much for your effort.

1 Like

Hii

When I make changes in the HTML, my wrapped images in the converted word document, go here and there. sometimes those pictures go to another page. why those positions are changing like that?? This happens only for wrapped images. They escape their wrapped content and go everywhere in the document, when I made new changes to the document.

changes means -I gave page margins to the document. I added header image to the document. I used aspose.words logics to avoid page breaks, I add extra content to the html, I removed some paragraphs from the html etc.

Do you have a solution to bind those wrapped images with the wrapped content to avoid such kind of issue???

@nethmi You should note that both HTML and MS Word documents are flow documents and when you add some content into the document other content is reflowed. Images in MS Word documents are anchored to a paragraph. If anchor point is moved the shape position is also moved and document content is reflowed again.
To fix position of shape on the page, you can set its relative vertical and horizontal position to Page, just like I have suggested in this post.

// Set relative shape position to page.
s.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
s.RelativeVerticalPosition = RelativeVerticalPosition.Page;

But in this case you have to calculate absolute position of shape on the page. And anyways if the anchor point the absolutely positioned shape will be moved to the next page, the shape will be moved to the next page too and content will be reflowed.

1 Like

got it. I’ll try

1 Like