【问题标题】:Need a way to input data in specific cells with Excel VBA需要一种使用 Excel VBA 在特定单元格中输入数据的方法
【发布时间】:2020-01-21 02:53:04
【问题描述】:

试图解决从“E2”开始读取“信息表”上“E”列中的帐号并获取该数字并将其输入到“证明”上包含空白单元格的第一行的循环" 帐号部分下的工作表 ('E4')。将号码放在那里后,与单元格“E4”中的帐号关联的“长名称”(在第 200 行的表格中找到)出现在帐户名称部分下的第一个空白单元格(“B4”)中.然后,循环继续并读取“输入表”上的下一个单元格('E3'),如果该帐号属于同一名称,则将该号码放在“证明”上的下一个白色单元格('G4')中“ 床单。如果帐号与单元格“B4”中的帐户名没有关联,请将其放在包含空白单元格“E12”的下一行中,并在单元格“B12”中的帐户名下的单元格中为该号码分配适当的名称,然后继续在信息表上的“E”列中的列表并重复该过程,直到第一张表上的所有帐号都完成并且所有适当的帐号都在具有这些帐号的适当“长名称”的行上.

如何将与帐户名称关联的所有帐户放在特定白色单元格的同一行中,而不在同一行中发布两次?

这是我的代码:

Sub loopything()


Dim infoSheet As Worksheet, proofSheet As Worksheet, refRange As         Range, lastRow As Long, r As Long
Dim acct As String, foundAcct As Range, nextRow As Long
Set infoSheet = ThisWorkbook.Sheets("Info Sheet")
Set proofSheet = ThisWorkbook.Sheets("Proof")

With proofSheet
nextRow = 4 ' waiting to adjust to normal table format
End With

With proofSheet

Set refRange = .Range("A200:L79000")

End with 

With InfoSheet

lastRow = 30 ' .cells(.rows.count, "E").end(xlup).row

For r = 2 To lastRow

acct = .Cells(r, "E")
Set foundAcct = refRange.Find(what:=acct)
longname = foundAcct.Offset(0, 1)


proofSheet.Cells(nextRow, "E") = acct
proofSheet.Cells(nextRow, "B") = longname
nextRow = nextRow + 8   ' would be nicer to just add one row (see  first note)

Next r

End With

End Sub

查看 sn-ps 以供参考。

信息输入表

校样表

代码目前正在这样做:

看看在应该模仿真实表格的练习示例中,名称如何出现在多行上,并带有各自的帐号,而它们应该以相同的名称出现在同一行上,并且所有帐号都在一个上排。

【问题讨论】:

  • No attempt was made。请始终包括您尝试过的内容。请注意,这不是免费的编码服务。你需要问一个问题(见How to AskWhy is “Can someone help me?” not an actual question?)。
  • 我很抱歉。我不知道我需要提供尝试证明。我确实浏览了整个网络,但找不到任何可以解决这个困境的东西,也不知道如何将这样的循环放在一起。我会尝试找到一些东西来证明我试图找出解决方案。
  • 至少你应该把你的问题缩短到一个特定的部分。我试图解释这个问题:你现在所做的是解释你的整个项目,这太宽泛了,不能在这里问。试着把它分成小部分,只询问你有问题的部分。绝对有必要问一些事情,因为你没有。 • 考虑一下您需要解决哪些步骤,实际上一个程序将执行或多或少完全相同的步骤,就像您手动执行一样。所以开始用手做/思考,找出你的步骤。然后询问一步。那么更有可能得到答案。
  • 我将我的帖子编辑为更短、更清晰的帖子,其中包含关于我需要帮助的步骤的问题。我还添加了我找到并根据我需要进行操作的代码,但仍然没有让它完全满足我的需要。我希望这是一个更好的帖子。
  • 在您的原始文档(输入表)中 - 您在哪些列中有“帐户名称”/“长名称”和“金额”/“代理编号”?是 F 和 G 还是 H 和 I? 2 张图片显示不同的结果。

标签: excel vba loops


【解决方案1】:

试试这个。我没有使用find 方法,因为您可能会在同一个数据集上进行多次搜索。所以我将它加载到一个数组中,而不是一个范围对象(它是faster)。

要记住一件事 - 在运行它之前,您需要删除 Proof sheet 中的所有帐号。

Sub loopything()

  Dim wsInfoSheet As Worksheet
  Dim wsProofSheet As Worksheet
  Dim lngLastRow As Long
  Dim r As Long
  Dim sAcct As String
  Dim lngNextRow As Long
  Dim sLongName As String

  Dim arrRef() As Variant
  Dim arrNames() As String
  Dim i As Long
  Dim lngRowInNames As Long
  Dim lngFoundName As Long

  Set wsInfoSheet = ThisWorkbook.Sheets("Info Sheet")
  Set wsProofSheet = ThisWorkbook.Sheets("Proof")

  ' Will be used in the Proof sheet
  lngNextRow = 4 ' waiting to adjust to normal table format

  arrRef = wsProofSheet.Range("A200:L79000").Value
  ReDim arrNames(1 To UBound(arrRef, 1) + 1, 1 To 2)

  With wsInfoSheet

    lngLastRow = 30 ' .cells(.rows.count, "E").end(xlup).row

    lngRowInNames = 1
    For r = 2 To lngLastRow
      sAcct = .Cells(r, "E")
      'lookup for sAcct in arrRef
      For i = 1 To UBound(arrRef, 1)
        If arrRef(i, 1) = sAcct Then
          sLongName = arrRef(i, 2) '(row i, column 2 from arrRef)
          arrNames(lngRowInNames, 1) = sLongName
          arrNames(lngRowInNames, 2) = lngNextRow
          lngRowInNames = lngRowInNames + 1
          Exit For
        End If
      Next
      'lookup for sLongName in arrNames
      For i = 1 To UBound(arrNames, 1)
        If arrNames(i, 1) = sLongName Then
          lngFoundName = i
          Exit For
        End If
      Next

      'if the name is new
      If arrNames(lngFoundName + 1, 1) = "" Then
        wsProofSheet.Cells(lngNextRow, "E") = sAcct
        wsProofSheet.Cells(lngNextRow, "B") = sLongName
        lngNextRow = lngNextRow + 8   ' would be nicer to just add one row (see  first note)
      'if the name already exists
      Else
        wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Columns.Count).End(xlToLeft).Column + 3) = sAcct
      End If

    Next 'r

  End With

End Sub

【讨论】:

  • 我能够修复它,但是您在代码中的哪一行寻找与帐号关联的“长名称”?包含帐号和长名称以及帐户名称的范围位于 A200 和 L79000 之间。它不是提取长名称,而是提取帐户名称。帐户名称在 B 列(B200:B7900),长名称在 L 列(L200:L79000)。链接到长名称的帐号在 A 列 (A200:A79000) 中,所有这些都在证明表上。除此之外,代码似乎正在运行。
  • 没关系。我能够修复它。问题是 'sLongName = arrRef(i, 2) '(第 i 行,来自 arrRef 的第 2 列)'。我把 12 放在我需要的信息所在的位置,而不是 2。非常感谢!代码完美运行!我将再进行几次测试,然后告诉你结果如何。
  • 在输入表上输入数据时如何触发代码运行?我已经有一个 Worksheet_Change 子输入表上的其他内容。我将您创建的代码放在了校样表中。有小费吗? @ZygD
  • 首先,您可以在此站点中编辑我的代码 - 粘贴适合您的版本。然后,我也许可以再次编辑它,这样您就不需要在运行代码之前删除所有帐号。然后,如果你真的想要,你可以将这个 sub 调用到 Worksheet_Change 事件中。 Here 您可以找到一个示例,其中某些代码仅在工作表中的特定单元格更改时才运行。关键行是If Not Intersect(Target, Me.Range("G1")) Is Nothing Then - 它使代码在 G1 更改时运行。
  • 那么,看帖子,我是在校样表还是信息输入表上输入这个代码?目前,代码在前一张表上,因为已经有一个带有“Worksheet_Change”的宏。因此,根据信息输入表上整行的更改,您的代码应该运行。有没有办法根据范围而不是特定单元格来调用?如您所知,有多个单元格会发生变化。
【解决方案2】:

所以,这是我目前正在使用的代码。当范围内的单元格发生更改时,我将代码嵌入到更改事件中。但是,我很想知道代码是否有办法确保如果帐号已经在一个单元格中,它不应该在同一行的下一个单元格中再次发布相同的号码。这意味着,每次范围发生变化时,宏都会重新运行并重复放置数字。我假设我需要在代码中的某处进行重置,但我不知道如何或在哪里。

Sub worksheet_Change(ByVal target As Range)

If Not Application.Intersect(target, Range("D2:D30")) Is Nothing Then
Application.EnableEvents = False
Dim wsInfoSheet As Worksheet
Dim wsProofSheet As Worksheet
Dim lngLastRow As Long
Dim r As Long
Dim sAcct As String
Dim lngNextRow As Long
Dim sLongName As String

Dim arrRef() As Variant
Dim arrNames() As String
Dim i As Long
Dim lngRowInNames As Long
Dim lngFoundName As Long

Set wsInfoSheet = ThisWorkbook.Sheets("Info Input")
Set wsProofSheet = ThisWorkbook.Sheets("Proof")

'Will be used in the Proof sheet
lngNextRow = 4 ' waiting to adjust to normal table format

arrRef = wsProofSheet.Range("A199:L79000").Value
ReDim arrNames(1 To UBound(arrRef, 1) + 1, 1 To 2)

With wsInfoSheet

lngLastRow = .Cells(.Rows.Count, "E").End(xlUp).Row

lngRowInNames = 1
For r = 2 To lngLastRow
  sAcct = .Cells(r, "E")
  'lookup for sAcct in arrRef
  For i = 1 To UBound(arrRef, 1)
    If arrRef(i, 1) = sAcct Then
      sLongName = arrRef(i, 12) '(row i, column 2 from arrRef)
      arrNames(lngRowInNames, 1) = sLongName
      arrNames(lngRowInNames, 2) = lngNextRow
      lngRowInNames = lngRowInNames + 1
      Exit For
    End If
  Next
  'lookup for sLongName in arrNames
  For i = 1 To UBound(arrNames, 1)
    If arrNames(i, 1) = sLongName Then
      lngFoundName = i
      Exit For
    End If
  Next

  'if the name is new
  If arrNames(lngFoundName + 1, 1) = "" Then
    wsProofSheet.Cells(lngNextRow, "E") = sAcct
    wsProofSheet.Cells(lngNextRow, "B") = sLongName
    lngNextRow = lngNextRow + 8   ' would be nicer to just add one row (see  first note)
  'if the name already exists
  Else
    wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Cells(arrNames(lngFoundName, 2), wsProofSheet.Columns.Count).End(xlToLeft).Column + 3) = sAcct
  End If

Next 'r

End With
Application.EnableEvents = True
End If

Dim iCell As Range
If Not Application.Intersect(target, Range("A2:A30")) Is Nothing Then
Application.EnableEvents = False
For Each iCell In Range("A2:A30")
    If iCell.Address = target.Address Then
        Range("C" & iCell.Row).ClearContents
        Range("D" & iCell.Row).ClearContents
        Range("I" & iCell.Row).ClearContents
    End If
Next iCell

End If
Application.EnableEvents = True
End Sub

【讨论】:

  • 这可能会在我查看之前被删除。值得发布另一个问题。
  • 好的@ZygD。我将发布一个新问题。
  • @ZygD 我创建了另一个问题Link
  • 关于您的第二部分(A2:A30),您可以删除所有 For Each 块并将其替换为这一行:Intersect(Target.EntireRow, Range("C:D,I:I")).ClearContents
猜你喜欢
  • 1970-01-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多