none
how to delete the correct shapes count in the headers/footers RRS feed

  • Question

  • Word 2007
    vb.net

    how do I get the correct count of shapes in my document headers?


    Ive experienced the same issue as this guy here>>>

     http://social.msdn.microsoft.com/Forums/en-AU/isvvba/thread/a514a54a-fc33-4c8b-9e9c-1f179b5e1d46

    However I cant select "All" shapes and delete
    due to other images/shapes contained in header /footer.

    I only want to delete watermarks with alternative text set to a specific name.


    The watermark shapes are inserted into the header.
    the code works fine if there is one watermark in the header.

    However the problem is two or more watermarks exist in the header.

    the first time the code runs the result is it deletes the first set of watermarks.

    when the code is run again it deletes the second set of watermarks.

    is there anyway to delete all specific watermarks on the first run of code

    pls see code


    many thanks

    dd

     

      

    Public Sub DeleteWatermark(ByVal worddoc As WordDocument, ByVal WATERMARK_STATUS As String, ByVal FirstPageWatermark As String, ByVal SecondPageWatermark As String)
    
    
    
    
    
                Dim i As Integer = Nothing
    
                Dim HeaderFooter As Microsoft.Office.Interop.Word.HeaderFooter
    
                Dim oShape As Microsoft.Office.Interop.Word.Shape
    
                Dim vaDocPropertyName As String = Nothing
    
                Dim varDocPropertyValue As String = "True"
    
                Dim WordDocument As MSWord.Range = worddoc.Document.Range
    
                Dim iSecCount As Integer = 0
    
                Dim iHeaderType As Integer = 0
    
    
                'Dim HeaderFooter As Microsoft.Office.Interop.Word.HeaderFooter
    
                'Dim i As Integer = 0
    
                ' Dim WordDocument As MSWord.Range = worddoc.Document.Range
    
    
                Dim oRange As MSWord.Range
    
    
                With WordDocument
    
    
                    For i = 1 To .Sections.Count
    
    
                        For Each HeaderFooter In .Sections(i).Headers
    
    
                            With HeaderFooter
    
    
                                For Each oShape In .Range.ShapeRange
    
    
                                    'if ClearAll button pressed then
    
                                    If WATERMARK_STATUS = "CLEAR" Then
    
                                        If InStr(oShape.AlternativeText, "WATERMARK") > 0 Then oShape.Delete()
                                             ElseIf (InStr(oShape.AlternativeText, FirstPageWatermark) > 0) Or (InStr(oShape.AlternativeText, SecondPageWatermark) > 0) Then
    
                                        oShape.Delete()
    
                                    End If
    
                                Next
                            End With
                        Next
                    Next
                End With
            End Sub
    
    
    
    

     


    • Edited by dd_ Monday, September 26, 2011 4:19 AM
    Monday, September 26, 2011 4:15 AM

Answers

  • hi Cindy

    this is now resolved thanks for your assistance.

    yes ive been worked on the code this afternoon and worked out the issue.

    with the first version of code, the instr variable names were abit "general"

    update - Ive redefined the variable names to check exact names and this works, and deletes the specific watermark.

    ive attached the working code

    many thanks again Cindy

            Public Sub DeleteWatermark(ByVal worddoc As WordDocument, ByVal WATERMARK_STATUS As String, ByVal FirstPageWatermark As String, ByVal SecondPageWatermark As String)
    
                Dim i As Integer = 0
                Dim j As Integer = 0
                Dim shpname As String = Nothing
                Dim HdFt As Microsoft.Office.Interop.Word.HeaderFooter
                Dim WordDocument As MSWord.Range = worddoc.Document.Range
                Dim strFirstPageWatermark As String = FirstPageWatermark & "_CORRS"
                Dim strSecondPageWatermark As String = SecondPageWatermark & "_CORRS"
    
    
    
                    'for each header 
                    With WordDocument
                        For i = 1 To .Sections.Count
                            For Each HdFt In .Sections(i).Headers
                                With HdFt
                                    For j = HdFt.Shapes.Count To 1 Step -1
                                        shpname = .Shapes(j).AlternativeText
    
                                        If WATERMARK_STATUS = "CLEAR" Then
                                            .Shapes(j).Delete()
                                        End If
    
                                        If (shpname = strFirstPageWatermark) Or (shpname = strSecondPageWatermark) Then
                                            .Shapes(j).Delete()
                                        End If
                                    Next j
                                End With
                            Next
                        Next
                    End With
    
    
    end sub
    
    
    


    dd

     

     

    • Marked as answer by Liliane Teng Thursday, October 6, 2011 9:14 AM
    Wednesday, October 5, 2011 5:45 AM

All replies

  • Hi dd

    Shapes in the Header/Footer area are a "delicate" proprosition. They are managed centrally by the document's Headers/Footers, but in order to work with them, you should address them via the specific Header or Footer Range. For example:

    doc.Sections(index).Headers(wdHeaderFooterPrimary).Range.ShapeRange(index)


    Cindy Meister, VSTO/Word MVP
    Monday, September 26, 2011 6:35 AM
    Moderator
  • The following code works for me.

    Sub FindWaterMark()
            
        Dim doc As Word.Document
        Dim scn As Word.Section
        Dim shp As Word.Shape
        Dim hdft As Word.HeaderFooter
        
        Set doc = Word.ActiveDocument
        
        With doc
          For Each scn In .Sections
            For Each hdft In scn.Headers
                For Each shp In hdft.Range.ShapeRange
                    If InStr(1, shp.Name, "WordArt") <> 0 Or InStr(1, shp.Name, "Power") <> 0 Then
                        If shp.TextEffect.Text = "Evaluation Only" Then
                            Debug.Print shp.Name
                        End If
                    End If
                Next shp
            Next hdft
          Next scn
        End With
    
    End Sub
    
    

     


    Kind Regards, Rich ... http://greatcirclelearning.com
    Monday, September 26, 2011 11:33 AM
  • Thanks Cindy.

    Thanks Rich

    I've 2 watermarks in the first page header and 2 watermarks in the primay header.

    so...I used your code to read all the shapes and display a msgbox and the result is reads the correct shapes total and displays their types ie

    2 in first header = 1. Group and 2. WordArt

    2 in primary header = 1. Textbox and 2. WordArt

    if I amend the code and the delete the shape the result is only deletes one watermark shape only for each header.

    If I run the code again to delete the header, it deletes only one watermark shape in each header, resulting in all watermarks removed.

    see code

             With WordDocument
              'With doc
                    For Each scn In .Sections
                        For Each hdft In scn.Headers
                            For Each shp In hdft.Range.ShapeRange
                                If InStr(1, shp.AlternativeText, "CORRS") <> 0 Then
                                    MsgBox(shp.Name & " shp.AlternativeText = " & shp.AlternativeText
                                    'shp.Delete()
                                End If
                            Next shp
                        Next hdft
                    Next scn
               End With
    
    
    
    
    
    


    Is this due to the different types of shapes?

    dd

     see screen captures

    1st screen is doc formatted with 2 watermarks on the each different header

     


    code reads in and displays the following shapes

    • Edited by dd_ Tuesday, September 27, 2011 6:31 AM
    Tuesday, September 27, 2011 6:18 AM
  • Maybe one of the inital deletes is erroring out. Parent/child issue??

    Try putting in at the top of the routine an On Error Resume Next command and then after the shp.Delete command, trap the error with an "If err.Number <> 0 then" and display the err.Description.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Tuesday, September 27, 2011 11:27 AM
  • Hi dd

    I believe the problem is that you're deleting within the For each loop. If you think about it, deleting an object destroys the indexing that's used for looping - you're removing objects from the collection. The Word team, recognizing that many vBA developers won't understand that, have built a "buffer" into the object model for many collections. But there are always a few that get "forgotten" and this seems to be one of those :-)

    There are two approaches to avoid this problem:

    1. For counter = shapes.Count to 1 Step -1

    This loops through the collection from "back to front", so even though members are being deleted, it doesn't destroy the indexing in a way that interferes with what you're doing.

    2. The "politically correct" way is to use For Each and assign the things that need to be deleted to a custom collection or array. After For Each completes, loop the array and delete each object in it. As this is usually more work, even though it's more "correct", I (and many others) tend to use the first approach :-)


    Cindy Meister, VSTO/Word MVP
    Tuesday, September 27, 2011 12:56 PM
    Moderator
  • Hi Cindy,

    I'm LOL ... I must have been brain dead this morning. Of course that was the problem and I do know better.

    Oh well just a little reminder to Think more and type less! :-)


    Kind Regards, Rich ... http://greatcirclelearning.com
    Tuesday, September 27, 2011 3:45 PM
  • Hi Rich

    I recognize that only too well! Just as long as we're around to catch each other's <duh>-moments so that the OPs aren't confused it's not so bad <g>


    Cindy Meister, VSTO/Word MVP
    Tuesday, September 27, 2011 4:32 PM
    Moderator
  • ah yes of course all makes sense now.

    thanks Cindy, thanks Rich

    ive amended my code to add the  "For counter = shapes.Count to 1 Step -1"

    I prefer using this code as its leaner and cleaner. otherwise ill have to write more code.

    when I run the code I get an exception error  "Object reference not set to an instance of an object"

    on line  -  For counter = shapes.Count to 1 Step -1

    im obviously not declaring and instansiating my object althought i dont know how

    pls see updated code

    any ideas?.

     dd

     

                    Dim scn As Microsoft.Office.Interop.Word.Section
                    Dim shps As Microsoft.Office.Interop.Word.Shapes = Nothing
                    Dim hdft As Microsoft.Office.Interop.Word.HeaderFooter
    
                    Dim counter As Integer = 0
    
                    With WordDocument
    
                        For Each scn In .Sections
                            For Each hdft In scn.Headers
    
                                For counter = shps.Count To 1 Step -1
    
                                    If WATERMARK_STATUS = "CLEAR" Then
                                        If InStr(shps(counter).AlternativeText, "CORRS") > 0 Then shps(counter).Delete()
    
                                    ElseIf (InStr(shps(counter).AlternativeText, FirstPageWatermark) > 0) Or (InStr(shps(counter).AlternativeText, SecondPageWatermark) > 0) Then
                                        shps(counter).Delete()
                                    End If
    
                                Next
                            Next hdft
                        Next scn
                    End With
    

     

     

     

    Wednesday, September 28, 2011 1:08 AM
  • Originally, you had

    For Each shp In hdft.Range.ShapeRange

    So you first need to do something like:

    Dim shps as Word.Shapes
    Set shps = hdft.Range.ShapeRange

    Before you use shps.Count in the loop.


    Cindy Meister, VSTO/Word MVP
    Wednesday, September 28, 2011 9:32 AM
    Moderator
  • thanks Cindy

    sorry nope still struggling...with trying to get this code working *shrug* & *sigh*

     

    Thursday, September 29, 2011 6:43 AM
  • Hi dd

    Well, that was definitely missing in the sample code you posted and would account for the error message you showed. You have not initialized a Shapes collection declared in order to do:

    If InStr(shps(counter)

    So if you say "that wasn't it" then please show us the code as it now stands and indicate what error you're getting on which line.


    Cindy Meister, VSTO/Word MVP
    Thursday, September 29, 2011 6:52 AM
    Moderator
  • hi Cindy

    I'm still using the code posted on Wednesday, September 28. the error is mentioned in the post ie exception error  "Object reference not set to an instance of an object"

    dd

     

    on line  -  For counter = shapes.Count to 1 Step -1

    Sunday, October 2, 2011 10:35 PM
  • Hi dd

    If you didn't declare and instantiate a variable shapes, then you cannot use shapes.Count. Make the change I suggested then test that code. If it doesn't work, post that code with the error message you get and indicate which line gives the error.


    Cindy Meister, VSTO/Word MVP
    Monday, October 3, 2011 3:57 AM
    Moderator
  • hi Cindy

    this is my code so far.

    The issue now is its not deleting the specific watermark name . its appears to be deleting any watermark.

    in vba when i step /debug through through the code the correct behaviour occurs and deletes only the specified watermark name.

    in vb.net when I run it the result is deletes random/ multiple watermarks in the header

    any ideas?

    dd

     

                Dim i As Integer = Nothing
                Dim j As Integer = 0
                Dim shpname As String = Nothing
                Dim HdFt As Microsoft.Office.Interop.Word.HeaderFooter
                Dim WordDocument As MSWord.Range = worddoc.Document.Range
    
                'With ActiveDocument
                With WordDocument
                    For i = 1 To .Sections.Count
                        For Each HdFt In .Sections(i).Headers
                            With HdFt
                                For j = HdFt.Shapes.Count To 1 Step -1
                                    shpname = .Shapes(j).AlternativeText
    
                                    If WATERMARK_STATUS = "CLEAR" Then
                                        .Shapes(j).Delete()
                                    ElseIf InStr(shpname, FirstPageWatermark) > 0 Or InStr(shpname, SecondPageWatermark) > 0 Then
                                        .Shapes(j).Delete()
                                    End If
                                Next j
                            End With
                        Next
                    Next
                End With
    



    Wednesday, October 5, 2011 3:37 AM
  • hi Cindy

    this is now resolved thanks for your assistance.

    yes ive been worked on the code this afternoon and worked out the issue.

    with the first version of code, the instr variable names were abit "general"

    update - Ive redefined the variable names to check exact names and this works, and deletes the specific watermark.

    ive attached the working code

    many thanks again Cindy

            Public Sub DeleteWatermark(ByVal worddoc As WordDocument, ByVal WATERMARK_STATUS As String, ByVal FirstPageWatermark As String, ByVal SecondPageWatermark As String)
    
                Dim i As Integer = 0
                Dim j As Integer = 0
                Dim shpname As String = Nothing
                Dim HdFt As Microsoft.Office.Interop.Word.HeaderFooter
                Dim WordDocument As MSWord.Range = worddoc.Document.Range
                Dim strFirstPageWatermark As String = FirstPageWatermark & "_CORRS"
                Dim strSecondPageWatermark As String = SecondPageWatermark & "_CORRS"
    
    
    
                    'for each header 
                    With WordDocument
                        For i = 1 To .Sections.Count
                            For Each HdFt In .Sections(i).Headers
                                With HdFt
                                    For j = HdFt.Shapes.Count To 1 Step -1
                                        shpname = .Shapes(j).AlternativeText
    
                                        If WATERMARK_STATUS = "CLEAR" Then
                                            .Shapes(j).Delete()
                                        End If
    
                                        If (shpname = strFirstPageWatermark) Or (shpname = strSecondPageWatermark) Then
                                            .Shapes(j).Delete()
                                        End If
                                    Next j
                                End With
                            Next
                        Next
                    End With
    
    
    end sub
    
    
    


    dd

     

     

    • Marked as answer by Liliane Teng Thursday, October 6, 2011 9:14 AM
    Wednesday, October 5, 2011 5:45 AM