故障参考表代码名称
这里的基本问题:我正在写一个Excel宏,我想用工作表代码名来尽量消除在道路上的任何错误。我可以使用Sheet1的代码名称,它工作正常,但是当我尝试使用其他代码时,如Sheet3或Sheet7,编辑器不能识别它们,如果我运行宏Excel会启动一个错误,告诉我我的“变量未定义“。故障参考表代码名称
例如:
Option Explicit
Sub Test()
Dim SheetObject As Worksheet
Dim SheetObject2 As Worksheet
Set SheetObject = Sheet1
Set SheetObject2 = Sheet3
MsgBox (SheetObject.Name)
MsgBox (SheetObject2.Name)
End Sub
如果我注释掉指SheetObject2任何代码的宏正常运行。如果我把它们放进去,我会得到错误。我肯定有一张Sheet3,代码名称绝对是Sheet3。我整天环顾Google,似乎无法提出任何解决方案,任何帮助都会很棒。
由于提前,
杰西
我最后的用人单位收集数据和创建国家统计。大部分数据都是以Excel工作簿的形式出现的,所以我有很多相关的经验。
如果您运行的是自己的宏,如果这是一个一次性的练习,然后像这样的测试可能就足够了:
Debug.Assert WbookTgt.WsheetTgt.Range("A1").Value = "Date"
许多语言有一个断言语句作为发展援助;这是VBA版本。如果断言不成立,宏将停止并突出显示此语句。
如果这种做法是不足够的,你应该考虑制定参数化宏进行检查和更新任务。我已经浏览了一些旧的宏,但大多数人不会理解VBA新手。我已经提取代码来创建两个宏,我希望能给你一些想法。
宏1 - OpenWorkbook
组织,定期提供数据经常使用的名称类似:“XXXXX 1409.xlsx”和“XXXXX 1410.xlsx”为自己的数据的九月和十月的版本。例如,您可以每月更新宏以获取最新名称,或者可以将文件名更改为标准值。这两种可能性都是麻烦的,我会特别反对第二种想法,因为我喜欢将我所处理的所有工作簿存档。
OpenWorkbook()使用Dir语句来搜索文件夹,一个模板,如“XXXXX的* .xls *”相匹配的文件。如果单个文件与此模板匹配,宏将打开工作簿并返回对其的引用。
宏2 - CheckWorksheets
您可能已经注意到,一些VBA程序有一个固定的参数数字,而其他具有可变数量的参数。例如,以下是CheckWorksheets的所有有效调用:
If CheckWorksheets(WbookTgt, WbookThis, “Name1”) then
If CheckWorksheets(WbookTgt, WbookThis, “Name1”, “Name2”) then
If CheckWorksheets(WbookTgt, WbookThis, “Name1”, “Name2”, “Name3”) then
CheckWorksheets有三个参数。前两个是工作簿参考。第三个是ParamArray SheetName() As Variant
。前两个之后的任何参数都放置在数组SheetName中,该数组的大小可以根据需要设置。这里所有的尾部参数都是字符串,但它们可以是任何类型。
我可以使用OpenWorkbook打开本月版本的源文件,然后使用CheckWorksheets确认我的宏所需的所有工作表都存在。
工作表错误,”
这两个宏需要一个工作表中的错误出现在指定的工作簿。如果宏检测到错误,则会向此工作表添加详细的错误消息。我发现这是一种方便的技术来捕获任何错误的细节。
宏demo1的和DEMO2
我已经包含了两个宏演示如何使用这些宏与我的系统上的工作簿。如果您修改Demo1和Demo2以在一些工作簿上进行操作,您应该了解OpenWorkbook和CheckWorksheets可以为您做些什么。
带回来作为必要的,但你可以破译OpenWorkbook和CheckWorksheets自己的越多,你会开发自己的技能
Option Explicit
Sub Demo1()
Dim Path As String
Dim WbookThis As Workbook
Dim WbookTgt As Workbook
' Application.ThisWorkbook identifies the workbook containing this macro.
Set WbookThis = Application.ThisWorkbook
' I find it convenient to place my target workbooks in the folder
' holding the workbook containing the macro(s).
Path = WbookThis.Path
Set WbookTgt = OpenWorkbook(Path, "Combined*.xls*", WbookThis)
If WbookTgt Is Nothing Then
' Detailed error message already recorded in "Errors"
Call MsgBox("Wokbook failed checks", vbOKOnly)
Else
With WbookTgt
Debug.Print .Path & "\" & .Name & " opened."
.Close SaveChanges:=False
End With
End If
End Sub
Sub Demo2()
Dim Path As String
Dim WbookThis As Workbook
Dim WbookTgt As Workbook
' Application.ThisWorkbook identifies the workbook containing this macro.
Set WbookThis = Application.ThisWorkbook
' I find it convenient to place my target workbooks in the folder
' holding the workbook containing the macro(s).
Path = WbookThis.Path
Set WbookTgt = OpenWorkbook(Path, "Combined 2.04.xls*", WbookThis)
If WbookTgt Is Nothing Then
' Detailed error message already recorded in "Errors"
Call MsgBox("Wokbook failed checks", vbOKOnly)
Exit Sub
End If
With WbookTgt
If Not CheckWorksheets(WbookTgt, WbookThis, "Critical Path", "Dyn Dims") Then
Call MsgBox("Wokbook failed checks", vbOKOnly)
.Close SaveChanges:=False
Exit Sub
End If
Debug.Print .Path & "\" & .Name & " contains worksheets Critical and Dym Dims"
.Close SaveChanges:=False
End With
End Sub
Function CheckWorksheets(ByRef WbookTgt As Workbook, ByRef WbookError As Workbook, _
ParamArray SheetName() As Variant) As Boolean
' * Return True if WbookTgt contains every specified worksheet.
' * WbookTgt is the workbook to be checked
' * WbookError identifies the workbook containing worksheet "Error" to which any
' error message will be added.
' * SheetName() is an array of worksheet names.
Dim ErrorMsg As String
Dim FoundError As Boolean
Dim FoundSheet() As Boolean
Dim FoundSheetsCount As Long
Dim InxName As Long
Dim InxWsheet As Long
Dim NotFoundSheetsCount As Long
Dim RowErrorNext As Long
Dim SheetNamesFound As String
' Size FoundSheet to match SheetName. Array elements initialised to False
ReDim FoundSheet(LBound(SheetName) To UBound(SheetName))
FoundSheetsCount = 0
NotFoundSheetsCount = 0
With WbookTgt
For InxName = LBound(SheetName) To UBound(SheetName)
NotFoundSheetsCount = NotFoundSheetsCount + 1 ' Assume not found until found
For InxWsheet = 1 To .Worksheets.Count
If SheetName(InxName) = .Worksheets(InxWsheet).Name Then
FoundSheet(InxName) = True
FoundSheetsCount = FoundSheetsCount + 1
NotFoundSheetsCount = NotFoundSheetsCount - 1
Exit For
End If
Next
Next
End With
If NotFoundSheetsCount = 0 Then
CheckWorksheets = True
Exit Function
End If
SheetNamesFound = ""
ErrorMsg = WbookTgt.Path & "\" & WbookTgt.Name & " does not contain "
If NotFoundSheetsCount = 1 Then
ErrorMsg = ErrorMsg & "this expected worksheet:"
Else
ErrorMsg = ErrorMsg & "these expected worksheets:"
End If
For InxName = LBound(SheetName) To UBound(SheetName)
If Not FoundSheet(InxName) Then
ErrorMsg = ErrorMsg & vbLf & " " & SheetName(InxName)
Else
SheetNamesFound = SheetNamesFound & vbLf & " " & SheetName(InxName)
End If
Next
If FoundSheetsCount = 0 Then
' No need to add list of found sheet names
Else
ErrorMsg = ErrorMsg & vbLf & "but does contain "
If FoundSheetsCount = 1 Then
ErrorMsg = ErrorMsg & "this expected worksheet:"
Else
ErrorMsg = ErrorMsg & "these expected worksheets:"
End If
ErrorMsg = ErrorMsg & SheetNamesFound
End If
With WbookError
With .Worksheets("Errors")
RowErrorNext = .Cells(Rows.Count, "A").End(xlUp).Row + 1
With .Cells(RowErrorNext, "A")
.Value = Now()
.VerticalAlignment = xlTop
End With
.Cells(RowErrorNext, "B").Value = ErrorMsg
End With
End With
CheckWorksheets = False
End Function
Function OpenWorkbook(ByVal Path As String, ByVal FileTemplate As String, _
ByRef WbookError As Workbook) As Workbook
' * If Path & FileTemplate identifies a single workbook, open it and return
' it as an object. If Path & FileTemplate does not represent a single
' workbook, report the problem in worksheet Errors and return Nothing.
' * WbookError identifies the workbook containing worksheet "Error".
' * Path must be the name of the folder in which the required workbook is located
' * FileTemplate can either be a specific filename or can contain wild cards
' providing only one file matches the template.
' * WbookError identifies the workbook containing worksheet "Error" to which any
' error message will be added.
Dim ErrorMsg As String
Dim FileNameCrnt As String
Dim FileNameMatch As String
Dim RowErrorNext As Long
FileNameMatch = Dir$(Path & "\" & FileTemplate, vbNormal)
If FileNameMatch = "" Then
' No matches found
ErrorMsg = "Template " & Path & "\" & FileTemplate & " does not match any file"
Else
' At least one match.
' If only one match, its name is in FileNameMatch
Do While True
FileNameCrnt = Dir$
If FileNameCrnt = "" Then
' No more matches
Exit Do
End If
' A second or subsequent match has been found.
If FileNameMatch <> "" Then
' This is the second match.
' Initialise error message and report name of first match
ErrorMsg = "Template " & Path & "\" & FileTemplate & " matches more than one file:" & _
vbLf & " " & FileNameMatch
FileNameMatch = "" ' No single match
End If
' Add name of current match to error message
ErrorMsg = ErrorMsg & vbLf & " " & FileNameCrnt
Loop
End If
If FileNameMatch = "" Then
' No single match found.
' ErrorMsg contains an appropriate error message
With WbookError
With .Worksheets("Errors")
RowErrorNext = .Cells(Rows.Count, "A").End(xlUp).Row + 1
With .Cells(RowErrorNext, "A")
.Value = Now()
.VerticalAlignment = xlTop
End With
.Cells(RowErrorNext, "B").Value = ErrorMsg
Set OpenWorkbook = Nothing
End With
End With
Else
' Single match found
Set OpenWorkbook = Workbooks.Open(Path & "\" & FileNameMatch)
End If
End Function
应对额外的问题更快
VBA有什么能问题就像VB的Try
一样方便,但是它在程序员控制下确实有一些错误处理。
如果您使用命令如:
Worksheets("Sheet2").Delete
用户将被要求确认删除。为了避免这种情况,使用方法:
Application.DisplayAlerts = False
Worksheets("Sheet2").Delete
Application.DisplayAlerts = True
我曾在一个宏,这意味着任何警报将显示,即使pogrammer没想到它的用户的关注开始看到有Application.DisplayAlerts = False
代码。通过包围Delete
,我确保只有我期望的警报被抑制。
考虑:
Sub OpenFile()
Dim InputFileNum As Long
InputFileNum = FreeFile
Open "Dummy.txt" For Input As InputFileNum
Debug.Print "File successfully opened"
Close InputFileNum
End Sub
文件 “Dummy.txt” 不存在这样的宏将停止在Open
声明。
有时你会看到这样的代码:
Sub OpenFile()
Dim InputFileNum As Long
On Error GoTo ErrorCode
InputFileNum = FreeFile
Open "Dummy.txt" For Input As InputFileNum
Call MsgBox("File successfully opened", vbOKOnly)
Close InputFileNum
Exit Sub
ErrorCode:
Debug.Print "Unexpected error: " & Err.Number & " " & Err.Description
End Sub
这里我提供了一个一般的处理程序可能发生的任何错误情况。我不赞成,尽管我接受这比稍微让非技术用户看到突出显示的错误陈述更好。问题是任何错误都会导致相同的无用错误消息。
我从不在开发过程中包含错误处理。如果发生错误,我希望宏停止在错误的语句,所以我可以考虑如何避免错误。在这里,我应该在试图打开它之前检查文件是否存在。我更喜欢这样的事情:
Sub OpenFile()
Dim FileSysObj As Object
Dim InputFileNum As Long
On Error GoTo ErrorCode
Set FileSysObj = CreateObject("Scripting.FileSystemObject")
If Not FileSysObj.FileExists("Dummy.txt") Then
Call MsgBox("I am unable to find ""Dummy.txt"". List of helpful suggestions.", vbOKOnly)
Exit Sub
End If
InputFileNum = FreeFile
Open "Dummy.txt" For Input As InputFileNum
Call MsgBox("File successfully opened", vbOKOnly)
Close InputFileNum
Exit Sub
ErrorCode:
Debug.Print "Unexpected error: " & Err.Number & " " & Err.Description
End Sub
我已经包括检查代码为我期望的错误。如果该文件不存在,我已经显示了一条消息,希望能够帮助用户解决问题。
有时你无法避免一个错误。为了测试下面的代码,我创建了文件Dummy.txt,但设置了“读访问被拒绝”标志。 (据我所知),VBA宏测试这个标志并不容易。我有一个处理意外错误的通用处理程序,但是我将它关闭以用于Open
声明,以便我可以包含打开失败的特定代码。我已经删除了使用FileExists()
来测试Dummy.txt是否存在的代码,因为将其与其他打开的文件错误测试结合使用会更容易。
Sub OpenFile()
Dim FileSysObj As Object
Dim InputFileNum As Long
On Error GoTo ErrorCode ' General handler for unexpected errors
InputFileNum = FreeFile
Err.Clear
On Error Resume Next ' Record error in Err object and continue
Open "Dummy.txt" For Input As InputFileNum
Select Case Err.Number
Case 0
' No error.
Case 53 ' File does not exist
Call MsgBox("I am unable to find ""Dummy.txt"". List of helpful suggestions.", vbOKOnly)
Exit Sub
Case 75 ' Path/File access error
Call MsgBox("It appears file ""Dummy.txt"" exists but I do not have permission to read it.", vbOKOnly)
Exit Sub
Case Else
Call MsgBox("My attempt to open ""Dummy.txt"" failed with an unexpected error condition" & vbLf & _
" " & Err.Number & " " & Err.Description, vbOKOnly)
Exit Sub
End Select
On Error GoTo ErrorCode ' Restore general handler for unexpected errors
Call MsgBox("File successfully opened", vbOKOnly)
Close InputFileNum
Exit Sub
ErrorCode:
Debug.Print "Unexpected error: " & Err.Number & " " & Err.Description
End Sub
的错误代码和错误处理更多信息的长列表,请访问http://support.microsoft.com/kb/146864。
非常感谢Tony提供的这些示例,我通过它们进行了工作,并且我相信我对如何实现基于您的代码类型非常了不起,它可以满足我的特殊需求。在阅读完所有内容后,唯一的问题是:VBA中是否存在错误捕获代码?例如,VB.net使用Try ... Catch,在VBA中是否存在等价物或者是为错误编程捕捉错误的唯一方法?这可能超出了原始问题的范围,请随时将我指向另一个地方! – 2014-10-16 02:05:46
我不确定提问者是否被告知是否修改了答案。这个评论是为了确保你被告知。 – 2014-10-16 10:29:01
你在哪个时区?你的帖子在我的时间凌晨3点。 – 2014-10-16 10:30:23
您确定'Sheet3'是实际的表单代码名称吗?试着循环遍历每一张表格并打印真实的代码名称,看看它们是否匹配,如下所示:'For Each wks In Worksheets Debug.Print wks.CodeName Next wks'或者试试像这样使用名称:'Set SheetObject2 = Worksheets (“Sheet3”)' – 2014-10-12 02:44:06
试试这个:'For i = 1 To Worksheets.Count Debug.Print“sheet name =”&Worksheets(i).Name&vbCr _ &“code name =”&Worksheets(i) .CodeName&vbCr Next' – ZAT 2014-10-12 06:02:08
'Set SheetObject = Sheets(1)',或'Set SheetObject = Sheets(“Sheet1”)',都可以,第一个是索引,第一个是它的名字。 – 2014-10-12 16:24:50