简体   繁体   English

VBA循环无法正常运行

[英]VBA loop isn't functioning properly

Sub Button2_Click()
Dim i As Integer, q As Integer
i = 2
q = 2
Do While i < 468 And q < 3450
If Worksheets("Sheet1").Range("A" & i).Value = Worksheets("Sheet2").Range("A" & q).Value Then
    If Len(Worksheets("Sheet1").Cells(i, 4)) < 12 Then
        Dim edate As String, adate As String, ed As String, ad As String, n As Integer, x As Integer, y As Integer
        edate = Sheets("sheet1").Cells(i, 4).Value
        adate = Sheets("sheet2").Cells(q, 2).Value
        ed = Right(Sheets("sheet1").Cells(i, 4), 4)
        ad = Right(Sheets("sheet2").Cells(q, 2), 4)
        n = CInt(ad) - CInt(ed)
        If InStr(edate, "Fall") And InStr(adate, "Fall") Then x = 7 + (5 * n)
        If InStr(edate, "Fall") And InStr(adate, "Spring") Then x = 9 + (5 * (n - 1))
        If InStr(edate, "Spring") And InStr(adate, "Spring") Then x = 9 + (5 * n)
        If InStr(edate, "Spring") And InStr(adate, "Fall") Then x = 12 + (5 * n)
        y = x - 1
        Worksheets("Sheet1").Cells(i, x).Value = Worksheets("Sheet2").Cells(q, 5).Value
        Worksheets("Sheet1").Cells(i, y).Value = Worksheets("Sheet2").Cells(q, 3).Value
        i= i +1
        q=2
    Else
        i = i + 1
        q = 2
    End If
Else
    If q < 3423 Then
        q = q + 1
    else
        i = 1 + 1
        q=2
    End If
    Else
        i = i + 1
        q = 2
    End If
End If
Loop
End Sub

Hey guys, the code above is something I've been working on to important some data from sheet2 to sheet1. 大家好,上面的代码是我一直在努力处理的重要数据,从Sheet2到Sheet1。 Sheet 2 has project Id numbers in column 1, terms (awarddate) in column 2, type of award in column 3, and amount in column 5. Sheet 1 has project id in column 1, and term (entry date) in column 4. Sheet 2 has awards given by semester and indexed by project id, I would like to important the data and place them into the columns given by the if instr statements int he middle of the text. 表格2在第1栏中有项目编号,在第2栏中有术语(授予),在第3栏中有奖励类型,在第5栏中有金额。表格1在第1栏中有项目编号,在第4栏中有期限(录入日期)。表格2的奖励由学期授予,并由项目ID索引。我想重要的是将数据放置在文本中间的if instr语句给出的列中。

The goal of this code is to loop through the project id numbers in sheet 1, column A and check to see if they exist in sheet 2 column A, and then to import the award type and amount sorted by the difference in years between the entry date on sheet 1 and the award date on sheet 2. The dates have spring/fall and a year, so I tried the left(string, #) command to only have years to subtract, and then the block of aforementioned if instr code is supposed to balance out the difference in semesters. 此代码的目的是循环浏览工作表1列A中的项目ID号,并检查它们是否存在于工作表2列A中,然后导入奖励类型和金额(按条目之间的年数差异排序)第1页上的日期和第2页上的授予日期。日期有春季/秋季和一年,所以我尝试了left(string,#)命令,只减去了几年,然后如果指令代码为应该平衡学期的差异。

There are multiples of the same project id in sheet 2, so I need the code to resume the loop after the previous row on sheet 2, until every project id on sheet 1 has been cross-referenced. 工作表2中有多个相同的项目ID,因此我需要代码来恢复工作表2的上一行之后的循环,直到工作表1中的每个项目ID被交叉引用为止。

Can someone point out the error in my code? 有人可以指出我的代码中的错误吗? Nothing happens when I click the command button. 单击命令按钮没有任何反应。

The problem is in the first if statement, it skips all of the operations that require the condition to be met, when I know that at least 450 of the data match. 问题出在第一个if语句中,当我知道至少有450个数据匹配时,它将跳过所有需要满足条件的操作。

Just edited my code, it's still running right now. 刚刚编辑了我的代码,它现在仍在运行。

List of edits thanks to comments: fixed logical statment issue, fixed range/cell/cells issue, fixed looping issue, fixed right/left string issue 多亏了评论,编辑列表:固定逻辑陈述问题,固定范围/单元格/单元格问题,固定循环问题,固定右/左字符串问题

Can I suggest that you refactor your code as follows: 我可以建议您按以下方式重构代码:

Sub Button2_Click()
    Dim i As Integer, q As Integer
    'Storing the ids in an array will make it much faster to access instead
    'of interfacing with Excel's object model a couple of million times
    Dim ids1, ids2
    Dim origCalcMode As XlCalculation

    'Switch off ScreenUpdating to improve speed
    Application.ScreenUpdating = False
    'Switch off auto calculation to improve speed
    origCalcMode = Application.Calculation
    Application.Calculation = xlCalculationManual

    ids1 = Application.Transpose(Worksheets("Sheet1").Range("A2:A467").Value)
    ids2 = Application.Transpose(Worksheets("Sheet2").Range("A2:A3422").Value)
    'Using For loops rather than manually keeping track of row counters
    'makes the code MUCH cleaner and less prone to errors
    For i = 2 To 467
        'Moving this test to earlier in the code avoids having to iterate
        'through all the rows on Sheet2 when there is nothing that can be
        'done with the matching data anyway
        If Len(Worksheets("Sheet1").Cells(i, 4)) < 12 Then
            For q = 2 To 3422
                If ids1(i - 1) = ids2(q - 1) Then
                    Dim edate As String, adate As String, ed As String, ad As String, n As Integer, x As Integer, y As Integer
                    edate = Sheets("sheet1").Cells(i, 4).Value
                    adate = Sheets("sheet2").Cells(q, 2).Value
                    ed = Right(Sheets("sheet1").Cells(i, 4), 4)
                    ad = Right(Sheets("sheet2").Cells(q, 2), 4)
                    n = CInt(ad) - CInt(ed)
                    If InStr(edate, "Fall") And InStr(adate, "Fall") Then x = 7 + (5 * n)
                    If InStr(edate, "Fall") And InStr(adate, "Spring") Then x = 9 + (5 * (n - 1))
                    If InStr(edate, "Spring") And InStr(adate, "Spring") Then x = 9 + (5 * n)
                    If InStr(edate, "Spring") And InStr(adate, "Fall") Then x = 12 + (5 * n)
                    y = x - 1
                    Worksheets("Sheet1").Cells(i, x).Value = Worksheets("Sheet2").Cells(q, 5).Value
                    Worksheets("Sheet1").Cells(i, y).Value = Worksheets("Sheet2").Cells(q, 3).Value
                    Exit For
                End If
            Next
        End If
    Next

    'Restore application settings
    Application.ScreenUpdating = True
    Application.Calculation = origCalcMode
End Sub

I'm not sure about the Exit For line. 我不确定Exit For行。 Your question implies that you need to process multiple entries from Sheet2 if they exist. 您的问题意味着您需要处理Sheet2中的多个条目(如果存在)。 If so, delete the Exit For line, but that will increase the runtime because it will need to iterate over all 3421 rows in Sheet2 for each row in Sheet1. 如果是这样,请删除Exit For行,但这将增加运行时间,因为它将需要为Sheet1中的每一行遍历Sheet2中的所有3421行。

Edit: Included changes to ScreenUpdating and Calculation as suggested by BruceWayne. 编辑:包括对BruceWayne建议的ScreenUpdating和Calculation的更改。

Thanks for all of the help, here is the code that works in case anyone stumbles upon this with a similar problem. 感谢您提供的所有帮助,如果有人遇到类似问题,请使用以下代码。

This code loops through sheet1 with integer i and sheet2 with integer q to find a match in the first/A column of both sheets. 该代码循环遍历具有整数i的sheet1和具有整数q的sheet2,以在两个工作表的第一/ A列中找到匹配项。 As I have multiples of the project ideas (Sheet 1 column A) on sheet2 in column A, it continues after finding a match at the row (q) found on sheet2. 由于我在A列的sheet2上有多个项目构想(Sheet 1列A),因此在sheet2上的行(q)找到匹配项之后,它会继续。 This then continues through the specified amount of rows (i) and secondly through all rows (q) for each i. 然后,这将继续执行指定数量的行(i),然后继续执行每个i的所有行(q)。

Public CalcState As Long
Public EventState As Boolean
Public PageBreakState As Boolean

Sub OptimizeCode_Begin()

Application.ScreenUpdating = False

EventState = Application.EnableEvents
Application.EnableEvents = False

CalcState = Application.Calculation
Application.Calculation = xlCalculationManual

PageBreakState = ActiveSheet.DisplayPageBreaks
ActiveSheet.DisplayPageBreaks = False

End Sub

Sub OptimizeCode_End()

ActiveSheet.DisplayPageBreaks = PageBreakState
Application.Calculation = CalcState
Application.EnableEvents = EventState
Application.ScreenUpdating = True

End Sub


Sub Button2_Click()
Dim i As Integer, q As Integer, origCalcMode As XlCalculation
i = 3
q = 2
Call OptimizeCode_Begin
Do While i < 467
If Len(Worksheets("Sheet1").Cells(i, 4)) < 12 Then
    If Worksheets("Sheet1").Cells(i, 1).Value = Worksheets("Sheet2").Cells(q, 1).Value Then
        Dim edate As String, adate As String, ed As String, ad As String, n As Integer, x As Integer, y As Integer
        edate = Sheets("sheet1").Cells(i, 4).Value
        adate = Sheets("sheet2").Cells(q, 2).Value
        ed = Right(Sheets("sheet1").Cells(i, 4), 4)
        ad = Right(Sheets("sheet2").Cells(q, 2), 4)
        n = CInt(ad) - CInt(ed)
        If InStr(edate, "Fall") And InStr(adate, "Fall") Then x = 7 + (5 * n)
        If InStr(edate, "Fall") And InStr(adate, "Spring") Then x = 9 + (5 * (n - 1))
        If InStr(edate, "Spring") And InStr(adate, "Spring") Then x = 9 + (5 * n)
        If InStr(edate, "Spring") And InStr(adate, "Fall") Then x = 12 + (5 * n)
        y = x - 1
        Worksheets("Sheet1").Cells(i, x).Value = Worksheets("Sheet2").Cells(q, 5).Value
        Worksheets("Sheet1").Cells(i, y).Value = Worksheets("Sheet2").Cells(q, 3).Value
        q = q + 1
    Else
        If q < 1236 Then
            q = q + 1
        Else
            i = i + 1
            q = 2
        End If
    End If
Else
   i = i + 1
   q = 2
End If
Loop
Call OptimizeCode_End
End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM