【问题标题】:VBA Syntax: Runtime Error 424 - Object requiredVBA 语法:运行时错误 424 - 需要对象
【发布时间】:2020-05-28 08:48:53
【问题描述】:

这可能已经被问过了,但我仍然需要问,因为我对 VBA 和整个编程还很陌生,我不知道我做错了什么。 我有一个用户表单,它从文本框(在本例中为数字)获取数据,并在我的表中搜索它。 然后,从那个范围,我正在采取步骤来检索连接到这个数字的数据:

定义变量:

Sub UserForm_Initialize()
Call CloseButtonSettings(Me, False)
Dim selected_col As Long
Dim PZ_ID As Single, KD_ID As Single, Customer_Combination As String, Ship_ID As String, Author_ID As String, _
Art_Lager As Single, Art_Bestell As Single, DTPicker1 As Date, Calc_Time As Single, Time1 As Single, _
Time2 As Single, Time3 As Single, Time_Special As Single, Time_Total As Single, Notes_Buero As String, Notes_Lager As Single
End Sub

搜索 + 将数据放入文本框

  Private Sub CommandButton1_Click()
    Dim PZ_RNG As Range
    Dim strSearch As String

    strSearch = Packzettelinfo.PZ_ID
    Set PZ_RNG = Range("B:B").Find(strSearch, , xlValues, xlWhole)
    If Not PZ_RNG Is Nothing Then
    Else
        MsgBox "Packzettel Nr. " & strSearch & " konnte nicht gefunden werden (Fehler #001)", vbOKOnly
        Packzettelinfo.PZ_ID.SetFocus
    End If
    Range("E1") = PZ_RNG.Row 'Saving for later

Packzettelinfo.KD_ID = Cells(PZ_RNG.Row, PZ_RNG.Column + 1)
Packzettelinfo.Customer_Combination = Cells(PZ_RNG.Row, PZ_RNG.Column + 2)
Packzettelinfo.Ship_ID = Cells(PZ_RNG.Row, PZ_RNG.Column + 3)
Packzettelinfo.Author_ID = Cells(PZ_RNG.Row, PZ_RNG.Column + 4)
Packzettelinfo.Art_Lager = Cells(PZ_RNG.Row, PZ_RNG.Column + 5)
Packzettelinfo.Art_Bestell = Cells(PZ_RNG.Row, PZ_RNG.Column + 6)
Packzettelinfo.DTPicker1 = Cells(PZ_RNG.Row, PZ_RNG.Column + 7)
Packzettelinfo.Calc_Time = Cells(PZ_RNG.Row, PZ_RNG.Column + 8)
Packzettelinfo.Time1 = Cells(PZ_RNG.Row, PZ_RNG.Column + 10)
Packzettelinfo.Time2 = Cells(PZ_RNG.Row, PZ_RNG.Column + 11)
Packzettelinfo.Time3 = Cells(PZ_RNG.Row, PZ_RNG.Column + 12)
Packzettelinfo.Time_Special = Cells(PZ_RNG.Row, PZ_RNG.Column + 13)
Packzettelinfo.Time_Total = Cells(PZ_RNG.Row, PZ_RNG.Column + 14)
Packzettelinfo.Notes_Buero = Cells(PZ_RNG.Row, PZ_RNG.Column + 15)
Packzettelinfo.Notes_Lager = Cells(PZ_RNG.Row, PZ_RNG.Column + 16)
End Sub

这很好用!

但是当我尝试保存文本框时(内容已更改),它显示“运行时错误 424”:

Private Sub CB_PZ_save_edit_Click()
Cells(PZ_RNG.Row, PZ_RNG.Column + 1) = Packzettelinfo.KD_ID
Cells(PZ_RNG.Row, PZ_RNG.Column + 2) = Packzettelinfo.Customer_Combination
Cells(PZ_RNG.Row, PZ_RNG.Column + 3) = Packzettelinfo.Ship_ID
Cells(PZ_RNG.Row, PZ_RNG.Column + 4) = Packzettelinfo.Author_ID
Cells(PZ_RNG.Row, PZ_RNG.Column + 5) = Packzettelinfo.Art_Lager
Cells(PZ_RNG.Row, PZ_RNG.Column + 6) = Packzettelinfo.Art_Bestell
Cells(PZ_RNG.Row, PZ_RNG.Column + 7) = Packzettelinfo.DTPicker1
Cells(PZ_RNG.Row, PZ_RNG.Column + 8) = Packzettelinfo.Calc_Time
Cells(PZ_RNG.Row, PZ_RNG.Column + 10) = Packzettelinfo.Time1
Cells(PZ_RNG.Row, PZ_RNG.Column + 11) = Packzettelinfo.Time2
Cells(PZ_RNG.Row, PZ_RNG.Column + 12) = Packzettelinfo.Time3
Cells(PZ_RNG.Row, PZ_RNG.Column + 13) = Packzettelinfo.Time_Special
Cells(PZ_RNG.Row, PZ_RNG.Column + 14) = Packzettelinfo.Time_Total
Cells(PZ_RNG.Row, PZ_RNG.Column + 15) = Packzettelinfo.Notes_Buero
Cells(PZ_RNG.Row, PZ_RNG.Column + 16) = Packzettelinfo.Notes_Lager
End Sub

再次,由于我是新手,对于我想做的事情来说,这可能是一种愚蠢的方法,但是哦,好吧......

【问题讨论】:

  • 我没有看到你在哪里定义了Packzettelinfo...
  • @braX Packzettelinfo 是我的用户表单,其中有文本框(KD_ID 等)
  • 一旦表单初始化,所有在UserForm_Initialize() 中定义的变量都会被遗忘...当您在CB_PZ_save_edit_Click() 中使用它们时,它们都将隐式类型为Variant - 仅供参考。您可能希望在要使用它们的每个模块中声明它们。
  • 看起来scope 在这里很重要。该链接将有助于全局变量(如果实际上需要它们)。
  • @NareshBhople 是的,我愿意!电子表格中的值已更改。另外,它是一个文本框。那我不需要声明它们吗? (bc 教科书总是文本格式对吗?我需要这些值,因为我可能正在计算,但这也可能在 excel 本身中......)

标签: excel vba syntax


【解决方案1】:

让我们退后一步,看看我们想要做什么。

  1. 从工作簿的某个范围内获取一些数据并将其填充到用户表单文本框中。
  2. 编辑用户窗体上的数据。
  3. 将新数据更新回工作表。

现在我们可以将精力集中在这 3 个步骤上。

但在我们开始之前,您会从了解 VBA 中的 scope 中受益。

现在您的代码不是最具描述性的(至少不是英文的),所以如果问题 cmets 中没有说明,我将做一些假设。

下面是在一个新的用户表单上写的,带有一个文本框、标签和 2 个命令按钮,所有这些都具有默认名称(下面的屏幕截图)。

第 1 步:

您获取数据并将其放入文本框的方法很好。为避免歧义,最好始终明确限定我们的语句,以便代码查看正确的工作簿/工作表或用户表单等。

Private Sub CommandButton1_Click()

    Dim TargetCell As Range
    Dim SearchString As String
    SearchString = ThisWorkbook.Sheets("Sheet1").Range("A1").Value 'Only "Range("A1").Value" implies ActiveSheet which may give false results.

    Set TargetCell = ThisWorkbook.Sheets("Sheet1").Range("B:B").Find(SearchString, , xlValues, xlWhole)

    If Not TargetCell Is Nothing Then
        'TargetRange Is Something, do the thing
        'You could assign the values to the textbox here rather than outside of the If statement
        'Or you could change it to If TargetCell Is Nothing Then - And only execute the code in the Else section below
    Else
        MsgBox "Packzettel Nr. " & strSearch & " konnte nicht gefunden werden (Fehler #001)", vbOKOnly
        UserForm1.TextBox1.SetFocus
        Exit Sub    'This stops the rest of the code from running - I'm assuming the above is an error that nothing was found.
    End If

    ThisWorkbook.Sheets("Sheet1").Range("E1") = TargetCell.Address 'Saving for later

    UserForm1.TextBox1.Value = ThisWorkbook.Sheets("Sheet1").Cells(TargetCell.Row, TargetCell.Column).Offset(0, 1).Value

End Sub

我对代码所做的唯一真正更改是明确where RangeCells 是或者我们想要访问该对象的Value 属性。

那并使用Offset 属性而不是+ 1 等作为列。

第 2 步:

用户根据需要更改数据 - 我们无需明智地进行编程。

您可以在此处添加一些步骤以进行数据验证等。

第三步:

再次将数据写回工作表,您已经写得很好。我再次确保使用相关的工作簿/工作表以及我们想要访问的属性(例如Value)明确限定RangeCells 之类的对象。

这次我将把工作簿/工作表分配给一个变量。

Private Sub CommandButton2_Click()

    Dim TargetSheet As Worksheet
    Set TargetSheet = ThisWorkbook.Sheets("Sheet1")
    Dim TargetCellAddress As String

    With TargetSheet
        TargetCellAddress = .Range("E1").Value  'Recall our saved cell address from the Commandbutton1 click
        .Range(TargetCellAddress).Offset(0, 1).Value = UserForm1.TextBox1.Value
        .Range("E1").ClearContents  'Remove TargetCellAddress value from the sheet
    End With

End Sub

这里与上面基本相同,但相反,虽然使用之前保存的Range.Address 属性(在E1 中)。

请注意,您可以将您的语句封装在With Statement 中,就像我对TargetSheet 所做的那样,您可以访问它的对象、属性和方法,而不必每次都对其进行限定——尽管每个语句都以@987654356 开头@


总结一下;

  • 不需要为任何文本框值声明变量,只需将它们直接从用户表单/工作表分配给/分配给用户表单/工作表,反之亦然。
  • 限定您的对象等,例如RangeCells,并明确引用您要使用的属性,即Value(有些默认为这个,但不是全部!)。

以下是每次点击时的一些屏幕截图。

用户窗体首次打开:

点击了Commandbutton1:

TextBox1 已编辑:

点击了Commandbutton2:

【讨论】:

  • 好的,首先我要非常感谢你的解释。这实际上帮助了我很多。这是对我有帮助的第一个“真正的答案”;再次,谢谢。偏移的步骤很好。我正在考虑使用 for 循环来获取所有值,但这对不同的文本框名称不起作用(如果它是 tb1-tb15 它可能会解决吗?)。这个阅读 - 保存部分将在我的 vba 项目的另一部分中派上用场,我想在其中添加一个新行,所有内容都是空白的,所以这也适用。我非常感谢您的时间和奉献精神!干杯。
  • 现在您的代码不是最具描述性的(至少不是英文的),所以如果问题 cmets 中没有说明,我将做一些假设。 - 这是德语,你的假设非常准确:)
  • @LeonS 很好,尽管 cmets 对您的问题很有帮助,但该网站的重点是问题 答案 - 我有一些时间可以解释一些事情! - 您可以创建一个循环并检查每个复选框,然后访问该值 - 有关如何执行此操作的简单示例,请参见 this answer。如果您有其他要忽略的文本框,那么编写代码可能会很长,所以也要记住这一点。如果你被卡住了,再问一个问题!快乐编码! :)
猜你喜欢
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
  • 1970-01-01
相关资源
最近更新 更多