VBA Project создает подпрограмму - PullRequest
1 голос
/ 29 марта 2020

У меня есть следующая задача:

"Создать подпрограмму 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?

Ответы [ 3 ]

2 голосов
/ 29 марта 2020

У вас есть End Sub, но нет Sub заявления ... это весь код? Что, если пользователь отменяет запросы?

Предполагая, что вы находитесь в стандартном модуле (например, Module1.bas), вы захотите, чтобы он имел Option Explicit вверху, а затем оператор Sub определяет процедуру, которую нужно реализовать - подумайте и о том, чтобы сделать ее явно Public:

Option Explicit

Public Sub WherePutMe()
    'TODO
End Sub

Сказанное «Куда меня положили» - ужасное название для процедуры. Рекомендуется использовать значимые имена, которые передают цель кода - и поскольку процедуры делают что-то , вам нужно, чтобы их имена обычно начинались с глагола.

Unqualified, InputBox вызывает VBA.Interaction.InputBox, стандартную библиотечную функцию VBA, которая запрашивает у пользователя строку, и пользователь может отменить из этого приглашения. Когда это происходит, вы получаете нулевой строковый указатель, который неявно преобразуется в пустую строку - но тогда пользователь вполне может ввести пустую строку и нажать Ok , поэтому прежде чем мы проверяем ввод, мы сначала нужно знать, как запрос был отклонен.

Это быстро усложняется и хаотично c. Мы могли бы абстрагировать эту сложность за функцией:

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

Избегайте кода, который делает слишком много предположений (нарушенное предположение => ошибка; подумайте о как любая конкретная инструкция может потерпеть неудачу и выдать ошибку, которая отправляет все в пламя), и не стесняйтесь разбить вещи на небольшие специализированные процедуры и функции - как вышеупомянутый l oop будет выглядеть довольно аккуратно в своем собственном TryGetValidRowNumber функция, которая возвращает False в случае отмены пользователем, True в противном случае с выходным параметром ByRef, содержащим целочисленное значение 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
0 голосов
/ 29 марта 2020
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
0 голосов
/ 29 марта 2020

Проблема, с которой вы столкнулись, заключается в том, что вы определяете 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
...