5

对于这个问题,我参考下面的帖子来澄清一下自己:
为什么我的条件格式被VBA添加时会偏移?

在我最近看到的许多帖子中,OP 被允许使用 .Activate、.Select、.Offset 等...虽然它们是潜在错误的敞开大门(通常由最终用户引起)。
有时甚至支持该代码。

我的问题:是否存在一种有效情况,您可以使用这些语句中的任何一个,而没有可用的直接替代方法来捕获由这些 stmts 导致的典型错误?

我指的是动态解决方案,在我看来,这是为 Excel 开发时必须的。就个人而言,在超过 6 年的时间里,我不记得我需要它的一个案例。它似乎总是最糟糕的选择之一。在我以前的公司中,永远不要使用它是一条无声的规则,它只会让我的 VBA 生活(以及最终用户的生活)变得更好。

为什么我提出这个问题是因为我认为让 VBA 的新手意识到他们在使用这些语句时所承担的风险是值得的(通过经验证明最终用户做一些意想不到的事情时的风险 - 最终他们没有任何对 VBA 的喜爱)并提出直接的替代方案(我不会说我之前总是这样做,但我的直觉认为,仅仅为已经有 bug 的怪物提供快速解决方案是有问题的)。

我相信,当静默允许时(在这种情况下它会自动增强),开始 VBA 开发人员会以错误的方式创建越来越多的工具(因此新手也会继承这种行为——他们也将从 Stack Overflow 学习,因为谷歌回归他们寻找的结果(!))。
如果开发人员不知道为什么他“可以”使用“选择”以及在什么情况下它是一个潜在的错误,他不应该使用它恕我直言。就个人而言,我可能会在即时窗口中使用 select stmt 对动态范围定义(错误模式)进行一些快速检查,但不是在书面代码中。

结果最终使 VBA 比现在更不受欢迎;如果出现问题,该语言将成为受害者(但恕我直言,它仍然是 Excel 和 Access 应用程序可用的“最佳”编程支持)。我已经在一家 VBA 总是“狗屎”的大公司看到这种情况发生太多次了。

这只是我自己的真实经历。
这不是对与错的问题;我很想听听你对这个问题的看法。

4

5 回答 5

3

我同意 Select and Activate,但不同意 ActiveWorkbook、ActiveSheet 和 ActiveCell(我同意它们被滥用,但不应该避免它们本身)。这些肯定有合法用途。我有一个程序可以从 ActiveCell 自动执行“填充系列”。我的程序无法预测将使用哪些单元格;由用户来选择它。这是用户界面的一部分。

但是,在三种情况下我不得不使用 Select(现在我读到了四种关于缩放的,但我从来没有使用过它)。

  1. 条件格式。有一个使用 Application.ConvertFormula 的解决方法,但它比仅存储选择、选择正确的单元格、执行操作并重新选择先前的选择更糟糕。
  2. 数据验证。同样的原因。
  3. 形状。我希望我能记住细节,但我已经很久没有使用 Shapes 了。如果不先选择形状,有些事情我是做不到的。

摆脱选择和激活的代码是一场崇高的战斗。

于 2012-09-14T16:40:59.007 回答
2

Excel 中有一些方法需要激活或 ActiveSheet/ActiveWorkbook 等,因为我有时会遇到问题。目前我唯一记得的是 zoom 属性。缩放仅影响窗口中当前处于活动状态的工作表,因此要缩放所有工作表,您需要类似

Sub SetZoom()
Dim ws As Worksheet
    Application.screenupdating = false

    For Each ws In Worksheets
        ws.Select
        ActiveWindow.Zoom = 80
    Next ws

    Application.screenupdating = true
End Sub
于 2012-09-14T16:12:43.637 回答
1

您可以使用.Select来确定运行代码后用户的视图是什么 - 例如,如果您在代码中创建一个新工作簿,但不使用ActivateSelect您的用户可能不知道会发生这种情况。

我经常结束创建新工作簿或其他大规模数据操作的长时间操作

FinalViewWorkbook.FinalViewSheet.Range("A1").Select

只是为了通知最终用户一些事情 - “哦,这创建了一个新的报告工作簿!” 等等

于 2012-09-14T19:23:03.637 回答
0

我认为在这个问题上区分一些是很重要的:

  • Active-something:只有在绝对有必要知道用户现在正在处理什么时才使用它。根据我的经验,这通常是数据验证或活动工作表检测(例如“更新用户刚刚按下按钮的工作表”)。
  • Selection: 有点像Active,只是用来阅读。对于数据验证或“将单元格值解释为路径并在新的资源管理器窗口中打开它”之类的噱头很有用。
  • Select, Activate: Imho 与 不同Selection,因为它实际上更改了选定的单元格、工作表等。永远不要使用它来读取或写入数据,因为它使用户只需单击即可弄乱您的程序。用户喜欢点击。仅在代码完成工作后使用它来缩放(请参阅@user3357963 的回答)或清理视图(请参阅@enderland 的回答)。(我不确定,但我认为处理 PageView 也需要 ActiveSheet)。
  • Select, Activate2nd: 如果你是 VBA 新手,并且正在通过 Macro Recorder 学习,你会发现很多代码是这样生成的:首先Range("A5").Select,然后Selection.Value="NewValue". 加入这个Range("A5").Value="NewValue"
  • Offset: 就我个人而言,我使用这个命令没有问题.Offset()- 我从来没有遇到过这个命令的问题。相反,我认为这是一种方便的方式来表达“此单元格旁边的单元格”,而不必每次都通过“此单元格的表在此单元格的行和列+1”。

在我最近看到的许多帖子中,OP 被允许使用 .Activate、.Select、.Offset 等。

我同意这一点。尽管只给出必要的答案以使一段代码工作更容易,但ActiveCell.Value应不鼓励使用 等。如果有一个解释清楚的线程可以链接到,这将容易得多,因为这里希望成为:-)

于 2015-10-13T13:23:19.033 回答
0

从我的角度来看,除了少数例外,您唯一应该使用的时间Select是作为用户输入,并且只有在仔细考虑了替代设计/UI 要求之后。

例如,我会说Selection当此方法在代码中继续执行时,通常不建议依靠让用户定义 Range 对象:

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

但是,如果您需要提示用户选择工作表上的特定形状或对象,那么最好让他们制作一个Selection(但是,如果没有良好的错误处理和逻辑来防止不受欢迎的用户操作...)。

这是我在 PowerPoint 中遇到的一个此类异常的示例。我有一些 RibbonUI XML 和 VBA,它们将按钮添加到ShapesPowerPoint 的右键单击上下文菜单中,并将类似的按钮添加到功能区本身。这些是无缝的 UI,可以为最终用户提供更“原生”的应用程序体验——用户希望能够右键单击图表,然后针对选定的图表或表格运行一些宏程序等。他们没有不想按下按钮打开用户表单并滚动浏览通用形状名称或 GUID 的列表框。

过程代码需要检查Selection以正确处理它,因此我可以使用如下所示的内容,其中

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
 '....
 '...
 '..
 '.

它从何而来?

宏记录器。从本质上讲,此功能记录了每个文字用户输入:滚动、选择、查看、激活、默认属性等,到了矫枉过正的地步。虽然这有时会有所帮助,但它确实鼓励那些不知道它很糟糕的人编写糟糕的代码,但我不会在这里强调这一点:

如何避免在 Excel VBA 宏中使用 Select

从概念上讲,什么更好?

直接对对象进行编程。如果您只是使用 VBA 来模拟击键和鼠标点击,那么您做错了。

例外:

我发现在将格式应用于图表中的系列数据时,Select有时是必要的。这似乎 IMO 是 Excel 的一个错误,而不是设计功能。

其他应用程序(因为 VBA不仅仅是Excel):

  • Word 是一种不同的动物,它更多地依赖于 Selection 对象
  • 在 PowerPoint 中,有些操作只能在应用程序和幻灯片/形状可见或以其他方式显示时才能执行。虽然您通常不需要“选择”任何东西,但它确实需要更繁琐的代码。

我在我的应用程序中找到了这个片段:

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

和这个:

    '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

而这个,处理单个Point对象:

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

这不是一个详尽的列表,只是我发现的一些例外示例。虽然这些来自 PowerPoint,但 PowerPoint 中的图表使用与 Excel 相同的对象模型,因此如果其中一些也需要在 Excel 和 Word 中被破解,我不会感到惊讶。

  • Outlook:我对 Outlook 做的不多,它很像 Word,实际上在 Inspector 中使用 Word 对象模型,但我对 Outlook 所做的很少依赖于 ActiveInspector 等。

Word 或 PowerPoint 都不再有“宏记录器”(实际上,我认为 Word 可能会,但它太无能以至于无用),当大多数人在其他应用程序中进行任何开发时,他们已经弄清楚了大部分.

于 2015-10-13T16:32:41.247 回答