写入MS word文档 [英] Writing to MS word documents
问题描述
我的MS Word文档很少(包含表格和所有文件,就像申请表格一样)。我的要求是使用WPF桌面应用程序输入的信息填写此类文档。基本上相同的文档用于多个场合。
如何使用.Net做到这一点。我试图在需要时创建整个文档。但是对于单个文档,它有很多工作要做。有没有办法将内容注入word文档,可以作为模板。
提前谢谢。
这是我放在项目中的一个帮助器类(在VB.NET中,你可以很容易地将它转换为C#)。这是它的工作原理:
1.创建单词模板(.dot文件)
2.将书签添加到需要设置数据的地方
3.格式化表格(目前只支持一个),设置标题等并且表格中有一个空行。该表也必须加入书签。
4.创建新的WordReport对象,设置模板名称,根据需要多次调用Add(BookmarkName,bookmarkData)
4a。如果你正在填写表格,那么在stringArray中给出列名列表
5.调用打印,你就完成了:) - 它将打开带有填充数据的word文档。
Imports Microsoft.Office.Interop
Imports PADOVA.Common.Utilities
公共 类 WordReport
#Region构造函数
公共 Sub 新()
如果书签 没什么 然后
Bookmarks = 新列表( 字符串)
< span class = code-keyword>结束 如果
如果 BookmarkData 没什么 然后
BookmarkData = 新 Hashtable
结束 如果
结束 Sub
#结束地区
#Region变量
私人 logger 作为 NLog.Logger = NLog.LogManager.GetCurrentClassLogger
#End Region
#RegionProperties
Public Property Temp lateName 作为 字符串
公开 属性书签作为列表( 字符串)
公共 属性 BookmarkColumns < span class =code-keyword> As Hashtable
公开 属性 BookmarkData 作为 Hashtable
公开 属性 GroupByIndex 作为 整数
公开 属性 ShowTableCount 作为 布尔 = True
#End Region
#Region助手
公共 Sub 添加(bookmarkName 作为 字符串,bookmarkData 作为 对象)
如果 bookmarkName.Trim = 字符串 .Empty 然后
投掷 新 ArgumentException( Naziv bookmarkanemožebitiprazan!)
返回
结束 如果
我 .Bookmarks.Add(bookmarkName)
Me .BookmarkData.Add(bookmarkName,bookmarkData)
结束 Sub
公开 Sub 添加(bookmarkName 作为 字符串,bookmarkData 作为 对象,bookmarkColumns 作为列表(< span class =code-keyword> String ))
我 .Add(bookmarkName,bookmarkData)
如果 bookmarkColumns IsNot Nothing 然后
如果 我 .BookmarkColumns 没什么 然后
我 .BookmarkColumns = 新 Hashtable
结束 如果
我 .BookmarkColumns .Add(bookmarkName,bookmarkColumns)
结束 如果
结束 Sub
公共 Sub 添加(bookmarkName 作为 字符串,bookmarkData 作为 对象,bookmarkColumns 作为 String ())
Dim list As List( 字符串)= 无
< span class =code-keyword>如果 bookmarkColumns IsNot Nothing 然后
如果 list Nothing 然后
list = 新列表( 字符串)
结束 如果
对于 每个 s As 字符串 在 bookmarkColumns
list.Add(s)
下一步
结束 如果
我 .Add(bookmarkName,bookmarkData,list)
结束 Sub
公开 Sub Print()
如果 TemplateName.Trim = 字符串 .Empty 那么
抛出 新 ArgumentException( 未设置模板名称!)
返回
结束 如果
如果 不 IO.File.Exists(TemplateName)然后
投掷 新 ArgumentException( 找不到给定名称的模板文件!)
返回
结束 如果
Dim appWord As Word .Application = Nothing
Dim appWordDocument As Word.Document = 没什么
尝试
appWord = CType (CreateObject( Word.Application),Word.Application)
Application.DoEvents()
appWordDocument = appWord.Documents.Add( CObj (TemplateName))
Application.DoEvents()
Dim 数据作为 对象 = 无
Dim 书签 As Word.Bookmark = Nothing
Dim 列作为列表( 字符串)= 没什么
Dim reportDataTable 作为 DataTable = 没什么
对于 每个 bm 作为 字符串 在书签
bookmark = appWordDocument.Bookmarks(bm)
如果书签是 没什么 然后 继续 对于
data = BookmarkData(bm)
如果 TypeOf 数据 DataTable 然后
columns = BookmarkColumns(bm)
如果 bookmar k.Range.Tables.Count = 0 然后 继续 对于
Dim 表作为 Word.Table = bookmark.Range.Tables( 1 )
reportDataTable = DirectCast (data,DataTable)
Dim row As DataRow = Nothing
Dim lastRowValue As 字符串 = 字符串 .Empty
用于 index 作为 整数 = 0 reportDataTable.Rows.Count - 1
row = reportDataTable.Rows(index)
Dim newRow As Word.Row = table .Rows.Add(table.Rows.Last)
For i As 整数 = 1 columns.Count
' ukoliko treba grupiratipoodređenojkoloni,nije zadnji red makni gornji border
如果 i = GroupByIndex 那么
如果 NullToString(行(列(i - 1 )))。Trim = lastRowValue 然后
newRow.Cells(i).Range.Text = 字符串 .Empty
' 如果索引<> reportDataTable.Rows.Count - 1然后
Dim border As Word.Borders = newRow.Cells(i).Range.Borders
Dim border As Word.Border = border(Word.WdBorderType.wdBorderTop)
border.LineStyle = Word.WdLineStyle.wdLineStyleNone
' 结束如果
Else
newRow.Cells(i).Range.Text = NullToString(row(columns(i - 1 )))。修剪
结束 如果
lastRowValue = NullToString(ro w(列(i - 1 )))。修剪
否则
newRow .Cells(i).Range.Text = NullToString(row(columns(i - 1 )))。修剪
结束 如果
下一步
下一步
如果 ShowTableCount 那么
Dim 总计 As Word.Row = table.Rows.Last
如果 totals.Cells.Count> 1 然后
总计.Cells(totals.Cells.Count - 1 )。范围
.Text = < span class =code-string> TOTAL
.Bold = 1
结束 使用
totals.Cells(totals.Cells.Count).Range.Text = reportDataTable.Rows.Count。 ToString
结束 如果
Else
table.Rows.Last.Delete()
结束 如果
Else
' nemoj prepisivati defaultni tekst s template-a akonemaništazaupisati
If NullToString(data).Trim<> 字符串 .Empty 然后
bookmark.Range.Text = NullToString(data) .Trim
结束 如果
结束 如果
下一步
appWord.Visible = True
Application.DoEvents()
appWord.ActiveDocument.Protect(Word.WdProtectionType.wdAllowOnlyReading, False ,字符串 .Empty, False , False )
Application.DoEvents()
Catch ex 作为异常
MsgBox( 填写报告数据时出错。,MsgBoxStyle.Exclamation)
logger。错误( {0}:{1}:{2},Now.ToString,< span class =code-string> WordReport:打印,ex)
最后
如果 appWordDocument IsNot 没什么 然后
System.Runtime.InteropServices.Marshal.ReleaseComObject(appWordDocument)
End 如果
如果 appWord IsNot 没什么 然后
系统.Runtime.InteropServices.Marshal.ReleaseComObject(appWord)
结束 如果
< span class =code-keyword>结束 尝试
结束 Sub
#End Region
结束 类
这就是你填写报告的方式:
私有 Sub IspisNepravilnosti(ispisNepravilnosti As DataTable)
尝试
如果 _nepravilnostZapisnikId = 0 那么 < span class =code-keyword>返回
Dim zm As 新 ZapisniciManager(GlobalContext)
Dim zapisnik As DataSet = zm.GetZapisnik(_nepravilnostZapisnikId)
如果 zapisnik 没什么 OrElse zapisnik.Tables.Count = 0 OrElse zapisnik。表( 0 )。Rows.Count = 0 然后
MsgBox( Ispis nepravilnosti nije uspio!,MsgBoxStyle.Exclamation)
返回
结束 如果
Dim wr 作为 新 WordReport
使用 wr
Dim templatePath 作为 字符串 = IO.Path.Combine (ApplicationExecutablePath, wordtemplates)
Dim templateFile As String = IO.Path.Combine(templatePath, IspisNepravilnosti.dot)
.TemplateName = templateFile
.ShowTableCount = 错误
.GroupByIndex = 1
.Add( BrojKutije,mtxtNinIdKutije.Text.Trim .ToUpperInvariant)
.Add( BrojZapisnika,zapisnik.Tables( 0 )。行( 0 )。项目( < span class =code-string> prikaz_broja_zapisnika))
.Add( ListaNepravilnosti,ispisNepravilnosti,{ NAZIV_NEDOSTATKA,< span class =code-string> ZADUZNICE, KLIJENT, BROJ_OVJERE})
' 。添加(Napomena,??)
.Add( OvlasteniRadnik1,GlobalContext.ImePrezime.ToUpper)
' 。添加(OvlasteniRadnik2,)'ne koristi se,odn。 radniktrebaručnoupisati
.Add( DatumNepravilnosti,Today.ToString ( dd.MM.yyyy))
.Print()
结束 使用
Catch ex As 异常
MsgBox(ex.Message,MsgBoxStyle.Exclamation)
结束 尝试
结束 子跨度>
I've few MS word documents (with tables and all, it's like an application form). My requirement is to fill such documents with information entered using a WPF desktop application. Basically the same document using for multiple occasions.
How can I do this with .Net. I tried to create the whole document when required. But it has lots of work to do for a single document. Is there a way to inject the content into the word document, may be as a template.
Thanks in advance.
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 ' ukoliko treba grupirati po određenoj koloni, a nije zadnji red makni gornji border If i = GroupByIndex Then If NullToString(row(columns(i - 1))).Trim = lastRowValue Then newRow.Cells(i).Range.Text = String.Empty 'If index <> reportDataTable.Rows.Count - 1 Then Dim borders As Word.Borders = newRow.Cells(i).Range.Borders Dim border As Word.Border = borders(Word.WdBorderType.wdBorderTop) border.LineStyle = Word.WdLineStyle.wdLineStyleNone 'End If 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 ' nemoj prepisivati defaultni tekst s template-a ako nema ništa za upisati 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("Napomena", "??") .Add("OvlasteniRadnik1", GlobalContext.ImePrezime.ToUpper) '.Add("OvlasteniRadnik2", "") ' ne koristi se, odn. radnik treba ručno upisati .Add("DatumNepravilnosti", Today.ToString("dd.MM.yyyy")) .Print() End With Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Exclamation) End Try End Sub
这篇关于写入MS word文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!