.Select, .Activesheet, .Activecell etc…

前端 未结 5 450
傲寒
傲寒 2021-01-13 04:40

For this question, I refer to the post below to clarify myself:
Why is my conditional format offset when added by VBA?

In many, many posts I see these days, OP\'

5条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-13 05:07

    From my perspective, with few exceptions, the only time you should use Select is as a user input, and only then after careful consideration of alternative design/UI requirements.

    For example, I'd say it's generally not advisable to rely on Selection to let user define a Range object when this method keeps execution within the code:

    Dim myRange as Range
    Set myRange = Application.InputBox("Select your range", Type:=8)
    

    However, if you need to prompt users to select a particular shape or object on the worksheet, then maybe it's better to let them make a Selection (however, this can open up a Pandora's Box of problems without good error-handling and logic to prevent undesired user actions...).

    Here is an example of one such exception that I have in PowerPoint. I have some RibbonUI XML and VBA that adds buttons to the Shapes right-click context menu in PowerPoint, and adds similar buttons to the Ribbon itself. These are seamless UI that give the end-user a more "native" experience with the application -- users want to be able to right-click the chart and then run some macro procedures against that selected chart or table, etc. They don't want to press a button to open up a user form and scroll through a listbox of generic shape names or GUIDs.

    The procedure code needs to examine the Selection in order to handle it properly so I can use something like below, where

    Sub UpdateOrEditSelection(update As Boolean)
    'This procedure invoked when user edits/updates a chart.
    Dim uid As Variant
    Dim sel As Selection
    Dim s As Integer
    Dim chartsToUpdate As Object
    Dim multipleShapes As Boolean
    Dim sld As Slide
    Set sel = ppPres.Windows(1).Selection
    
    If update Then
        Set chartsToUpdate = CreateObject("Scripting.Dictionary")
        Select Case sel.Type
            Case ppSelectionShapes
                For s = 1 To sel.ShapeRange.count
                    uid = sel.ShapeRange(s).Name
                    '....
                    '...
                    '..
                    '.
                Next
            Case ppSelectionSlides
                For Each sld In sel.SlideRange
                    For s = 1 To sld.Shapes.count
                        uid = sld.Shapes(s).Name
                        '....
                        '...
                        '..
                        '.
    
                    Next
                Next
            Case ppSelectionText
                s = 1
                If sel.ShapeRange(s).HasTable Or sel.ShapeRange(s).HasChart Then
                    uid = sel.ShapeRange(s).Name
                    '....
                    '...
                    '..
                    '.
    
                End If
        End Select
     '....
     '...
     '..
     '.
    

    Where does it come from?

    The Macro Recorder. Essentially, this feature records every literal user input: scrolling, selecting, viewing, activating, default properties, etc., to the point of overkill. While this is sometimes helpful, it does encourage bad code written by people who don't know that it's bad, but I will not belabor that point which has been made here:

    How to avoid using Select in Excel VBA macros

    What is better, conceptually?

    Program to the objects directly. If you're merely using VBA to mimic keystrokes and mouseclicks, you're doing it wrong.

    Exceptions:

    I've found when applying formatting to series data in charts, where Select is occasionally necessary. This seems IMO to be a bug with Excel and not a design feature.

    Other applications (because VBA is not only Excel):

    • Word is a different animal, which relies a lot more on Selection object
    • In PowerPoint there are some sort of operations that can only be performed when the application and slide/shape are visible or otherwise in view. While you don't usually need to "select" anything, it does require more cumbersome code.

    I found this snippet in my App:

        Set tb = cht.Shapes.AddTextbox(msoTextOrientationHorizontal, ptLeft, tBoxTop, ptWidth, ptHeight)
        tb.Select  '<--- KEEP THIS LINE OTHERWISE TEXTBOX ALIGNMENT WILL NOT WORK ## ## ##
    

    And this:

        'PPT requires selecting the slide in order to export an image preview/jpg
    sld.Select
    ppPres.Windows(1).View.GotoSlide sld.SlideIndex
    sld.Shapes(1).Chart.Export imgPath, ppShapeFormatJPG
    

    And this, dealing with individual Point objects:

            pt.Select
            pt.format.Line.Visible = msoTrue
            pt.format.Line.Visible = msoFalse
            pt.MarkerSize = pt.MarkerSize + 2
    

    This is not an exhaustive list, just some examples of exceptions that I found. While these were from PowerPoint, the charts in PowerPoint use the same object model as Excel so I would not be surprised if some of these also need to be hacked in Excel, and Word, too.

    • Outlook: I don't do much with Outlook, it is a lot like Word and actually uses the Word object model in the Inspector, but what little I do with Outlook does rely on things like ActiveInspector, etc.

    Neither Word or PowerPoint have a "macro recorder" anymore (actually, I think Word might but it's so damn impotent as to be useless) and by the time most people do any development in other applications, they've figured most of this out already.

提交回复
热议问题