Rick,
I don't know that you need to use a separate text file to save the data; I
do something very similar (to provide the ability for users to rerun a
template without having to re-enter everything) using document variables. And
I do some pretty complex stuff this way.
For example, I have a template that allows a user to collect multiple
instances of similar information (names and addresses of parties to a
contract). This information is loaded into an array when it's initially
collected, so saving this information and re-displaying it when rerunning the
template can be quite involved. I'll post some code below to give you an idea
of how I do this, but first just a quick comment on something else you
mentioned.
You said:
"A check box could result in a form field being set to a paragraph in the
code."
Whenever possible, I try to avoid writing large blocks of text into a
document using code; formatting can be a nightmare, and Word is a much better
text editor. ;-P What I usually do is either: wrap a bookmark around some
existing text in the template and then hide or show the text depending on the
value in the UserForm; or, set a bookmark at the proper location and then
insert an AutoText entry at the point identified by the bookmark. Note that
in the second case, I make sure that my AutoText entry includes the same
bookmark as the one that I'm using to identify when to insert the AutoText.
This way the bookmark is "retained" so the template can be rerun.
Before getting into using document variables for saving and re-displaying
values, a bit of explanation on how I work.
Generally, I try to avoid using the ActiveDocument object. Instead, I create
a Document object and set this object to the ActiveDocument then refer to
this object explicitly in my code. That way I don't end up accidentally doing
something to the wrong document. Accordingly, you'll see references to
"MyDoc" throughout my code.
I also follow the same basic rule with UserForms: create a UserForm object
and set it to a specific instance of a particular UserForm. Thus, you may see
references to "MyForm" or "Me" in my code.
Finally, I try to keep the document-related operations separate from the
UserForm-related operations. This means that I have a separate "main" module,
which includes all of the "document ops" code, as well as code for creating
and displaying the UserForm. Then when I click the 'OK' button on a UserForm,
I collect most of the UserForm values in various variables in the main module
and then work with the values from these variables when creating my document.
The most notable exception is the "parties to the contract" array I discussed
above. In this case, I use a Public array because creating a large number of
variables on the fly is just too much work, and the Public array is easy
enough to work with in this limited application.
Now on to the code.
First, because the "mechanics" of saving a value in a variable is the same
regardless of what the value might be, I write a standard procedure that
accepts arguments, like this:
Sub SaveVarValue(VarName As String, ByVal VarVal As String)
With myDoc
If fcnFindVar(VarName) = False Then .Variables.Add VarName
With .Variables(VarName)
If VarVal <> "" Then .Value = VarVal Else .Value = " "
End With
End With
End Sub
This procedure uses a Boolean function (that also accepts arguments) to
determine if the variable exists before trying to write into it and creates
it if it's not there. I also use this function when retrieving saved values,
which is why it's declared as Public.
Public Function fcnFindVar(VarName As String) As Boolean
Dim myVar As Variable
fcnFindVar = False
For Each myVar In myDoc.Variables
If myVar.Name = VarName Then
fcnFindVar = True
Exit For
End If
Next myVar
End Function
An example of the above procedure in use:
Private Sub SaveGoodsVars()
SaveVarValue "GoodsTypeIdx", GoodsTypeIdx
SaveVarValue "NewUsedOption", NewUsedOption
SaveVarValue "AttachedScheduleChk", CStr(bAttachedScheduleChk)
SaveVarValue "GoodsField1", GoodsField1
SaveVarValue "GoodsField2", GoodsField2
SaveVarValue "GoodsField3", GoodsField3
SaveVarValue "GoodsDescription", GoodsDescription
End Sub
And an explanation of the same: 'GoodsTypeIdx' is an Integer variable that
records the ListIndex of a ComboBox control. 'NewUsedOption' is a String
variable that records which of two OptionButton controls is selected.
'bAttachedScheduleChk' is a Boolean variable that records the state of a
CheckBox control. (I convert it to a String because document variables don't
accept Boolean values.) The remainder are String variables that hold the
values from various TextBox controls.
As discussed above, these values are collected in the Click event of the
'OK' button in the UserForm, as follows:
Private Sub CollectGoodsDetails()
With myLAForm
GoodsTypeIdx = .cboGoodsType.ListIndex
Select Case True
Case .optNewGoods.Value
NewUsedOption = "New Goods"
Case .optUsedGoods.Value
NewUsedOption = "Used Goods"
End Select
GoodsField1 = .txtGoodsFld1.Value
GoodsField2 = .txtGoodsFld2.Value
GoodsField3 = .txtGoodsFld3.Value
GoodsDescription = .txtGoodsDescr.Value
bAttachedScheduleChk = CBool(.chkAttachedSchedule.Value)
End With
End Sub
Another example of how I save values from my "parties" array:
Private Sub SaveCustomerVars()
Dim i As Integer
Dim CustomerNameVar As String
Dim CustomerAddressL1Var As String
Dim CustomerAddressL2Var As String
Dim CustomerTypeVar As String
For i = 1 To CustomerCount
CustomerNameVar = "CustomerName" & i
SaveVarValue CustomerNameVar, CustomersArray(0, i)
CustomerAddressL1Var = "CustomerAddressL1" & i
SaveVarValue CustomerAddressL1Var, CustomersArray(1, i)
CustomerAddressL2Var = "CustomerAddressL2" & i
SaveVarValue CustomerAddressL2Var, CustomersArray(2, i)
CustomerTypeVar = "CustomerType" & i
SaveVarValue CustomerTypeVar, CustomersArray(3, i)
Next i
End Sub
Again, the values in 'CustomersArray' are all Strings, and the 'For...Next'
loop just loops through the array, creates document variable names for each
array value and saves the value into the appropriate doc var, which do get
created on the fly. (Note that if I'm rerunning the template, I delete all of
the old "parties" doc vars first before saving the new ones. This works very
similar to the above but uses a procedure that deletes the doc vars instead
of creating them.) Since it's a Public array, I don't have to worry about
collecting the values.
The "re-use" side is a bit more complex, but I'll try to show you the
relationship what I used above to describe the save process and the code in
the UserForm_Initialize event.
As is the case with saving the doc vars, the process for retrieving the
values is basically the same regardless of the variable involved. However,
depending on the property of the control that I'm trying to set with the doc
var, I have to use slightly different functions.
For retrieving a String (e.g. the Value of a TextBox):
Function fcnLoadVarTextValue(VarName As String) As String
Dim Temp As String
With myDoc
If fcnFindVar(VarName) Then
With .Variables(VarName)
If .Value <> " " Then Temp = .Value Else Temp = ""
End With
Else: Temp = ""
End If
End With
fcnLoadVarTextValue = Temp
End Function
For retrieving an Integer (e.g. the ListIndex of a ComboBox):
Function fcnLoadVarNumberValue(VarName As String) As Integer
Dim Temp As Integer
With myDoc
If fcnFindVar(VarName) Then
With .Variables(VarName)
If .Value <> " " Then
If IsNumeric(.Value) Then Temp = .Value Else Temp = 0
Else: Temp = 0
End If
End With
Else: Temp = 0
End If
End With
fcnLoadVarNumberValue = Temp
End Function
For retrieving a "Boolean" (e.g. the state of a CheckBox):
Function fcnLoadVarBoolValue(VarName As String) As Boolean
Dim bTemp As Boolean
With myDoc
If fcnFindVar(VarName) Then
With .Variables(VarName)
If .Value <> " " Then
Select Case .Value
Case "True"
bTemp = True
Case Else
bTemp = False
End Select
Else: bTemp = False
End If
End With
Else: bTemp = False
End If
End With
fcnLoadVarBoolValue = bTemp
End Function
And the above in action in the Initialize event:
Private Sub LoadGoodsVars()
cboGoodsType.ListIndex = fcnLoadVarNumberValue("GoodsTypeIdx")
If fcnFindVar("NewUsedOption") Then
Select Case myDoc.Variables("NewUsedOption").Value
Case "New Goods"
optNewGoods.Value = True
Case Else
optUsedGoods.Value = True
End Select
Else: optNewGoods.Value = True
End If
txtGoodsFld1.Value = fcnLoadVarTextValue("GoodsField1")
txtGoodsFld2.Value = fcnLoadVarTextValue("GoodsField2")
txtGoodsFld3.Value = fcnLoadVarTextValue("GoodsField3")
txtGoodsDescr.Value = fcnLoadVarTextValue("GoodsDescription")
chkAttachedSchedule.Value = fcnLoadVarBoolValue("AttachedScheduleChk")
End Sub
(Note that OptionButtons don't lend themselves to using a function very
well, although I could probably do something with my Boolean function to set
the status of each OptionButton individually. Of course then I'd have to
store this information in separate doc vars... more work than it's worth
IMHO.)
And finally, the process for rebuilding the "parties" array:
Private Sub LoadCustomerVars()
Dim i As Integer
Dim CustomerNameVar As String
Dim CustomerAddressL1Var As String
Dim CustomerAddressL2Var As String
Dim CustomerTypeVar As String
ReDim CustomersArray(3, 1 To CustomerCount)
For i = 1 To CustomerCount
CustomerNameVar = "CustomerName" & i
CustomersArray(0, i) = fcnLoadVarTextValue(CustomerNameVar)
CustomerAddressL1Var = "CustomerAddressL1" & i
CustomersArray(1, i) = fcnLoadVarTextValue(CustomerAddressL1Var)
CustomerAddressL2Var = "CustomerAddressL2" & i
CustomersArray(2, i) = fcnLoadVarTextValue(CustomerAddressL2Var)
CustomerTypeVar = "CustomerType" & i
CustomersArray(3, i) = fcnLoadVarTextValue(CustomerTypeVar)
If i = CustomerCount Then
Select Case CustomersArray(3, i)
Case "I"
optCustomerIndividual.Value = True
Case "T"
optCustomerTrust.Value = True
Case Else
optCustomerCompany.Value = True
End Select
End If
Next i
LoadCustomersList
End Sub
As well as the process for displaying the array values for the "Name" and
"Type" in a ListBox:
Private Sub LoadCustomersList()
Dim n As Integer
With lstCustomers
.Clear
If CustomerCount > 0 Then
For n = 1 To CustomerCount
.AddItem CustomersArray(0, n)
.List(n - 1, 1) = CustomersArray(3, n)
Next n
End If
End With
End Sub
Now, how to trigger all of this...
I have a toolbar with just one button on it: a "Rerun" button. When a
document based on this template is opened, this toolbar is displayed. If the
user clicks on the button, the code for creating the document is launched.
Because this is the same code that's called in the AutoNew procedure, this
code checks to see if this a new document or an existing one, like so:
Private Sub UserForm_Initialize()
If fcnFindVar("NewDoc") Then
If LCase(myDoc.Variables("NewDoc").Value) = "true" Then LoadDefaults
Else LoadDocumentVars
Else: LoadDefaults
End If
End Sub
This has been stripped down substantially - stuff like building ComboBox
lists and enabling/disabling various other controls has been left out - but
you should get the idea. The relevant portions of 'LoadDocumentVars' is
below, followed by 'LoadDefaults'.
Private Sub LoadDocumentVars()
LoadCustomerVars
LoadGoodsVars
End Sub
Private Sub LoadDefaults()
optCustomerCompany.Value = True
cboGoodsType.ListIndex = 0
End Sub
A lot to take in, I know, but if you take your time and sort through it
carefully, I'm sure you can work it out. Feel free to post back if you have
any questions.
--
Cheers!
Gordon
The Kiwi Koder
Uninvited email contact will be marked as SPAM and ignored. Please post all
follow-ups to the newsgroup.