Click here to Skip to main content
Click here to Skip to main content

Word Style Automation

, 2 Apr 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Set Style of Word Document from Template

Introduction

This article discusses how to set the style of your Word Document using a template file and an Excel File.

Styles name is saved in an Excel File, and style formation in a template file. Word Document is parsed, and depending on Search Text, MaxFinds, Style will be set.

How To Use Code

Use Com Word Reference:

I use lateBinding in Excel. There is no need to add reference.

Process in the Application

  1. First parse the Excel File, save Style in ArrayList.
  2. Open Word Document.
  3. Apply Template File to Document.
  4. Parse Word Document Paragraph.
  5. Set Style to Paragraph:
    1. Check if the Paragraph Text contains the Search String
    2. Higher Priority for Upper Style names in Excel file
    3. Check If found Less Than Max
''Saving value in App Setting to Get Values When Run Application again
My.Settings.TemplateFilePath = txtTemplateFilePath.Text
My.Settings.ExcelStyleFilePath = txtExcleStylePath.Text
ErrorLog.Clear()
Dim excelParser As New OfficeModule.ExcelParser_
xcleStylePath.Text, "Formatting")
Dim iExcelStlyeCollection As System.Collections.ArrayList
 iExcelStlyeCollection = excelParser.PasreExcelStyle()
bgWorker.ReportProgress(2)
 If Not iExcelStlyeCollection Is Nothing Then
     Dim wordPaser As New OfficeModule.WordParser_
rdPath.Text, txtTemplateFilePath.Text, bgWorker)
    wordPaser.ExcelStyles = iExcelStlyeCollection
    wordPaser.ParseWord()
     e.Result = wordPaser.UnFoundStyle
Else
    ProgressBar1.Value = ProgressBar1.Maximum
    gridErrorLog.DataSource = ErrorLog.GetDataTableException()
End If

1. First Parse the Excel File

The priority of style will be for first rows.

Class ExcelStyle to save SearchString, Style Max Finds, Defaults:

Public Class ExcelStyle
Public Property SearchString() As String
    Get
        Return _searchString
    End Get
    Set(ByVal value As String)
        _searchString = value
    End Set
End Property
  Public Property Style() As String
    Get
        Return _style
    End Get
    Set(ByVal value As String)
        _style = value
    End Set
End Property
    Public Property Defaults() As String
    Get
        Return _defaults
    End Get
    Set(ByVal value As String)
        _defaults = value
    End Set
End Property
    Public Property Founds() As Int64
    Get
        Return _currentFounds
    End Get
    Set(ByVal value As Int64)
        _currentFounds = value
    End Set
End Property
         Public Property MaxFinds() As Int64
    Get
        Return _maxFinds
    End Get
    Set(ByVal value As Int64)
        _maxFinds = value
    End Set
End Property        

Class ExcelParser is used to parse Excel sheet. Every row is added ExcelStyle object and added to ArrayListCollection.

Example of ExcelSheet:

Public Class ExcelParser
''ExcelStyle Object Add To Collection 
'' Public ExcelStylesList As System.Collections.ArrayList
Public ExcelStylesList As System.Collections.ArrayList
''Late Biding for Excel Sheet
     ''No Need  To Add reference to Project
     ''Reading the values From Bottom to top
     ''Priority for Top Rows
     ''* Will be for all paragraphs
     Public Function PasreExcelStyle() As System.Collections.ArrayList
         If IsExcelFile(FilePath) = True Then
             Try
                 Dim xlApp As Object 'Application
                 Dim xlWorkBook As Object 'Workbook
                 Dim xlWorkSheet As Object 'Worksheet
                 Dim range As Object 'Range
                 Dim Obj As Object
                  Dim rowIndex As Int64
                 xlApp = CreateObject("Excel.Application")
                 xlWorkBook = xlApp.Workbooks.Open(FilePath)
                 xlWorkSheet = xlWorkBook.Worksheets(ExcelSheet)
                  ''The cells Have Data
                 range = xlWorkSheet.UsedRange
                 If Not range Is Nothing Then
                      For rowIndex = range.Rows.Count To 2 Step -1
                         Dim excelStyle As New ExcelStyle
                         Obj = range.Cells(rowIndex, 1) ''SearchString Cell
                         If Obj.value Is Nothing Then
                             excelStyle.SearchString = String.Empty
                         Else
                             excelStyle.SearchString = CStr(Obj.value)
                          End If
                         Obj = range.Cells(rowIndex, 2) ''Style Cell
                         If Obj.value Is Nothing Then
                             excelStyle.Style = String.Empty
                         Else
                             excelStyle.Style = CStr(Obj.value)
                         End If
                          Obj = range.Cells(rowIndex, 3) ''MaxFound Cell
                         If Obj.value Is Nothing Then
                             excelStyle.MaxFinds = -1
                         Else
                             excelStyle.MaxFinds = Convert.ToInt64(Obj.value)
                         End If
                          Obj = range.Cells(rowIndex, 4) ''Defaults
                          If Obj.value Is Nothing Then
                             excelStyle.Defaults = -1
                         Else
                             excelStyle.Defaults = CStr(Obj.value)
                         End If
                          ExcelStylesList.Add(excelStyle)
                     Next
                End If
                 '' xlWorkBook.Close()
                 releaseObject(xlApp)
                 releaseObject(xlWorkBook)
                 releaseObject(xlWorkSheet)
                Return ExcelStylesList
             Catch ex As Exception
                 Dim LogExc As New LogException(ex.Source, ex.Message)
                 ErrorLog.Add(LogExc)
                 Return Nothing
             End Try
         Else
             Return Nothing
         End If
      End Function      

2. Open Word Document

Import Word = Microsoft.Office.Interop.Word

Public Class WordParser is used to parse the Word Document and set paragraph style depending on the ExcelStyle collection.

Member of class:

Private ParagraphDefination As ParagraphSetting
Dim orgDoc As Word.Document ''To Load Word Document
Private doc As Word.Document 'To Load Word Document in new File Object
''Private docTemplate As Word.Document ''Object
Shared wordApp As Word.ApplicationClass '' Object 'Application  

To run Word and Open Document:

''Run Word Exe
''Set Document Object
Private Sub RunWord()
    Try
        If FilePath <> String.Empty And TemplePath <> String.Empty Then
            Dim o_nullobject As Object = System.Reflection.Missing.Value
             Dim o_filePath As Object = FilePath
            Dim o_NewfilePath As Object
            ''    Dim oTemplate As Object = TemplePath
            Dim NewFileName As String
            NewFileName = FilePath.Substring(0, FilePath.LastIndexOf(".")) & _
		"_Final." & FilePath.Substring(FilePath.LastIndexOf(".") + 1)
            o_NewfilePath = NewFileName
             Dim oFalse As Object = False
            Dim oTrue As Object = True
              '' If wordApp Is Nothing Then
            ''Create Word Application Object
            If wordApp Is Nothing Then
                wordApp = New Word.Application()
            Else
                ''To not create more than one instance of word Application
                ''When You Run process more than once
                wordApp = GetObject(Nothing, "Word.Application")
             End If
             ''Open word Document With File Path
            orgDoc = wordApp.Documents.Open(o_filePath, o_nullobject, oFalse, _
            	o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
		o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
		oFalse, o_nullobject, o_nullobject, o_nullobject, o_nullobject)
            orgDoc.SaveAs(NewFileName)
            ''doc = orgDoc ''try to open it in new document
            orgDoc.Close(oFalse)
            releaseObject(orgDoc)
            ''Open Template DOT ,DOTX
            '' docTemplate = wordApp.Documents.Open(oTemplate, o_nullobject, _
            	oTrue, o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
            	o_nullobject, o_nullobject, o_nullobject, o_nullobject, oFalse, _
            	o_nullobject, o_nullobject, o_nullobject, o_nullobject)
            '' doc.AttachedTemplate = docTemplate ''Set Template Document
             doc = wordApp.Documents.Open(NewFileName, o_nullobject, oFalse, _
             	o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
             	o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
             	oFalse, o_nullobject, o_nullobject, o_nullobject, o_nullobject)
            doc.CopyStylesFromTemplate(TemplePath) ''oTHER Way To Load Style
             ParagraphCount = doc.Paragraphs.Count - 1
        End If
    Catch ex As Exception
        Dim LogExc As New LogException(ex.Source, ex.Message)
        ErrorLog.Add(LogExc)
    End Try
End Sub  

3. Apply Template File to Document

There are two ways to apply Template Styles to Word Document:

First Way

doc = wordApp.Documents.Open(NewFileName, o_nullobject, oFalse, _
	o_nullobject, o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
	o_nullobject, o_nullobject, o_nullobject, oFalse, o_nullobject, _
	o_nullobject, o_nullobject, o_nullobject)
doc.CopyStylesFromTemplate(TemplePath)

Second Way

 docTemplate = wordApp.Documents.Open(oTemplate, o_nullobject, oTrue, _
	o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
	o_nullobject, o_nullobject, o_nullobject, o_nullobject, _
	oFalse, o_nullobject, o_nullobject, o_nullobject, o_nullobject)
doc.AttachedTemplate = docTemplate

4. Parse Word Document Paragraph

        Public Sub ParseWord()
            Try
                doc.Activate()
                ''TO Update Style from Template Document
                doc.UpdateStyles()

                ''word Application will be visible if you are in Debug Mode
#If DEBUG Then
                wordApp.Visible = True
                doc.Application.Visible = True
                ''   docTemplate.ActiveWindow.Visible = False
#End If

               ''Parsing process
                ParseWordStyle()

                wordApp.Visible = True
                doc.Application.Visible = True
                ''    docTemplate.ActiveWindow.Visible = False
                doc.Save()
            Catch ex As Exception
                Dim LogExc As New LogException(ex.Source, ex.Message)
                ErrorLog.Add(LogExc)
                backgroudWorker.CancelAsync()
            Finally
                Clear()
            End Try
        End Sub

5. Set Style to Paragraph

  • Parsing Word to set styles
  • Remove empty paragraph
  • Remove extra spaces between words
  • If paragraph contains table, it will be skipped
  • Bullet will be set if not set by user
Private Sub ParseWordStyle()
    Try
        Dim i As Int64
        Dim ParagraphCount As Int64
        ''When Delete Paragraph It remove From Collection ,Counter Must be set
        ParagraphCount = doc.Paragraphs.Count
        i = 1
         ''For beginner Levels All coms Collection First Index is 1
        While i <= ParagraphCount
             ''To Increase progressBar by 1
            backgroudWorker.ReportProgress(1)
            ''Image will not take style
            'Paragraph Settings
            'Priority as Follows
             ''Check if paragraph contains Table
            If doc.Paragraphs(i).Range.Tables.Count > 0 Then
                ParagraphDefination = ParagraphSetting.Table
            Else
                 Dim txt As String
                txt = doc.Paragraphs(i).Range.Text
                txt = txt.Trim("")
                txt = txt.Trim()
                 ''Check Empty Paragraph
                If doc.Paragraphs(i).Range.Words.Count = 1 Or txt = "" _
                	Or txt = String.Empty Then  '' String.Empty For Empty 
					 '' Paragraph will be Deleted
                    ParagraphDefination = ParagraphSetting.EmptyParagraph
                 Else
                     If doc.Paragraphs(i).Range.ListFormat.ListType = _
				Word.WdListType.wdListNoNumbering Then
                        ParagraphDefination = ParagraphSetting.ParagaraphStyle
                    End If
                     If doc.Paragraphs(i).Range.ListFormat.ListType = _
					Word.WdListType.wdListBullet Then
                        ParagraphDefination = ParagraphSetting.WdListBullet
                    End If
                     If doc.Paragraphs(i).Range.ListFormat.ListType = _
				Word.WdListType.wdListSimpleNumbering Then
                        ParagraphDefination = ParagraphSetting.wdListSimpleNumbering
                    End If
                     ''Seeing If user missed up without using enum or bullet
                     If txt <> String.Empty Then
                        If txt.Substring(0, 1) = "-" Then
                            ParagraphDefination = ParagraphSetting.WdListBullet
                         Else
                            If txt.IndexOf(".") <> -1 Then
                                If IsNumeric(txt.Substring(0, txt.IndexOf("."))) = _
								True Then
                                    ParagraphDefination = _
					ParagraphSetting.wdListSimpleNumbering
                                End If
                            End If
                        End If
                    End If
                 End If
             End If
             Select Case ParagraphDefination
                Case ParagraphSetting.Table
                    'Skip Table Style
                 Case ParagraphSetting.EmptyParagraph
                    doc.Paragraphs(i).Range.Delete() 'Delete Empty Paragraph
                    ParagraphCount = ParagraphCount - 1
                    i = i - 1
                 Case ParagraphSetting.WdListBullet  '-'
                    RemoveExtraSpaces(doc.Paragraphs(i))
                    ListParagraphSettings(doc.Paragraphs(i), "BulletPoint")
                     Dim index As Object = 1
                    Dim myTemplate As Word.ListTemplate = wordApp.ListGalleries_
			(Microsoft.Office.Interop.Word.WdListGalleryType._
				wdBulletGallery).ListTemplates.Item(index)
                    With myTemplate.ListLevels(1)
                        .NumberFormat = "-"
                        .TrailingCharacter = Word.WdTrailingCharacter.wdTrailingTab
                        .StartAt = 0
                     End With
                    doc.Paragraphs(i).Range.ListFormat.ApplyListTemplate(myTemplate)
                     RemoveWritenBullets(doc.Paragraphs(i))
                 Case ParagraphSetting.wdListSimpleNumbering '1.2.3.4'
                    RemoveExtraSpaces(doc.Paragraphs(i))
                    ListParagraphSettings(doc.Paragraphs(i), "Enumeration")
                    ParagraphStyleSetting(doc.Paragraphs(i))
                  Case ParagraphSetting.ParagaraphStyle
                    RemoveExtraSpaces(doc.Paragraphs(i))
                    ParagraphStyleSetting(doc.Paragraphs(i))
                Case Else ''whatever case
                    RemoveExtraSpaces(doc.Paragraphs(i))
                    ParagraphStyleSetting(doc.Paragraphs(i))
            End Select
             i = i + 1
        End While
     Catch ex As Exception
        Dim LogExc As New LogException(ex.Source, ex.Message)
        ErrorLog.Add(LogExc)
        '' backgroudWorker.CancelAsync()
    End Try
End Sub  

Set Style to paragraph from template file:

Private Sub ParagraphStyleSetting(ByVal Paragaph As Word.Paragraph)
    Try
        Dim exStyle As OfficeModule.ExcelStyle
        Dim parsText As String
         Dim iCollection As Int64
        Dim lastFoundIndex As Int64
         lastFoundIndex = -1
         parsText = Paragaph.Range.Text ''Text In paragraph
        parsText = parsText.ToUpper() ''to match Upper And Lower case
         For iCollection = 0 To ExcelStyles.Count - 1  ''Looping throw 
						''Excel Setting Object
             exStyle = ExcelStyles(iCollection)
             exStyle.SearchString = exStyle.SearchString.ToUpper()
            exStyle.SearchString = FixSeacrhText(exStyle.SearchString) ' To ensure 
							       ' correct inputs
             If parsText.IndexOf(exStyle.SearchString) <> -1 Or _
					exStyle.SearchString = "*" Then
                If (exStyle.Founds < exStyle.MaxFinds) Or (exStyle.MaxFinds = -1) Then
                    lastFoundIndex = iCollection
                End If
            End If
         Next ''Collection Of styles
         ''Index Of Object Style
        If lastFoundIndex <> -1 Then
            exStyle = ExcelStyles(lastFoundIndex)
             ''Check If the Style exists In Document Before
            If SetStyleParagraph(Paragaph, exStyle.Style) = True Then
                exStyle.Founds = exStyle.Founds + 1
            End If
         End If
    Catch ex As Exception
        Dim LogExc As New LogException(ex.Source, ex.Message)
        ErrorLog.Add(LogExc)
    End Try
 End Sub
 ''Set Style to paragraph from template file
 Private Function SetStyleParagraph(ByVal Paragaph As Word.Paragraph, _
					ByVal Style As String) As Boolean
     Dim isSetStyle As Boolean = False
    Style = FixStyleText(Style)
    If Paragaph.Style.NameLocal <> Style Then
         Try
            If IsStylExsist(Style) Then 'Ensure Style exists in Template Document
                Paragaph.Style = Style
                isSetStyle = True
            End If
        Catch ex As Exception
            isSetStyle = False
            Dim LogExc As New LogException(ex.Source, ex.Message)
            ErrorLog.Add(LogExc)
        End Try
    End If
    Return isSetStyle
End Function    

Almost Done

You will see more details in the source file on parsing and setting Styles to document.

The following things are not explained in the article:

  • Process will be done in async Mode. I used Backgroundworker and passed by reference to class WordParser.
  • Late binding of Excel Object. See this link.
  • I have tired to use LateBinding to Word com but objects like the paragraph object can't be set by value. I notice that it's a bug in using Com in .NET.
  • Error logs done by using shared ArrayList which will be used in all class objects.
Public Class ErrorLog
Private Shared _logException As New System.Collections.ArrayList
    Private Shared Property LogException() As System.Collections.ArrayList
    Get
        Return _logException
    End Get
    Set(ByVal value As System.Collections.ArrayList)
        _logException = value
    End Set
End Property
Public Shared Sub Add(ByVal LogExcp As LogException)
    LogException.Add(LogExcp)
End Sub
 Public Shared Function GetDataTableException() As System.Data.DataTable
    Dim dt As New System.Data.DataTable
    Dim iCollection As Int64
     dt.Columns.Add(New DataColumn("Source", GetType(String)))
    dt.Columns.Add(New DataColumn("Message", GetType(String)))
     For iCollection = 0 To LogException.Count - 1
        Dim LogExc As LogException = LogException(iCollection)
        Dim row As System.Data.DataRow
        row = dt.NewRow()
        row("Source") = LogExc.Source
        row("Message") = LogExc.Message
        dt.Rows.Add(row)
    Next
     Return dt
End Function        
  • You can modify Errors Reporting with whatever you need, writing to XML, text file, Event log of window.
  • WinWord.exe will still be running in the background. I can't kill a process because the user might still want to modify the opened document.
  • Examples of Word, Excel, template file are included in the source code.

History

  • 26th March, 2009: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Amr M. K.
Web Developer
Jordan Jordan
- Need is the mother of the invitation .
- To be acknowledge is matter of time..
be skillfull..needs...

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 2 Apr 2009
Article Copyright 2009 by Amr M. K.
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid