如何为工作簿声明灵活变量?

时间:2019-09-26 17:39:32

标签: excel vba

我想以某种方式声明动态工作簿变量,以便我可以更改工作簿文件名而不会引起错误。我最初的想法是使用Set Variable = ActiveWorkbook,但这似乎会带来一些特殊的错误:

    Set WkBk1 = ActiveWorkbook

    MsgBox (WkBk1.Name)
    WkBk1.Worksheets(1).Select

上面的代码本身可以正常工作。然后,按照相同的步骤,打开一个新的工作簿并运行以下命令:

    Set WkBk2 = ActiveWorkbook

    MsgBox (WkBk2.Name)
    WkBk2.Worksheets(1).Select
    WkBk1.Worksheets(1).Select

我在最后一行“运行时错误1004;工作表类的选择方法失败”出现错误。谁能解释这个问题的根源?我猜想这与使用ActiveWorkbook声明变量或在工作簿之间切换的错误方法有关。

我应该提到打开的文件是在excel中打开的.dat文件。

最终,我想拥有将两个工作表(无论文件名如何)分配给它们自己的变量的代码。然后,我想在两个工作簿之间复制和粘贴数据。

实际代码如下。问题出在for循环中的copy语句。
“运行时错误'438'对象不支持此属性或方法”。我以前使用过类似的语法,无法弄清楚为什么它在这里不起作用。

Sub Import3()
    ' Imports TSS samples from backlog

    Dim TSS As Workbook, Backlog As Workbook
    Dim Sample As Range, SearchRange As Range
    Dim Count As Long

    Set TSS = ActiveWorkbook

    ChDir ("C:\lwuser6")
    Workbooks.OpenText Filename:="C:\lwuser6\BACKLOG.DAT", Origin:=437, _
           StartRow:=1, DataType:=xlFixedWidth, FieldInfo:=Array(Array(0, 1), Array(7, _
           1), Array(68, 1), Array(78, 1), Array(86, 1), Array(126, 1), Array(150, 1)), _
           TrailingMinusNumbers:=True
        ' for some reason _ has to be in between "Array(7, _1)"
            ' Can't be between list elements of encompassing list "Array"
    Set Backlog = ActiveWorkbook

    Set SearchRange = Backlog.Worksheets("BACKLOG").Range(Cells(1, 1), _
        Cells(Rows.End(xlDown).Row, 1))
    Count = 14

    For Each Sample In SearchRange
        Backlog.Range(Sample(1, 1), Sample(1, 3)).Copy
        TSS.Range("G" & Count).PasteSpecial (xlValues)
        Count = Count + 2
    Next

End Sub

1 个答案:

答案 0 :(得分:2)

我热烈建议您通过Rubberduck inspections(它是免费的和开放源代码的;我管理该项目)来运行代码,因为它不仅可以解释您要询问的特定错误,而且还可以防止您进入许多常见的初学者陷阱。

问题在于BacklogWorkbook对象,并且Workbook没有Range成员:

"Member not found" inspection result

  

未找到成员

     

成员访问调用是针对Rubberduck无法解析或无法找到成员的扩展接口进行的。如果VBA在运行时无法解析类型,则将引发错误438。 [...]

您需要Worksheet才能访问RangeWorkbook无效。

请注意,随后的TSS.Range调用同样是非法的;-)


采取这个:

Set Backlog = ActiveWorkbook

通过捕获Workbook返回的Workbooks.Open对象,摆脱对打开工作簿的副作用的依赖:

Set Backlog = Workbooks.OpenText(Filename:="C:\lwuser6\BACKLOG.DAT", Origin:=437, _
       StartRow:=1, DataType:=xlFixedWidth, FieldInfo:=Array(Array(0, 1), Array(7, _
       1), Array(68, 1), Array(78, 1), Array(86, 1), Array(126, 1), Array(150, 1)), _
       TrailingMinusNumbers:=True)

没关系,Workbooks.OpenText不会返回Workbook对象引用。

然后接受:

 Backlog.Worksheets("BACKLOG")

并将其拉入局部变量:

Dim backlogSheet As Worksheet
Set backlogSheet = Backlog.Worksheets("BACKLOG")

现在,您可以在需要该特定工作表的任何地方使用它:

With backlogSheet
    Set SearchRange = .Range(.Cells(1, 1), .Cells(.Rows.End(xlDown).Row, 1))
End With

..并且这应该起作用,尽管IMO向Range属性提供Worksheet.Range对象感觉有些错误(如果Sample范围不在{上,则会引发错误1004 {1}}):

backlogSheet

不确定要粘贴backlogSheet.Range(Sample(1, 1), Sample(1, 3)).Copy 工作簿中的哪个特定工作表,但是适用相同的原理。就是说,您甚至可能不需要参与剪贴板:

TSS