How To Add An Unknown Number of Paragraphs & Tables When Automating Word

Posted on 2008-01-26
Medium Priority
Last Modified: 2013-12-17
I am trying to change a working Word automation  subroutine to allow a variable number of paragraphs and tables and have run into some difficulty. I had hoped to be able to define the range, paragraph and table objects as arrays and then define them as part of the Word document as I looped through the data. The problem is that some of the items are members of  System.Array so that approach will not work. I would like suggestions on how to address a variable number of paragraphs and tables when automating Word. My several E-E searches have been unsuccessful.
Public Sub WordPrintTWSampleSize(ByVal gNbrCategories As Short)
            Dim oWord As Object
            Dim oDoc As Object
            Dim oPara1 As Object
            Dim oPara2 As Object
            Dim oRng() As Object
            Dim DateTime As Date
            Dim iCatInProcess As Short = 0
            Dim oPar() As Object
            Dim oTable(iCatInProcess)() As Object
            ReDim oPar(gNbrCategories - 1)
            ReDim oTable(iCatInProcess)(gNbrCategories - 1)
            ReDim oRng(gNbrCategories - 1)
            DateTime = Now
            'Start Word and open the document template.
            oWord = CreateObject("Word.Application")
            oDoc = oWord.Documents.Add
            oPara1 = oDoc.Content.Paragraphs.Add
            oPara2 = oDoc.Content.Paragraphs.Add
            oWord.Visible = True
            oDoc.PageSetup.Orientation = 1 ' 1 is landscape, 0 is portrait
            oDoc.PageSetup.TopMargin = 1.0#
            oDoc.PageSetup.BottomMargin = 0.75
            'Insert a paragraph at the beginning of the document.
            oPara1 = oDoc.Content.Paragraphs.Add
            oPara1.Range.Font.Size = 8
            oPara1.Range.Text = Space(283) & DateTime & vbCrLf
            oPara1.Range.Font.Size = 12
            oPara1.Range.ParagraphFormat.Alignment = 1
            oPara1.Range.Text = "Two Way Stratification and Sample Size Report" & vbCr
            If gParentCompanyName.Length > 0 Then
                oPara1.Range.Text = Trim(gParentCompanyName) & vbCr & vbCr
            End If
            Dim R, c As Short
            For iCatInProcess = 0 To gNbrCategories - 1
                oPar(iCatInProcess) = oDoc.Content.Paragraphs.Add
                oPar(iCatInProcess).Range.Text = Trim(TWAuditInfo(iCatInProcess).CompanyName) & vbCr
                oPar(iCatInProcess).Range.Bold = False
                oPar(iCatInProcess).Format.SpaceAfter = 12
                '  Insert a TWAuditInfo(icatinprocess).nbrstrata row by 8 column table here and make the first row
                '  bold.  Fill the other cells with data
                oRng(iCatInProcess) = oDoc.bookmarks.item("\endofdoc").range
                oTable(iCatInProcess) = oDoc.Tables.Add(oRng(iCatInProcess), TWAuditInfo(iCatInProcess).NbrStrata + 2, 7, DefaultTableBehavior:=1, AutoFitBehavior:=1)
                oTable(iCatInProcess)(iCatInProcess).Range.ParagraphFormat.SpaceAfter = 6
                oTable(iCatInProcess)(iCatInProcess).Range.Font.Size = 11
                oTable(iCatInProcess).Rows(1).Range.Font.Bold = True
                R = 1
                c = 1
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(0.75)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Stratum"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                c = 2
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(1)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Lower Boundary"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                c = 3
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(1)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Upper Boundary"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                c = 4
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(1)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Stratum Size"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                c = 5
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(1.5)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Stratum Total"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                c = 6
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(1)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Standard Deviation"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                c = 7
                oTable(iCatInProcess).Columns(c).Width = oWord.InchesToPoints(1)
                oTable(iCatInProcess).Cell(R, c).Range.Text = "Sample Size"
                oTable(iCatInProcess).Cell(R, c).Range.ParagraphFormat.Alignment = 1
                For R = 0 To TWAuditInfo(iCatInProcess).NbrStrata - 1
                    oTable(iCatInProcess).Rows(R + 2).Range.Font.Bold = False
                    oTable(iCatInProcess).Cell(R + 2, 1).Range.Text = (R + 1).ToString
                    oTable(iCatInProcess).Cell(R + 2, 1).Range.ParagraphFormat.Alignment = 1
                    oTable(iCatInProcess).Cell(R + 2, 2).Range.Text = TWStratSumm(iCatInProcess).Lower(R).ToString("$#,###,##0.00")
                    oTable(iCatInProcess).Cell(R + 2, 2).Range.ParagraphFormat.Alignment = 2
                    oTable(iCatInProcess).Cell(R + 2, 3).Range.Text = TWStratSumm(iCatInProcess).Upper(R).ToString("$#,###,##0.00")
                    oTable(iCatInProcess).Cell(R + 2, 3).Range.ParagraphFormat.Alignment = 2
                    oTable(iCatInProcess).Cell(R + 2, 4).Range.Text = TWAuditInfo(iCatInProcess).Nh(R).ToString("##,##0")
                    oTable(iCatInProcess).Cell(R + 2, 4).Range.ParagraphFormat.Alignment = 2
                    oTable(iCatInProcess).Cell(R + 2, 5).Range.Text = TWAuditInfo(iCatInProcess).Th(R).ToString("$##,##0.00")
                    oTable(iCatInProcess).Cell(R + 2, 5).Range.ParagraphFormat.Alignment = 2
                    oTable(iCatInProcess).Cell(R + 2, 6).Range.Text = TWAuditInfo(iCatInProcess).Sh(R).ToString("#,##0.00")
                    oTable(iCatInProcess).Cell(R + 2, 6).Range.ParagraphFormat.Alignment = 2
                    oTable(iCatInProcess).Cell(R + 2, 7).Range.Text = TWAuditInfo(iCatInProcess).NHh(R).ToString("###,##0")
                    oTable(iCatInProcess).Cell(R + 2, 7).Range.ParagraphFormat.Alignment = 2
                Next R
                R = TWAuditInfo(iCatInProcess).NbrStrata + 2
                oTable(iCatInProcess).Cell(R, 3).Range.Text = "Totals"
                oTable(iCatInProcess).Cell(R, 3).Range.ParagraphFormat.Alignment = 2
                oTable(iCatInProcess).Cell(R, 4).Range.Text = TWAuditInfo(iCatInProcess).NN.ToString("###,##0")
                oTable(iCatInProcess).Cell(R, 4).Range.ParagraphFormat.Alignment = 2
                oTable(iCatInProcess).Cell(R, 5).Range.Text = TWAuditInfo(iCatInProcess).TotalInvoices.ToString("$###,###,##0.00")
                oTable(iCatInProcess).Cell(R, 5).Range.ParagraphFormat.Alignment = 2
                oTable(iCatInProcess).Cell(R, 7).Range.Text = TWAuditInfo(iCatInProcess).TotalSamsize.ToString("###,##0")
                oTable(iCatInProcess).Cell(R, 7).Range.ParagraphFormat.Alignment = 2
            Next iCatInProcess
        Catch ex As Exception
        End Try
    End Sub

Open in new window

Question by:rkulp
  • 3
  • 2
LVL 12

Accepted Solution

vb_jonas earned 750 total points
ID: 20752944
Hi, just a first thought : you will get better with the objects if you use early binding instead of late binding. (Add a reference to Microsoft.Office.Interop.Word)

Assisted Solution

ianmair329 earned 750 total points
ID: 20753378
Could you explain in more detail the data you want to drop into your document. Reading over your question it sounds as though you can drop each paragraph into an arraylist and then send each one in turn to the Word Document once you've created it. Are the paragraphs and table entries seperate things? If there's more to it than that let me know!

Also i've included some tried & tested code below for creating and adding to a Word Document. When you 'Add()' the document, you can specify a template if you want, which would save you having to insert all the text you wanted. You can also use find & replace to add text to drop in dynamic data, but it might not be appropriate for this project.

Reply back if you have more information
' Make sure this is at the top of your page
Imports Word = Microsoft.Office.Interop.Word
Public Class WordDocBuilder
Private ParaArray As New ArrayList
    Sub CreateParaArray()
        ' You can add the arraylist data how you like
        ' eg with a database, but i've just done it
        ' statically for an example.
        ParaArray.Add("Paragraph1 Text")
        ParaArray.Add("Paragraph2 Text")
        ParaArray.Add("Paragraph3 Text")
        ParaArray.Add("Paragraph4 Text")
        ParaArray.Add("Paragraph5 Text")
    End Sub
    Sub CreateWordDoc()
        'Create The Application
        Dim oWord As Word.Application
        oWord = New Word.Application
        'Create The Document
        Dim oDoc As Word.Document
        oWord.Visible = True
        oDoc = oWord.Documents.Add()
        Dim ArrItem As String
        For Each ArrItem In ParaArray
            ' You could also fill table data here
        ' This is the find and replace method - 
        ' Just stick <<date>> into you template
        'oDoc.Content.Find.Execute(FindText:="<<date>>", ReplaceWith:=Now.ToShortDateString, Replace:=Word.WdReplace.wdReplaceAll)
        ' Or Save...
        'Dim StrFileName As String
        'StrFileName = "Test.doc"
    End Sub
End Class

Open in new window


Author Comment

ID: 20753761
vb jonas & ianmair329:

Thanks for your suggestions. I have to use late binding since I don't know which version of Office any particular user is using. Otherwise, unlike VB6, I would need to compile a different version for each different version of Office.
I thought of an array list but could not figure out how to implement it. The paragraphs for the individual categories are the same except for the data itself, so that may work fine. The tables all have the same number of columns but have different numbers of rows. Each row is filled from a structure which is an item in an array list. The structures have all the statistical information for a single audit. I will investigate using a template for the column structure provided I can handle the number of rows.
The big problem is that one time the document could have just two tables and another time it may be ten. I think I can put the associated paragraph into the table so all I have to work out is adding a variable number of tables. Is there a way to create the table in a separate subroutine and then insert it into the primary document?  As you can tell, Word automation is essentially foreign territory for me.
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.


Author Comment

ID: 20756222
vb jonas & ianmair329:

I figured it out this afternoon. Dimensioning the paragraphs in an array of objects works fine. This does not work for tables because it is not necessary. Tables are a collection in a Word document so all that is necessary is to dimension one table as an object and then use that in the For . . . Next loop. It works very well.
The paragraphs are only titles so I am going to try to put them in a title row of the table and do away with the paragraphs in the For . . . Next loops. I am still trying to figure out how to select only the first row and then merge the cells. If you can help with that, I would appreciate it.
I am going to close this question and split the points evenly. Thanks for your suggestions.

Author Comment

ID: 20756426
Got the merge, too:

                Dim oCell as Word.Cell              
                oCell = oTable.cell(1, 1)
                oTable.cell(1, 7).merge(oCell)

Expert Comment

ID: 20759478
Happy to help - and glad you sorted that merge! Good luck with the rest of your project

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Native ability to set a user account password via AD GPO was removed because the passwords can be easily decrypted by any authenticated user in the domain. Microsoft recommends LAPS as a replacement and I have written an article that does something …
The video will let you know the exact process to import OST/PST files to the cloud based Office 365 mailboxes. Using Kernel Import PST to Office 365 tool, one can quickly import numerous OST/PST files to Office 365. Besides this, the tool also comes…
Watch the video to know the simple way to remove or recover or reset lost or forgotten passwords of Outlook PST file. With Kernel Outlook Password Recovery tool such operation is very easy to perform. It is a freeware with limitation to use with 500…

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question