使用personal.xls中的宏时的VBA逻辑

使用personal.xls中的宏时的VBA逻辑,vba,excel,Vba,Excel,我运行了一个电子表格报告,其中包含了1到5000行中大约50列的数据。我只对4列感兴趣,但它们永远不会位于同一位置,因为这些报告的设置对于每个客户机都有点不同。然后,我将这4列粘贴到一个新工作簿中,以便导入到另一个程序中 我创建了三个宏,如果从本地文件运行,它们可以完美地完成此任务。当我将它们加载到personal.xls以用于各种文件时,我遇到了问题。特别是工作簿/工作表引用问题 宏的一部分运行到我打算从它们生成的工作表,而其他部分作用于personal.xls文件本身。这让我很困惑,因为我没

我运行了一个电子表格报告,其中包含了1到5000行中大约50列的数据。我只对4列感兴趣,但它们永远不会位于同一位置,因为这些报告的设置对于每个客户机都有点不同。然后,我将这4列粘贴到一个新工作簿中,以便导入到另一个程序中

我创建了三个宏,如果从本地文件运行,它们可以完美地完成此任务。当我将它们加载到personal.xls以用于各种文件时,我遇到了问题。特别是工作簿/工作表引用问题

宏的一部分运行到我打算从它们生成的工作表,而其他部分作用于personal.xls文件本身。这让我很困惑,因为我没有任何行使用诸如“thisworkbook”或“activeworksheet”之类的命令

例如: -第一行编码为重命名Sheet1。宏重命名personal.xls中的Sheet1。
-下一行是四个Find命令中的第一个,它们定位我感兴趣的列所在的位置,然后移动它们。这个宏在我想要的工作表上运行得很好

我认为我最好的做法是从命名活动工作簿开始,然后将每个命令分解到工作簿级别,而不是从工作表、范围等开始


有谁能帮助我理解VBA在从personal.xls执行宏时的想法,以及如何最好地避免宏在该工作表上运行?

您可以采取两种方法。我在代码中使用一个或两个-这不是一个或其他情况

声明变量

首先在变量中定义要处理的每个工作表。我通常停留在床单层面,但那只是个人的选择。如果你想在工作簿级别,那也没关系。过程可能如下所示:

Dim shSource as Worksheet
Dim shDest as Worksheet

Set shSource = Workbooks("SomeBook").Worksheets(1)
Set shDest = ActiveWorkbook.Worksheets("Summary")
然后,每当我引用一个范围、单元格或工作表上的任何其他内容时,我都会使用该工作表对象变量作为它的开头。即使我需要进入工作簿,我也从工作表开始。例如,如果我需要关闭上面示例中的源工作簿,我将使用

shSource.Parent.Close False
我设置了我需要的表变量,然后我所做的一切都是基于这些变量

编辑

如果您正在打开或创建工作簿,那么变量无疑是一种方法。例如,如果要打开工作簿,可以使用以下两个示例之一

Dim wb As Workbook
Set wb = Workbooks.Open(C:\...)

Dim ws As Worksheet
Set ws = Workbooks.Open("C:\...).Worksheets(1)
或创建新的,以下两个示例之一:

Dim wb As Workbook
Set wb = Workbooks.Add

Dim ws as Worksheet
Set ws = Workbooks.Add.Worksheets(1)
用积木

当我只想在某个时间得到某个东西时,设置一堆变量似乎是一种浪费。在这些情况下,我使用With块,这样我仍然可以拥有完全限定的引用,但代码中没有一堆混乱

With Workbook("MyBook")
    With .Worksheets("First_Sheet")
        .Range("A1").Value = "stuff"
    End With

    With .Worksheets("Second_Sheet")
        .Range("G10").Formula = "=A1"
    End With
End With
我可能更喜欢变量方法,但我两者都使用

编辑2:隐式引用

您应该始终明确地引用您的工作簿和工作表,但如果您不这样做,了解Excel将如何运行仍然是很有指导意义的。以
Range(“A1”).Value=…
开头的代码行称为非限定引用。您引用的是一个范围,但并不是说它位于哪个工作表上或该工作表位于哪个工作簿中。根据代码所在的位置,Excel处理非限定引用的方式有所不同

在工作表的类模块中(例如使用SelectionChange之类的工作表事件),非限定引用指的是该模块表示的工作表。如果您在Sheet1模块中处理更改事件,并且您编码
x=Range(“G1”)。值
,则您所指的G1位于Sheet1上。在这种情况下,您应该使用
Me
关键字,而不是依赖Excel

在任何其他模块(如标准模块)中,非限定引用指的是ActiveSheet。相同的
x=Range(“G1”)。标准模块中的值
code是指具有焦点的任何一页上的G1


Excel对不合格引用的处理非常可靠。通过依赖Excel解析合格的引用,您可以轻松创建健壮的代码。但你不应该。如果您对每个引用进行限定,那么您的代码将更具可读性,更易于调试。我对每一个推荐人都有资格。这不是我“总是”做的事情之一,除非当我懒惰的时候——我真的100%的时间都这么做。

如果包含一些相关的代码,回答起来会更容易。一般来说,您的做法是正确的,因为您应该始终完全限定工作簿名称。+1,还有一件事要补充,以便让OP更好地理解代码中可能出现的错误:如果在访问
范围
单元格
对象时不使用显式工作表引用,Excel隐式使用
ActiveWorkbook
。这些工作簿是临时文件。我从数据库中运行它们,然后在需要时保存,但在运行宏之前,该文件永远不会使用文件名保存。我刚才打开的文件不认为是activeworkbook吗?你是说personal.xls被认为是Active工作簿,即使在我打开一个新文件之后?如果是这样的话,在我的每个宏的开头激活一个简单的ThisWorkBook.Activate可以解决引用问题,并使宏不是在personal.xls上运行,而是在我想要的工作表上运行,对吗?是的,您刚才打开的工作簿是活动的。Open方法返回对工作簿的引用,因此此时最好指定一个变量。Personal.xls几乎从未被视为活动工作簿,因为它几乎总是隐藏的。如果您的代码位于Personal.xls中,并且您试图激活它,您将收到一个错误,因为您无法激活隐藏的工作簿。不要依赖Excel来引用正确的工作簿。始终明确引用工作簿和工作表。声明所有my变量后的第一行代码是ActiveSheet.Name=“Planning”。这会导致我的Personal.xls文件中的Sheet1重命名为“Planning”,而我需要的是我正在创建的当前工作表