Here is a helper class I put in my project (its in VB.NET, you can easily convert it to C#). This is how it works:
1. create word template (.dot file)
2. add bookmarks to places where you need to set the data
3. format the table (currently supports only one), set headers etc AND HAVE ONE EMPTY ROW of the table. The table has to be bookmarked too.
4. Create new WordReport object, set template name, call Add ("BookmarkName", bookmarkData) as many times as you need it
4a. if you're filling the table then give the list of column names in stringArray
5. Call Print and you're done :) - it will open word document with filled data.
Imports Microsoft.Office.Interop
Imports PADOVA.Common.Utilities
Public Class WordReport
#Region "Constructor"
Public Sub New()
If Bookmarks Is Nothing Then
Bookmarks = New List(Of String)
End If
If BookmarkData Is Nothing Then
BookmarkData = New Hashtable
End If
End Sub
#End Region
#Region "Variables"
Private logger As NLog.Logger = NLog.LogManager.GetCurrentClassLogger
#End Region
#Region "Properties"
Public Property TemplateName As String
Public Property Bookmarks As List(Of String)
Public Property BookmarkColumns As Hashtable
Public Property BookmarkData As Hashtable
Public Property GroupByIndex As Integer
Public Property ShowTableCount As Boolean = True
#End Region
#Region "Helpers"
Public Sub Add(bookmarkName As String, bookmarkData As Object)
If bookmarkName.Trim = String.Empty Then
Throw New ArgumentException("Naziv bookmarka ne može biti prazan!")
Return
End If
Me.Bookmarks.Add(bookmarkName)
Me.BookmarkData.Add(bookmarkName, bookmarkData)
End Sub
Public Sub Add(bookmarkName As String, bookmarkData As Object, bookmarkColumns As List(Of String))
Me.Add(bookmarkName, bookmarkData)
If bookmarkColumns IsNot Nothing Then
If Me.BookmarkColumns Is Nothing Then
Me.BookmarkColumns = New Hashtable
End If
Me.BookmarkColumns.Add(bookmarkName, bookmarkColumns)
End If
End Sub
Public Sub Add(bookmarkName As String, bookmarkData As Object, bookmarkColumns As String())
Dim list As List(Of String) = Nothing
If bookmarkColumns IsNot Nothing Then
If list Is Nothing Then
list = New List(Of String)
End If
For Each s As String In bookmarkColumns
list.Add(s)
Next
End If
Me.Add(bookmarkName, bookmarkData, list)
End Sub
Public Sub Print()
If TemplateName.Trim = String.Empty Then
Throw New ArgumentException("Template name not set!")
Return
End If
If Not IO.File.Exists(TemplateName) Then
Throw New ArgumentException("Template file not found by given name!")
Return
End If
Dim appWord As Word.Application = Nothing
Dim appWordDocument As Word.Document = Nothing
Try
appWord = CType(CreateObject("Word.Application"), Word.Application)
Application.DoEvents()
appWordDocument = appWord.Documents.Add(CObj(TemplateName))
Application.DoEvents()
Dim data As Object = Nothing
Dim bookmark As Word.Bookmark = Nothing
Dim columns As List(Of String) = Nothing
Dim reportDataTable As DataTable = Nothing
For Each bm As String In Bookmarks
bookmark = appWordDocument.Bookmarks(bm)
If bookmark Is Nothing Then Continue For
data = BookmarkData(bm)
If TypeOf data Is DataTable Then
columns = BookmarkColumns(bm)
If bookmark.Range.Tables.Count = 0 Then Continue For
Dim table As Word.Table = bookmark.Range.Tables(1)
reportDataTable = DirectCast(data, DataTable)
Dim row As DataRow = Nothing
Dim lastRowValue As String = String.Empty
For index As Integer = 0 To reportDataTable.Rows.Count - 1
row = reportDataTable.Rows(index)
Dim newRow As Word.Row = table.Rows.Add(table.Rows.Last)
For i As Integer = 1 To columns.Count
If i = GroupByIndex Then
If NullToString(row(columns(i - 1))).Trim = lastRowValue Then
newRow.Cells(i).Range.Text = String.Empty
Dim borders As Word.Borders = newRow.Cells(i).Range.Borders
Dim border As Word.Border = borders(Word.WdBorderType.wdBorderTop)
border.LineStyle = Word.WdLineStyle.wdLineStyleNone
Else
newRow.Cells(i).Range.Text = NullToString(row(columns(i - 1))).Trim
End If
lastRowValue = NullToString(row(columns(i - 1))).Trim
Else
newRow.Cells(i).Range.Text = NullToString(row(columns(i - 1))).Trim
End If
Next
Next
If ShowTableCount Then
Dim totals As Word.Row = table.Rows.Last
If totals.Cells.Count > 1 Then
With totals.Cells(totals.Cells.Count - 1).Range
.Text = "TOTAL"
.Bold = 1
End With
totals.Cells(totals.Cells.Count).Range.Text = reportDataTable.Rows.Count.ToString
End If
Else
table.Rows.Last.Delete()
End If
Else
If NullToString(data).Trim <> String.Empty Then
bookmark.Range.Text = NullToString(data).Trim
End If
End If
Next
appWord.Visible = True
Application.DoEvents()
appWord.ActiveDocument.Protect(Word.WdProtectionType.wdAllowOnlyReading, False, String.Empty, False, False)
Application.DoEvents()
Catch ex As Exception
MsgBox("Error in filling the report data.", MsgBoxStyle.Exclamation)
logger.Error("{0}: {1}: {2}", Now.ToString, "WordReport:Print", ex)
Finally
If appWordDocument IsNot Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(appWordDocument)
End If
If appWord IsNot Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(appWord)
End If
End Try
End Sub
#End Region
End Class
This is how you're filling the report:
Private Sub IspisNepravilnosti(ispisNepravilnosti As DataTable)
Try
If _nepravilnostZapisnikId = 0 Then Return
Dim zm As New ZapisniciManager(GlobalContext)
Dim zapisnik As DataSet = zm.GetZapisnik(_nepravilnostZapisnikId)
If zapisnik Is Nothing OrElse zapisnik.Tables.Count = 0 OrElse zapisnik.Tables(0).Rows.Count = 0 Then
MsgBox("Ispis nepravilnosti nije uspio!", MsgBoxStyle.Exclamation)
Return
End If
Dim wr As New WordReport
With wr
Dim templatePath As String = IO.Path.Combine(ApplicationExecutablePath, "wordtemplates")
Dim templateFile As String = IO.Path.Combine(templatePath, "IspisNepravilnosti.dot")
.TemplateName = templateFile
.ShowTableCount = False
.GroupByIndex = 1
.Add("BrojKutije", mtxtNinIdKutije.Text.Trim.ToUpperInvariant)
.Add("BrojZapisnika", zapisnik.Tables(0).Rows(0).Item("prikaz_broja_zapisnika"))
.Add("ListaNepravilnosti", ispisNepravilnosti, {"NAZIV_NEDOSTATKA", "ZADUZNICE", "KLIJENT", "BROJ_OVJERE"})
.Add("OvlasteniRadnik1", GlobalContext.ImePrezime.ToUpper)
.Add("DatumNepravilnosti", Today.ToString("dd.MM.yyyy"))
.Print()
End With
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Exclamation)
End Try
End Sub