none
How to delete an inline shape so that it gets deleted? RRS feed

  • Question

  • In Word 2016 I have a Word-document that has tables. I want to delete the inline shapes of a given table. Code looks like this:

            private static void DeletePictures(Word.Table targettable)
            {
                Word.InlineShapes shapes = targettable.Range.InlineShapes;
    
                foreach (Word.InlineShape shape in shapes)
                {
                    Debug.Print("Inline shape count: " + targettable.Range.InlineShapes.Count.ToString());
                    if (shape.Type == Word.WdInlineShapeType.wdInlineShapePicture)
                    {
                        shape.Delete();
                    }
                }
            }

    That shape.Delete() works... kind of. It doesn't throw any kind of error which I understand means that the command is successful. However, that Debug.Print prints every time the same number and this results in an infinite loop i.e. there's always the same amount of members in that collection i.e. the shape.Delete() does not work.

    So am I supposed to use something else than Delete? Can I somehow check if the collection is read-only (in which case I'd guess the shape.Delete() would throw an error)?

    Or what am I doing wrong here?


    • Edited by ArtKilp Monday, January 29, 2018 11:40 PM Added version info
    Monday, January 29, 2018 11:40 PM

All replies

  • Hello ArtKilp,

    I note that you would delete the inline shape only once it is wdInlineShapePicture. Are you sure is there any wdInlineShapePicture  inline shapes ? I'm wondering if shape.Deleted() has ever been called.

    If you add a Debug.Print before shape.Delete(), could you see its debug result?

     private static void DeletePictures(Word.Table targettable)
            {
                Word.InlineShapes shapes = targettable.Range.InlineShapes;
    
                foreach (Word.InlineShape shape in shapes)
                {
                    Debug.Print("Inline shape count: " + targettable.Range.InlineShapes.Count.ToString());
                    if (shape.Type == Word.WdInlineShapeType.wdInlineShapePicture)
                    {
                        Debug.Print("An Inlien Shape will be deleted");
                        shape.Delete();
                    }
                }
            }

    Best Regards,

    Terru


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Tuesday, January 30, 2018 2:13 AM
  • Hello ArtKilp,

    I note that you would delete the inline shape only once it is wdInlineShapePicture. Are you sure is there any wdInlineShapePicture  inline shapes ? I'm wondering if shape.Deleted() has ever been called.

    If you add a Debug.Print before shape.Delete(), could you see its debug result?

     private static void DeletePictures(Word.Table targettable)
            {
                Word.InlineShapes shapes = targettable.Range.InlineShapes;
    
                foreach (Word.InlineShape shape in shapes)
                {
                    Debug.Print("Inline shape count: " + targettable.Range.InlineShapes.Count.ToString());
                    if (shape.Type == Word.WdInlineShapeType.wdInlineShapePicture)
                    {
                        Debug.Print("An Inlien Shape will be deleted");
                        shape.Delete();
                    }
                }
            }

    Best Regards,

    Terru


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Thanks for the answer!

    Output:

    Inline shape count: 5
    An Inlien Shape will be deleted
    Inline shape count: 5
    An Inlien Shape will be deleted
    Inline shape count: 5
    An Inlien Shape will be deleted
    Inline shape count: 5
    An Inlien Shape will be deleted


    And so on. So yes, the command is executed, like I wrote in the opening post.


    • Edited by ArtKilp Tuesday, January 30, 2018 8:56 PM
    Tuesday, January 30, 2018 8:55 PM
  • Hello ArtKilp,

    >>this results in an infinite loop

    Infinite loop? Will it cause the loop loop all the time event it looped more times than the shape count? 

    Could you please show us a whole code how you operate the word document? From creating the word application to the end. Besides, will this issue occur while operating on specific document or every document? If it is former, I would suggest you share us a simply document file so we could use it to reproduce your issue.

    Best Regards,

    Terry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, January 31, 2018 7:37 AM
  • Hello ArtKilp,

    >>this results in an infinite loop

    Infinite loop? Will it cause the loop loop all the time event it looped more times than the shape count? 

    Could you please show us a whole code how you operate the word document? From creating the word application to the end. Besides, will this issue occur while operating on specific document or every document? If it is former, I would suggest you share us a simply document file so we could use it to reproduce your issue.

    Best Regards,

    Terry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Yes, it tries to operate on each element, but it gets stuck in the first one. A bit like if you would have a for-loop without the iterator-operation, so instead of working a set of three like 1,2,3, it works like 1,1,1,1,1,...

    Let's see if I can fit the code here. That determining the table is not exactly the simplest code, but I think any table _should_ return the same result. There's no "creating application" since this is an add-in.

            private void btnAddBelow_Click(object sender, RibbonControlEventArgs e)
            {
                AddNewPage.AddNewPageToForm();
            }
    
    class AddNewPage
        {
            internal static void AddNewPageToForm()
            {
                Word.Selection selected = Globals.DocCameraAddIn.Application.Selection;
                Word.Range rng = selected.Range;
    
                Word.Table targettable = SelectCopyPasteTableToNewPage(selected);
               
                if (targettable == null)
                {
                    MessageBox.Show("No table located!");
                    return;
                }
    
                DeletePictures(targettable);
            }
            
            
            private static void DeletePictures(Word.Table targettable)
            {
                Word.InlineShapes shapes = targettable.Range.InlineShapes;
    
                foreach (Word.InlineShape shape in shapes)
                {
                    Debug.Print("Inline shape count: " + targettable.Range.InlineShapes.Count.ToString());
                    if (shape.Type == Word.WdInlineShapeType.wdInlineShapePicture)
                    {
                        Debug.Print("An Inlien Shape will be deleted");
                        shape.Delete();
                    }
                }
            }      
            
    
            internal static Word.Table SelectCopyPasteTableToNewPage(Word.Selection selected)
            {
                Word.Table sourcetable = ParentTable(selected, 1);
                if (sourcetable == null)
                {
                    return null;
                }
    
                sourcetable.Select();
                sourcetable.Range.Copy();
                selected.Move(Word.WdUnits.wdCharacter, 1);
                selected.InsertBreak(Word.WdBreakType.wdPageBreak);
    
                selected.Paste();
    
                if (selected.Tables.Count == 1)
                {
                    //There are more than one table.
                    //Make sure you select the second and only first of them
                    return selected.Tables[1];
                }
                else if (selected.Tables.Count > 1)
                {
                    //There are more than one table.
                    //Make sure you select the second and only first of them
                    return selected.Tables[2];
                }
    
                return null;
            }
    
    
            internal static Word.Table ParentTable(Word.Selection selected, long nestlevel = 0)
            {
                //Pass 1 to return patriarch table, Pass 0 to return immediate parent.
                //Pass numbers greater than 1 to return ancestors other than patriarch of deep nested tables.
    
                Word.Table oTbl = PT(selected, nestlevel);
    
                if (nestlevel > 0)
                {
                    if (oTbl != null)
                    {
                        return oTbl;
                    }
                }
                if (Globals.DocCameraAddIn.Application.Selection.Tables.Count == 0)
                {
                    return null;
                }
    
                return Globals.DocCameraAddIn.Application.Selection.Tables[1];
            }
    
            private static Word.Table PT(Word.Selection selected, long nestlevel = 0)
            {
                try
                {
                    //Pass 1 to return patriarch table, Pass 0 to return immediate parent.
                    //Pass numbers greater than 1 to return ancestors other than patriarch of deep nested tables.
                    Word.Table sourcetable = selected.Tables[1];
                    if (sourcetable == null)
                    {
                        return null;
                    }
    
                    if (nestlevel == 0)
                    {
                        return sourcetable;
                    }
    
                    long nest = sourcetable.NestingLevel;
                    Word.Range range = sourcetable.Range.Cells[sourcetable.Range.Cells.Count].Range;
                    range.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
    
                    if (nest > 1)
                    {
                        nestlevel = nest - 1;
                    }
                    else
                    {
                        nestlevel = 1;
                    }
    
                    while (nest > nestlevel)
                    {
                        do
                        {
                            range.Move(Word.WdUnits.wdCharacter, 1);
                        } while (range.InRange(sourcetable.Range));
    
                        int i = sourcetable.Range.Cells.Count;
                        Word.Range rng2 = range.Tables[1].Range;
                        range = rng2.Cells[rng2.Cells.Count].Range;
    
                        range.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
                        sourcetable = range.Tables[1];
                        nest = sourcetable.NestingLevel;
                    }
    
                    if (nestlevel <= nest)
                    {
                        return range.Tables[1];
                    }
                    return null;
                }
                catch (Exception Ex)
                {
                    Debug.Print(Ex.StackTrace);
                    return null;
                }
            }
        }


    • Edited by ArtKilp Wednesday, January 31, 2018 9:53 PM
    Wednesday, January 31, 2018 9:51 PM