5.1鸟瞰Application对象

5.2 必须了解的面向显示特性

5.2.1 使用ScreenUpdating改进和完善执行性能

代码清单5.1:实现屏幕更新的性能

'代码清单5.1: 实现屏幕更新的特性
Sub TimeScreenUpdating()
    Dim dResult As Double
    
    'test with screen updating turned on
    dResult = TestScreenUpdating(True)
    MsgBox Format(dResult, "0.00") & " seconds.", vbOKOnly
    
    'test with screen updating turned off
    dResult = TestScreenUpdating(False)
    MsgBox Format(dResult, "0.00") & " seconds.", vbOKOnly
    
    
End Sub

Function TestScreenUpdating(bUpdatingOn As Boolean) As Double
    
    'record the start time
    Dim dStart As Double
    dStart = Timer
    
    'turn screen updating on or off
    Application.ScreenUpdating = bUpdatingOn
    
    'loop through each worksheet
    'in the workbook 250 times
    Dim nRepetition As Integer
    Dim ws As Worksheet
    For nRepetition = 1 To 250
        For Each ws In ThisWorkbook.Worksheets
            ws.Activate
        Next
    Next
    
    'turn screen updating on
    Application.ScreenUpdating = True
    
    'return elapsed time since procedure started
    TestScreenUpdating = Timer - dStart
    
    'clean up
    Set ws = Nothing
    
End Function

5.2.2 使用状态栏为最终用户提供信息

代码清单5.2:使用StatusBar属性显示信息

'代码清单5.2: 使用StatusBar属性显示信息
'this subroutine tests the impact of
'using statusbar to display lots of frequent messages.
Sub TimeStatusBar()
    Dim dStart As Double
    Dim dResult As Double
    Dim bDisplayStatusBar As Boolean
    
    'remember original status bar setting
    bDisplayStatusBar = Application.DisplayStatusBar
    'turn on the status bar
    Application.DisplayScrollBars = True
    
    'baseline test - no status bar, every row
    'to isolate how long it takes to
    'perform mod statement on all rows
    dStart = Timer
    TestStatusBar 100, False
    dResult = Timer - dStart
    MsgBox Format(dResult, "0.00") & " Seconds.", vbOKOnly


    'time using statusbar -every row
    dStart = Timer
    TestStatusBar 100, True
    dResult = Timer - dStart
    MsgBox Format(dResult, "0.00") & " Seconds.", vbOKOnly
    
    'time using statusbar -every fifth row
    dStart = Timer
    TestStatusBar 500, True
    dResult = Timer - dStart
    MsgBox Format(dResult, "0.00") & " Seconds.", vbOKOnly
    
    'restore the status bar to its original setting
    Application.DisplayScrollBars = bDisplayStatusBar

End Sub

'this subroutine displays a message to the status bar
'(if desired) for each row in a worksheet using the
'interval specified.
Private Sub TestStatusBar(nInterval As Integer, bUseStatusBar As Boolean)
    Dim lRow As Long
    Dim lLastRow As Long
    Dim ws As Worksheet
    
    'using the first worksheet in this workbook
    'no changes will be made to the worksheet.
    Set ws = ThisWorkbook.Worksheets(1)
    
    'every version since excel 97 has had
    '65,536 rows. excel 5 had 16,384 rows.
    lLastRow = ws.Rows.Count
    
    For lRow = 1 To lLastRow
    
        'test to see if the current row
        'is the interval specified.
        If lRow Mod nInterval = 0 Then
        If bUseStatusBar Then
            Application.StatusBar = "processing row: " & lRow & _
            " of " & lLastRow & " rows."
        End If
        End If
    Next
    
    Application.StatusBar = False
    Set ws = Nothing
End Sub

 

5.3 需要了解的面向显示特性

代码清单5.3:带有Cursor属性的可用光标 

'代码清单5.3: 带有Cursor属性的可用光标
Sub ViewCursors()
    Application.Cursor = xlNorthwestArrow
    MsgBox "Do you like the xlNorthwestArrow? Hover over the worksheet to see it."
    
    Application.Cursor = xlIBeam
    MsgBox "How about xlIBeam? Hover over the worksheet to see it."
    
    Application.Cursor = xlWait
    MsgBox "How about xlWait? Hover over the worksheet to see it."
    
    Application.Cursor = xlDefault
    MsgBox "How about xlDefault? Hover over the worksheet to see it."
    
End Sub

 

代码清单5.4:示范各种面向窗口的属性  

'代码清单5.4: 示范各种面向窗口的属性
Sub GetWindowInfo()
    Dim lState As Long
    Dim sInfo As String
    Dim lResponse As Long
    
    'Determine window state
    lState = Application.WindowState
    Select Case lState
        Case xlMaximized
            sInfo = "Window is maximized." & vbCrLf
        Case xlMinimized
            sInfo = "Window is maximized." & vbCrLf
        Case xlNormal
            sInfo = "window is normal." & vbCrLf
    End Select
    
    'prepare message to be displayed
    sInfo = sInfo & "Usable Height = " & Application.UsableHeight & vbCrLf
    sInfo = sInfo & "Usable Width = " & Application.UsableWidth & vbCrLf
    sInfo = sInfo & "Height = " & Application.Height & vbCrLf
    sInfo = sInfo & "Width = " & Application.Width & vbCrLf & vbCrLf
    
    sInfo = sInfo & "Would you like to minimize it? " & vbCrLf
    
    'Display message
    lResponse = MsgBox(sInfo, vbYesNo, "")
    
    'Minimize window if user clicked yes
    If lResponse = vbYes Then
        Application.WindowState = xlMinimized
    End If    

End Sub

 

5.4 便捷的Excel对象属性

属性 返回 描述
ActiveCell Range  
ActiveChart Chart  
ActivePrinter String  
ActiveSheet Sheet  
ActiveWindow Window  
ActiveWorkbook Workbook  
Selection Range/Chart/Control 取决于用户的选择
ThisCell Range 调用一个用户定义的函数单元格
ThisWorkbook Workbook  
Caller Range 返回使用此函数的单元格

 

5.5 常用的简化文件操作

5.5.1从用户那里获得文件名

代码清单5.5:从用户那里获取单个工作薄 

'代码清单5.5: 从用户那里获取单个工作薄
Sub TestGetFile()
    Dim nIndex As Integer
    Dim sFile As String
    
    'Get a batch of Excel files
    sFile = GetExcelFile("Testing GetExcelFile Function")
    
    'make sure dialog wasn't cancelled - in which case
    'sFile would equal False
    If sFile = "False" Then
        Debug.Print "No file selected."
        Exit Sub
    End If
    
    'OK - we have a valid file
    Debug.Print sFile
    
End Sub

'Presents user with a GetOpenFileName dialog which allows
'single file selection.
'return a single of filename
Function GetExcelFile(sTitle As String) As String
    
    Dim sFilter As String
    Dim bMultiSelect As Boolean
    
    sFilter = "Workbooks (*.xls),*.xls"
    bMultiSelect = False
    
    GetExcelFile = Application.GetOpenFilename _
        (FileFilter:=sFilter, Title:=sTitle, MultiSelect:=bMultiSelect)
    
End Function

 

代码清单5.6:从用户那里获取一批工作薄 

'代码清单5.6: 从用户那里获取一批工作薄
Sub TestGetFiles()
    Dim nIndex As Integer
    Dim vFiles As Variant
    
    'Get a batch of Excel files
    vFiles = GetExcelFiles("Testing GetExcelFiles Function")
    
    'make sure dialog wasn't cancelled - in which case
    'vFiles would equal False
    If Not IsArray(vFiles) Then
        Debug.Print "No files selected."
        Exit Sub
    End If
    
    'OK - loop through the fileNames
    For nIndex = 1 To UBound(vFiles)
        Debug.Print vFiles(nIndex)
    Next nIndex

End Sub

'Presents user with a GetOpenFileName dialog that allows
'Multiple file selection.
'Returns an array of filenames.
Function GetExcelFiles(sTitle As String) As Variant
    Dim sFilter As String
    Dim bMultiSelect As Boolean
    
    sFilter = "Workbooks (*.xls), *.xls "
    bMultiSelect = True
    
    GetExcelFiles = Application.GetOpenFilename _
    (filefilter:=sFilter, Title:=sTitle, MultiSelect:=bMultiSelect)
    
End Function

 默认情况下,VBA数组是基于0的。但是,GetOpenFilename多选模式返回的数组是基于1的。

5.5.2 使用GetSaveAsFilename选取合适的位置

代码清单5.7GetSaveAsFilename的基本使用 

'代码清单5.7: GetSaveAsFilename 的基本使用
Sub SimpleGetSaveAsFilename()
    Dim sFile As String
    Dim lResponse As Long
    Dim sMsg As String
    
    Do
        sFile = Application.GetSaveAsFilename
        sMsg = "you chose:  " & sFile & " . Keep experimenting?"
        lResponse = MsgBox(sMsg, vbYesNo)
        
    Loop While lResponse = vbYes
    
End Sub

 

5.5.2.1 分解文件名

代码清单5.8:分解文件名为路径和文件名

'代码清单5.8: 分解文件名为路径和文件名
'A simple procedure for testing the
'BreakDownName procedure
Sub TestBreakdownName()
    Dim sPath As String
    Dim sName As String
    
    Dim sFileName As String
    Dim sMsg As String
    
    sFileName = Application.GetSaveAsFilename
    BreakdownName sFileName, sName, sPath
    sMsg = "the file name is:  " & sName & vbCrLf
    sMsg = sMsg & "the path is:  " & sPath & vbCrLf
    
    MsgBox sMsg, vbOKOnly

End Sub

Function GetShortName(sLongName As String) As String
    Dim sPath As String
    Dim sShortName As String
    
    BreakdownName sLongName, sShortName, sPath
    GetShortName = sShortName

End Function

'当有2个返回值时,用byRef参数过程
Sub BreakdownName(sFullName As String, ByRef sName As String, ByRef sPath As String)
    Dim nPos As Integer
    
    'Find out where the filename begins
    nPos = FileNamePosition(sFullName)
    If nPos > 0 Then
        sName = Right(sFullName, Len(sFullName) - nPos)
        sPath = Left(sFullName, nPos - 1)
    Else
    'invalid sFullName - don't change anything
    End If
     
End Sub

'Returns the position or index of the first
'character of the filename given a full name
'A full name consists of a path and a filename
'Ex. FileNamePosition("c: \Testing\Test.txt") = 11
Function FileNamePosition(sFullName As String) As Integer
    Dim bFound As Boolean
    Dim nPosition As Integer
    
    bFound = False
    nPosition = Len(sFullName)
    
    Do While bFound = False
        If nPosition = 0 Then Exit Do
        
        If Mid(sFullName, nPosition, 1) = "\" Then
            bFound = True
        Else
            nPosition = nPosition - 1
        End If
    Loop
    
    If bFound = False Then
        FileNamePosition = 0
    Else
        FileNamePosition = nPosition
    End If

End Function

 

5.6 检查操作环境

代码清单5.9:使用Application对象属性获取有效的系统信息 

'代码清单5.9:使用Application 对象属性获取有效的系统信息
Sub InspectTheEnvironment()
    Debug.Print Application.CalculationVersion
'    Debug.Print Application.MemoryFree
'    Debug.Print Application.MemoryUsed
    Debug.Print Application.OperatingSystem
    Debug.Print Application.OrganizationName
    Debug.Print Application.UserName
    Debug.Print Application.Version
    
End Sub

 

5.7有用的两个额外成员

第一个是CutCopyMode属性,这个属性决定当剪切或复制时,是否在选中区域边界周围显示移动的破折号。

Application.CutCopyMode = False

第二个功能是InputBox方法:

'5.7 InputBox 函数用法的例子
Sub SimpleInputBox()
    Dim vInput As Variant
    vInput = InputBox("What is your name?", "introduction", Application.UserName)
    MsgBox "Hello, " & vInput & ". Nice to meet you.", vbOKOnly, "Introduction"
    
End Sub