VBA Word宏允许用户多次选择和复制文本

时间:2018-08-29 23:20:03

标签: vba ms-word

我正在使用Microsoft Word处理VBA脚本,该脚本允许用户选择要复制到剪贴板的文本,以便可以将其导出到Excel文件。当剪贴板中的内容复制到模板Excel文件中时,用户将进行很多选择,最后指示完成。

有两种形式:第一种(在下面的代码中为UserForm1)向用户查询Word文件名。 filename变量将传递给第二种形式。第二种形式(frmModeLessForInput)是无模式形式。我需要的行为是程序控制转到带有两个按钮“继续”和“完成”的第二种形式。

允许用户浏览文档并将光标放置在文档中的任何位置。然后,当按下“继续”时,表单将调用子例程(Highlight_Sentence),以将所选文本复制到“剪贴板”变量中。按下“完成”后,控制权将传递到被调用的主模块,该主模块随后将剪贴板复制到Excel文件。

下面是代码。我在注释中指出了我对代码有麻烦的地方。一个问题是在ThisDocument模块中定义为Public的变量未在用户窗体及其子例程中定义。

第二个问题是在主模块中,应该显示frmModelessForInput并且不应将控制权转移到下一条语句{MsgBox“句子现在将被复制到Excel文件”。...这是我在这里将把代码复制到剪贴板上的代码中。},但消息出现在运行frmModelessForInput窗体之前...因此剪贴板将为空。

第三个问题是,在frmModelessForInput表单中,语句str_clipboard = str_clipboard + str_clipboard_line不起作用。每次按下“继续”按钮,str_clipboard都会丢失先前的内容。

感谢您为解决这些问题提供的任何帮助。由于VBA编程对我来说是一个副业,所以我仍在学习。

请注意,这是一个更新的问题Pause VBA Word macro, allow user to make a selection, and restart where it left off,其中增加了有关需求和示例代码的更多细节。

主要模块:

Option Explicit
Public str_clipboard As String
Public txt_active_document As String
Public i_how_many_sentences As Integer
Private Sub Test_master_macro()
    UserForm1.Show
    i_how_many_sentences = 0
    Call DisplayModeless
    MsgBox "Sentences will now be copied to Excel file" 'Problem: this msg displays before the frmModelessForInput is displayed
End Sub
Sub DisplayModeless()
    Dim frm As frmModelessForInput
    Set frm = New frmModelessForInput
    With frmModelessForInput
        .str_word_doc_filename = txt_active_document
        .str_no_copied = "0"
        .Show False
    End With
    Set frm = Nothing
End Sub

USERFORM1:表单具有供用户向用户输入文档文件名的字段(str_filename)和用于关闭表单的命令按钮(cmd_start_selecting_text)

Private Sub cmd_start_selecting_text_Click()
    'User enters filename on form for use in frmModelessForInput subroutine 
    txt_active_document = UserForm1.str_filename  'Problem: VBA reports txt_active_document as undefined even though it is a Public variable
    Unload Me
End Sub

FRMMODELESSFORINPUT:表单显示在UserForm1中输入的Word文件的文件名以及已将多少个句子复制到剪贴板

Option Explicit

Private Sub cmdContinue_Click()
 Dim str_clipboard, str_clipboard_line As String
       Call Highlight_Sentence(str_clipboard_line)
        i_how_many_sentences = i_how_many_sentences + 1 'Problem: VBA reports i_how_many_sentences as undefined even though it is a Public variable 
        frmModelessForInput.str_no_copied = i_how_many_sentences  'Same Problem
    str_clipboard = str_clipboard + str_clipboard_line 'Problem: each time I select a new text/sentence str_clipboard does not contain the contents of the previous selection
End Sub


Private Sub cmdDone_Click()
    Me.Hide
End Sub

Private Sub UserForm_Activate()
    'Position the form near the top-left of the window
    'So that the user can work with the document
    Me.Top = Application.ActiveWindow.Top + 15
    Me.Left = Application.ActiveWindow.Left + 15
End Sub

Private Sub Highlight_Sentence(clipboard As String)
    'This sub extends the selection to the entire sentence and copies the selection, the page number on which the selection is contained and the filename to the clipboard variable
    Dim txt_sentence, txt_page_no As String
    With Selection
     ' Collapse current selection.
     .Collapse
     ' Expand selection to current sentence.
     .Expand Unit:=wdSentence
    End With
    txt_sentence = Selection.Text
    txt_page_no = Selection.Information(wdActiveEndPageNumber)
    clipboard = txt_active_document & vbTab & txt_page_no & vbTab & txt_sentence & vbCrLf 'Problem: VBA reports txt_active_document as undefined even though it is a Public variable 
End Sub

1 个答案:

答案 0 :(得分:1)

根据您所说的,您正在ThisDocument类模块中运行此操作,除非您完全使用类名称来限定对这些Public变量的引用,这就是为什么您无法从UserForms类模块访问它们的原因。

如果要将“主模块”代码保留在ThisDocument类模块中,则每当引用这些Public变量时,都需要向命令中添加ThisDocument.str_clipboard

但是,我建议将主模块放置在诸如NewModule之类的常规模块中,如果需要在Document_Open事件中运行它,则可以在的Private Sub Document_Open事件中调用主模块及其公共变量。 ThisDocument类模块。

您的Msgbox出现在错误的时间,因为您正在显示无模式的用户窗体,这意味着在显示用户窗体后,VBA脚本线程将继续运行。将Msgbox移至要显示的第二个UserForm的UserForm_Activate例程,或将其移至第一个UserForm的Click_Done例程,然后再隐藏或卸载它。

最后,您并不是真正使用剪贴板,使用该术语会使您的代码混乱。我认为您应该重命名。您的代码似乎也只是建立一个连续的文本字符串。那真的是您想要做的吗?或者,您是否真的要捕获每个选定的文本字符串,并最终将每个文本字符串放入Excel工作表中的单独单元格中?如果是这种情况,请对单独的文本字符串使用数组。