【问题标题】:Using modules to run all sheets in a workbook - VBA使用模块运行工作簿中的所有工作表 - VBA
【发布时间】:2016-10-08 02:41:31
【问题描述】:

对于我一直在从事的一个项目,我终于完成了用于分析季度计划的代码,现在我正试图让我的代码分析工作簿中的所有四张工作表(每张工作表代表一个不同的季度)。

我遇到的错误是“对象_global的运行时错误1004方法范围失败”

我目前正在使用一个模块来运行所有四张纸的代码。我的代码如下:

sub scheduleAnalyzer()

Dim ws_count As Integer
Dim I As Integer

ws_count = ActiveWorkbook.Worksheets.Count

For I = 1 To ws_count 

    'then my code which analyzes the schedule and prints results on a new sheet

Next I

End Sub

这是我第一次使用模块来运行代码。错误发生在以下地方:

Dim month1 As Range
Dim month2 As Range
Dim month3 As Range
Dim month1_start As String
Dim month1_end As String
Dim month2_start As String
Dim month2_end As String
Dim month3_start As String
Dim month3_end As String  

month1_start = "B6"
monthRow = 6
dayRow = 7

For k = 2 To maxCol
    If Cells(monthRow, k).Interior.color = colorArray(10) And Cells(monthRow, k + 1).Interior.color = colorArray(11) Then
        month1_end = Cells(monthRow, k).Address
        month2_start = Cells(monthRow, k + 1).Address
    ElseIf Cells(monthRow, k).Interior.color = colorArray(11) And Cells(monthRow, k + 1).Interior.color = colorArray(10) Then
        month2_end = Cells(monthRow, k).Address
        month3_start = Cells(monthRow, k + 1).Address
    ElseIf Cells(monthRow, k).Interior.color = colorArray(10) And Cells(monthRow, k + 1).Interior.color = colorArray(9) Then
        month3_end = Cells(monthRow, k).Address
    End If
Next k

month1 = Range(month1_start, month1_end) '<--------------- run-time error 1004 method range of object _global failed
month2 = Range(month2_start, month2_end)
month3 = Range(month3_start, month3_end)

我知道当我只为一张特定的工作表运行时,此代码有效。这是在整个工作簿中运行它的最佳方式吗?如果是这样,我该如何解决这个错误?我尝试使用带有“ActiveWorkbook.Worksheets()”的 With 语句,但我无法命名一个单数 ws 放在括号中,因为我希望它在所有四个中都运行。

【问题讨论】:

  • 处理四分之一的代码是子程序吗?您是否将适当的工作表作为参数传递给该子例程?或者处理四分之一的代码是否刚刚嵌入到您的主模块中(即您问题中的第二个代码块只是插入到您的第一个代码块的循环中)? (您的问题几乎可以肯定是由于处理代码不知道它正在处理哪个工作表,但是在没有看到确定要处理哪个工作表的代码的情况下帮助您解决这个问题有点困难。)
  • @YowE3K 是的,一切都在一个sub scheduleAnalyzer() 之内。我相信问题的一部分是它不知道运行代码的工作表(季度)。使用模块是让代码在所有工作表中运行的最佳方法吗?
  • month1 = Range(month1_start, month1_end) 应该是 Set month1 = Range(month1_start, month1_end),但这让我想知道代码是如何在一张纸上工作的。
  • 就个人而言,我将拥有在子例程中处理单个工作表的代码,并且我会向该子例程传递一个参数,说明它应该使用哪个工作表。例如。 Sub ProcessAQuarter(ws As Worksheet) With ws ... Set month1 = .Range(month1_start, month1_end) ... End With End Sub 然后在主模块中调用该子程序四次。但这只是我个人的偏好(“分隔”代码)——它可以在主模块中轻松完成。
  • 使用工作表对象实例限定 Range 调用,例如Sheet1.RangeCells 同上;不合格,这些函数隐式引用活动工作表。向它们传递引用其他工作表的参数会导致您遇到错误。

标签: vba excel


【解决方案1】:

据我所知,由于未使用 Set 设置 Range 变量,您肯定会遇到错误,但这将是“对象变量或未设置块变量”错误。

您得到的“对象_global 的方法范围失败”错误可能是因为尚未设置month1_end,这可能是因为您的代码从未设置变量maxCol(因此您的For k = 循环永远不会有已执行),或者您可能在问题中未发布的代码中设置了 maxCol,在这种情况下,month1_end 可能没有正确设置,因为它没有处理您想要的工作表。

希望以下代码可以解决其中的一些错误,并为您提供一个可以构建循环的结构:

sub scheduleAnalyzer()

    Dim ws As Worksheet
    Dim month1 As Range
    Dim month2 As Range
    Dim month3 As Range
    Dim month1_start As String
    Dim month1_end As String
    Dim month2_start As String
    Dim month2_end As String
    Dim month3_start As String
    Dim month3_end As String  
    'monthRow is not defined in original code
    Dim monthRow As Long
    'dayRow is not defined in original code
    Dim dayRow As Long
    'k is not defined in original code
    Dim k As Long
    'maxCol isn't defined or assigned a value in original code
    Dim maxCol As Long
    maxCol = 36 ' <-- purely random number - please assign it how you were assigning it when code was working

    For Each ws in ActiveWorkbook.Worksheets

        With ws

            month1_start = "B6"
            monthRow = 6
            dayRow = 7

            For k = 2 To maxCol
                If .Cells(monthRow, k).Interior.color = colorArray(10) And .Cells(monthRow, k + 1).Interior.color = colorArray(11) Then
                    month1_end = .Cells(monthRow, k).Address
                    month2_start = .Cells(monthRow, k + 1).Address
                ElseIf .Cells(monthRow, k).Interior.color = colorArray(11) And .Cells(monthRow, k + 1).Interior.color = colorArray(10) Then
                    month2_end = .Cells(monthRow, k).Address
                    month3_start = .Cells(monthRow, k + 1).Address
                ElseIf .Cells(monthRow, k).Interior.color = colorArray(10) And .Cells(monthRow, k + 1).Interior.color = colorArray(9) Then
                    month3_end = .Cells(monthRow, k).Address
                End If
            Next k

            Set month1 = .Range(month1_start, month1_end)
            Set month2 = .Range(month2_start, month2_end)
            Set month3 = .Range(month3_start, month3_end)

        End With

    Next

End Sub

编辑以下 cmets:

启用名为 scheduleAnalyzer 的现有 Sub(当前正在为单个活动工作表工作)处理工作簿中每个工作表的极简方法是:

Sub RunAllScheduleAnalyzer
    Dim ws As Worksheet
    For Each ws in Worksheets
        ws.Activate
        scheduleAnalyzer
    Next
End Sub

我不建议将此作为短期解决方法之外的任何其他方法 - 使用 Activate(和 Select)来确定 VBA 应用程序将处理哪些单元格是应尽可能避免的事情,因为它导致太多“但是这段代码通常可以工作!?!?”问题类型。

【讨论】:

  • 我明白你在说什么。我的代码大约是。 600 行(并且它有效),所以这将是很多编辑。让我们后退一分钟以更好地查看问题。我在工作表模块 Sheet1 (OCT-DEC) 中有我的工作代码。我还需要它在接下来的三张纸上运行。有没有办法我可以简单地将一些东西放在ActiveWorkbook.Worksheets("OCT-DEC") scheduleAnalyzer() 的行中,然后重复它并更改工作表的名称?
  • 我知道我的整体问题很简单,我只是不了解 VBA 中模块的层次结构。不幸的是,学习 VBA 的资源并不像 Python 或其他任何东西那样丰富。
  • @JonSnow - 我已经编辑了我的答案,以展示一种简单的方法,您可以获得当前成功处理单个工作表的 Sub 以处理所有工作表。
猜你喜欢
  • 1970-01-01
  • 2021-01-05
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多