none
Failed to delete last blank page in C# with VSTO RRS feed

  • Question

  • Hi,

    In the thread, http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/5b684577-f5c1-40c0-8794-baefe12cdb06, I can delete pages with specific bookmark "TO_BE_REMOVED_" on it from a word document.

    However, it always leave me a blank page at the end of the document. I tried to use the following codes to delete the blank page, but it seems no effect, would you share me some advice why this does not work?

        // remove last blank page
        wholeDocRange = theDocument.ActiveWindow.Document.Range(ref missing, ref missing);
        maxPage = (int)wholeDocRange.get_Information(Word.WdInformation.wdNumberOfPagesInDocument);

        object last_page = maxPage;

        theDocument.Application.Selection.GoTo(ref what, ref which, ref last_page, ref missing);
        object page_bkm = @"\Page";
        Word.Range lastpageRange = theDocument.Bookmarks.get_Item(ref page_bkm).Range;
        lastpageRange.Select();

        if (lastpageRange != null)
        {
            if (lastpageRange.Text == null)
            {
                Console.Out.WriteLine("Try to delete the last blank page");
                //theDocument.Bookmarks.get_Item(ref page_bkm).Range.Delete(ref missing, ref missing);
                lastpageRange.Bookmarks.get_Item(ref page_bkm).Range.Delete(ref missing, ref missing);
            }
        }    

     I tried both statements (I am sure either the following statement was executed):

     theDocument.Bookmarks.get_Item(ref page_bkm).Range.Delete(ref missing, ref missing);

     and

     lastpageRange.Bookmarks.get_Item(ref page_bkm).Range.Delete(ref missing, ref missing);

     but still no effect to remove the last blank page.

     Do you have any idea what I did wrongly?

     Thanks,

    Raymond

    Friday, January 30, 2009 10:48 AM

Answers

  • The following method works for me. Internally, Word probably works with the Integer data type (the value for the Enum), which is why this didn't happen when I was testing the other day, on a machine without Visual Studio installed. The Enum Integer values for the WdBreakType and WdSectionStart are probably the same, and VBA didn't care...

            public void ChangeLastSectionBreak_Click(Office.IRibbonControl ctl)  
            {  
                Word.Application app = Globals.ThisAddIn.Application;  
                Word.Document doc = app.ActiveDocument;  
                Word.Section sec = doc.Sections.Last;  
                if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)  
                {  
                    sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;  
                }  
            }  
     

    Cindy Meister, VSTO/Word MVP
    Thursday, February 5, 2009 10:41 AM
    Moderator
  • Hi,

    I update my code to
    Word.Section sec = theDocument.ActiveWindow.Document.Sections.Last;
    if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)
    {
        sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;
    }

    and I am sure that the

    sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;

    was executed, (I used debug mode to check the step)

    but the blank page is still at the end and the "section break (next page)" still exists.

    What should I do now?

    Please help.

    Thanks,
    Raymond
    Friday, February 6, 2009 4:41 AM
  • Raymond Lee chun man said:

    Do the codes successfully remove the section break from my uploaded doc?

    http://www.4shared.com/file/83737982/5d832127/test_result.html
    (This is the result document, 3 pages in it, the last page is blank)


    Hmmm, I see what you mean. It would be interesting to learn the background of this document. I get the feeling it may be damaged, internally...

    In any case, I've modified the code sample to check whether the section type has changed, if it has not, then it deletes the section break (since you said there's no need to worry about formatting carrying forward).

                Word.Application app = Globals.ThisAddIn.Application;  
                Word.Document doc = app.ActiveDocument;  
                Word.Section sec = doc.Sections.Last;  
                if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)  
                {  
                    sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;  
                    if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)  
                    {  
                        Word.Range rng = sec.Range;  
                        object oCollapseStart = Word.WdCollapseDirection.wdCollapseStart;  
                        rng.Collapse(ref oCollapseStart);  
                        object oChar = Word.WdUnits.wdCharacter;  
                        object oNeg1 = -1;  
                        rng.MoveStart(ref oChar, ref oNeg1);  
                        object missing = System.Type.Missing;  
                        rng.Delete(ref missing, ref missing);  
                    }  
                }  
     


    Cindy Meister, VSTO/Word MVP
    Friday, February 6, 2009 7:51 AM
    Moderator

All replies

  • Hi Raymond

    I don't think this can ever be null:

        lastpageRange.Text == null

    Are you sure your code is entering that clause (Console.Out.WriteLine)? The last page of a Word document, even if it appears "empty" will contain a paragraph mark. If the entire range of a page is selected it cannot be null or zero-length. It must contain at least one character, ANSI 13 (a carriage return).

    Sometimes, such a paragraph may be "protected", depending on what the last thing on the preceding page is. Since I have no idea what the documents you're manipulating contain, it's very difficult for me to judge what the problem may be. But here are a couple of examples of things that could create an empty page that you cannot delete directly.

    - The paragraph is formatted with "Page Break Before". This is often used for section or chapter headings. This formatting is "cleaner" than inserting a manual page break to force a new page. Solution: set the PageBreakBefore property to False.

    - Odd/even pages is activated for the document. This will force an additional (empty) page if the document ends on an odd page (the following even page is required).

    - The last paragraph of the preceding page is a special kind of object that is storing additional information in the following paragraph mark, that has been pushed to a new page. This protects that paragraph mark so that the information is not lost. A table can "protect" a following paragraph mark, for example.

    When I hit a situation like this, I work with the document as an end-user. I go to that last page and inspect how it's formatted, what's located around it, and how/whether I can manage to delete that last paragraph mark "by hand". Once I figure it out, I can code those steps.

    Note: In order to actually see this paragraph mark, turn on the display of non-printing characters (the "backwards P" in the toolbar).
    Cindy Meister, VSTO/Word MVP
    Monday, February 2, 2009 11:02 AM
    Moderator
  • Hi,

    I am sure that the "lastpageRange.Text" is null at last page because it printed out
    "Try to delete the last blank page" on screen output.

    I turn on the normal view of the result document and I found there is nothing on the last page
    except an "arrow".

    I think the last page is the result of deleting pages at the end of the document.

    What should I do now? I uploaded the documents to web for your investigation.

    http://www.4shared.com/file/83738188/eb2689d7/test_original.html
    (THis is the original document that is going to have some pages removal)

    http://www.4shared.com/file/83737982/5d832127/test_result.html
    (This is the result document, 3 pages in it, the last page is blank)

    Really thanks for your attention on my case.

    Raymond

    Monday, February 2, 2009 4:51 PM
  • Hi,

    I think the document is not protected, I have checked it, for the original document, it has totally 8 pages,
    the page 3 and page 4 are main content and all other pages (page 1, 2, 5, 6, 7, 8) can be removed.

    After the removal process, do not know why a blank page is appended at the end with page 3 and 4.

    I think there is no special formatting on the document, because I turned on the "normal view"
    on the original document and no special "break" on those pages.

    Please help.

    Thanks,
    Raymond
    Monday, February 2, 2009 4:59 PM
  • Hi Raymond

    OK, I downloaded the result document, then turned on the display of non-printing characters, as I recommended you to do in my last reply. When I look at the end of the second page I see that it has a Section Break (Next Page). This is forcing a following page and thus you cannot delete that page.

    You must either delete this section break (which could cause page layout settings to change), or change it to the section type "Continuous" (which will hopefully maintain all necessary Page Layout settings). Here's a bit of sample code that checks the type of the last section of the document and changes it to "Continuous" if it's of type "Next Page"

    Sub ChangeSectionNextPageToContinuous(doc as Word.Document)
        Dim sec As Word.Section = doc.Sections.Last
        
        If sec.PageSetup.SectionStart = Word.WdBreakType.wdSectionNewPage Then
            sec.PageSetup.SectionStart = Word.WdBreakType.wdSectionContinuous
        End If
    End Sub

    Cindy Meister, VSTO/Word MVP
    Tuesday, February 3, 2009 7:48 AM
    Moderator
  • Hi Cindy,

    Thanks for your quick response. It doesn't matter that it may change the formatting.

    For the codes, Dim sec As Word.Section = doc.Sections.Last,

    does it get the last section page of the document?

    I will try it tonight and let you know the result.

    Thanks,
    Raymond

    Tuesday, February 3, 2009 10:16 AM
  • Hi Raymond

    Yes, doc.Sections.Last gets the last section of the document. That's usually faster than doing something like doc.Sections(doc.Sections.Count).
    Cindy Meister, VSTO/Word MVP
    Tuesday, February 3, 2009 10:42 AM
    Moderator
  • Hi,

    I change your codes to C# :

                        Word.Section sec = theDocument.ActiveWindow.Document.Sections.Last;
                        if (sec.PageSetup.SectionStart == Word.WdBreakType.wdSectionNewPage)
                        {
                            sec.PageSetup.SectionStart = Word.WdBreakType.wdSectionContinuous;
                        }                   

    But there is no "wdSectionNewPage" and "wdSectionContinuous", so I change it to

                       if (sec.PageSetup.SectionStart == Word.WdBreakType.wdSectionBreakNextPage )
                        {
                            sec.PageSetup.SectionStart = Word.WdBreakType.wdSectionBreakContinuous;
                        }   

    Then C# complains another errors:

    Error    4    Operator '==' cannot be applied to operands of type 'Microsoft.Office.Interop.Word.WdSectionStart' and 'Microsoft.Office.Interop.Word.WdBreakType'    C:\MyWorks\AutomateWordTest2\AutomateWordTest2\Word2003.cs    459    25    AutomateWordTest2

    Error    5    Cannot implicitly convert type 'Microsoft.Office.Interop.Word.WdBreakType' to 'Microsoft.Office.Interop.Word.WdSectionStart'. An explicit conversion exists (are you missing a cast?)    C:\MyWorks\AutomateWordTest2\AutomateWordTest2\Word2003.cs    461    54    AutomateWordTest2

    It seems because of invalid property matching.

    Would you kindly help to check it? I have tried to find what property values are available for
    PageSetup.SectionStart, but the online documentation is not really helpful (Not like the MSDN
    documents for C#, which states what property values are defined for a field)

    Please help.

    Thanks,
    Raymond
    Tuesday, February 3, 2009 10:54 AM
  • The following method works for me. Internally, Word probably works with the Integer data type (the value for the Enum), which is why this didn't happen when I was testing the other day, on a machine without Visual Studio installed. The Enum Integer values for the WdBreakType and WdSectionStart are probably the same, and VBA didn't care...

            public void ChangeLastSectionBreak_Click(Office.IRibbonControl ctl)  
            {  
                Word.Application app = Globals.ThisAddIn.Application;  
                Word.Document doc = app.ActiveDocument;  
                Word.Section sec = doc.Sections.Last;  
                if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)  
                {  
                    sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;  
                }  
            }  
     

    Cindy Meister, VSTO/Word MVP
    Thursday, February 5, 2009 10:41 AM
    Moderator
  • Hi,

    Are you using VS2005 with VSTO for your codes?

    Raymond
    Thursday, February 5, 2009 2:12 PM
  • VSTO 2008, but that should make absolutely no difference. The object model in Word has not changed in this regard for over ten years. The version of Visual Studio / VSTO makes absolutely no difference.

    FWIW, my test environment was a VSTO add-in.
    Cindy Meister, VSTO/Word MVP
    Thursday, February 5, 2009 4:28 PM
    Moderator
  • Hi,

    I update my code to
    Word.Section sec = theDocument.ActiveWindow.Document.Sections.Last;
    if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)
    {
        sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;
    }

    and I am sure that the

    sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;

    was executed, (I used debug mode to check the step)

    but the blank page is still at the end and the "section break (next page)" still exists.

    What should I do now?

    Please help.

    Thanks,
    Raymond
    Friday, February 6, 2009 4:41 AM
  • Hi  Meister,

    Do the codes successfully remove the section break from my uploaded doc?

    http://www.4shared.com/file/83737982/5d832127/test_result.html
    (This is the result document, 3 pages in it, the last page is blank)

    Thanks,
    Raymond
    Friday, February 6, 2009 6:08 AM
  • Raymond Lee chun man said:

    Do the codes successfully remove the section break from my uploaded doc?

    http://www.4shared.com/file/83737982/5d832127/test_result.html
    (This is the result document, 3 pages in it, the last page is blank)


    Hmmm, I see what you mean. It would be interesting to learn the background of this document. I get the feeling it may be damaged, internally...

    In any case, I've modified the code sample to check whether the section type has changed, if it has not, then it deletes the section break (since you said there's no need to worry about formatting carrying forward).

                Word.Application app = Globals.ThisAddIn.Application;  
                Word.Document doc = app.ActiveDocument;  
                Word.Section sec = doc.Sections.Last;  
                if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)  
                {  
                    sec.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionContinuous;  
                    if (sec.PageSetup.SectionStart == Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage)  
                    {  
                        Word.Range rng = sec.Range;  
                        object oCollapseStart = Word.WdCollapseDirection.wdCollapseStart;  
                        rng.Collapse(ref oCollapseStart);  
                        object oChar = Word.WdUnits.wdCharacter;  
                        object oNeg1 = -1;  
                        rng.MoveStart(ref oChar, ref oNeg1);  
                        object missing = System.Type.Missing;  
                        rng.Delete(ref missing, ref missing);  
                    }  
                }  
     


    Cindy Meister, VSTO/Word MVP
    Friday, February 6, 2009 7:51 AM
    Moderator
  • It works like a magic. Thank you, MVP.

    By the way, where can I learn more about the object model in Word in VSTO? I think starting with
    MSDN documentation is an effective way to learn it at the beginning. Where can I get some codings
    examples for using WORD object model to do formatting on a document.

    Thanks a lot.
    Raymond
    Friday, February 6, 2009 10:09 AM
  • Raymond Lee chun man said:

    It works like a magic. Thank you, MVP.

    By the way, where can I learn more about the object model in Word in VSTO? I think starting with
    MSDN documentation is an effective way to learn it at the beginning. Where can I get some codings
    examples for using WORD object model to do formatting on a document.



    I'm glad we finally got this problem solved :-)

    There really isn't a lot of VSTO-specific information about the Word object model. VSTO extends only a minute fraction of Word's capabilities. Everything else (such as all of our discussions) revolves around Word's native object model, that everyone can use (classic VB, VBA, Delphi, C++, etc.) This means that anything you find can usually be "translated" to be used with C# (and VSTO).

    Formatting is potentially a huge and very complex topic, depending on what you want to achieve. Unless the documents you're generating are one-off, throw-away, it pays big dividends to thoroughly analyze the result you require, then work out how to best achieve that with the tools Word offers. If you have little to no experience with Word, this means you should engage a Word specialist. For "free support", this would mean the Word newsgroups (links in the forum's Please Read First message). Most code samples you get there will be classic VB(A), but with the aid of the object model Help files one can usually convert these to C# - and the more you do it, the easier it gets :-)

    there is some information in this forum, with a few code samples. I've typed quite a few messages that go into detail about working with headers/footers and styles, for example. I don't pretend to be an expert on numbering, however :-)

    As far as Word object model and C# goes, the only resource I know about is in German...

    Cindy Meister, VSTO/Word MVP
    Friday, February 6, 2009 8:13 PM
    Moderator
  • Forgot to say thank you to your help.

    THanks a lot.

    Raymond
    Thursday, July 30, 2009 9:57 AM
  • You're welcome :-)
    Cindy Meister, VSTO/Word MVP
    Thursday, July 30, 2009 10:55 AM
    Moderator
  • Hi guys, I found this code on the internet and I adapted to my problem, when it generates the final document, always has an empty page at the end of the document. If anyone can help, thanks.

    using System;
    using System.Data;
    using System.Configuration;
    using System.IO;
    using MyWord = Microsoft.Office.Interop.Word;
    using Microsoft.Office.Core;
    
    namespace WordCreate
    {
        public class MsWord
        {
            /// <summary>
            /// This is the default Word Document Template file
            /// </summary>
            private const string defaultWordDocumentTemplate = @"Normal.dot";
    
            /// <summary>
            /// A function that merges Microsoft Word Documents that uses the default template
            /// </summary>
            /// <param name="filesToMerge">An array of files that we want to merge</param>
            /// <param name="outputFilename">The filename of the merged document</param>
            /// <param name="insertPageBreaks">Set to true if you want to have page breaks inserted after each document</param>
            public void Merge(string[] filesToMerge, string outputFilename, bool insertPageBreaks)
            {
                Merge(filesToMerge, outputFilename, insertPageBreaks, defaultWordDocumentTemplate);
            }
    
            /// <summary>
            /// A function that merges Microsoft Word Documents that uses a template specified by the user
            /// </summary>
            /// <param name="filesToMerge">An array of files that we want to merge</param>
            /// <param name="outputFilename">The filename of the merged document</param>
            /// <param name="insertPageBreaks">Set to true if you want to have page breaks inserted after each document</param>
            /// <param name="documentTemplate">The word document you want to use to serve as the template</param>
            public static void Merge(string[] filesToMerge, string outputFilename, bool insertPageBreaks, string documentTemplate)
            {
                object defaultTemplate = documentTemplate;
                object missing = System.Type.Missing;
                object pageBreak = MyWord.WdBreakType.wdPageBreak;
                object sectionBreak = MyWord.WdBreakType.wdSectionBreakNextPage;
                object outputFile = outputFilename;
    
                // Create  a new Word application
                MyWord._Application wordApplication = new MyWord.Application();
    
                try
                {
                    // Create a new file based on our template
                    MyWord._Document wordDocument = wordApplication.Documents.Add(
                                                  ref defaultTemplate
                                                , ref missing
                                                , ref missing
                                                , ref missing);
    
                    // Make a Word selection object.
                    MyWord.Selection selection = wordApplication.Selection;
    
                    // Loop thru each of the Word documents
                    foreach (string file in filesToMerge)
                    {
                        // Insert the files to our template
                        selection.InsertFile(
                                                    file
                                                , ref missing
                                                , ref missing
                                                , ref missing
                                                , ref missing);
    
                        //Do we want page breaks added after each documents?
                        if (insertPageBreaks)
                        {
                            selection.InsertBreak(ref sectionBreak);
                            wordDocument.PageSetup.Orientation = MyWord.WdOrientation.wdOrientLandscape;
                            //selection.InsertBreak(ref pageBreak);
                            
                        }
                    }
    
                    // Save the document to it's output file.
                    wordDocument.SaveAs(
                                    ref outputFile
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing
                                , ref missing);
    
                    // Clean up!
                    wordDocument = null;
                }
                catch (Exception ex)
                {
                    //I didn't include a default error handler so i'm just throwing the error
                    throw ex;
                }
    
                finally
                {
                    // Finally, Close our Word application
                    wordApplication.Quit(ref missing, ref missing, ref missing);
                }
            }
        }
    }


    Thursday, August 27, 2009 1:14 PM
  • Hi Dezaum,

    Just read back the threads and found you replied my question.

    Really thanks for your effort.

    Raymond

    Thursday, May 5, 2011 4:16 PM
  • Hi Raymond/Cindy,

        Even im facing a similar kind of a issue.Im populating a word document with some data from database and converting it to PDF dynamically.

    But it adds spaces in to few pages in the pdf,Can u help me how can i check blank pages in word document before converting it to pd.

    Along with this i have another problem, while inserting images into the word document dynamically .i need to change the orientation of that particular page where the image is getting insertied to either landscape or potrait.

    Im using VS2010.

    Friday, July 26, 2013 8:00 AM