У меня есть цикл, однако он находит только первую итерацию и не переходит к следующей итерации.
Я установил цикл. На данный момент он открывает лист под названием «Имена», подсчитывает строки, содержащие IMP и EXP, и присваивает их переменной. Рабочий лист «Имена» содержит список. Столбец A — это инициалы пользователя, столбец B — имя пользователя, а столбец C содержит IMP или EXP в зависимости от пользователя. Затем макрос открывает лист под названием «Средние» и запускает цикл.
Цикл начинается со счетчика For, равного количеству строк IMP. Устанавливает диапазон с помощью счетчика. Затем он просматривает лист «Имена» и находит в нем строку с IMP. Если ячейка содержит данные, задается номер строки. Затем он устанавливает переменную ячейку rng и устанавливает ее в текущую строку IMP и две ячейки слева. (Пользовательский инициал) и продолжает устанавливать ячейку rng вправо и устанавливает ее в текущую строку IMP и 1 ячейку влево. (Имя пользователя).
Итак, этот тип работы работает. Он выполняет цикл 10 раз, как и должно быть, однако моя проблема в том, что он находит первую строку IMP и вводит инициал пользователя, а затем имя. Но просто копируйте это 10 раз вместо того, чтобы просматривать следующую строку с IMP и вводить инициал и имя следующего пользователя. Таким образом, я получаю 10 строк, состоящих только из инициалов и имени одного человека. Мне трудно разобраться в циклах. Может ли кто-нибудь показать мне мою ошибку? Код ниже.
Worksheets("Names").Activate
Range("C2").Select
'counts the rows
IMPRows = Application.WorksheetFunction.CountIf(Range("C:C"), "IMP")
EXPRows = Application.WorksheetFunction.CountIf(Range("C:C"), "EXP")
Worksheets("Averages").Activate
'Start of loop to insert data
For counter = 6 To 6 + IMPRows
Set rng = Worksheets("Averages").Cells(counter, 1)
Set rng2 = Worksheets("Names").Columns("C:C").Find(What: = "IMP", MatchCase:=True)
If Not rng2 Is Nothing Then
rownumber = rng2.Row
rng.Offset(0, 0) = rng2.Offset(0, -2)
rng.Offset(0, 1) = rng2.Offset(0, -1)
Else
End If
'end of loop
Next counter
Похоже, вы пытаетесь перестроить встроенную функцию ФИЛЬТР?
Чтобы ответить на логику вашего вопроса, вы выполняете цикл, но каждый раз выполняете один и тот же поиск. Чтобы получить более поздние результаты, вам нужно использовать .FindNext
и указать, что он должен начать следить за вашим последним результатом.
Option Explicit
Sub LookupIMP()
Const SEARCH_STRING As String = "IMP"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Sheets("Names")
Dim srg As Range:
Set srg = sws.Range("C2", sws.Cells(sws.Rows.Count, "C").End(xlUp))
Dim dws As Worksheet: Set dws = wb.Sheets("Averages")
Dim dcell As Range: Set dcell = dws.Range("A6")
Dim scell As Range: Set scell = srg.Find(What:=SEARCH_STRING, _
After:=srg.Cells(srg.Cells.Count), LookIn:=xlValues, LookAt:=xlWhole, _
MatchCase:=True)
If scell Is Nothing Then
MsgBox "No occurrence of """ & SEARCH_STRING & """ found!", _
vbExclamation
Exit Sub
End If
Dim sFirstAddress As String: sFirstAddress = scell.Address
Do
dcell.Offset(, 0).Value = scell.Offset(, -2).Value
dcell.Offset(, 1).Value = scell.Offset(, -1).Value
Set dcell = dcell.Offset(1)
Set scell = srg.FindNext(After:=scell)
Loop While scell.Address <> sFirstAddress
MsgBox "Looking up """ & SEARCH_STRING & """ finished.", _
vbInformation
End Sub
Спасибо VBasic! По какой-то причине сразу это не сработало. У меня были ошибки, но я установил wb как фактическое имя листа Excel вместо просто «ThisWorkbook», а также установил sws как wb,Worksheets («Имена»). Опять же, не знаю почему, но их изменение устранило ошибку. Спасибо за вашу помощь. очень ценю.
Альтернативой использованию ADO с учетом регистра является:
Sub Test()
Dim adoCN As Object, RS As Object
Dim myFile As String, strSQL As String
myFile = ThisWorkbook.FullName
Set adoCN = CreateObject("ADODB.Connection")
Set RS = CreateObject("ADODB.Recordset")
adoCN.Provider = "Microsoft.ACE.OLEDB.12.0"
adoCN.Properties("Data Source") = myFile
adoCN.Properties("Extended Properties") = "Excel 12.0 Macro; HDR=Yes; IMEX=1"
adoCN.Open
strSQL = "Select [Name], [Num] From [Names$] Where StrComp([Crit], 'IMP', 0) = 0"
RS.Open strSQL, adoCN
Sheets("Averages").Range("A2").CopyFromRecordset RS
RS.Close
Set RS = Nothing
Set adoCN = Nothing
End Sub
Спасибо, Халук. К сожалению, из-за моих ограниченных знаний это слишком сложно для понимания.
Во-первых, научитесь правильно делать отступы в коде. Это значительно упрощает отслеживание хода выполнения и выявление логических ошибок. Далее, не используйте предложение
Else
, если вам не нужно, чтобы что-то произошло в этомElse
состоянии. Наконец, научитесь использовать отладчик для установки точек останова, чтобы вы могли пошагово выполнять код по мере его выполнения и точно видеть, что происходит. Это помогает вам оценить содержимое переменных и проследить точный ход выполнения кода.