Inserting Images with Aspose Word

So I the requirement for a project was to have documents to be mailed to customers show to render from a mvc website so a user could print them and mail them out.  We contemplated connecting to the printer from the web server and forcing the print, but we decided to mail merge the document together and simply dump it to the end user to print out through their own means.  Which down the road will save us time.  Because there could be hundreds of these a day, we decided to do all of them in the same word document so only one download and one print would be needed.  So I had to do a multi merge, not too hard.  But then we needed to put labels in there document.  Inserting images, isn't straight forward I quickly learned.

To accomplish this, I first created a controller function for it looked like the following:

public ActionResult Print(string id, string carrier)
        {
            var ctx = new ContextManaged();
            var returns = get data;
            //do printing
            var doc = new Document(HttpContext.Server.MapPath(Config.GetString("PrintTemplateFile")));
            doc.MailMerge.FieldMergingCallback = new HandleMergeImageFieldFromBlob(HttpContext);
            var ds = new DataSet();
            ds.Tables.Add("Returns");
            ds.Tables["Returns"].Columns.Add("CustomerName");
            ds.Tables["Returns"].Columns.Add("AddressLine1");
            ds.Tables["Returns"].Columns.Add("AddressLine2");
            ds.Tables["Returns"].Columns.Add("City");
            ds.Tables["Returns"].Columns.Add("State");
            ds.Tables["Returns"].Columns.Add("Zip");
            ds.Tables["Returns"].Columns.Add("OrderNumber");
            ds.Tables["Returns"].Columns.Add("Date");
            ds.Tables["Returns"].Columns.Add("CompanyName");
            ds.Tables["Returns"].Columns.Add("Image");
            foreach (var ret in returns)
            {
                var dr = ds.Tables["Returns"].NewRow();
                dr["CustomerName"] = ret.CustomerName;
                dr["AddressLine1"] = ret.CustomerAddressLine1;
                dr["AddressLine2"] = ret.CustomerAddressLine2;
                dr["City"] = ret.CustomerCity;
                dr["State"] = ret.CustomerState;
                dr["Zip"] = ret.CustomerZip;
                dr["OrderNumber"] = ret.OrderNumber;
                dr["Date"] = DateTime.Now.ToString("MMMM d, yyyy");
                dr["CompanyName"] = ret.tbl_Company.CompanyName;
                if (ret.Image != null)
                    try
                    {
                        dr["Image"] = ret.Id;
                    }
                    catch (Exception ex)
                    {
                        dr["Image"] = "";
                    }
                else
                    dr["Image"] = "";
                ds.Tables["Returns"].Rows.Add(dr);
            }

            doc.MailMerge.Execute(ds.Tables["Returns"]);
            var ms = new System.IO.MemoryStream();
            doc.Save(ms, SaveFormat.Doc);
            ms.Position = 0;
            var fileStreamResult = new FileStreamResult(ms, "application/ms-word");
            fileStreamResult.FileDownloadName = "PrintReturns.doc";
            return fileStreamResult;
        }

Then I created functions that overrides the Image Field merging and puts them into the word document as a stream.  This was a bit tricky, but it works.  I also had a function to resize the image as my images were too large.

/// <summary>
        /// This is called when mail merge engine encounters Image:XXX merge field in the document.
        /// You have a chance to return an Image object, file name or a stream that contains the image.
        /// </summary>
        void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs e)
        {
            if (e.FieldValue.ToString() == String.Empty)
            {
                e.ImageStream = new FileStream(context.Server.MapPath(Config.GetString("NoImage")), FileMode.Open);
            }
            else
            {
                try
                {
                    //get image
                    var ctx = new PPSHP_ShippingServiceContextManaged();
                    var returns = (from ret in ctx.tbl_Returns where ret.Id == Convert.ToInt32(e.FieldValue) select ret.Image).FirstOrDefault();
                    //resize image
                    var bit = ResizeBitmap(new System.Drawing.Bitmap(new MemoryStream(returns.ToArray())), 700, 500);
                    // The field value is a byte array, just cast it and create a stream on it.
                    var ms = new MemoryStream();
                    bit.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    MemoryStream imageStream = ms;
                    // Now the mail merge engine will retrieve the image from the stream.
                    e.ImageStream = imageStream;
                }
                catch (Exception ex)
                {
                    e.ImageStream = new FileStream(context.Server.MapPath(Config.GetString("BadImage")), FileMode.Open);
                }
            }
        }

        Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
        {
            Bitmap result = new Bitmap(nWidth, nHeight);
            using (Graphics g = Graphics.FromImage((Image)result))
            {
                g.DrawImage(b, 0, 0, nWidth, nHeight);
                //draw border
                /*
                g.DrawLine(new Pen(Brushes.Black, 2), new Point(0, 0), new Point(0, nHeight));
                g.DrawLine(new Pen(Brushes.Black, 2), new Point(0, nHeight), new Point(nWidth, nHeight));
                g.DrawLine(new Pen(Brushes.Black, 2), new Point(nWidth, nHeight), new Point(nWidth, 0));
                g.DrawLine(new Pen(Brushes.Black, 2), new Point(nWidth, 0), new Point(0, 0));
                */
            }
            return result;
        }
    }

Comments (2) -

Nice program. i have question though, is there a way i can add an image to a template word document , i am new to programming and there is a project i am working on that requires an image logo to be added after selecting the image in a dropdown menu. i am using asp.net and c#. kindly help me out

I know with aspose you can place images similar to what I did here, but I have never done it, sorry.

Add comment