Insert an unknown number of images into a Document

Hello devs,

I have a template where I need to merge an unknown number of attached images to notes. This template is the layout for notes and each note has X number of images. Currently, I am trying to put a MERGEFIELD in the template named “AttachedImages” and then my data has only one filed which is a list of strings containing file name each which; when the backend receives a request, it processes each item to download image from a storage and then create a Picture which I am trying to append to the content when merge field is inserted. This approach could be different provided it merges every image for each note.

Template:

Code:

private void MergeAttachedImages(int? tenantId, DocumentModel templateDoc, FormRequestDto formRequest)
{
    templateDoc.MailMerge.FieldMerging += async (sender, e) =>
    {
        if (true || e.IsValueFound && e.Value != null)
        {
            switch (e.FieldName) // TODO: change this swtich to if
            {
                case "-------------AttachedImages":
                    if (true || e.Value is IEnumerable<object> objList)
                    {
                        List<ImageBlob>? imageFileNameList = formRequest.attachedImages;
                        //e.Inlines.Remove(e.Inline);
                        if (imageFileNameList != null)
                        {

                            foreach (var imageFileName in imageFileNameList)
                            {
                                string templateContainer = tenantId != null ? "tenant" + tenantId.ToString()?.PadLeft(4, '0') : "defaultform";
                                byte[]? imageDataBytes = _storageService.Read(templateContainer, imageFileName.ImageBlobName);
                                if (imageDataBytes != null)
                                {
                                    MemoryStream memoryStream = new MemoryStream(imageDataBytes, true);
                                    //e.Inline = new Picture(e.Document, memoryStream);

                                    Picture picture = new Picture(e.Document, memoryStream);

                                    /////////////////////////////////////////////////////////////////////////////////////////////
                                    Layout? pictureLayout = picture.Layout;
                                    Size? pictureSize = pictureLayout?.Size;
                                    var pageSize = new Size(
                                        imageFileName.MaxWidth, //?? pictureSize.Value.Width,
                                        imageFileName.MaxHeight,
                                        LengthUnit.Inch); //?? pictureSize.Value.Height);
                                    var ratioX = pageSize.Width / pictureSize.Value.Width;
                                    var ratioY = pageSize.Height / pictureSize.Value.Height;
                                    var ratio = Math.Min(ratioX, ratioY);
                                    if (ratio < 1)
                                        pictureLayout.Size = new Size(pictureSize.Value.Width * ratio, pictureSize.Value.Height * ratio);

                                    e.Inlines.Add(picture);

                                    /////////////////////////////////////////////////////////////////////////////////////////////
                                    //Layout? pictureLayout = picture.Layout;
                                    //Size? pictureSize = pictureLayout?.Size;
                                    //PageSetup? pageSetup = e.Inline.Document.Sections.FirstOrDefault()?.PageSetup;
                                    //PageMargins? pageMergins = pageSetup?.PageMargins;
                                    //var pageSize = new Size(
                                    //    pageSetup.PageWidth - pageMergins.Left - pageMergins.Right,
                                    //    pageSetup.PageHeight - pageMergins.Top - pageMergins.Bottom);
                                    //var ratioX = pageSize.Width / pictureSize.Value.Width;
                                    //var ratioY = pageSize.Height / pictureSize.Value.Height;
                                    //var ratio = Math.Min(ratioX, ratioY);
                                    //if (ratio < 1)
                                    //    pictureLayout.Size = new Size(pictureSize.Value.Width * ratio, pictureSize.Value.Height * ratio);


                                }
                            }
                        }
                    }
                    break;
                    //case "MyImage":
                    //    if (e.Inline is Picture image)
                    //        image.Metadata.Description = "Three dancing penguins.";
                    //    break;
            }
        }
    };
}

Hi Noe,

Instead of that, you could use a merge range with a single picture mail merge field.
In other words, something like this:

img1

Then you could execute the mail merge process like this:

var document = DocumentModel.Load("input.docx");

document.MailMerge.Execute(
    new
    {
        MyImages = new[]
        {
            new { MyImage = "image1.png" },
            new { MyImage = "image2.png" },
            new { MyImage = "image3.png" },
        }
    });

document.Save("output.docx");

The result would be:

img2

For more information, please check the Merge Pictures and Merge Ranges examples.

I hope this helps.

Regards,
Mario

1 Like

Thank you, this is the kind of approach I was looking for: simpler and effictive.