VBA Неправильные числовые аргументы кода пользовательской формы, передающие переменные? - PullRequest
0 голосов
/ 06 октября 2018

Пытаясь создать электронную таблицу составления бюджета, в которой расходы считываются из файла CSV, я получаю распределение по категориям (через форму пользователя), и для этого бита входящие средства получают отдельную форму пользователя, в которую я могу поместить краткое описание.в текстовом поле, которое затем записывается рядом со значением в выходном листе.

Использовал этот сайт для загрузки, чтобы понять, как все это сделать - но застрял здесь.Макрос

работает хорошо, но выпадает в коде пользовательской формы с «Неверным числом аргументов или неправильным назначением свойства» и выделяет бит indescript (x) из строки bene.Caption.

Исходная подпрограмма -

Public x, xmax As Integer
Public incmng(1 To 100) As Variant
Public incdescript(1 To 100), inctot As String

' add in the incoming payments with user entered short description
    inctot = ""
    For x = 1 To xmax
        indes.Show
        inctot = incdescript(x) & "; " & inctot
        Cells(r - 2, 7) = inctot
    Next x

код пользовательской формы (названный indes) -

Private Sub UserForm_Initialize()
    ' Load the expenditure details
    expend.Caption = incdescript(x) & ": " & incmng(x)
    incans.Value = "change me :-)"
End Sub

Private Sub OKButton_Click()
    ' Allow user to put in a short description
    incdescript(x) = incmng(x) & " " & incans.Text
Unload Me
End Sub
Private Sub CancelButton_Click()
    Unload Me
    End
End Sub

Это почти как если бы он не мог передать значения для "x" между подпрограммами, так какв первом случае он отображается в виде значения = 1, а в коде пользовательской формы - как неспособный к компиляции.

спасибо за любой совет!

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Даже если это сработало, вы не хотите использовать такие переменные.Им должна быть предоставлена ​​самая узкая область действия, чтобы избежать вероятности того, что вы забудете (или кто-то другой, обслуживающий ваш код, забудет), что они объявлены глобально.

Как уже упоминалось в комментариях, объявления, разделенные запятыми, похожи на это ...

Public x, xmax As Integer

... строго типизированы только для тех, которые имеют As {Type} после них.В этом случае xmax является Integer, а x неявно является Variant, поскольку тип не был объявлен.

Пользовательские формы являются классами в VBA, и как классы они могут быть расширены с помощьюпубличные методы и свойства.Проблема в том, что вы используете экземпляр формы по умолчанию вместо создания новых экземпляров в цикле.Когда вы вызываете Unload из внутри формы, вы делаете именно это, и вся информация просто теряется.

Решение состоит в том, чтобы явно создавать экземпляры ваших форм.Таким образом, вы можете настроить их с помощью пользовательских инициализаторов или свойств и легко передавать информацию от вызывающей стороны.Код формы будет выглядеть примерно так:

'indes
Option Explicit

Private incdescript As String
Private incmg As String
Private userEntry

Public Sub LoadValues(descript As String, incoming As String)
    expend.Caption = descript & ": " & incoming
    incdescript = descript
    incmg = incoming
End Sub

Public Property Get UserDescription() As String
    UserDescription = incdescript = incmg & " " & incans.Text
End Property

Private Sub OKButton_Click()
    Me.Hide
End Sub

Несколько замечаний - в этой форме ничто не зависит от глобальных переменных.Вся конфигурация обрабатывается передачей параметров в процедуру LoadValues, а «возвращаемое значение» предоставляется через пользовательское свойство UserDescription.

Также обратите внимание, что кнопка OK не Unloadформа.Это важно, потому что вы собираетесь использовать это для передачи информации назад вызывающей стороне.

Код вызова будет выглядеть примерно так:

Dim x As Integer, xmax As Integer
Dim incmng(1 To 100) As Variant
Dim incdescript(1 To 100) As String, inctot As String

' add in the incoming payments with user entered short description
inctot = ""
Dim paymentDialog As indes
For x = 1 To xmax
    Set paymentDialog = New indes
    paymentDialog.LoadValues incdescript(x), incmng(x)
    paymentDialog.Show vbModal
    inctot = paymentDialog.UserDescription & "; " & inctot
    Unload paymentDialog
    Cells(r - 2, 7) = inctot
Next x

Вы создаетеновый экземпляр формы, передайте ему значения, необходимые для формы, прежде чем показывать ее.Когда форма вызывает Me.Hide, управление переходит обратно к вызывающей процедуре, а затем вы запрашиваете у формы , что вводил пользователь.Затем вызывающая процедура выгружает ее.

Обратите внимание, что это всего лишь приблизительный набросок того, что я бы назвал "лучшими практиками" для обработки UserForm.Для более подробного описания я бы посмотрел на этот ответ @MathieuGuindon и прочитал его пост в блоге здесь .

0 голосов
/ 06 октября 2018

Поэтому решили упростить и использовать переменную «pass», создавая информацию, которую я хочу поместить в заголовок пользовательской формы, вне пользовательской формы, отправить ее с помощью pass , отобразить, зафиксировать ввод пользователяиспользуя ту же переменную (может отличаться, но не нужно), а затем собрать мои строки обратно в модуль ядра.

' add in the incoming payments with user entered short description
    Cells(r - 2, 5) = inctot
    For m = 1 To mmax
        pass = incdescript(m) & ": " & Incmng(m)
        indes.Show
        Inctotdes = Incmng(m) & " " & pass & "; " & Inctotdes
        Cells(r - 2, 7) = Inctotdes
    Next m

О, и я понял, что x был предопределенным вариантом.не то изменение, которое имело значение в любом случае.Обычно я никогда не использовал его (по этой причине я сейчас вспоминаю - это лучшая часть 10 лет с тех пор, как я использовал VBA!), Но мое предпочтительное письмо для подсчета уже использовалось.

Private Sub UserForm_Initialize()
    ' Load the expenditure details
    expend.Caption = pass
    incans.Value = "change me :-)"
End Sub

Private Sub OKButton_Click()
    ' Allow user to put in a short description
    pass = incans.Text
Unload Me
End Sub
Private Sub CancelButton_Click()
    Unload Me
    End
End Sub

Решение работает, но почему не работает передача массивов переменных, я все еще застрял.Я использую ту же стратегию для других пользовательских форм создания подписей из массивов в публичной памяти.Хотя разница в том, что код пользовательской формы не манипулирует ими, а просто передает ответ, так как я изменил это.Я думаю, что там, где это не удалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...