【问题标题】:VBA Project creating a subroutineVBA项目创建子程序
【发布时间】:2020-03-29 20:08:33
【问题描述】:

我有以下任务:

“创建一个名为 WherePutMe 的子例程,它要求用户输入行号和列字母,然后将选择的 2,2 位置放入该单元格中。

到目前为止,我做到了

Sub Whereputme()
  Dim x as integer, y as string
  x= Inputbox ("Enter a row number")
  y= Inputbox ("Enter a column letter")
  z= selection.range("B2")
End Sub

仍然缺少一些东西..如何将输入框输入与 z 链接?

【问题讨论】:

  • 你能解释一下“将选择的 2,2 位置放入该单元格”吗?
  • 这个问题需要进一步澄清“单元格”指的是什么以及 2,2 位置包含什么?作为一个 sn-p 也将有助于显示输出应该是什么样子。

标签: vba input subroutine inputbox


【解决方案1】:

你有End Sub,但没有Sub 声明..这是整个代码吗?如果用户取消提示怎么办?

假设您在一个标准模块中(例如Module1.bas),您会希望它的顶部有Option Explicit,然后Sub 语句定义您需要实现的过程 - 考虑制作它也明确Public

Option Explicit

Public Sub WherePutMe()
    'TODO
End Sub

这就是说“把我放在哪里”是一个可怕的程序名称。最佳做法是使用有意义的名称来传达代码的目的 - 由于过程做某事,您会希望它们的名称通常以动词开头。

不合格,InputBox 正在调用VBA.Interaction.InputBox,这是一个提示用户输入字符串的 VBA 标准库函数,用户可以在该提示之外Cancel。当这种情况发生时,你得到的是一个空字符串指针,它隐式转换为一个空字符串 - 但是,用户可以很好地输入一个空字符串并点击 Ok,所以在我们验证输入之前,我们首先需要知道提示是如何被解除的。

这很快就会变得复杂和混乱。我们可以将这种复杂性抽象为一个函数:

Private Function TryGetUserInput(ByVal prompt As String, ByRef result As String) As Boolean
    result = InputBox(prompt)
    TryGetUserInput = (StrPtr(result) <> 0)
End Function

现在我们可以这样做了:

Option Explicit

Public Sub WherePutMe()
    Dim userRowInput As String, userRow As Long, isValid As Boolean
    Do While Not isValid
        If TryGetUserInput("Enter a row number", userRowInput) Then
            'user submitted a value, now validate it
            If IsNumeric(userRowInput) Then
                'looks legit
                userRow = CLng(userRowInput)
                '...but is it?
                isValid = userRow > 0
            End If
        Else
            'user cancelled the prompt
            Exit Sub
        End If

        If Not isValid Then MsgBox "Invalid row number. Please enter a positive integer between 1 and 1,048,576.", vbExclamation
    Loop
    'TODO: get and validate the column letter
End Sub

避免做出过多假设的代码(假设错误 => 错误;想想任何给定的指令可能会失败并引发错误,从而将所有内容都付之一炬),并且毫不犹豫地将事情分解成小块,专门的过程和函数——像上面的循环在它自己的TryGetValidRowNumber函数中看起来很整洁,如果用户取消,则返回False,否则TrueByRef输出参数保存Long整数值调用者可以直接使用:

Public Sub WherePutMe()
    Dim rowNumber As Long
    If Not TryGetValidRowNumber(rowNumber) Then Exit Sub

    Dim columnLetter As String
    If Not TryGetValidColumnLetter(columnLetter) Then Exit Sub

    Dim targetCell As Range
    Set targetCell = ActiveSheet.Range(columnLetter & rowNumber)

    'TODO consume the targetCell as needed
End Sub

【讨论】:

    【解决方案2】:

    您遇到的问题是您将z 定义为某种东西,但您没有使用它。

    通过简单地删除代码中的 z = 部分,您现在告诉 VBA 您想要发生某些事情,而不是想要定义变量。

    您可能需要执行以下操作,其中CStr 将数字转换为字符串,以防在将字符串和整数组合在一起时出现问题。

    Sub Whereputme()
      Dim x As Integer, y As String
      x = InputBox("Enter a row number")
      y = InputBox("Enter a column letter")
      Cells(2, 2).Value = y & CStr(x)
    End Sub
    

    【讨论】:

    • 谢谢你的解释..因为我是初学者..还有很多东西要学
    • 没问题。这有帮助吗?
    【解决方案3】:
    Sub WherePutMe()
        Dim x As Integer, y As String, z As String
        Dim str As String
    
        x = InputBox("Enter a row number")
        y = InputBox("Enter a column letter")
        z = Selection.Range("B2")
        str = y & x
    
        ActiveSheet.Range(str) = z
    
    End Sub
    

    【讨论】:

    • 纯代码答案可能会解决问题,但如果您解释它们如何解决问题,它们会更有用。社区需要理论和代码才能完全理解您的答案。
    猜你喜欢
    • 2023-02-09
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-28
    • 2012-06-26
    • 2021-06-07
    相关资源
    最近更新 更多