如何将对象传递给表单?

时间:2018-09-05 12:12:30

标签: excel vba ms-word

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

表单frmModelessForInput允许用户选择复制到字符串变量(str_clipboard)的文本,按“继续”按钮重复选择其他文本,然后在菜单项中按“完成”。文本字符串被复制到剪贴板,然后粘贴到之前打开的Excel文件中。

问题是,当我尝试将Windows剪贴板中的内容粘贴到frmModelessForInput窗体的cmdDone子项中的Excel文件中时,wb_open对象大约一半时间给我一个错误91。我相信在Check_Excel_RTM_Template_Test子目录中也遇到了同样的问题,并通过将oExcel对象传递给子目录来解决了该问题。我正在尝试将oExcel对象传递给表单,但是即使我按照以下建议合并了表单的Property,它也会呈现与上一个子相同的错误。

我创建了“最小”代码,并添加了注释以解释每个子组件正在完成的关键任务。我已经运行了此代码,但失败的方式与我的“生产”代码相同。

预先感谢您帮助我解决问题。

主模块

' This is the minimal master module where I open the Excel Template and Word document to process
Option Explicit
Public str_clipboard As String
Public i_how_many_sentences, i_starting_row_ID As Integer
Public str_active_document As String
Public str_Excel_Filename As String
Public b_abort As Boolean
Public i_rows_of_data As Integer


Sub Master_Module_Test()
Dim oExcel As Object
Set oExcel = New Excel.Application
str_Excel_Filename = "C:\Test\Excel_Template.xlsx"
str_active_document = "C\Test\Doc_to_process.docx"
Documents.Open (str_active_document)

oExcel.Visible = True
oExcel.ScreenUpdating = True 
oExcel.Workbooks.Open str_Excel_Filename
Call Check_Excel_RTM_Template(oExcel)
i_how_many_sentences = 0
Call Select_Sentence_Form_Test(oExcel)
End Sub

主模块中的子

   ' This sub now works without errors
    ' The calling routine passes the object oExcel....this approach works
    ' Previously I didn't pass oExcel but used the following statements
    ' Dim wb_open as Workbook
    ' Set Wb_open = ActiveWorkBook
    ' This also worked sometimes and failed about half the time

    ' This sub checks the Excel file whether it is of the expected format and then selects the cell where the new data will be pasted
    ' I have only included the statement to do the selection
    ' This sub works without any errors
    Sub Check_Excel_RTM_Template_Test(oExcel As Object)
        oExcel.ActiveSheet.range("A6").Select
    End Sub

主模块中的子

' This sub activates the frmModelessForInput so that the user can select sentences; the form executes and works as expected
Sub Select_Sentence_Form_Test(wb_open As Object)
    Dim frm As frmModelessForInput
    Set frm = New frmModelessForInput
' Here is where I set the property of the frmModelessForInput to open Excel workbook as suggested in the response 
    Set frmModelessForInput.Book = wb_open
    With frmModelessForInput
        .str_word_doc_filename = str_active_document
        .str_no_copied = "0"
        .Show False
    End With
    Set frm = Nothing
End Sub

从完整路径名提取文件名的功能。

Function getName(pf)
getName = Split(Mid(pf, InStrRev(pf, "\") + 1), ".")(0) & ".xlsx"
End Function

frmModelessForInput表单代码

' Here I implemented the suggested property for the form 
' I changed the declaration to "Object" since oExcel in Master_Module_Test is declared as an object
Option Explicit
Private m_Book As Object

Public Property Get Book() As Object
   Set Book = m_Book
End Property

Public Property Set Book(ByRef Value As Object)
   Set m_Book = Value
End Property



' This sub works without errors
Private Sub cmdContinue_Click()
    Dim str_clipboard_line As String
    Dim i_row_number As Integer

    ' When the "Continue" button is pressed the code selects the sentence at the cursor and adds the contents to str_clipboard variable
    i_row_number = i_how_many_sentences + i_starting_row_ID
    i_how_many_sentences = i_how_many_sentences + 1
    Call Highlight_Sentence(str_clipboard_line, i_row_number)
    frmModelessForInput.str_no_copied = i_how_many_sentences
    str_clipboard = str_clipboard + str_clipboard_line
End Sub

Private Sub cmdDone_Click()
    Unload frmModelessForInput
 '  When the "Done" button is pressed the contents of the str_clipboard variable is copied to the Windows clipboard
    Dim str_filename As String
    str_filename = getName(str_Excel_Filename)
    MsgBox "I will now copy the data to the Excel file."
    Dim wb_open As Object
    Set wb_open = ActiveWorkbook
    Call SendToClipboard(str_clipboard) 'This sub puts the contents of str_clipboard into the Windows clipboard
    ' The following statement works sometimes but other times it has runtime error 91: Object variable or With block variable not set
    wb_open.ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
    MsgBox "Done pasting data to: " & getName(str_Excel_Filename)    
End Sub


' This sub works without errors
Private Sub Highlight_Sentence_Test(clipboard As String, i_row_no As Integer)
    Dim txt_sentence, txt_page_no As String 
    Dim txt_section_index 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)
'I Use tabs to line up data in the correct columns in template file
    clipboard = i_row_no & vbTab & str_active_document & vbTab & txt_page_no & vbTab & vbTab & vbTab & vbTab & txt_sentence & vbCrLf
End Sub

2 个答案:

答案 0 :(得分:1)

这可以通过在表单中​​添加新的Property来完成。在您的表单中,添加以下代码:

Private m_Book As WorkBook

Public Property Get Book() As WorkBook
   Set Book = m_Book
End Property

Public Property Set Book(ByRef Value As WorkBook)
   Set m_Book = Value
End Property

然后在您的调用代码中,添加要使用的工作簿,如下所示:

Set frmModelessForInput.Book = wb_open

或:

Set frmModelessForInput.Book = ActiveWorkbook

答案 1 :(得分:0)

基本问题是问题中的代码不适用于正确的Excel对象。由于与Excel有关的所有事情都声明为数据类型Object,因此VBA无法提供更准确的错误消息-它必须猜测是什么意思。设置对Excel对象库的引用(工具/参考)并声明确切的数据类型可能会有所帮助,直到代码正常工作为止。然后,如果要使用后期绑定,则可以将声明更改为Object

这里有一些示例,说明了如何传递错误的对象类型,这导致VBA感到困惑。

在以下过程中,我添加了一个Excel.Workbook对象声明,并在打开工作簿时实例化它。由于UserForm需要使用工作簿对象,因此此将传递给Select_Sentence_Form_Test ...

Sub Master_Module_Test()
    Dim oExcel As Object
    Dim wb As Excel.Workbook 'Object
    Set oExcel = New Excel.Application
    str_Excel_Filename = "C:\Test\Excel_Template.xlsx"
    str_active_document = "C\Test\Doc_to_process.docx"
    Documents.Open (str_active_document)

    oExcel.Visible = True
    oExcel.ScreenUpdating = True
    Set wb = oExcel.Workbooks.Open(str_Excel_Filename)
    Call Check_Excel_RTM_Template(oExcel)
    i_how_many_sentences = 0
    Call Select_Sentence_Form_Test(wb)
End Sub

在代码中的问题中,正在传递 Excel应用程序,并将其分配给Book属性。 VBA允许这样做,因为所有内容都键入为Object。但是,当需要使用工作簿时,它就不起作用了(从逻辑上讲是不可行的)。

Sub Select_Sentence_Form_Test(wb_open As Object) 'As Excel.Workbook
    Dim frm As frmModelessForInput
    Set frm = New frmModelessForInput
' Here is where I set the property of the frmModelessForInput to open Excel workbook as suggested in the response
    Set frmModelessForInput.Book = wb_open
    With frmModelessForInput
        .str_word_doc_filename = str_active_document
        .str_no_copied = "0"
        .Show False
    End With
    Set frm = Nothing
End Sub

然后cmdDone_Click不能与属性一起使用,并且即使没有ActiveWorkbook对象限定符,也尝试访问Excel.Application,但此过程中也不可用。这是Word VBA,它不是“知道” ActiveWorkbook

相反,代码应使用Book属性(毕竟是创建它的原因)。

Private Sub cmdDone_Click()
    Unload frmModelessForInput
 '  When the "Done" button is pressed the contents of the str_clipboard variable is copied to the Windows clipboard
    Dim str_filename As String
    str_filename = getName(str_Excel_Filename)
    MsgBox "I will now copy the data to the Excel file."
'''        Dim wb_open As Object
'''        Set wb_open = ActiveWorkbook 'can' work without Excel.Application
    Call SendToClipboard(str_clipboard) 'This sub puts the contents of str_clipboard into the Windows clipboard
    ' Uses the Book property 
    Me.Book.ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
    MsgBox "Done pasting data to: " & getName(str_Excel_Filename)
End Sub

请注意,我尚未对此进行测试,因为设置环境会花费太多时间。