acdagirl
asked on
prefilling word bookmarks through vb.net - need to preserve bookmarks
I have the following vb.net code to populate bookmarks in a word doc. My problem is that I want to preserve the bookmarks following the text input.
I pretty much list the bookmark names and values I wish to import into the doc in an array and push the values in. I believe that because I'm not matching the actual bookmarks to the *range* (only the bookmark name), I can't reset the bookmark properly. The prefilling of the qualifier does work though...
here is the sub:
Protected Sub prefillDoc(ByVal docName As String)
Try
Dim bookmarkArray As New ArrayList
Dim bookmarkArrayValue As New ArrayList
Dim file_title As String = docName.Substring(docName. LastIndexO f("\") + 1)
Dim file_path As String = docName.Substring(0, docName.LastIndexOf("\"))
Dim word_server As New Word.Application
word_server.Visible = True
word_server.ChangeFileOpen Directory( file_path)
word_server.Documents.Open (FileName: =file_titl e)
If word_server.Selection.Form Fields.App lication.A ctiveDocum ent.Protec tionType = Word.WdProtectionType.wdAl lowOnlyFor mFields Then
word_server.Selection.Form Fields.App lication.A ctiveDocum ent.Unprot ect()
bookmarkArray = getBookmark() ' NOTE: this gets 2-D array from another sub
For Each bookmarkName As String In bookmarkArray
Dim strbookmarkName As String() = bookmarkName.Split(";")
Dim bmname As String = strbookmarkName(LBound(str bookmarkNa me))
Dim bmvalue As String = strbookmarkName(UBound(str bookmarkNa me))
word_server.Selection.GoTo (What:=Wor d.WdGoToIt em.wdGoToB ookmark, Name:=bmname)
'word_server.Selection.Typ eText(Text :=bmvalue)
'here's where it all goes wrong
Dim range As Word.Range = word_server.Selection.Form Fields.App lication.A ctiveDocum ent.Bookma rks(bmname ).Range()
range.Text = bmvalue
word_server.ActiveDocument .Bookmarks .Add(bmnam e, range)
'end of wrong
word_server.Visible = True
Next
word_server.Selection.Form Fields.App lication.A ctiveDocum ent.Protec t(Word.WdP rotectionT ype.wdAllo wOnlyFormF ields)
word_server.Documents.Save ()
'word_server.Documents.Clo se(SaveCha nges:=True )
word_server.Application.Qu it()
word_server.Quit()
word_server = Nothing
Else
word_server.Application.Qu it()
word_server.Quit()
'word_server.Documents.Clo se(SaveCha nges:=Fals e)
word_server = Nothing
Throw New ApplicationException("Erro r accessing protected qualifier document: " & qualifierName)
End If
Catch comex As COMException
'word_server.Application.Q uit(False)
'word_server.Quit()
'word_server = Nothing
Throw comex
Catch ex As Exception
'word_server.Application.Q uit(False)
'word_server.Quit()
'word_server = Nothing
Throw ex
End Try
End Sub
I pretty much list the bookmark names and values I wish to import into the doc in an array and push the values in. I believe that because I'm not matching the actual bookmarks to the *range* (only the bookmark name), I can't reset the bookmark properly. The prefilling of the qualifier does work though...
here is the sub:
Protected Sub prefillDoc(ByVal docName As String)
Try
Dim bookmarkArray As New ArrayList
Dim bookmarkArrayValue As New ArrayList
Dim file_title As String = docName.Substring(docName.
Dim file_path As String = docName.Substring(0, docName.LastIndexOf("\"))
Dim word_server As New Word.Application
word_server.Visible = True
word_server.ChangeFileOpen
word_server.Documents.Open
If word_server.Selection.Form
word_server.Selection.Form
bookmarkArray = getBookmark() ' NOTE: this gets 2-D array from another sub
For Each bookmarkName As String In bookmarkArray
Dim strbookmarkName As String() = bookmarkName.Split(";")
Dim bmname As String = strbookmarkName(LBound(str
Dim bmvalue As String = strbookmarkName(UBound(str
word_server.Selection.GoTo
'word_server.Selection.Typ
'here's where it all goes wrong
Dim range As Word.Range = word_server.Selection.Form
range.Text = bmvalue
word_server.ActiveDocument
'end of wrong
word_server.Visible = True
Next
word_server.Selection.Form
word_server.Documents.Save
'word_server.Documents.Clo
word_server.Application.Qu
word_server.Quit()
word_server = Nothing
Else
word_server.Application.Qu
word_server.Quit()
'word_server.Documents.Clo
word_server = Nothing
Throw New ApplicationException("Erro
End If
Catch comex As COMException
'word_server.Application.Q
'word_server.Quit()
'word_server = Nothing
Throw comex
Catch ex As Exception
'word_server.Application.Q
'word_server.Quit()
'word_server = Nothing
Throw ex
End Try
End Sub
ASKER
So to summarize, here's what you'd have...
'declarations to show types
Dim word_server As Application
Dim wdDoc As Word.Document
Dim bmname As String
Set wdDoc = word_server.Selection.Docu ment -- I'm confused here
Dim rng As Word.range
rng = wdDoc.Bookmarks(bmname).ra nge
rng.Text = bmvalue
wdDoc.Bookmarks.Add( bmname, rng)
can you elaborate on the selection.Document part?
'declarations to show types
Dim word_server As Application
Dim wdDoc As Word.Document
Dim bmname As String
Set wdDoc = word_server.Selection.Docu
Dim rng As Word.range
rng = wdDoc.Bookmarks(bmname).ra
rng.Text = bmvalue
wdDoc.Bookmarks.Add( bmname, rng)
can you elaborate on the selection.Document part?
ASKER
I tried it and no matter what I do I can't add the bookmarks back in. there are no errors during run, but as it's running I can see the bookmarks don't get re-set and when I reopen the doc, the fields are filled in but no bookmarks,
What am I doing wrong?
What am I doing wrong?
Set wdDoc = word_server.Selection.Docu ment tries to set the wdDoc variable to the document being worked on.
That way, we should be able to define the current range for the bookmark.
When the range's text is set to the new value, the new rng variable should then define a different range in the document, and this should be captured by the re-adding of the bookmark.
Where does the bookmark end up?
Try capturing (as in debug.print) the Start and End properties of the range before and after the addition of the text.
That way, we should be able to define the current range for the bookmark.
When the range's text is set to the new value, the new rng variable should then define a different range in the document, and this should be captured by the re-adding of the bookmark.
Where does the bookmark end up?
Try capturing (as in debug.print) the Start and End properties of the range before and after the addition of the text.
I have tried to emulate what you are doing using vb.net (So it's my second lesson in .Net)
Here is the result, which seems to work as required.
It needs a forms-protected test document with three bookmarks: bmone, bmtwo and bmthree.
The program save the result under a new name, e.g MyFile.Doc becomes MyFileNew.doc
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.ICon tainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Butto n
<System.Diagnostics.Debugg erStepThro ugh()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Butto n()
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(190, 53)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(85, 40)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.AddRange(New System.Windows.Forms.Contr ol() {Me.Button1})
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Protected Sub prefillDoc(ByVal docName As String)
Try
Dim bookmarkArray As New ArrayList()
Dim bookmarkArrayValue As New ArrayList()
Dim bookmarkName As String
Dim getbookmark(1, 2) As String
Dim file_title As String = docName.Substring(docName. LastIndexO f("\") + 1)
Dim file_path As String = docName.Substring(0, docName.LastIndexOf("\"))
Dim wdDoc As Word.DocumentClass
Dim word_server As New Word.ApplicationClass()
Dim i As Integer
word_server.Visible = True
word_server.ChangeFileOpen Directory( file_path)
wdDoc = word_server.Documents.Open (FileName: =file_titl e)
If wdDoc.FormFields.Applicati on.ActiveD ocument.Pr otectionTy pe = Word.WdProtectionType.wdAl lowOnlyFor mFields Then
wdDoc.FormFields.Applicati on.ActiveD ocument.Un protect()
getbookmark(0, 0) = "bmone"
getbookmark(0, 1) = "bmtwo"
getbookmark(0, 2) = "bmthree"
getbookmark(1, 0) = "one"
getbookmark(1, 1) = "two"
getbookmark(1, 2) = "three"
Dim bmname As String
Dim bmvalue As String
'bookmarkArray = getbookmark ' NOTE: this gets 2-D array from another sub
'For Each bookmarkName As String In bookmarkArray
For i = 0 To 2
'Dim strbookmarkName As String() = bookmarkName.Split(";")
bmname = getbookmark(0, i)
bmvalue = getbookmark(1, i)
'word_server.Selection.GoT o(What:=Wo rd.WdGoToI tem.wdGoTo Bookmark, Name:=bmname)
'word_server.Selection.Typ eText(Text :=bmvalue)
'here's where it all goes wrong
Dim rng As Word.Range = wdDoc.Bookmarks.Item(bmnam e).Range()
rng.Text = bmvalue
wdDoc.Bookmarks.Add(bmname , rng)
'end of wrong
word_server.Visible = True
Next
wdDoc.Protect(Word.WdProte ctionType. wdAllowOnl yFormField s)
wdDoc.SaveAs(Replace(file_ title, ".", "new."))
wdDoc.Close()
'word_server.Documents.Sav e()
'word_server.Documents.Clo se(SaveCha nges:=True )
word_server.Quit()
word_server = Nothing
Else
word_server.Quit()
'word_server.Documents.Clo se(SaveCha nges:=Fals e)
word_server = Nothing
'Throw New ApplicationException("Erro r accessing protected qualifier document: " & qualifiername)
End If
'Catch comex As COMException
'word_server.Application.Q uit(False)
'word_server.Quit()
'word_server = Nothing
'Throw comex
Catch ex As Exception
'word_server.Application.Q uit(False)
'word_server.Quit()
'word_server = Nothing
Throw ex
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
prefillDoc("C:\Documents and Settings\Graham Skan\My Documents\bookmarktest.doc ")
End Sub
End Class
Here is the result, which seems to work as required.
It needs a forms-protected test document with three bookmarks: bmone, bmtwo and bmthree.
The program save the result under a new name, e.g MyFile.Doc becomes MyFileNew.doc
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.ICon
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Butto
<System.Diagnostics.Debugg
Me.Button1 = New System.Windows.Forms.Butto
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(190, 53)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(85, 40)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.AddRange(New System.Windows.Forms.Contr
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Protected Sub prefillDoc(ByVal docName As String)
Try
Dim bookmarkArray As New ArrayList()
Dim bookmarkArrayValue As New ArrayList()
Dim bookmarkName As String
Dim getbookmark(1, 2) As String
Dim file_title As String = docName.Substring(docName.
Dim file_path As String = docName.Substring(0, docName.LastIndexOf("\"))
Dim wdDoc As Word.DocumentClass
Dim word_server As New Word.ApplicationClass()
Dim i As Integer
word_server.Visible = True
word_server.ChangeFileOpen
wdDoc = word_server.Documents.Open
If wdDoc.FormFields.Applicati
wdDoc.FormFields.Applicati
getbookmark(0, 0) = "bmone"
getbookmark(0, 1) = "bmtwo"
getbookmark(0, 2) = "bmthree"
getbookmark(1, 0) = "one"
getbookmark(1, 1) = "two"
getbookmark(1, 2) = "three"
Dim bmname As String
Dim bmvalue As String
'bookmarkArray = getbookmark ' NOTE: this gets 2-D array from another sub
'For Each bookmarkName As String In bookmarkArray
For i = 0 To 2
'Dim strbookmarkName As String() = bookmarkName.Split(";")
bmname = getbookmark(0, i)
bmvalue = getbookmark(1, i)
'word_server.Selection.GoT
'word_server.Selection.Typ
'here's where it all goes wrong
Dim rng As Word.Range = wdDoc.Bookmarks.Item(bmnam
rng.Text = bmvalue
wdDoc.Bookmarks.Add(bmname
'end of wrong
word_server.Visible = True
Next
wdDoc.Protect(Word.WdProte
wdDoc.SaveAs(Replace(file_
wdDoc.Close()
'word_server.Documents.Sav
'word_server.Documents.Clo
word_server.Quit()
word_server = Nothing
Else
word_server.Quit()
'word_server.Documents.Clo
word_server = Nothing
'Throw New ApplicationException("Erro
End If
'Catch comex As COMException
'word_server.Application.Q
'word_server.Quit()
'word_server = Nothing
'Throw comex
Catch ex As Exception
'word_server.Application.Q
'word_server.Quit()
'word_server = Nothing
Throw ex
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
prefillDoc("C:\Documents and Settings\Graham Skan\My Documents\bookmarktest.doc
End Sub
End Class
ASKER
Thanks alot - I can only see a few differences:
you're using the DocumentClass and ApplicationClass - not sure why not just the interfaces
also you're changing the filename wdDoc.SaveAs(Replace(file_ title, ".", "new.")) -- I want to keep it the same, but that's a moot point - if it works like that, I can certainly work around it.
I'll give it a try and see what happens...
you're using the DocumentClass and ApplicationClass - not sure why not just the interfaces
also you're changing the filename wdDoc.SaveAs(Replace(file_
I'll give it a try and see what happens...
I used the extended 'Class' objects because I was getting 'ambiguous' -type error messages like:
C:\Documents and Settings\Graham Skan\My Documents\Visual Studio Projects\WindowsApplicatio n16\Form1. vb(107): 'Close' is ambiguous across the inherited interfaces 'Word._Document' and 'Word.DocumentEvents2_Even t'.
The save under a new name was done to ensure that the input document doesn't get modified.
I have also modified some things in the error handling. Some errors - which I didn't understand - were being set and preventing the code from completing.
C:\Documents and Settings\Graham Skan\My Documents\Visual Studio Projects\WindowsApplicatio
The save under a new name was done to ensure that the input document doesn't get modified.
I have also modified some things in the error handling. Some errors - which I didn't understand - were being set and preventing the code from completing.
ASKER
oh right...
You removed the throw COM exception.. ok, I'll do the same and see what I get. Thanks again :-)
You removed the throw COM exception.. ok, I'll do the same and see what I get. Thanks again :-)
ASKER
hmm, everything works the same as with my other code - the bookmarks aren't reattached. I must be doing something in the bookmark array or the way the bookmarks are set in the doc? because the code is fine...
ASKER
can you add this method to your code and see if it still works:
Protected Function getBookmark() As ArrayList
Try
Dim bookmarkArray As New ArrayList
Dim bookmarkArrayValue As New ArrayList
arraybmone = "bmone;one"
bookmarkArray.Add(arraybmo ne )
arraybmtwo = "bmtwo;two"
bookmarkArray.Add(arraybmt hree )
arraybmthree = "bmthree;three"
bookmarkArray.Add(arraybmt hree )
return bookmarkArray
End Function
and then within the prefill function use this logic for the retrieving the bookmarks and values?
[.......]
Dim bmname As String
Dim bmvalue As String
bookmarkArray = getbookmark
For Each bookmarkName As String In bookmarkArray
Dim strbookmarkName As String() = bookmarkName.Split(";")
bmname = strbookmarkName(LBound(str bookmarkNa me))
bmvalue = strbookmarkName(UBound(str bookmarkNa me))
[........]
If your code still works, then obviously I'm doing something incorrect in the array or somewhere external to the prefill.
Protected Function getBookmark() As ArrayList
Try
Dim bookmarkArray As New ArrayList
Dim bookmarkArrayValue As New ArrayList
arraybmone = "bmone;one"
bookmarkArray.Add(arraybmo
arraybmtwo = "bmtwo;two"
bookmarkArray.Add(arraybmt
arraybmthree = "bmthree;three"
bookmarkArray.Add(arraybmt
return bookmarkArray
End Function
and then within the prefill function use this logic for the retrieving the bookmarks and values?
[.......]
Dim bmname As String
Dim bmvalue As String
bookmarkArray = getbookmark
For Each bookmarkName As String In bookmarkArray
Dim strbookmarkName As String() = bookmarkName.Split(";")
bmname = strbookmarkName(LBound(str
bmvalue = strbookmarkName(UBound(str
[........]
If your code still works, then obviously I'm doing something incorrect in the array or somewhere external to the prefill.
ASKER
oh sorry - you'll need to add the declarations at the top of your page:
Dim arraybmone As String = ""
Dim arraybmtwo As String = ""
Dim arraybmthree As String = ""
Dim arraybmone As String = ""
Dim arraybmtwo As String = ""
Dim arraybmthree As String = ""
ASKER
oh man! I just realized what's going on... unbelievable...
the bookmarks are being reattached as supposed to, so the code is correct...
my problem is that the bookmarks were originally input fields - not just bookmarks.
Is there any way to make these new bookmarks input fields again after prefilling them? I think that's what I wasn't getting correct...
the bookmarks are being reattached as supposed to, so the code is correct...
my problem is that the bookmarks were originally input fields - not just bookmarks.
Is there any way to make these new bookmarks input fields again after prefilling them? I think that's what I wasn't getting correct...
Do you mean that they are TextInput formfields?
ASKER
yes, exactly...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ok, i think it works - i got some bad parameter name error, but i think that has something to do with the form field name not being a bookmark name maybe. I'll check, but so far it looks alot better... thanks so much for your help!
Thanks. Just to note that if a FormField has a name, then it is the name of its bookmark.
ASKER
ok thanks :-)
Avoid the use of the Selection object and the GoTo method
Use a document object
Avoid giving object variables their class name (Range)
You have:
word_server.Selection.GoTo
'word_server.Selection.Typ
'here's where it all goes wrong
Dim range As Word.Range = word_server.Selection.Form
range.Text = bmvalue
word_server.ActiveDocument
'end of wrong
The way that I would do that (in VB6) is:
'declarations to show types
Dim word_server As Application
Dim wdDoc As Word.Document
Dim bmname As String
Set wdDoc = word_server.Selection.Docu
'word_server.Selection.GoT
'word_server.Selection.Typ
'here's where it all goes wrong
Dim rng As Word.range
Set rng = wdDoc.Bookmarks(bmname).ra
rng.Text = bmvalue
wdDoc.Bookmarks.Add bmname, rng
'end of wrong
Putting the executable code into .Net:
Dim rng As Word.range
rng = wdDoc.Bookmarks(bmname).ra
rng.Text = bmvalue
wdDoc.Bookmarks.Add( bmname, rng)
'end of wrong