Microsoft Excel:宏可多次重复执行特定操作

时间:2018-07-13 09:24:28

标签: excel vba excel-vba

我的任务是使用Excel处理大量数据,我听说过使用宏,但是我不太懂代码。我记录了使用宏功能所需的步骤,但是我需要添加更多代码行来利用循环,并确保每次重复执行后循环前进2。

我在下面发布了我的步骤:

Range("A5:C5").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A5").Select
ActiveCell.FormulaR1C1 = "=R[-1]C+0.1"
Range("B7:C7").Select
Selection.Copy
Range("B5").Select
ActiveSheet.Paste
Application.CutCopyMode = False

基本上,选择3个单元格(A5:C5)插入单元格并向下移动单元格。在新清空的A5中使用公式将0.1添加到A4,然后从B7:C7复制值并将其粘贴到B5:C5。

下图显示了我正在讲的内容前后的含义。

之前
Before

之后
After

下一步将是:

Range("A7:C7").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A7").Select
ActiveCell.FormulaR1C1 = "=R[-1]C+0.1"
Range("B9:C9").Select
Selection.Copy
Range("B7").Select
ActiveSheet.Paste
Application.CutCopyMode = False

以此类推。

任何对此的帮助将不胜感激。我也很抱歉,我要问的内容是否仍然令人困惑或不清楚。

2 个答案:

答案 0 :(得分:3)

[序言:]

您好,我会为您提供答案,我尝试在其中进行注释,以使其对初学者尽可能友好,但事实是:

我可以向您解释它是如何完成的,但是直到您正确理解了诸如循环之类的基本编程方法之后,您才永远无法正确理解其完成的原因,这是只有您和您一个人必须坐在那里全面了解


[逻辑空白:]

  

最大的问题可能是,您尚未指定会发生什么情况   当您的数据到达空单元格时(我的意思是)-如果在   您的循环位于第10行(7,M,N),您将不再   要添加的字母,因为接下来的两行(12)不再包含eny数据。

鉴于此,我将循环修改为从第n-2行开始,以防止这种情况发生(这意味着在您的示例中,该循环将以(或更确切地说开始)结束于6.1因为它是可以检索数据的最后一行)

通常,我建议您不仅发布一张输入数据的图片,而且发布当前结果的图片,在这种情况下,正确解释的预期结果将对我们有所帮助和理解,并且可以为我节省很多时间这里的猜测。


[您问题的理论部分:]

在这里,我会用一些有用的事实为您节省一些搜索时间。

  1. 如果您想重复执行特定操作,则应该始终使用fordo (while/until)循环中的2个循环(或3个,具体取决于您对它们的分类方式)中的一个
  2. >
  3. 更好的是,如果您希望循环执行不同数量的动作重复多次,则应该使用过程Sub或函数Function,以便可以使用执行操作的参数作为循环变量。
  4. 通常在添加或删除行时,从下到上(从最后到第一个)循环很重要。为什么?因为如果您添加额外的行,将会弄乱您的行顺序。

考虑到所有这些,过程本身可能看起来像这样:


[解决方案本身:]

您可以在指定范围内每次使用以下步骤。

Option Explicit 'prevents typo. errors, undeclared variables and so on

Private Sub extra_row(ByVal rng As Range) 'declaration of procedure

 Dim i As Long
 ' we loop for the n-th - 2 row (last row - 2) to the pre-first (added) row.
 For i = (rng.Rows.Count + rng.Row - 2) To rng.Row + 1 Step -1
 'why the -2? ^ Because if you add the letters from next 2 rows,_
  the last 2 would have no to grab _
  eg. Row 10 and 11 in your original data would have no data under them to grab

 ' a bit harder section to comprehend, if it's the first data entry _
   we need to account for the fact that we have not added any extra rows yet_
   hence we also need to decrement the row from which we receive the data by 1 _
   it 's bit of difficult to word, i'd highly recommend debugging yourself _
   and seeing what happens with or without it
  Dim fp As Integer
    If (i - 2 = rng.Rows.Count) Then
      fp = 1
    Else
      fp = 0
    End If

    ' now we just add the extra rows where we can
    Rows(i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
    Cells(i, 1) = Cells(i, 1).Offset(-1, 0) + 0.1 'we add 0.1 to cell one above
    Cells(i, 2) = Cells(i + 3 - fp, 2) ' similar case, with letters, but two below
    Cells(i, 3) = Cells(i + 3 - fp, 3) ' similar case, with letters, but two below
  Next i 'and we loop for every cell in our specified range

End Sub

例如。您可以使用以下命令运行该过程:

Call extra_row(Range("A4:A11"))

[实际使用]

尽管解决方案本身应该可以工作,但在实际示例中,不使用特定范围来调用每个过程可能更聪明。尤其是如果这意味着必须查看工作表,请检查范围并手动计算行数。

这就是我们在此处创建一个过程的原因之一。因此,我在大多数编程语言中又创建了一个类似于main()的过程,该过程将检测最后一个活动行,并通过自动检测该过程将其应用于您的数据范围。

所以最后,您应该看起来像这样:

Option Explicit
Private Sub extra_row(ByVal rng as Range)
  '... code from the answer here
End Sub

Private Sub rundata()
    Dim lr As Long
    lr = Sheets("Your Sheet Name").Cells(Rows.Count, 1).End(xlUp).Row 
    'detects the last active (nonempty) row _
     rememeber to change the  Sheets("") to wherever your data is stored

    Dim mydata As Range
    Set mydata = Range("A4:A" & lr) 'under presumption your data always begins with A4

    Call extra_row(mydata)     
End Sub

现在,无论何时(手动)或Call run_data()过程运行时,它都会自动检测范围并将我们定义的过程应用于该范围。


[预期结果可视化和结束语:]

我们从这里开始:

enter image description here

运行过程之后:

enter image description here

现在我知道了,这里似乎有很多新颖的概念,但事实是,一旦您扎根并尝试逐行理解代码,所有这些概念都相当容易。大部分是简单的数学运算。

如果您仍然无法理解此处的任何内容,请先进行自己的研究,然后再在此处发表评论,或者做得更好,然后提出一个新问题(如果可以的话)。


祝您在编码过程中一切顺利! :)
Rawrplus

答案 1 :(得分:1)

此代码可以解决问题。
该代码为您提供了InputBox,您可以在其中键入运行代码的次数。

Sub test()
Application.ScreenUpdating = False
Dim Grab As Range
Dim RunTimes As Long

On Error GoTo Get_Out
RunTimes = InputBox("How many times shall the code run?", "Run times")
On Error GoTo 0

For x = 1 To RunTimes * 1.5 + 3 Step 2
    Set Grab = ActiveSheet.Range("A" & x + 4)
    Grab.EntireRow.Insert
    Grab.Offset(-1, 0).Value = Grab.Offset(-2, 0).Value + 0.1
    Grab.Offset(-1, 1).Value = Grab.Offset(1, 1).Value
    Grab.Offset(-1, 2).Value = Grab.Offset(1, 2).Value
Next x

MsgBox "Succes"

Get_Out:
Application.ScreenUpdating = True
End Sub

如果您对代码有任何疑问或希望我进一步解释它,请告诉我:)