What about ReplaceTextWithImage!?

Jul 13, 2011 at 8:48 PM

Hi Cathal,

It would be possible to instead of replace the text with another text, replace the text with a image!?

This would be useful if you need to insert a different barcode image for each document.

Thanks a lot,

Bruno

Oct 5, 2011 at 7:12 PM

Yes please - that'd be fantastic!

Oct 5, 2011 at 7:19 PM

Hi,

I extended the DOCX library to support this...

My code:

#region static class DocXEx
  /// <summary>
  /// 
  /// </summary>
  public static class DocXEx
  {
    #region static void ReplaceTextWithImage(this DocX document, string value, Bitmap image, int count)
    /// <summary>
    /// Replaces a text with a image
    /// </summary>
    /// <param name="document">The docx document</param>
    /// <param name="value">The text to be replaced</param>
    /// <param name="image">The image to replace</param>
    /// <param name="count">How many times it should replace</param>
    public static void ReplaceTextWithImage(this DocX document, string value, Bitmap image, int count)
    {
      var imageStream = image.ToStream();
      try
      {
        var docImage = document.AddImage(imageStream);
        var docPicture = docImage.CreatePicture();

        var countReplace = 0;
        foreach (var paragraph in document.Paragraphs)
        {
          var valuesIndex = paragraph.FindAll(value);
          if (valuesIndex.Count > 0)
          {
            if (count > 0)
            {
              if (valuesIndex.Count > count)
              {
                valuesIndex.RemoveRange(count, valuesIndex.Count - count);
              }
            }
            valuesIndex.Reverse();

            foreach (var valueIndex in valuesIndex)
            {
              countReplace++;
              paragraph.RemoveText(valueIndex, value.Length);
              paragraph.InsertPicture(docPicture, valueIndex);
              if (countReplace == count)
              {
                return;
              }
            }
          }
        }
      }
      finally
      {
        if (image != null)
        {
          image.Dispose();
        }

        if (imageStream != null)
        {
          imageStream.Dispose();
        }
      }
    }
    #endregion
  }
  #endregion
 

Oct 5, 2011 at 7:25 PM
Edited Oct 5, 2011 at 7:25 PM

I tried adding your code but get the following compilation errors:

 

------ Build started: Project: docxTest, Configuration: Debug x86 ------

c:\docxTest\Program.cs(123,37): error CS1061: 'System.Drawing.Bitmap' does not contain a definition for 'ToStream' and no extension method 'ToStream' accepting a first argument of type 'System.Drawing.Bitmap' could be found (are you missing a using directive or an assembly reference?)

c:\docxTest\Program.cs(147,29): error CS1502: The best overloaded method match for 'Novacode.Paragraph.RemoveText(int, bool)' has some invalid arguments

c:\docxTest\Program.cs(147,62): error CS1503: Argument 2: cannot convert from 'int' to 'bool'

c:\docxTest\Program.cs(148,29): error CS1502: The best overloaded method match for 'Novacode.Paragraph.InsertPicture(int, string)' has some invalid arguments

c:\docxTest\Program.cs(148,53): error CS1503: Argument 1: cannot convert from 'Novacode.Picture' to 'int'

c:\docxTest\Program.cs(148,65): error CS1503: Argument 2: cannot convert from 'int' to 'string'

Oct 5, 2011 at 7:43 PM

Ups.. sorry for that.. I extended the Bitmap class too..

About those 'Novacode' errors, are you using the last change set 64267!?

There it goes the extension for Bitmap:

  #region static class BitmapEx
  /// <summary>
  /// 
  /// </summary>
  public static class BitmapEx
  {
    #region static Stream ToStream(this Bitmap bitmap)
    /// <summary>
    /// 
    /// </summary>
    /// <param name="bitmap"></param>
    /// <returns></returns>
    public static Stream ToStream(this Bitmap bitmap)
    {
      var stream = toMemoryStream(bitmap);

      return stream;
    }
    #endregion

    #region static MemoryStream toMemoryStream(Bitmap bitmap)
    /// <summary>
    /// 
    /// </summary>
    /// <param name="bitmap"></param>
    /// <returns></returns>
    private static MemoryStream toMemoryStream(Bitmap bitmap)
    {
      if (bitmap == null)
      {
        throw new ArgumentNullException("bitmap");
      }

      var memoryStream = new MemoryStream();
      bitmap.Save(memoryStream, ImageFormat.Png);
      bitmap.Dispose();

      return memoryStream;
    }
    #endregion
  }
  #endregion

Developer
Oct 5, 2011 at 10:35 PM

brubru can you commit the changes to Cathal so he can include this into his release? Also maybe you could join the project as seem skillful enough ?

Oct 17, 2011 at 3:23 PM

Hi there!

Working with brubru's extended methods I got the following error while runing the code:

var docPicture = docImage.CreatePicture(); //Exception: Parameter not valid

After talking to brubru he instructed me to add the line below into the code. Worked just fine!

        imageStream.Position = 0;       

var docImage = document.AddImage(imageStream);   


By the way, great job with the DocX library Cathal!!
Coordinator
Nov 2, 2011 at 5:50 PM

bru bru,

I would be really happy if you added this feature to the source tree.

If you are interested, can you please contact me?

Kind regards,
Cathal

May 29, 2012 at 3:58 PM

Ok, this might be a bit late. I've just started using DocX. since I'm a VBer (don't hold that against me) this is what I came up with for replacing text with an image file. I used your code above and just changed the streamer. haha

 

    Public Shared Sub ReplaceTextWithImage(ByRef document1 As DocX, ByVal value As String, ByVal image As String, ByVal count As Integer)

        Dim docImage As Novacode.Image = document1.AddImage(image)
        Dim docPicture As Novacode.Picture = docImage.CreatePicture()

        Dim countReplace = 0
        For Each paragraph In document1.Paragraphs
            Dim valuesIndex = paragraph.FindAll(value)
            If valuesIndex.Count > 0 Then
                If count > 0 Then
                    If valuesIndex.Count > count Then
                        valuesIndex.RemoveRange(count, valuesIndex.Count - count)
                    End If
                End If
                valuesIndex.Reverse()

                For Each valueIndex In valuesIndex
                    countReplace += 1
                    paragraph.InsertPicture(docPicture)
                    paragraph.RemoveText(valueIndex, value.Length)
                    If countReplace = count Then
                        Return
                    End If
                Next
            End If
        Next

    End Sub

Jul 20, 2012 at 9:17 PM

This is great stuff, thanks!

 

I noticed one issue, that is when the text being replaced is the entire content of the paragraph.  It seems like once the text is all removed, the paragraph does not show in the document (even after the image is inserted.

 

I was able to work around it like so:

public void ReplaceWithImage(string tagBody, byte[] replacement)
{
    using (var image = new MemoryStream(replacement))
    {
        var img = document.AddImage(image);
        var picture = img.CreatePicture();

        foreach (var paragraph in document.Paragraphs)
        {
            paragraph.FindAll(tagBody).ForEach(index => {
                paragraph.RemoveText(index, tagBody.Length - 1);
                paragraph.InsertPicture(picture, index + 1);
                paragraph.RemoveText(index, 1);
            });
        }
    }
}

Thanks again!

 

Alex

Feb 28, 2013 at 11:25 AM
maybe i'm doing something wrong,
i'm using the following code to get an image from one document, and put it in another document instead of the word "image":
        static void Main(string[] args)
        {
            Bitmap bitmap;
            using (DocX document1 = DocX.Load("ImageSource.docx"))
            {
                Novacode.Image img = document1.Images[0];
                bitmap = new Bitmap(img.GetStream(FileMode.Open, FileAccess.ReadWrite));
            }

            using (DocX document = DocX.Load("TestDocument.docx"))
            {
                document.ReplaceTextWithImage("image", bitmap, 1);
                document.Save();
            }
        }
but for some reason the word is being replaced with nothing and i get an empty document.
just to be clear the file "ImageSource.docx" contains only one picture with nothing else in it and the file "TestDocument.docx" contains only the word "image" and nothing else in it.

your help is much appreciated.
Feb 7, 2014 at 9:39 AM
Edited Feb 7, 2014 at 9:42 AM
Hi :) Thanks for all. I was very handy your examples to solve their problems.
bodgybrothers, your decision inserts the image only in the beginning of the paragraph
brubru, your solution is not always inserted image (I think, if you delete all the text strings)

Solving the above problems. Source code VB.net
    <Extension()>
    Public Sub ReplaceTextWithImage(ByVal document As DocX, value As String, image As Bitmap, count As Integer)
        If image Is Nothing Then Throw New ArgumentNullException("bitmap")

        Using memoryStream = New MemoryStream()
            image.Save(memoryStream, ImageFormat.Png)
            memoryStream.Seek(0, SeekOrigin.Begin)

            Dim docImage As Novacode.Image = document.AddImage(memoryStream)
            Dim docPicture As Novacode.Picture = docImage.CreatePicture()
            Dim countReplace = 0

            For Each paragraph In document.Paragraphs
                Dim valuesIndex = paragraph.FindAll(value)

                If valuesIndex.Count > 0 Then
                    If count > 0 Then
                        If valuesIndex.Count > count Then
                            valuesIndex.RemoveRange(count, valuesIndex.Count - count)
                        End If
                    End If
                    valuesIndex.Reverse()

                    For Each valueIndex In valuesIndex
                        countReplace + = 1
                        paragraph.InsertPicture(docPicture, valueIndex + value.Length)
                        paragraph.RemoveText(valueIndex, value.Length)
                        If countReplace = count Then
                            Return
                        End If
                    Next
                End If
            Next
        End Using
    End Sub
A little later, I will add to the message source code C#
Once again thank you for all your work :)
Mar 28, 2014 at 2:45 PM
Edited Mar 31, 2014 at 2:08 PM
Solving the above problems
Apr 15, 2014 at 5:49 PM
Hi All,

Thanks for the contributions - I needed to implement a markup style way of inserting signature images into documents based upon a template and this has helped enormously. I've had to re-write chekakis's extension above into c# but my initial tests have all been successful.

Can any of the "main" contributors explain simply (or direct me to a link) how to submit source code to the project rather than post it and I'll see if I can start contributing properly?

Thanks,

Paul.

c# version of the above code:
        /// <summary>
        /// Replaces a text with a image
        /// </summary>
        /// <param name="document">The docx document</param>
        /// <param name="tag">The text to be replaced</param>
        /// <param name="image">The image to replace</param>
        /// <param name="count">How many times it should replace</param>
        public static void ReplaceTextWithImage(this DocX document, string value, Bitmap image, int count)
        {       
            if (image == null) 
                throw new ArgumentNullException("Bitmap expected");

            using (MemoryStream memoryStream = new MemoryStream())
            {
                image.Save(memoryStream, ImageFormat.Png);
                memoryStream.Seek(0, SeekOrigin.Begin);

                Novacode.Image docImage = document.AddImage(memoryStream);
                Novacode.Picture docPicture = docImage.CreatePicture();
            
                int countReplace = 0;

                foreach(Paragraph paragraph in document.Paragraphs)
                {
                    List<int> valuesIndex = paragraph.FindAll(value);

                    if (valuesIndex.Count > 0)
                    {
                        if (count > 0) 
                        {
                            if(valuesIndex.Count > count)
                                valuesIndex.RemoveRange(count, valuesIndex.Count - count);
                        }
                        valuesIndex.Reverse();

                        foreach(int valueIndex in valuesIndex)
                        {
                            countReplace += 1;
                            paragraph.InsertPicture(docPicture, valueIndex + value.Length);
                            paragraph.RemoveText(valueIndex, value.Length);
                            if (countReplace == count) 
                                return;                         
                        }
                    }
                }
            }
        }
Oct 29, 2014 at 3:22 PM
Hey guys I'm replacing the text with an image but I can only see the image with Microsoft Office Word.

With LibreOffice I can't see. Do any of you know what might be the problem?
Jan 15, 2015 at 11:27 AM
I have same problem. It only works in LibreOffice if file is first open with MS Word.
Any solution?
Feb 13, 2015 at 4:00 PM
Edited Feb 13, 2015 at 4:01 PM
Hi

this code work fine too:
    /// <summary>
    /// Replace a specific text with Image
    /// </summary>
    /// <param name="template">DocX template file</param>
    /// <param name="textToReplace">bookmark text</param>
    /// <param name="image">FileStream image</param>
    public static void ReplaceTextWithImage(this DocX template, String textToReplace, FileStream image, ReadOnlyCollection<Paragraph> paragraphs = null)
    {
        try
        {
            var docImage = template.AddImage(image);
            var docPicture = docImage.CreatePicture();

            ReadOnlyCollection<Paragraph> docParagraphs;
            if (paragraphs == null)
                docParagraphs = template.Paragraphs;
            else
                docParagraphs = paragraphs;

            foreach (var paragraph in docParagraphs)
            {
                var valuesIndex = paragraph.FindAll(textToReplace);
                if (valuesIndex.Count > 0)
                {
                    foreach (var valueIndex in valuesIndex)
                    {
                        paragraph.InsertPicture(docPicture);
                        paragraph.RemoveText(valueIndex);
                    }
                }
            }

            //var paragraph = template.Paragraphs.FirstOrDefault(e => e.Text == textToReplace);
            //if(paragraph != null)
            //{
            //    paragraph.InsertPicture(docPicture);
            //}
        }
        finally
        {
            if (image != null)
            {
                image.Dispose();
            }
        }
    }