none
Word 2007 Addin to add Watermark image RRS feed

  • Question

  • I have already asked a question attempting to troubleshoot my existing code as posted here:

    https://social.msdn.microsoft.com/Forums/office/en-US/a848f926-fa9f-4664-950f-15a0782745a3/vsto-word-2007-addin-watermark-not-working-correctly?forum=worddev

    but, I am now willing to step back and simply ask the question...How would you create a Word 2007 Addin that adds a watermark image.  I have tried so many things that I dont even know what I havent tried anymore.  I am thinking but starting fresh perhaps someone can help me get to the end result I am looking for.  I can add images to the doc but they are not watermarked to allow text to by typed over the image.  When I attempt to add the image to the wdheaderfooterprimary all goes hay wire, so....

    How would you do this?

    Thanks a bunch!

    Monday, January 5, 2015 4:35 PM

Answers

  • Hi Voyagr12,

    To add watermark picture into the Word2007 document, you can check this code snippet, it works fine for me:

    private void btnAddWartermark_Click(object sender, RibbonControlEventArgs e)
            {
                Application app = Globals.ThisAddIn.Application;
                Document doc = Globals.ThisAddIn.Application.ActiveDocument;
                object missingValue = Missing.Value;
                string watermarkPath = @"C:\test.jpg";
                object linkToFile = false;
                object saveWithDocument = true;
                WdHeaderFooterIndex hfIndex = WdHeaderFooterIndex.wdHeaderFooterPrimary;
                HeaderFooter headerFooter;
    
                for (int i = 1; i < doc.Sections.Count + 1; i++)
                {
    
                    if (doc.Sections[i].Headers != null)
                    {
                        headerFooter = doc.Sections[i].Headers[hfIndex];
                    }
                    else if (doc.Sections[i].Footers != null)
                    {
                        headerFooter = doc.Sections[i].Footers[hfIndex];
                    }
                    else
                    {
                        headerFooter = null;
                    }
    
                    if (headerFooter != null)
                    {
                        //Shape watermarkShape;
                        //watermarkShape = headerFooter.Shapes.AddPicture(watermarkPath,
                        //    ref linkToFile, ref saveWithDocument, ref refmissing, ref refmissing,
                        //    ref refmissing, ref refmissing, ref refmissing);
                        //watermarkShape.Left = Convert.ToSingle(WdShapePosition.wdShapeLeft);
                        //watermarkShape.Top = Convert.ToSingle(WdShapePosition.wdShapeCenter);
                        object headerfooterRange = headerFooter.Range;
                        Shape shape = doc.InlineShapes.AddPicture(watermarkPath, ref linkToFile, ref saveWithDocument, ref headerfooterRange).ConvertToShape();
                        shape.Left = Convert.ToSingle(WdShapePosition.wdShapeLeft);
                        shape.Top = Convert.ToSingle(WdShapePosition.wdShapeCenter);
                    }
                }
    
                app.ActiveWindow.View.SeekView = WdSeekView.wdSeekMainDocument;
                app.ActiveWindow.ActivePane.View.Type = Microsoft.Office.Interop.Word.WdViewType.wdPrintView;
    
            }

    It's in C#, if you want VB.NET code, just use some tools to translate it, or translate it by youself.

    For how to delete the watermark, take a look at this thread:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/eb24e114-42c3-4f23-9f0e-09767e88e08f/word-interop-errors-attempted-to-read-or-write-protected-memory-when-trying-to-delete-shape-from?forum=vsto


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, January 7, 2015 8:58 AM
    Moderator
  • Hi Starain,

    I was able to get it to work in both 2007 and 2010 by checking the current version of Word and using the code that works for that version.  I did indeed have an additional test user note the lag as well and I saw the lag both on my a dev machine and an additional VM I powered up.  It seems to be a reported issue with the lag in typing so I have written it off as a bug to simply 'deal with'.  I have seen solutions from using a different Document view, to compressing the image, etc.

    Thanks,

    Tuesday, January 13, 2015 11:25 AM

All replies

  • I have developed an addin that works perfectly in Word 2010.  However, when using with 2007 it does not.

    The addin adds a watermark image to the first page of the document.  When the button is clicked again, it removes the watermark image.  (in Word 2010).

    The first time I click the button to insert the watermark which uses this code:

                        For Each section As Word.Section In oDoc.Sections
                            Try
                                Dim nshape As Word.Shape = section.Headers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Shapes.AddPicture(strWatermarkFile, True, True)
                                nshape.Name = "WordPictureWatermark"
    
                            Catch ex As Exception
    
                            End Try
                        Next

    I get this error...

    Error HRESULT E_FAIL has been returned from a call to a COM component.

    However, the second press of the button, it will insert the image successfully and not produce the error.

    Then, when the button is pressed again, it is suppose to remove the image using this code:

                For i = 1 To oDoc.Sections.Count
                    For Each hdft As Word.HeaderFooter In oDoc.Sections(i).Headers
                        With hdft
                            For j = hdft.Shapes.Count To 1 Step -1
                                If Mid(hdft.Shapes(j).Name, 1, 20) = "WordPictureWatermark" Then
                                    Try
                                        .Shapes(j).Delete()
                                    Catch ex As Exception
    
                                    End Try
                                End If
                            Next
                        End With
                    Next
                Next
    

    but it get hung up on ".shapes(j).delete()" with the following error:

    Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    Does anyone have any ideas?  Again, this works in Word 2010 perfectly?

    THanks!


    Saturday, January 3, 2015 1:55 AM
  • Hello,

    > I get this error...

    Error HRESULT E_FAIL has been returned from a call to a COM component.

    What method exactly fires the exception? Did you try to run the code under the debugger?

    I'd suggest breaking the chain of calls and declare each property and method call on a separate line of code. Thus, you will be able to find the problematic call.

    Sunday, January 4, 2015 3:59 PM
  • This is the line:

    Dim nshape As Word.Shape = section.Headers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Shapes.AddPicture(strWatermarkFile, True, True)

    Sorry, I had forgotten to include exactly what line.

    I am not sure what you mean by "Breaking the chain of calls and declare each property and method call..."

    Thanks for the help so far!

    Sunday, January 4, 2015 4:03 PM
  • I see multiple property and method calls on that line. What property or method exactly throws an exception?
    Sunday, January 4, 2015 4:07 PM
  • I guess I am not sure how to break it apart. :)  ?  But looking into it.
    Sunday, January 4, 2015 4:30 PM
  • So I took that line and broke into this:

    Dim HF As Word.HeaderFooter = section.Headers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary)
    
    Dim nshape As Word.Shape = HF.Shapes.AddPicture(strWatermarkFile, True, True)

    and it fails on the second line with the error 

    Error HRESULT E_FAIL has been returned from a call to a COM component.

    Sunday, January 4, 2015 4:36 PM
  • It is really odd that the second time through the code will insert the watermark picture without issue.  I get the error on the first press of the button, but the second press will successfully insert.... ?
    Sunday, January 4, 2015 5:17 PM
  • Does anyone have any additional ideas?
    Monday, January 5, 2015 3:26 PM
  • I am still looking for a solution.... :)
    Wednesday, January 7, 2015 2:03 AM
  • do you have complete code sample? i want to test it for you.
    Wednesday, January 7, 2015 7:09 AM
  • Hi Voyagr12,

    To add watermark picture into the Word2007 document, you can check this code snippet, it works fine for me:

    private void btnAddWartermark_Click(object sender, RibbonControlEventArgs e)
            {
                Application app = Globals.ThisAddIn.Application;
                Document doc = Globals.ThisAddIn.Application.ActiveDocument;
                object missingValue = Missing.Value;
                string watermarkPath = @"C:\test.jpg";
                object linkToFile = false;
                object saveWithDocument = true;
                WdHeaderFooterIndex hfIndex = WdHeaderFooterIndex.wdHeaderFooterPrimary;
                HeaderFooter headerFooter;
    
                for (int i = 1; i < doc.Sections.Count + 1; i++)
                {
    
                    if (doc.Sections[i].Headers != null)
                    {
                        headerFooter = doc.Sections[i].Headers[hfIndex];
                    }
                    else if (doc.Sections[i].Footers != null)
                    {
                        headerFooter = doc.Sections[i].Footers[hfIndex];
                    }
                    else
                    {
                        headerFooter = null;
                    }
    
                    if (headerFooter != null)
                    {
                        //Shape watermarkShape;
                        //watermarkShape = headerFooter.Shapes.AddPicture(watermarkPath,
                        //    ref linkToFile, ref saveWithDocument, ref refmissing, ref refmissing,
                        //    ref refmissing, ref refmissing, ref refmissing);
                        //watermarkShape.Left = Convert.ToSingle(WdShapePosition.wdShapeLeft);
                        //watermarkShape.Top = Convert.ToSingle(WdShapePosition.wdShapeCenter);
                        object headerfooterRange = headerFooter.Range;
                        Shape shape = doc.InlineShapes.AddPicture(watermarkPath, ref linkToFile, ref saveWithDocument, ref headerfooterRange).ConvertToShape();
                        shape.Left = Convert.ToSingle(WdShapePosition.wdShapeLeft);
                        shape.Top = Convert.ToSingle(WdShapePosition.wdShapeCenter);
                    }
                }
    
                app.ActiveWindow.View.SeekView = WdSeekView.wdSeekMainDocument;
                app.ActiveWindow.ActivePane.View.Type = Microsoft.Office.Interop.Word.WdViewType.wdPrintView;
    
            }

    It's in C#, if you want VB.NET code, just use some tools to translate it, or translate it by youself.

    For how to delete the watermark, take a look at this thread:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/eb24e114-42c3-4f23-9f0e-09767e88e08f/word-interop-errors-attempted-to-read-or-write-protected-memory-when-trying-to-delete-shape-from?forum=vsto


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, January 7, 2015 8:58 AM
    Moderator
  • Hi Caillen!

    Thanks so much for your assistance!  This worked perfectly!  Except that is slows Word down to a crawl.  Typing is extremely laggy now when the image is inserted.  Any ideas on that?

    I also needed to add a few lines to get the watermark sized properly within the page as shown below in vb.net:    

        Public Shared Function AddWatermark(strType As String) As Boolean
            Dim app As Application = Globals.ThisAddIn.Application
            Dim doc As Document = Globals.ThisAddIn.Application.ActiveDocument
            Dim missingValue As Object = Missing.Value
            'Dim watermarkPath As String = "C:\test.jpg"
            Dim linkToFile As Object = False
            Dim saveWithDocument As Object = True
            Dim hfIndex As WdHeaderFooterIndex = WdHeaderFooterIndex.wdHeaderFooterPrimary
            Dim headerFooter As HeaderFooter
            Dim strWatermarkFile As String
    
            blWatermarkPresent = False
    
            If RemoveExistingWaterMark() Then
                If blWatermarkPresent = False Then
                    strWatermarkFile = GetWatermarkFile(strType)
                    If File.Exists(strWatermarkFile) Then
    
    
                        For i As Integer = 1 To doc.Sections.Count
    
                            If doc.Sections(i).Headers IsNot Nothing Then
                                headerFooter = doc.Sections(i).Headers(hfIndex)
                            ElseIf doc.Sections(i).Footers IsNot Nothing Then
                                headerFooter = doc.Sections(i).Footers(hfIndex)
                            Else
                                headerFooter = Nothing
                            End If
    
                            If headerFooter IsNot Nothing Then
                                'Shape watermarkShape;
                                'watermarkShape = headerFooter.Shapes.AddPicture(watermarkPath,
                                '    ref linkToFile, ref saveWithDocument, ref refmissing, ref refmissing,
                                '    ref refmissing, ref refmissing, ref refmissing);
                                'watermarkShape.Left = Convert.ToSingle(WdShapePosition.wdShapeLeft);
                                'watermarkShape.Top = Convert.ToSingle(WdShapePosition.wdShapeCenter);
                                Dim headerfooterRange As Object = headerFooter.Range
                                Dim shape As Shape = doc.InlineShapes.AddPicture(strWatermarkFile, linkToFile, saveWithDocument, headerfooterRange).ConvertToShape()
    
                                'shape.Left = Convert.ToSingle(WdShapePosition.wdShapeLeft)
                                'shape.Top = Convert.ToSingle(WdShapePosition.wdShapeCenter)
    
                                shape.LockAspectRatio = Microsoft.Office.Core.MsoTriState.msoTrue
                                shape.WrapFormat.AllowOverlap = -1
                                'shape.WrapFormat.Side = WdWrapSideType.wdWrapBoth
                                'shape.WrapFormat.Type = WdWrapType.wdWrapBehind
    
                                shape.RelativeHorizontalPosition = WdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin
                                shape.Left = WdShapePosition.wdShapeCenter
                                shape.ScaleHeight(1, Microsoft.Office.Core.MsoTriState.msoTrue)
    
                                shape.RelativeVerticalPosition = WdRelativeVerticalPosition.wdRelativeVerticalPositionMargin
                                shape.Top = WdShapePosition.wdShapeCenter
                                shape.ScaleWidth(1, Microsoft.Office.Core.MsoTriState.msoTrue)
    
                            End If
                        Next
    
                        app.ActiveWindow.View.SeekView = WdSeekView.wdSeekMainDocument
                        app.ActiveWindow.ActivePane.View.Type = Microsoft.Office.Interop.Word.WdViewType.wdPrintView
                    Else
                        MsgBox("Unable to locate the watermark.", MsgBoxStyle.Exclamation, "Unable to locate Watermark")
                    End If
    
                End If
    
            End If
        End Function



     
    • Edited by Voyagr12 Wednesday, January 7, 2015 12:13 PM
    Wednesday, January 7, 2015 12:13 PM
  • Since Office 2007 there has been what many of us consider a "bug" in how Watermarks operate. This effects all versions since, but you say your code works correctly in 2010 so I'm surprised.

    What happens is that Word deletes all Watermarks when a new one is added to Section 1 of the document. The developers claim this is by design so that two watermarks cannot be accidentally inserted. Whether I personally believe them is a whole other story...

    This "delete other watermarks" is supposedly controlled by the watermark name so the way around this is to build your own custom shape, set its opacity at about 40% and insert it into each section header. I would also suggest that you give the shape a custom tag name and during your delete loop you check for a match on the shape tag name.

    Hope this helps


    Kind Regards, Rich ... http://greatcirclelearning.com

    Wednesday, January 7, 2015 12:25 PM
  • In addition to the last post, delete will not work.  I get the "Attempted to read or write protected memory..." error.  I followed the example by Helmut Obertanner in your link.  Here is my delete code following that example:

                For i = 1 To oDoc.Sections.Count
                    For Each hdft As Word.HeaderFooter In oDoc.Sections(i).Headers
                        Dim headerstoDelete As New List(Of Word.Shape)
                        For Each shape As Word.Shape In hdft.Shapes
                            If InStr(shape.Name, "WordPictureWatermark") > 0 Then
                                headerstoDelete.Add(shape)
                            End If
                        Next
                        For Each shape As Word.Shape In headerstoDelete
                            shape.Delete()
                        Next
                    Next
                Next

    Wednesday, January 7, 2015 12:27 PM
  • HI Rich,

    Thanks for the response!  I am not sure how I would go about creating my own 'custom shape'.  I actually got some code to work but still having issues with the delete...

    Thanks for the assistance so far!

    Wednesday, January 7, 2015 12:37 PM
  • To add yet another note to this...it appears this does not work properly in Word 2010...the code does not resize the image properly as it had in 2007....oh my...what a mess I have.  I guess I will need to use both sets of code I have...one for 2010 and one for 2007????  

    Thanks,

    Wednesday, January 7, 2015 12:55 PM
  • Here's VBA code I use in my Mac Office applications. On the PC I use VB.Net so it looks a bit different but the same principles apply.

    Function SetWatermarks(ByRef doc As Word.Document)
        Dim scn As Word.Section, hdft As Word.HeaderFooter, shp As Word.Shape
        Dim rng As Word.Range
        Dim sMark As String
        sMark = "Evaluation Only"
        
        On Error Resume Next
        With doc
            For Each scn In .Sections
                For Each hdft In scn.Headers
                    If hdft.index = wdHeaderFooterEvenPages Or _
                        hdft.index = wdHeaderFooterFirstPage Or _
                        hdft.index = wdHeaderFooterPrimary Then
                            If hdft.Shapes.Count > 0 Then
                                For Each shp In hdft.Shapes
                                    If shp.Type = msoTextEffect Then
                                        If shp.TextEffect.Text = sMark Then shp.Delete
                                    End If
                                Next
                            End If
                    End If
                Next
            Next
        End With
    
        With doc
            Set rng = doc.Content
            For Each scn In rng.Sections
                For Each hdft In scn.Headers
                    If hdft.index = wdHeaderFooterEvenPages Or _
                        hdft.index = wdHeaderFooterFirstPage Or _
                        hdft.index = wdHeaderFooterPrimary Then
                            hdft.Range.Select
                            Set shp = hdft.Shapes.AddTextEffect(msoTextEffect2, sMark, "Tahoma", 10, False, False, 0, 0)
                            With shp
                                .Line.Visible = False
                                With .TextEffect
                                    .NormalizedHeight = False
                                    .FontItalic = False
                                    .FontBold = True
                                End With
                                With .Fill
                                    .Visible = True
                                    .Solid
                                    .ForeColor.RGB = 12632256
                                    .Transparency = 0.5
                                End With
                                .Rotation = 315
                                .LockAspectRatio = True
                                .Height = Word.InchesToPoints(1.96)
                                .Width = Word.InchesToPoints(7.2)
                                With .WrapFormat
                                    .AllowOverlap = True
                                    .Side = Word.WdWrapSideType.wdWrapBoth
                                    .Type = 3
                                End With
                                .RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin
                                .RelativeVerticalPosition = Word.WdRelativeVerticalPosition.wdRelativeVerticalPositionMargin
                                .Left = Word.WdShapePosition.wdShapeCenter
                                .Top = Word.WdShapePosition.wdShapeCenter
                            End With
                            hdft.Range.Collapse (Word.WdCollapseDirection.wdCollapseEnd)
                    End If
                Next hdft
            Next scn
        End With
        rng.Select
        Selection.Collapse Word.WdCollapseDirection.wdCollapseStart
    End Function
    

    Note that an "On Error Resume Next" command is used because if the shape does not exist then the delete would fail. This is hold over code that was there before I started making my named shape. I mention it because that might be what your issue is because as I said in an earlier post, Word deletes all watermarks (named with its default names) when you add the first one to Section 1.

    Also note that I am using a shape that is a text shape (WordArt would be a text shape) so that's what you might use as well.

    Hope this helps


    Kind Regards, Rich ... http://greatcirclelearning.com

    Wednesday, January 7, 2015 1:45 PM
  • Hi Rich,

    I am actually adding images.  I was able to add text without issues in my attempts.  The images are causing me headaches. :)

    Wednesday, January 7, 2015 1:53 PM
  • Hi Voyagr12,

    Base on my test with your code in office 2007, it works fine and it won’t affect the performance (e.g. typing is smooth)

    It can resize the image, if I change 1 to 0.5. (shape.ScaleHeight(0.5,…..)

    Could you reproduce that issue in another machine? Please share a simple project that could reproduce that issue on the OneDrive, we will check it.

    Regards

    Starain


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, January 13, 2015 7:31 AM
    Moderator
  • Hi Starain,

    I was able to get it to work in both 2007 and 2010 by checking the current version of Word and using the code that works for that version.  I did indeed have an additional test user note the lag as well and I saw the lag both on my a dev machine and an additional VM I powered up.  It seems to be a reported issue with the lag in typing so I have written it off as a bug to simply 'deal with'.  I have seen solutions from using a different Document view, to compressing the image, etc.

    Thanks,

    Tuesday, January 13, 2015 11:25 AM