|
|
Our Hot Pick: Rising Antivirus 2006 - Certified by TUV & Checkmark! Get 10% discount by entering this coupon code: ONDISCOUNT10
Hi Anybody help me with this.
I have a user form set up that when called within a macro - macro1 - uses the selected word or words in the document and creates a Sub index mark for them. - It displays all the existing main index words in a list box on the form, so the user only needs to select a word an click "ok". - It also checks for a couple of document variables that another macro sets to indicate if the index foint should be italic and or bold or none.
All the commands against the form are Private Subs.
The form works great - no problems.
However, here is the problem - If I create a new macro (with no user form), macro2, in the module to do something else - e.g. change index mark page number formats globally in my document - this new macro works OK - but my original userform macro will no longer run - I get a Run time error 5 pointing to my code line:-
userForm1.show
And now for the really strange thing - if I then delete the new macro, recompile, save and close down Word, when I open the .dot file again, the original macro has the same problem still with userForm1.show
I am at a complete loss :-(
To summrise 1 - works ok 2 - add new macro - falls over 3 - remove new macro - still falls over
Any clues anybody??
Regards Alan F.
|
|
ps - I'm using Word 2002 SP3
The Form has a list box, a Cancel Button and a OK button. The object code is:- --------------------- Private Const ArrTop As Integer = 1000 Private MyArray(ArrTop) As String ------------------------- Private Sub QuickSort(strArray() As String, intBottom As Integer, intTop As Integer) Dim strPivot As String Dim strTemp As String Dim intBottomTemp As Integer Dim intTopTemp As Integer
intBottomTemp = intBottom intTopTemp = intTop strPivot = strArray((intBottom + intTop) \ 2) While (intBottomTemp <= intTopTemp) While (strArray(intBottomTemp) < strPivot And intBottomTemp < intTop) intBottomTemp = intBottomTemp + 1 Wend While (strPivot < strArray(intTopTemp) And intTopTemp > intBottom) intTopTemp = intTopTemp - 1 Wend If intBottomTemp < intTopTemp Then strTemp = strArray(intBottomTemp) strArray(intBottomTemp) = strArray(intTopTemp) strArray(intTopTemp) = strTemp End If If intBottomTemp <= intTopTemp Then intBottomTemp = intBottomTemp + 1 intTopTemp = intTopTemp - 1 End If Wend ' Recursive call If (intBottom < intTopTemp) Then QuickSort strArray, intBottom, intTopTemp If (intBottomTemp < intTop) Then QuickSort strArray, intBottomTemp, intTop End Sub ------------------------------------------ Private Sub cmdCancel_Click() Unload Me End Sub ---------------------------------------------------------- Private Sub cmdOK_Click() Dim strIndex
Dim aVar As Variant Dim vBld As Boolean Dim vItl As Boolean
' get the number font format from the document variable For Each aVar In ActiveDocument.Variables If aVar.Name = "IndEntBold" Then If aVar.Value = "y" Then vBld = True ElseIf vBld = False Then End If End If If aVar.Name = "IndEntItalic" Then If aVar.Value = "y" Then vItl = True ElseIf vItl = False Then End If End If Next aVar
If lbxIndex.ListCount >= 1 Then If lbxIndex.ListIndex <> -1 Then ' Remove any trailing blanks. Do While Asc(Selection.Characters.Last.Text) <= 32 Selection.MoveEnd unit:=wdCharacter, Count:=-1 Loop ' Highlight selected word Selection.Range.HighlightColorIndex = wdYellow ' Add word as sub-entry strIndex = lbxIndex.List(lbxIndex.ListIndex) strIndex = strIndex & ":" strIndex = strIndex & Selection.Range.Text ActiveDocument.Indexes.MarkEntry Range:=Selection.Range, Entry:=strIndex, Italic:=vItl, Bold:=vBld
End If End If Unload Me End Sub ----------------------------------------------------- Private Sub UserForm_Initialize() Dim i As Integer Dim j As Integer Dim strIndex As String
i = 0 For Each Field In ActiveDocument.Fields If Field.Type = wdFieldIndexEntry Then strIndex = Field.Code strIndex = Right(strIndex, Len(strIndex) - InStr(strIndex, """")) strIndex = Left(strIndex, InStr(strIndex, """") - 1) If i < 1000 Then i = i + 1 MyArray(i) = strIndex End If End If Next Field If i > 0 Then cmdOK.Enabled = True QuickSort MyArray, 1, i For j = 1 To i If j = 1 Then lbxIndex.AddItem MyArray(j) Else If MyArray(j) <> MyArray(j - 1) Then lbxIndex.AddItem MyArray(j) End If End If Next j End If End Sub ---------------------------------------------------------------------------------------------
And is called from:- --------------------- Private Sub AddWordAsSubIndexEntry() EntriesExist = False Dim vWord$ ' This section selects a word at the cursor position if not already selected
If Selection.Type = wdSelectionIP Then Selection.StartOf unit:=wdWord, Extend:=wdMove If Selection.ExtendMode = False Then Selection.ExtendMode = True Selection.MoveRight unit:=wdWord vWord$ = Selection.Text vWord$ = Trim(vWord$) End If If Len(Selection) = 1 Then MsgBox ("I do not know which word you want to index, please select one") Else If Selection.Type = wdSelectionNormal Then For Each Field In ActiveDocument.Fields ' Loop thru all field codes If Field.Type = wdFieldIndexEntry Then ' If Index entry EntriesExist = True Exit For End If Next Field If EntriesExist Then
frmSubIndex.Show ' This is the offending line!
Else MsgBox ("No main index entries available") End If Else MsgBox ("No word selected") End If ' UpdateIndex End If Selection.MoveRight unit:=wdCharacter, Count:=1 'deselects text End Sub ------------------------------------
The new macro I have added that screws up the form is:- ------------------------------------------ Sub Italic()
Dim aVar As Variant Dim IndEntBold As Variant Dim aBld As String Dim aBldVar As String Dim IndEntItalic As Variant Dim aIt As String Dim aItVar As String Dim oRange As Range
Application.ScreenUpdating = False ' turn off screen updating ' delete document variables if existing For Each aVar In ActiveDocument.Variables If aVar.Name = "IndEntBold" Then aVar.Delete ElseIf aVar.Name = "IndEntItalic" Then aVar.Delete End If Next aVar
aIt = "y"
' Add document variable for Italics ActiveDocument.Variables("IndEntItalic").Value = aIt
' Loop thru all index field codes and remove any existing font symbols ' and add a new Italic marker For Each Field In ActiveDocument.Fields If Field.Type = wdFieldIndexEntry Then Set oRange = Field.Code oRange.Find.Execute FindText:=" \b ", _ ReplaceWith:=" ", Replace:=wdReplaceAll oRange.Find.Execute FindText:=" \i ", _ ReplaceWith:=" ", Replace:=wdReplaceAll oRange.Find.Execute FindText:=" \B ", _ ReplaceWith:=" ", Replace:=wdReplaceAll oRange.Find.Execute FindText:=" \I ", _ ReplaceWith:=" ", Replace:=wdReplaceAll oRange.Find.Execute FindText:=""" ", _ ReplaceWith:=""" \i ", Replace:=wdReplaceAll End If Next Field
Application.ScreenUpdating = True ' turn on screen updating End Sub --------------------------------------------
Regards Alan F.
|
|
Maybe this is one of the rare cases where using Magic Forms, their detractors call them, falls over.
Here's what one of the detractors has to say about them:
Quote
By magic form I mean the practice of intantiating (sic) an object implicitly.
So example, say you create a form class called frmLetter then the wrong way to instantiate the form would be:
frmLetter.Show
This is because frmLetter is a CLASS and not an OBJECT. What happens is that a default object is created. There are a load of issues with this method.
The first is that the scope of such an implicit object is global. Now, one of the whole point about writing proper code is that objects and variables have their own scopes - all designed to be as tight as possible.
If you go and bust the whole scope open then (a) it's bad programming practice and (b) people can actually access the form from anywhere within the code. Also, it goes to show other developers that the programmer has a problem distinguishing between classes and objects. Not good for one's reputation.
The other problem; one that I have seen time and time again is that quite often the implicit object is not destroyed in memory if the same template is run again within the same session. For example, the last time I was called out to solve this problem was to a London Law Firm who were complaining that the users were calling up a letter or fax template and that the information entered in the fields last time were there for the next letter.
The problem was with Magic Forms and the way that the programmer called them. The answer is to create an object explicitly:
Dim oForm as frmLetter
Set oForm = New frmLetter oForm.txtDate.Text = Format$(Date(), "d mmmm yyyy") oForm.Show vbModal ' ---------------------------------- Unload oForm Set oForm = Nothing
Then everything is nicely wrapped up at the end and there is nothing horrible hanging about in memory afterwards.
It is not a co-incidence that in .Net magic forms are no longer allowed. One has to create an explicit object. The general response from the VB community was "finally they have fixed this".
Magic forms are one of the dreadful shortcuts and defaults permitted (nay, encouraged) by Microsoft and they never, ever, should be used. There are a number of these diseased defaults in Word and over the course of the New Year I will itemise these on my web site.
But, please believe me that using magic forms (i.e. implicitly calling the Class) is not good programming at all. I have not met anyone who who disagrees with me and can put forward a valid reason. All of the serious VB and VBA developers that I know and respect all say the same thing "magic forms are a spawn of the devil and should be avoided".
Until someone can give me a good strong reason why magic forms are a good idea this will be my stance. And, believe me, I and others better than I have thought long and hard about this.
Unquote
There were a few people who disagreed with this person (Malcolm Smith, I think his name was)
-- Hope this helps.
Please reply to the newsgroup unless you wish to avail yourself of my services on a paid consulting basis.
Doug Robbins - Word MVP
<googly-al[ at ]ashbourne-town.com> wrote in message news:1139237657.999962.157690[ at ]o13g2000cwo.googlegroups.com...
[Quoted Text] > ps - I'm using Word 2002 SP3 > > The Form has a list box, a Cancel Button and a OK button. > The object code is:- > --------------------- > Private Const ArrTop As Integer = 1000 > Private MyArray(ArrTop) As String > ------------------------- > Private Sub QuickSort(strArray() As String, intBottom As Integer, > intTop As Integer) > Dim strPivot As String > Dim strTemp As String > Dim intBottomTemp As Integer > Dim intTopTemp As Integer > > intBottomTemp = intBottom > intTopTemp = intTop > strPivot = strArray((intBottom + intTop) \ 2) > While (intBottomTemp <= intTopTemp) > While (strArray(intBottomTemp) < strPivot And intBottomTemp < > intTop) > intBottomTemp = intBottomTemp + 1 > Wend > While (strPivot < strArray(intTopTemp) And intTopTemp > intBottom) > intTopTemp = intTopTemp - 1 > Wend > If intBottomTemp < intTopTemp Then > strTemp = strArray(intBottomTemp) > strArray(intBottomTemp) = strArray(intTopTemp) > strArray(intTopTemp) = strTemp > End If > If intBottomTemp <= intTopTemp Then > intBottomTemp = intBottomTemp + 1 > intTopTemp = intTopTemp - 1 > End If > Wend > ' Recursive call > If (intBottom < intTopTemp) Then QuickSort strArray, intBottom, > intTopTemp > If (intBottomTemp < intTop) Then QuickSort strArray, intBottomTemp, > intTop > End Sub > ------------------------------------------ > Private Sub cmdCancel_Click() > Unload Me > End Sub > ---------------------------------------------------------- > Private Sub cmdOK_Click() > Dim strIndex > > Dim aVar As Variant > Dim vBld As Boolean > Dim vItl As Boolean > > ' get the number font format from the document variable > For Each aVar In ActiveDocument.Variables > If aVar.Name = "IndEntBold" Then > If aVar.Value = "y" Then > vBld = True > ElseIf vBld = False Then > End If > End If > If aVar.Name = "IndEntItalic" Then > If aVar.Value = "y" Then > vItl = True > ElseIf vItl = False Then > End If > End If > Next aVar > > If lbxIndex.ListCount >= 1 Then > If lbxIndex.ListIndex <> -1 Then > ' Remove any trailing blanks. > Do While Asc(Selection.Characters.Last.Text) <= 32 > Selection.MoveEnd unit:=wdCharacter, Count:=-1 > Loop > ' Highlight selected word > Selection.Range.HighlightColorIndex = wdYellow > ' Add word as sub-entry > strIndex = lbxIndex.List(lbxIndex.ListIndex) > strIndex = strIndex & ":" > strIndex = strIndex & Selection.Range.Text > ActiveDocument.Indexes.MarkEntry Range:=Selection.Range, > Entry:=strIndex, Italic:=vItl, Bold:=vBld > > End If > End If > Unload Me > End Sub > ----------------------------------------------------- > Private Sub UserForm_Initialize() > Dim i As Integer > Dim j As Integer > Dim strIndex As String > > i = 0 > For Each Field In ActiveDocument.Fields > If Field.Type = wdFieldIndexEntry Then > strIndex = Field.Code > strIndex = Right(strIndex, Len(strIndex) - InStr(strIndex, """")) > strIndex = Left(strIndex, InStr(strIndex, """") - 1) > If i < 1000 Then > i = i + 1 > MyArray(i) = strIndex > End If > End If > Next Field > If i > 0 Then > cmdOK.Enabled = True > QuickSort MyArray, 1, i > For j = 1 To i > If j = 1 Then > lbxIndex.AddItem MyArray(j) > Else > If MyArray(j) <> MyArray(j - 1) Then > lbxIndex.AddItem MyArray(j) > End If > End If > Next j > End If > End Sub > --------------------------------------------------------------------------------------------- > > > And is called from:- > --------------------- > Private Sub AddWordAsSubIndexEntry() > EntriesExist = False > Dim vWord$ ' This section selects a word at the cursor position if > not already selected > > If Selection.Type = wdSelectionIP Then > Selection.StartOf unit:=wdWord, Extend:=wdMove > If Selection.ExtendMode = False Then Selection.ExtendMode = True > Selection.MoveRight unit:=wdWord > vWord$ = Selection.Text > vWord$ = Trim(vWord$) > End If > If Len(Selection) = 1 Then > MsgBox ("I do not know which word you want to index, please select > one") > Else > If Selection.Type = wdSelectionNormal Then > For Each Field In ActiveDocument.Fields ' Loop thru all field > codes > If Field.Type = wdFieldIndexEntry Then ' If Index entry > EntriesExist = True > Exit For > End If > Next Field > If EntriesExist Then > > frmSubIndex.Show ' This is the offending line! > > Else > MsgBox ("No main index entries available") > End If > Else > MsgBox ("No word selected") > End If > ' UpdateIndex > End If > Selection.MoveRight unit:=wdCharacter, Count:=1 'deselects text > End Sub > ------------------------------------ > > > The new macro I have added that screws up the form is:- > ------------------------------------------ > Sub Italic() > > Dim aVar As Variant > Dim IndEntBold As Variant > Dim aBld As String > Dim aBldVar As String > Dim IndEntItalic As Variant > Dim aIt As String > Dim aItVar As String > Dim oRange As Range > > Application.ScreenUpdating = False ' turn off screen updating > ' delete document variables if existing > For Each aVar In ActiveDocument.Variables > If aVar.Name = "IndEntBold" Then > aVar.Delete > ElseIf aVar.Name = "IndEntItalic" Then > aVar.Delete > End If > Next aVar > > aIt = "y" > > ' Add document variable for Italics > ActiveDocument.Variables("IndEntItalic").Value = aIt > > ' Loop thru all index field codes and remove any existing font symbols > ' and add a new Italic marker > For Each Field In ActiveDocument.Fields > If Field.Type = wdFieldIndexEntry Then > Set oRange = Field.Code > oRange.Find.Execute FindText:=" \b ", _ > ReplaceWith:=" ", Replace:=wdReplaceAll > oRange.Find.Execute FindText:=" \i ", _ > ReplaceWith:=" ", Replace:=wdReplaceAll > oRange.Find.Execute FindText:=" \B ", _ > ReplaceWith:=" ", Replace:=wdReplaceAll > oRange.Find.Execute FindText:=" \I ", _ > ReplaceWith:=" ", Replace:=wdReplaceAll > oRange.Find.Execute FindText:=""" ", _ > ReplaceWith:=""" \i ", Replace:=wdReplaceAll > End If > Next Field > > Application.ScreenUpdating = True ' turn on screen updating > End Sub > -------------------------------------------- > > Regards Alan F. >
|
|
Doug
I tried your suggestion, I got the userform working ok with suggested code, Added my new macro and.... Now it falls over on
Set oForm = New frmSubIndex :-(
Same problem.
regards Alan F.
|
|
Hi Alan,
The form is almost certainly not falling over on that line, but rather on some line of code within the firm. Put a breakpoint into the UserForm_Initialize event, and then step through from there to see where the error really occurs.
If you don't understand the reason for the problem, then post back here the code where the error occurs and we'll see if we can help.
-- Regards Jonathan West - Word MVP www.intelligentdocuments.co.uk Please reply to the newsgroup Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
<googly-al[ at ]ashbourne-town.com> wrote in message news:1139175149.319022.85290[ at ]f14g2000cwb.googlegroups.com...
[Quoted Text] > Hi > Anybody help me with this. > > I have a user form set up that when called within a macro - macro1 > - uses the selected word or words in the document and creates a Sub > index mark for them. > - It displays all the existing main index words in a list box on the > form, so the user only needs to select a word an click "ok". > - It also checks for a couple of document variables that another macro > sets to indicate if the index foint should be italic and or bold or > none. > > All the commands against the form are Private Subs. > > The form works great - no problems. > > However, here is the problem - > If I create a new macro (with no user form), macro2, in the module to > do something else - e.g. change index mark page number formats globally > in my document - this new macro works OK - but my original userform > macro will no longer run - I get a Run time error 5 pointing to my > code line:- > > userForm1.show > > And now for the really strange thing - if I then delete the new macro, > recompile, save and close down Word, when I open the .dot file again, > the original macro has the same problem still with userForm1.show > > I am at a complete loss :-( > > To summrise > 1 - works ok > 2 - add new macro - falls over > 3 - remove new macro - still falls over > > Any clues anybody?? > > Regards Alan F. >
|
|
Jonathon
Many many thanks! I was so focused on the debug error! A breakpoint in the Initialize event !!! Great - that identified the problem - my InStr command!! It was due to a data problem, all the new macros I created and tested with all added a " \i " to the XE mark. My UserForm then was falling over as it was not finding the search character where it expected it. A simple addition of 2 letters has fixed it - "1," to the front of the inStr command. I'll just pop to the bathroom and wash the egg off my face!!
Many thanks again for the suggestion!!
Kind Regards Alan F.
|
|
|