VBA обходит меня за l oop, не выполняя - PullRequest
1 голос
/ 23 апреля 2020

Я пытаюсь создать уникальный идентификатор для каждого образца в наборе данных переменной длины. Для этого я хочу использовать часть из двух строк данных, называемых Имя и Тип образца. Я хочу, чтобы я go опустил каждую строку в столбце, взял кусочки каждой строки и соединил их вместе, однако, когда я перехожу через l oop, он никогда не входит в мой l oop, только вокруг него. может кто-нибудь сказать мне, почему?

Sheets("Data").Activate
setlastrow = Sheets("Data").Range("b5000").End(xlUp).Row
setlastcol = Sheets("Data").Cells(5, Columns.Count).End(xlToLeft).Column 'this is still assuming that row 5 has the header in it

colname = Rows(5).Find("Name", LookAt:=xlWhole).Column  ' this can be repeated for any other columns we want to asign values to. These variables will make the rest of this much easier
colSampleText = Rows(5).Find("Sample Text", LookAt:=xlWhole).Column

For i = 6 To lastrow
    Sheets("Data").Range(Cells(i, 1)) = workbookfunction.if(workbookfunction.CountIf(Range(Cells(6, colname), Cells(i, colname)), Cells(i, colname)) < 10, "0", "") & workbookfunction.CountIf(Range(Cells(6, colname), Cells(i, colname)), Cells(i, colname) & "-" & Left(Cells(i, colSampleText), 5))
    'this should find the unique identifying infomation for each sample and analyte
Next i

Ответы [ 3 ]

2 голосов
/ 23 апреля 2020

В вашем коде есть две основные ошибки - плюс небольшая. Один из них структурный. Вы объявляете не те переменные, которые используете. Это все равно, что сказать: «Поскольку я не знаю, как водить машину, я мог бы с таким же успехом закрыть глаза, как мы несемся вперед». Это не без логики c, но мало что дает для того, чтобы вы туда, куда вы хотите go.

Другое дело в путанице между функцией рабочего листа, которую вы хотите выполнить VBA, и той, которую вы используете. sh назначить ячейку для выполнения в Excel. Записать сложную формулу в ячейку сложнее, чем заставить VBA вычислить сложную формулу. Для метода, если вы хотите создать формулу в VBA, вы должны сначала присвоить ее строке, например MyFormula = "=COUNTIF(D6:D12, "MyName")", а затем, после тестирования, присвоить эту строку свойству Formula ячейки, например Cells(R, ClmName).Formula = MyFormula". В приведенном ниже коде я выбрал VBA для расчета. Поскольку не совсем ясно, что вы хотите (неисправный код никогда не является хорошим способом показать, что вы собираетесь!), Пожалуйста, измените его. В VBA это проще, чем в функции рабочего листа.

Private Sub Test()

    Dim LastRow As Long
    Dim LastClm As Long
    Dim ClmName As Long                 ' R use "col" for color, "clm" for column
    Dim ClmSampleText As Long
    Dim CountRng As Range
    Dim Output As Variant
    Dim R As Long                       ' R use R for row, C for column

    Sheets("Data").Activate
    LastRow = Sheets("Data").Range("b5000").End(xlUp).Row
    ' this is still assuming that row 5 has the header in it
    LastClm = Sheets("Data").Cells(5, Columns.Count).End(xlToLeft).Column

    ' this can be repeated for any other columns we want to asign values to.
    ' These variables will make the rest of this much easier
    ClmName = Rows(5).Find("Name", LookAt:=xlWhole).Column
    ClmSampleText = Rows(5).Find("Sample Text", LookAt:=xlWhole).Column

    For R = 6 To LastRow
        'this should find the unique identifying infomation for each sample and analyte
        Set CountRng = Range(Cells(6, ClmName), Cells(R, ClmName))
        Output = WorksheetFunction.CountIf(CountRng, Cells(R, ClmName).Value)
        If Output < 10 Then Output = 0
        Cells(R, 1).Value = CStr(Output) & "-" & Left(Cells(R, ClmSampleText).Value, 5)
    Next R
End Sub

"Незначительная" ошибка связана с отсутствием понимания объекта Cell. Ячейка Range. Он имеет много свойств, таких как Cell.Row и Cell.Column или Cell.Address, и других свойств, таких как Cell.Value или Cell.Formula. Свойство Value является значением по умолчанию. Поэтому Cell совпадает с Cell.Value НО не всегда. В этом примере, не думая о Cell.Value, вы также пропустили Cell.Formula и, поместив Cell в WorksheetFunction, вы перепутали VBA с тем, что вы имели в виду: Cell the Value или Cell the Range. При том, что все участники смущены, результат был предсказуем

Рекомендуется всегда писать Cell.Value, когда вы имеете в виду значение ячейки, и использовать только Cell, только если вы имеете в виду диапазон.

0 голосов
/ 23 апреля 2020

Вот вариант вашего кода; Я изменил ваш код, чтобы установить два столбца, используя Find, l oop через каждый cel в диапазоне (используя текущую строку), установите varcnt для подсчета количества совпадений, определив первые 5 буквы значения в столбце Sample Text как str и использовали оператор basi c If для записи объединенного уникального идентификатора в первый столбец.

Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Data")
Dim lRow As Long: lRow = ws.Range("b5000").End(xlUp).Row

Dim dataCol As Long: dataCol = ws.Range("A5:J5").Find(What:="Name", LookIn:=xlValues, lookat:=xlWhole).Column
Dim smplTextCol As Long: smplTextCol = ws.Range("A5:J5").Find(What:="Sample Text", LookIn:=xlValues, lookat:=xlWhole).Column

    For Each cel In ws.Range(ws.Cells(6, dataCol), ws.Cells(lRow, dataCol))

        Dim varcnt As Long: varcnt = Application.WorksheetFunction.CountIf(ws.Range(ws.Cells(6, dataCol), ws.Cells(cel.Row, dataCol)), ws.Cells(cel.Row, dataCol).Value)
        Dim str As String: str = Left(ws.Cells(cel.Row, smplTextCol).Value, 5)

        If varcnt < "4" Then
            ws.Cells(cel.Row, 1).Value = "0" & "-" & str

        Else
            ws.Cells(cel.Row, 1).Value = "" & "-" & str
        End If

    Next cel
0 голосов
/ 23 апреля 2020

У вас есть ошибка с end частью вашего оператора For...Next.

Из кода, который вы разместили, LastRow явно нигде не объявлен, поэтому при запуске кода LastRow создается как Тип Variant со значением по умолчанию Empty.

Рассмотрим этот код:

Sub LoopTest()

Dim DeclaredVariable As Long
Dim i As Long

DeclaredVariable = 10

For i = 1 To UnDeclaredVariable
    Debug.Print i & " UnDeclaredVariable"
Next i

For i = 1 To DeclaredVariable
    Debug.Print i & " DeclaredVariable"
Next i

End Sub

Вывод в окне непосредственного взаимодействия будет:

1 DeclaredVariable
2 DeclaredVariable
3 DeclaredVariable
4 DeclaredVariable
5 DeclaredVariable
6 DeclaredVariable
7 DeclaredVariable
8 DeclaredVariable
9 DeclaredVariable
10 DeclaredVariable

Это показывает нам, что l oop для UnDeclaredVariable не был введен - И это связано с тем, что end часть For...Next l oop равна Empty (значение по умолчанию типа данных Variant), поэтому существует нет определенного конца для l oop для итерации.

NB Точнее говоря, проблема в том, что UnDeclaredVariable не имеет назначенного ему значения (цифра c) - если вы присваиваете значение необъявленной переменной он становится типом данных Variant/<Type of data you assigned to it>, например UnDeclaredVariable = 10 делает его типом Variant/Intiger.

Причиной почему он переходит через l oop и не выбрасывает ошибка в том, что у вас нет Option Explicit в верхней части вашего модуля кода (или проверены Сервис> Параметры> «Требовать объявление переменной»), что означает, что код все еще может работать с необъявленными переменными (в том числе, если вы написали объявленную переменную) неправильно).

Если вы добавите Option Explicit в начало вашего кодового модуля:

Option Explicit

Sub LoopTest()

Dim DeclaredVariable As Long
Dim i As Long

DeclaredVariable = 10

For i = 1 To UnDeclaredVariable
    Debug.Print i & " UnDeclaredVariable"
Next i

For i = 1 To DeclaredVariable
    Debug.Print i & " DeclaredVariable"
Next i

End Sub

Вы получите следующую ошибку:

Compile Error: 
Variable not defined

Это фантастика c пример того, почему Option Explicit является важным объявлением, которое нужно сделать в всех модулях кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...