问题
The headline really says it all, but here's my situation: I have a userform set up to collect user input, then uses that input in a macro and executes it. That, in itself, works exactly like I want it to. The problem comes when more than one document is open.
To illustrate: I have two documents, 'doc a' and 'doc b'. I open both documents, then select 'doc a', open the userform using a show userform macro, input my data, and hit either 'Okay' or 'Cancel' (both of which are set to unload the userform once clicked). The macro runs, and then I select 'doc b' to do the same. This time, however, when I run my 'show userform' macro, 'doc a' is selected and the userform is opened there.
This seems like a pretty basic issue, but I haven't been able to figure out any fixes. After putting 'unload me' failed to work in my button-click subs, I tried creating an unload macro and calling it from those subs instead, but neither is working for me. Any thoughts? (Also, while I'm already here- are there any good tricks to autofill the Userform with the most recently filled data? Not between opening/closing word, which I've seen some solutions for, but just while word is open, and I'm switching between active documents)
Option Explicit
Option Compare Text
Private Sub UserForm_Initialize()
Folder_Name = ""
Tag_Name = ""
Checklist.Value = True
Site_Report.Value = False
Space_Check.Value = False
End Sub
Public Sub Okay_Click()
folder = Folder_Name.Text
tag = Tag_Name.Text
tagtxt = Tag_Name.Text & "[0-9]{1,}"
tagnum = Len(Tag_Name.Text)
If Checklist.Value = True Then
report_type = "cl"
Else
report_type = "sr"
End If
If Space_Check.Value = True Then
space = "yes"
Else
space = "no"
End If
If Len(Folder_Name.Text) > 0 Then
Application.Run "Mass_Hyperlink_v_5_0"
Application.Run "UnloadIt"
Else
Application.Run "UnloadIt"
End If
Unload Me
End Sub
Private Sub Cancel_Click()
Application.Run "UnloadIt"
Unload Me
End Sub
I don't think the issue is with the macros that this userform uses (it runs fine on its own, though the code is likely a bit hackneyed), but here's the code for good measure:
Option Explicit
Option Compare Text
Public tag As String
Public tagtxt As String
Public tagnum As String
Public folder As String
Public space As String
Public report_type As String
Public Sub Mass_Hyperlink_v_5_0()
Dim fileName As String
Dim filePath As String
Dim rng As Word.Range
Dim rng2 As Word.Range
Dim fileType As String
Dim start As String
Dim temp As String
Application.ScreenUpdating = False
fileType = "jpg"
If space = "Yes" Then
start = "%20("
Else: start = "("
End If
If report_type = "cl" Then
folder = "..\Images\" & folder
Set rng = ActiveDocument.Range
Else: folder = folder
End If
If report_type = "sr" Then
folder = "Images\" & folder
Set rng = Selection.Range
Else: folder = folder
End If
Set rng2 = rng.Duplicate
'tagtxt = tag & "[0-9]{1,}"
If Len(rng) > 0 And report_type = "sr" Then
With rng.Find
.Text = tagtxt
.Forward = False
.MatchWildcards = True
.Wrap = wdFindStop
Do While .Execute(findText:=tagtxt) = True
If rng.InRange(rng2) Then
rng.Select
'Selection.start = Selection.start + Len(tag)
Selection.start = Selection.start + tagnum
'ActiveDocument.Range(Selection.start - Len(tag), Selection.start).Delete
ActiveDocument.Range(Selection.start - tagnum, Selection.start).Delete
fileName = Selection.Text
filePath = folder & "\" & Hyperlinker.Tag_Name.Text & start & fileName & ")" & "." & fileType
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, address:= _
filePath, SubAddress:="", ScreenTip:="", TextToDisplay:= _
(Hyperlinker.Tag_Name.Text & Selection.Text)
Else
Exit Sub
End If
rng.Collapse wdCollapseStart
Loop
End With
End If
If report_type = "cl" Then
With rng.Find
.Text = tagtxt
.Forward = False
.MatchWildcards = True
.Wrap = wdFindStop
Do While .Execute(findText:=tagtxt) = True
If rng.InRange(rng2) Then
rng.Select
'Selection.start = Selection.start + Len(tag)
Selection.start = Selection.start + tagnum
'ActiveDocument.Range(Selection.start - Len(tag), Selection.start).Delete
ActiveDocument.Range(Selection.start - tagnum, Selection.start).Delete
fileName = Selection.Text
filePath = folder & "\" & Hyperlinker.Tag_Name.Text & start & fileName & ")" & "." & fileType
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, address:= _
filePath, SubAddress:="", ScreenTip:="", TextToDisplay:= _
(Hyperlinker.Tag_Name.Text & Selection.Text)
Else
Exit Sub
End If
rng.Collapse wdCollapseStart
Loop
End With
End If
Application.ScreenUpdating = True
End Sub
Sub Show_Linker()
Hyperlinker.Show
Hyperlinker.Folder_Name.SetFocus
End Sub
Sub UnloadIt()
Unload Hyperlinker
End Sub
回答1:
Working with UserForms in VBA can be tricky, because they're actually a kind of Class. Since VBA tries to make everything exceptionally simple, classes are not obvious, nor is how to work with them correctly. There are situations where they become traps for the unwary.
So VBA makes it possible for you to work with an instance of a UserForm class without you needing to declare and instantiate a new object, as would normally be the case with a class object. The result being that the object can "hang around" and cause unexpected behavior, such as you're seeing.
The more correct way to work with a UserForm may seem like a lot more work (code to type and complexity), but it helps to keep things sorted. Indeed, this approach would theoretically allow you to have a separate UserForm for various documents.
Dim frmHyperlinker as Hyperlinker
Set frmHyperlinker = New Hyperlinker
frmHyperlinker.Folder_Name.SetFocus
frmHyperlinker.Show
'Execution waits...
'Now you're done with it, so clean up
Unload frmHyperlinker
Set frmHyperlinker = Nothing
There's an Answer in this discussion that goes into more technical detail, although the topic of that question is different from yours: Add Public Methods to a Userform Module in VBA
来源:https://stackoverflow.com/questions/36432835/word-userform-wont-open-in-second-currently-active-document-after-opened-unloa