Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 如何使用带有显式选项的命名常量?_Excel_Vba_Ms Word - Fatal编程技术网

Excel 如何使用带有显式选项的命名常量?

Excel 如何使用带有显式选项的命名常量?,excel,vba,ms-word,Excel,Vba,Ms Word,当我试图遵循最佳实践时,我将optionexplicit放在代码的顶部,并声明所有变量。但这与另一种使用命名常量的最佳实践产生了冲突。我该怎么办 第一个问题是xlFalse;我对其他任何xl变量都没有任何问题,所以这似乎是一个独立的案例。但我并不真的担心,因为我可以输入False,代码就能正常工作。它有效,对吗 Sub GetEOP() 'Executes when the user clicks the "Import Data" button, imports the EOP da

当我试图遵循最佳实践时,我将optionexplicit放在代码的顶部,并声明所有变量。但这与另一种使用命名常量的最佳实践产生了冲突。我该怎么办

第一个问题是xlFalse;我对其他任何xl变量都没有任何问题,所以这似乎是一个独立的案例。但我并不真的担心,因为我可以输入False,代码就能正常工作。它有效,对吗

Sub GetEOP()

    'Executes when the user clicks the "Import Data" button, imports the EOP data

    GlobalDeclarations

    'Open Open dialog, assigns selected file path to wordFileName
    wordFileName = Application.GetOpenFilename("Rich Text Files (*.rtf), *.rtf," & "Word Files (*.doc;*.docx), *.doc;*.docx", , "EOP Table File?")

    'Stop code if the user clicks Cancel (otherwise, wordFileName would be assigned a value of "False")
    If wordFileName = False Then Exit Sub

    'Open the selected file in Word
    Set wordDoc = GetObject(wordFileName)

    'Copy the values of the first table in the Word document to Excel
    With wordDoc.Tables(1)
        For wordRow = 1 To .Rows.Count
            For wordCol = 1 To .Columns.Count
                EOP.Cells(wordRow, wordCol).Value = WorksheetFunction.Clean(.cell(wordRow, wordCol).Range.Text)
            Next wordCol
        Next wordRow
    End With

    'Close Word
    Set wordDoc = Nothing

    'Find the last row and column of the EOP sheet.
    rw2 = EOP.Cells.Find("*", after:=Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=xlFalse).Row 'ERROR: Variable not defined -- xlFalse
    cl2 = EOP.Cells.Find("*", after:=Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=xlFalse).Column 'ERROR: Variable not defined -- xlFalse

    'Format EOP worksheet
    EOP.Cells(1, 1).RowHeight = 15
    EOP.Cells(2, 1).RowHeight = 15
    EOP.Cells(1, 1).Resize(50, 12).Interior.Color = clrbg
    EOP.Cells(1, 1).Resize(1, cl2).Interior.Color = clr2
    EOP.Cells(2, 1).Resize(rw2 - 1, cl2).Interior.Color = clr1

End Sub
但更严重的问题是,当我从Excel运行Word代码时,如wordDoc.Close savechanges:=wdDoNotSaveChanges。我可以直接使用wdDoNotSaveChanges=0,不用担心,但我认为可能有更好的方法来处理这种情况

这里有大量的代码;抛出错误的行一直位于代码块的底部

Sub DrillFolder(Folder)

    Dim SubFolder
    For Each SubFolder In Folder.SubFolders

        'Skip Archive and Old folders
        If InStr(UCase(SubFolder.Name), UCase("Archive")) > 0 Or _
           InStr(UCase(SubFolder.Name), UCase("Old")) > 0 Or _
           InStr(UCase(SubFolder.Name), UCase("do not use")) > 0 Then GoTo SkipFolder

        DrillFolder SubFolder

SkipFolder:
    Next

    Dim File
    Dim sortFile As Worksheet

    For Each File In Folder.Files

        'Checks if the file name has any of these time points in it.
        If InStr(UCase(File.Name), UCase("bl")) > 0 Or _
           InStr(UCase(File.Name), UCase("eop")) > 0 Or _
           InStr(UCase(File.Name), UCase("t2")) > 0 Or _
           InStr(UCase(File.Name), UCase("t3")) > 0 Then

            'Only look at RTFs
            If File.Type = "Rich Text Format" Then

                'Sorts the file according to the time point in the file name.
                If InStr(UCase(File.Name), UCase("bl")) > 0 Then Set sortFile = Worksheets("Base")
                If InStr(UCase(File.Name), UCase("eop")) > 0 Then Set sortFile = Worksheets("EOP")
                If InStr(UCase(File.Name), UCase("t2")) > 0 Then Set sortFile = Worksheets("T2")
                If InStr(UCase(File.Name), UCase("t3")) > 0 Then Set sortFile = Worksheets("T3")

                'sortTotalRow is used to make sure that entries in one worksheet don't skew the alignment of other worksheets
                Dim sortTotalRow As Integer
                Select Case sortFile.Name

                    Case "Base"
                        sortTotalRow = baseTotalRow
                    Case "EOP"
                        sortTotalRow = eopTotalRow
                    Case "T2"
                        sortTotalRow = t2TotalRow
                    Case "T3"
                        sortTotalRow = t3TotalRow
                    Case Else
                        sortTotalRow = 0

                End Select

                        'Opens the selected file in Word
                        Set wordDoc = wordApp.Documents.Open(File.Path)

                        'Adds file information to the Import worksheet
                        With Import.Cells(docCount + 2, 1)
                            .Value = wordDoc
                            .Offset(0, 1).Value = wordDoc.Tables(1).Rows.Count
                            .Offset(0, 2).Value = sortFile.Name
                            .Offset(0, 3).Value = wordDoc.FullName
                        End With


                        'Copies values of first table in document to Excel
                        If wordDoc.Tables.Count > 0 Then
Restart:                       With wordDoc.Tables(1)

                                'Combine Birth Month and Birth Year columns, if they're separate
                               Dim i As Integer
                               For i = 1 To .Columns.Count
                                    If InStr(UCase(WorksheetFunction.Clean(.cell(1, i).Range.Text)), UCase("Birth year")) = 1 Then

                                        'Change Birth Month column to Birth Month and Year column
                                        Dim k As Long
                                        For k = 1 To .Rows.Count
                                            .cell(k, i - 1).Range.Text = .cell(k, i - 1).Range.Text & .cell(k, i).Range.Text
                                        Next k

                                        'Then delete the Birth Year column, so it doesn't get copied twice
                                        .Columns(i).Delete
                                        GoTo Restart

                                    End If

                                    'Delete "describe yourself" and "Where are you taking this survey?" columns
                                    If InStr(UCase(WorksheetFunction.Clean(.cell(1, i).Range.Text)), UCase("describe")) > 0 Then
                                        .Columns(i).Delete
                                        GoTo Restart
                                    End If
                                    If InStr(UCase(WorksheetFunction.Clean(.cell(1, i).Range.Text)), UCase("taking this survey")) > 0 Then
                                        .Columns(i).Delete
                                        GoTo Restart
                                    End If
                                Next i

                                'Account for Grandma code by putting in dummy values for non-Gcode rounds
                                Dim gmaFind As Boolean

                                'Check for Gma in the table
                                With wordDoc.Range.Find
                                    .Text = "Grandmother"
                                    .MatchCase = False
                                    gmaFind = .Execute
                                End With

                                'If you don't find it, add a column and fill it with XXX
                                If gmaFind = True Then

                                Else
                                    .Columns.Add
                                    For i = 1 To .Rows.Count
                                        .cell(i, .Columns.Count).Range.Text = "XXX"
                                    Next i
                                End If



                                For wordRow = 1 To .Rows.Count
                                    For wordCol = 1 To .Columns.Count

                                        'Takes off headers for the tables after the first
                                        If sortTotalRow <> 0 And wordRow = 1 Then GoTo Skip

                                        'Skip "How do you describe yourself?" column
                                        If InStr(WorksheetFunction.Clean(.cell(1, wordCol).Range.Text), "describe") > 0 Then GoTo Skip

                                        'Skip "Please tell us the place where you are taking this survey." column
                                        If InStr(WorksheetFunction.Clean(.cell(1, wordCol).Range.Text), "taking this survey") > 0 Then GoTo Skip

                                        'If you're in the Obs column, also add in the name of the round.
                                        If wordCol = 1 Then
                                            sortFile.Cells(wordRow + sortTotalRow, wordCol).Value = Left(wordDoc.Name, 8) & " " & WorksheetFunction.Clean(.cell(wordRow, wordCol).Range.Text)
                                        Else
                                            sortFile.Cells(wordRow + sortTotalRow, wordCol).Value = WorksheetFunction.Clean(.cell(wordRow, wordCol).Range.Text)
                                        End If
'This is a flag
'to tell GoTo
'where to go.
Skip:                               Next wordCol
                                Next wordRow

                                'Adds number of records to totalRow, so the next table appears under the previous.
                                Select Case sortFile.Name

                                    Case "Base"
                                        'The -1 is accounting for the headers of the tables that have been omitted
                                        '(otherwise it would be a blank row)
                                        baseTotalRow = baseTotalRow + .Rows.Count - 1
                                    Case "EOP"
                                        eopTotalRow = eopTotalRow + .Rows.Count - 1
                                    Case "T2"
                                        t2TotalRow = t2TotalRow + .Rows.Count - 1
                                    Case "T3"
                                        t3TotalRow = t3TotalRow + .Rows.Count - 1
                                    Case Else

                                End Select

                            End With
                        End If

                'At the end of importing, docCount is used as "Debug.print "Time taken to import docCount documents""
                docCount = docCount + 1

                'Closes Word Document
                'Const wdDoNotSaveChanges As Integer = 0
                wordDoc.Close savechanges:=wdDoNotSaveChanges 'ERROR: Variable not defined -- wdDoNotSaveChanges

            End If
        End If


    Next


End Sub

谢谢你的帮助

如果我理解正确,您将发现Option Explicit是如何将您从非常严重的错误中解救出来的

如果您的代码因为WDDONOTSAVECHANGS未定义而拒绝编译,那是因为未引用Microsoft Word对象库,即您可能延迟绑定了它

如果没有Option Explicit,VBA将愉快地编译,并且未定义的标识符在执行时被动态定义为隐式变量局部变量,该变量保留任何变量的默认值:Empty。。。当传递给接受整数类型的函数/过程/方法时,该函数/过程/方法会自动转换为0,而不管您将其命名为什么

如果延迟绑定Word对象模型,则不会加载Word对象库中定义的常量,因此,为了使用命名常量并避免使用幻数,请参考最佳做法,您需要定义自己的-因此您点击或临时引用对象模型,点击F2以找到您需要的值,并在您自己的代码中重现这些值:

Private Enum WdSaveOptions
    wdDoNotSaveChanges = 0 ' equivalent to Boolean value False
    wdPromptToSaveChanges = -2
    wdSaveChanges = -1 ' equivalent to Boolean value True
End Enum

现在不仅OptionExplicit不会干扰,您的代码也会正常工作

请使用问题下方的链接包含代码示例。但这与使用命名常量的另一个最佳实践产生了冲突-嗯,怎么做?我认为您可能会将变量与constants@MathieuGuindon延迟绑定Word,然后尝试使用单词enum?这就是我所能解释的。@BigBen这就是我在下面所做和假设的:我过去做的另一件事是使用,这样,如果您决定切换到早期绑定并添加单词reference,您在将来就不会遇到问题。您可以添加一个条件编译常量,如USE_EARLY_BINDING,然后在条件编译中包装常量声明,如果块是@Zack good point-Const预编译器常量是模块作用域,那么它们需要无处不在。最好在项目级别定义它们=是的,我同意在项目级别定义常量。非常感谢您的回答!我很肯定您正确地假设了这个问题,但我在上面添加了代码示例以确保这一点。如果我理解正确,似乎xlFalse和wdDoNotSaveChanges都在0处枚举,这就是代码行为没有问题的原因。这太可怕了!假设,如果我改用wdSaveChanges,同样的事情也会发生,对吗?但它实际上不会保存更改。这就是为什么要使用Option Explicit。@花序我很确定xlFalse在任何地方都不存在。你的意思是布尔值为False吗?如果是这样,那就错了。