【问题标题】:VBA code returning compile error for if statementVBA 代码返回 if 语句的编译错误
【发布时间】:2019-11-19 14:05:12
【问题描述】:

这是我在 Sheet1 上的代码的简要说明(我对 VBA 很陌生);

我有三个工作簿,一个工作簿(Sheet1 是写入 VBA 代码的名为“Operator”的工作表的代号)和另外两个具有不同文件路径的外部工作簿,称为“Changes”(文件路径是:Database_IRR 20-2S New.xlsm 在我的代码中,这是 CHANGES 数据库)和“HE171”(文件路径是:我的代码中的 Technology_Changes\Changes_Database_IRR_20-2S_New.xlsm,这是 MAIN 数据库)。

1) 如果操作员在 Commandbutton1 上点击“YES”,我希望代码检查 Sheet1 中单元格“H4”中的值是否存在于 MAIN 数据库中“HE 171”表的 A 列中,

2) 如果“H4”中的值在主数据库中存在,我希望代码检查 Sheet1 中单元格“H4”中的值是否存在于 CHANGES 数据库中“更改”表的 A 列中如果“更改”表中存在“H4”的值,我希望代码使用模块 13(我尚未发布)在“更改”表的两列中设置日期和时间戳,以及模块8将某些列“K”中的值发送到“更改”表内的单元格(例如,我希望模块8过滤A列中“H4”的值并将其放在第2行中,因为第1行有我的标题,并将“K30”的值从 Sheet1 放置到“更改”表中的单元格 (1,6))

2.1)如果“H4”中的值在主数据库中存在,并且如果“H4”的值在“更改”表中不存在,我希望代码使用模块 14(尚未发布)将“H4”的值添加到 CHANGES 数据库的“CHANGES”表中的新行的 A 列,模块 13(我没有发布它)在“CHANGES”的两列中设置日期和时间戳工作表和模块 8 将某些列“K”中的值发送到“更改”工作表内的单元格

3) 如果主数据库中不存在“H4”中的值,我希望代码使用模块 7(尚未发布)将“H4”的值添加到新行的 A 列中主数据库中的“HE 171”表,模块 14(尚未发布)将“H4”的值添加到模块 13“更改”表中新行的 A 列(我尚未发布它) 在“更改”表的两列中设置日期和时间戳,模块 8 将某些列“K”中的值发送到“更改”表内的单元格

5) 如果操作员在 Commandbutton1 上点击“NO”或“x”,我希望代码使用密码保存并关闭两个外部工作簿(主数据库和更改数据库),然后保护 Sheet1 并保留它打开时什么都没有清除

    Option Explicit


    Dim Cd As Workbook
    Dim Md As Workbook

    Dim Changes As Worksheet
    Dim HE171 As Worksheet

    Dim nConfirmation As Integer

    'Actions for when the "Confirm Changes" button is clicked
    Private Sub CommandButton1_Click()


        Set Cd = Workbooks.Open("\FILEPATH/Technology_Changes\Changes_Database_IRR_20-2S_New.xlsm")
        Set Md = Workbooks.Open("\FILEPATH\Database_IRR 20-2S New.xlsm")


        Set Changes = Cd.Sheets("Changes")

        On Error Resume Next

        Set HE171 = Md.Sheets("HE 171")


        'Creating the "Yes or No" message box displayed when operators click the "Confirm Changes" button on the Operator Sheet
        nConfirmation = MsgBox("Do you want to send a notification about the sheet update?", vbInformation + vbYesNo, "Sheet Updates")

        'Declares the variable for the string that we will be finding, which is the key in this case (for the With statement)
        Dim FindString As String

        'Declares the variable for the range in which we will be locating the string (for the With statement)
        Dim RNG As Range

        'Sets the string we need to find as the key value which is in cell "H4" of the Operator sheet (for the With Statement)
        FindString = Sheet1.Range("H4").Value

        'Actions if "YES" is clicked when the "Confirm Changes" button is clicked on the Operator Sheet
        If nConfirmation = vbYes Then

            'Opens and activates the Main Database workbook, with "HE 171" as the active sheet
            HE171.Activate

            'Temporarily unprotects the Main Database Workbook and Operator sheet (this is the sheet the code is in)
            ActiveSheet.Unprotect "Swrf"
            Sheet1.Unprotect "Swrf"

            'Searches all of column A in the Main Database in sheet "HE 171" for the string(key)
            With ActiveSheet.Range("A:A")            'searches all of column A
                Set RNG = .Find(What:=FindString, _
                                After:=.Cells(.Cells.Count), _
                                LookIn:=xlValues, _
                                LookAt:=xlWhole, _
                                SearchOrder:=xlByRows, _
                                SearchDirection:=xlNext, _
                                MatchCase:=False)
                'End With
                '////////////////////////////////////////////////////////////////////////////

                'Actions if the key is present in column A of the MAIN database
                If Not RNG Is Nothing Then

                    'Since Key is present in main database, now opens and sets the Changes_Database "Changes" Sheet as active contents
                    Changes.Activate

                    'Temporarily unprotects the Changes_Database
                    ActiveSheet.Unprotect "Swrf"

                    'Declares the variable for the string that we will be finding, which is the key in this case (for the With statement)
                    Dim FindString2 As String

                    'Declares the variable for the range in which we will be locating the string (for the With statement)
                    Dim RNG2 As Range

                    'Sets the string we need to find as the key value which is in cell "H4" of the Operator sheet (for the With Statement)
                    FindString2 = Sheet1.Range("H4").Value

                    'Searches all of column A in the Changes_Database "Changes" sheet for the string(key)
                    With ActiveSheet.Range("A:A")    'searches all of column A
                        Set RNG2 = .Find(What:=FindString, _
                                         After:=.Cells(.Cells.Count), _
                                         LookIn:=xlValues, _
                                         LookAt:=xlWhole, _
                                         SearchOrder:=xlByRows, _
                                         SearchDirection:=xlNext, _
                                         MatchCase:=False)


                        'Actions if the key is present in column A of the Changes_Database (So a change request was previously made for the key and it already has a row in the "Changes" sheet)
                        If Not RNG2 Is Nothing Then

                            'Calls module 13 to set the date and time of the requested change in the "Changes" sheet
                            Call TimeStamp

                            'Calls module 8 to send over the requested changes to the "Changes" sheet
                            Call SendChanges

                            'On Error Resume Next

                            'Protects the Changes_Database
                            ActiveSheet.Protect "Swrf"

                            '////////////////////////////////////////////////////////////////////////////

                            'Actions if the key DOES NOT exist in column A of the Changes_Database


                        Else

                            'Module 14: Adds a new row with the key to the Changes_Database
                            Call NewPart2

                            'Calls module 13 to set the date and time of the requested change in the "Changes" sheet
                            Call TimeStamp

                            'On Error Resume Next

                            'Calls module 8 to send over the requested changes to the "Changes" sheet
                            Call SendChanges

                        End If

                    End With

                Else

                    'Module 7:  Adds a new row with the key to the MAIN Database
                    Call NewPart

                    'Module 14: Adds a new row with the key to the Changes_Database
                    Call NewPart2

                    'Module 13: to set the date and time of the requested change in the "Changes" sheet
                    Call TimeStamp

                    'Module 10: Fills in the date and time the key was created for the "HE 171" sheet
                    Call TimeStamp2

                    'On Error Resume Next

                    'Calls module 8 to send over the requested changes to the "Changes" sheet
                    Call SendChanges

                End If

            End With


            'Actions if "No" is clicked when the "Confirm Changes" button is clicked on the Operator Sheet
        Else

            '''''''If nConfirmation = vbNo Then


            'Protects Changes_Database (as it was activated after the Main Database and is therefore the active contents and saves/closes it
            Changes.Activate
            ActiveSheet.Protect "Swrf"
            ActiveWorkbook.Save
            ActiveWorkbook.Close SaveChanges:=True

            'Sets Main Database as active contents to protect it, save it and close it
            HE171.Activate
            ActiveSheet.Protect "Swrf"
            ActiveWorkbook.Save
            ActiveWorkbook.Close SaveChanges:=True

            'Protects Operator Sheet and saves it
            Sheet1.Protect "Swrf"
            'Workbook.Close SaveChanges:=True

        End If

    End Sub

这里是 模块 8, 目前我的代码没有粘贴当前工作簿中 k 列的值(这是写入 VBA 代码的地方,在表 1 中标题为“操作员”的工作簿)。

    'Module 8: Sends the requested changes over to the "Changes" sheet

    Sub SendChanges()

        Set Cd = Workbooks.Open("\FILEPATH\Technology_Changes\Changes_Database_IRR_20-2S_New.xlsm")
        Set Changes = Cd.Sheets("Changes")

        Changes.Activate
        ActiveSheet.Unprotect "Swrf"

        '////////////////////////////////////////////////////////////////////////////'

        'Only executes this macro if the the new/change requested value in column "K" of the Operator sheet has a numerical value present
        If Sheet1.Range("K30").Value <> "" Then


            'Filters the Changes_Database for the part name & process (the key) which is in cell "H4" of the Operator sheet
            ActiveSheet.Range("A1").AutoFilter Field:=1, Criteria1:=Sheet1.Range("H4")


            'Copies the changed content in cell "K30" from the Operator Sheet
            Sheet1.Range("K30").Copy

            'Finds the row in the Changes_Database that has matched all filters and;
            'Pastes the value of cell "K30" into the matching parameter cell in the Changes_Database,which is in column 6 in this case
            ActiveSheet.AutoFilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, 6).PasteSpecial xlPasteValues


            'Removes all filters and shows all data'
            ActiveSheet.ShowAllData


        End If
        '////////////////////////////////////////////////////////////////////////////'


        'Repeats the If and Else code bordered with slashes "////", for all parameter changes in the K column ("KXX")'
        If Sheet1.Range("K31").Value <> "" Then
            ActiveSheet.Range("A1").AutoFilter Field:=1, Criteria1:=Sheet1.Range("H4")
            Sheet1.Range("K31").Copy
            ActiveSheet.AutoFilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, 7).PasteSpecial xlPasteValues

            ActiveSheet.ShowAllData
        End If


        If Sheet1.Range("K32").Value <> "" Then
            ActiveSheet.Range("A1").AutoFilter Field:=1, Criteria1:=Sheet1.Range("H4")
            Sheet1.Range("K32").Copy
            ActiveSheet.AutoFilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, 8).PasteSpecial xlPasteValues

            ActiveSheet.ShowAllData
        End If

        'On Error Resume Next

        Sheet1.Range("K30:K115").ClearContents

        'On Error Resume Next

        ActiveSheet.Protect "Swrf"
        ActiveWorkbook.Save
        ActiveWorkbook.Close SaveChanges:=True

    End Sub

【问题讨论】:

  • 建议:正确缩进代码有助于发现问题。
  • ^ 看看这个smart indenter
  • 您没有关闭您的If...End If 语句。阅读更多 here 以更好地了解它的实用性。
  • 您可以从缩进代码开始。通常,如果您这样做,这些类型的问题会立即变得明显。请删除 On error Resume next 。这只是为了向你隐藏你的错误。
  • 您缺少End With。并确保End WithWith 对齐。

标签: excel vba if-statement compiler-errors


【解决方案1】:

如果你去掉所有没有开始或结束语句块的东西,你会得到这个代码:

Private Sub CommandButton1_Click() '#1
    If nConfirmation = vbYes Then ' #2
        With ActiveSheet.Range("A:A") ' #3
            If Not RNG Is Nothing Then ' #4
                With ActiveSheet.Range("A:A") ' #5
                    If Not RNG Is Nothing Then ' #6
                    Else ' #6.1
                    End If ' #7
                ' ##### THERE SHOULD BE AN END WITH HERE ####
            Else ' #4.1
            End If ' #8
        End With ' #9
    Else ' #2.1
    End If ' #10
End Sub ' #11

每次开始一个新的块,你可以考虑将新块添加到一堆块语句的顶部。每当您关闭一个块时,您都必须关闭当前位于堆栈顶部的块。如果不匹配(例如堆栈顶部的块是With 块但您尝试使用End If 关闭它),则会发生错误

我在程序的每一行都添加了数字(Else 语句略有不同)。以下是每一行执行后堆栈的外观,直到我们到达导致错误的行:

1:

  • Sub 来自#1

2:

  • If 来自#2
  • Sub 来自#1

3:

  • With 来自#3
  • If 来自#2
  • Sub 来自#1

4:

  • If 来自#4
  • With 来自#3
  • If 来自#2
  • Sub 来自#1

5:

  • With 来自#5
  • If 来自#4
  • With 来自#3
  • If 来自#2
  • Sub 来自#1

6:

  • If 来自#6
  • With 来自#5
  • If 来自#4
  • With 来自#3
  • If 来自#2
  • Sub 来自#1

6.1:

来自#6.1的Else替换了来自#6的If

  • Else 来自 #6.1
  • With 来自#5
  • If 来自#4
  • With 来自#3
  • If 来自#2
  • Sub 来自#1

7:

End If#7 匹配Else#6.1

  • With 来自#5
  • If 来自#4
  • With 来自#3
  • If 来自#2
  • Sub 来自#1

8:

错误:#4.1 处的 Else 无法与堆栈顶部的#5 处的 With 匹配。这 Else 实际上与 If 在#4

【讨论】:

  • 非常感谢您的详细解释和视觉效果,我感谢您的努力,它真的很有帮助!我已经相应地调整了我的代码(相对于您显示的内容),并且我已经缩进了所有内容以对齐,并在您推荐的地方包括 End with 语句。我现在唯一的问题是外部工作簿中的另外两个工作表,一个工作簿中的“更改”工作表和另一个工作簿中的“HE171”工作表保持打开状态,并且不粘贴我原始工作表中的任何值。你能看看我编辑的代码和模块 8
  • 我在原始代码的底部添加了模块 8,您可以看看吗?
  • 您需要开始一个新问题,因为您已转到另一个问题。乍一看,您多次引用Sheet1,但Sheet1 所指的内容取决于当时哪个工作簿处于活动状态。尝试阅读How to avoid using Select in Excel VBA。还要注释掉所有On Error Resume Next 行,并确保用于保护/取消保护工作表的密码是一致的(至少出现一次“Swarf”而不是“Swrf”)
  • 感谢您的评论,我编了一个随机密码只是为了发布它(在我的代码中,我到处都有相同的密码)但感谢您注意到这一点。此外,由于某种原因,我无法发布,因为我之前的问题被否决了,所以我刚刚更新了我当前的问题,因为它告诉我编辑我的问题以改进它们。我会阅读你给出的那篇文章,希望我能更好地理解活动表。我的理解是 Sheet1 总是指正在编写代码的工作簿的“Sheet 1”。
  • 要在编写代码的工作簿中引用名为“Sheet1”的工作表,请使用ThisWorkbook.Worksheets("Sheet1")。如果您只是参考Sheet1,那么无论哪个工作簿处于活动状态,那都是代号为“Sheet1”的工作表。实际工作表名称可以是任何名称,因为代码名称和工作表名称不需要匹配
猜你喜欢
  • 1970-01-01
  • 2021-09-22
  • 2016-07-31
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2014-08-20
  • 2015-10-24
  • 2013-10-27
相关资源
最近更新 更多