У меня есть серия блоков кода, содержащих For Loops здесь, и я хотел бы уменьшить этот код, чтобы он мог работать одинаково, но до тех пор, пока один из этих блоков кода, а не 12 блоков в длину. Как вы можете видеть, каждый блок представляет собой группу из 6, задача, которую я имею здесь, заключается в сокращении кода, сохраняя мои переменные в группах по 6. В этой программе значения генерируются в двух столбцах и идут в последовательном порядке. Например:
Когда m равно от 1 до 6, значение p должно быть равным 1 для всех шести значений
. Когда m равно от 7 до 12, значение p должно быть равным 2 для все шесть значений
Когда m равно от 13 до 18, значение p должно быть равно 3 для всех шести значений
и т. д. ....
For m = 1 To 6 'Riser
For p = 1 To 1 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 7 To 12 'Riser
For p = 2 To 2 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 13 To 18 'Riser
For p = 3 To 3 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 19 To 24 'Riser
For p = 4 To 4 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 25 To 30 'Riser
For p = 5 To 5 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 31 To 36 'Riser
For p = 6 To 6 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 37 To 42 'Riser
For p = 7 To 7 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 43 To 48 'Riser
For p = 8 To 8 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 49 To 54 'Riser
For p = 9 To 9 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 55 To 60 'Riser
For p = 10 To 10 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 61 To 66 'Riser
For p = 11 To 11 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
For m = 67 To 72 'Riser
For p = 12 To 12 'Car
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
Exit For
End If
Next p
Next m
Есть ли способ увеличить эти значения m и p, чтобы они поднялись до 78, сохраняя эти группы по шесть для каждого блока?
, следуя логике кода OP, я бы сделал следующее:
For p = 1 To 12 ' loop through cars
If Not IsEmpty(ws.Range("Car_" & p)) Then ' proceed only if current car isn't empty
For m = (p - 1) * 6 + 1 To p * 6 'Riser ' loop through current car corresponding risers range
If Not IsEmpty(ws.Range("Riser" & m)) Then ' if current riser isn't empty
ws.Range("C1").Offset(m).Value = p ' mark with current car
Exit For ' exit loop and process next car
End If
Next
End If
Next
Ваши внутренние петли for не нужны. Вы можете просто заменить for p = 1 to 1 на p = 1 и удалить соответствующий Next p.
Тем не менее, я думаю, что следующая структура может немного уменьшить дублирование кода:
For m = 1 To 72 'Riser
Select Case m
Case 1 to 6
p = 1
Case 7 to 12
p = 2
' and so on...
End Select
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
'Exit For ' You might need to replace this line with something adequate if necessary
End If
Next m
Теперь инструкция Select Case позаботится о том, чтобы присвоить значения p, и вы можете выполнять всю работу в одном цикле. Это решение было бы предпочтительнее, если бы это правило увеличивало p за каждые шесть м, не было установлено в камне. (Легче изменить назначения таким образом.)
Теперь, если вы скажете, что увеличение p за каждые шесть м правило установлено в камне, тогда я бы рекомендовал вам использовать ответ @ Marcucciboy2 вместо этого.
Обычно я предлагаю переместить логику, чтобы присвоить значение p в зависимости от m в свою собственную функцию.
Public Sub YourSubStartsHere()
' [...]
For m = 1 To 72 'Riser
p = GetPFromM(m)
If Not IsEmpty(ws.Range("Riser" & m)) And Not IsEmpty(ws.Range("Car_" & p)) Then
ws.Range("C1").Offset(m).Value = p
'Exit For ' You might need to replace this line with something adequate if necessary
End If
Next m
End Sub
Private Function GetPFromM(ByVal m as Long) as Long
' Your preferred logic to get the new p here
' be it Select Case
Select Case m
Case 1 to 6
GetPFromM = 1
End Select
' or rounding up
GetPFromM = Application.WorksheetFunction.RoundUp(m / 6, 0)
End Function
Таким образом, было бы довольно легко быстро подключить новое правило для p, если это необходимо.
Может быть более умный способ сделать это, но я бы использовал функцию modulo. По модулю возвращает остаток, когда вы делите два числа, поэтому, если вы разделите m на 6, остаток будет равен 0, если m кратно 6. Если это так, вы просто увеличиваете добавленную переменную everySix
Dim everySix As Long
everySix = 1
Dim wasFound As Boolean
For m = 1 To 78
If Not IsEmpty(ws.Range("Car_" & everySix)) Then
If Not IsEmpty(ws.Range("Riser" & m)) And Not wasFound Then
ws.Range("C1").Offset(m).Value2 = everySix
wasFound = True
End If
If m Mod 6 = 0 Then
everySix = everySix + 1
wasFound = False
End If
End If
Next m