2013-08-13 3 views
0

Итак, вчера я опубликовал свой первый вопрос SO, и он спустился, как тонна кирпичей. Тем не менее, я подобрал себя, пыхтел, и, надеюсь, этот вопрос будет более приемлемым ... :-)Excel VBA: ошибки компилятора

Я пытаюсь удалить дубликаты данных из списка анкет по вопросам здравоохранения, которые я должен контролировать, но сложный бит, с которым я боролся, заключался в том, чтобы найти дубликат в одном столбце, а затем проверить, что данные в той же строке для 3 соседних столбцов также являются дубликатами. Хранение поиска «дублированной строки» - это бит, который меня отбрасывал.

Вот код, который я вымотал из других аналогично функционирующих скриптов. Я сейчас в режиме отладки и продолжаю получать ошибки ... У меня нет большого опыта работы с VBA, поэтому у меня заканчиваются варианты.

В настоящее время я получаю ошибки несоответствия типа с переменной g, а также firstAddress. Почему эти проблемы?

Могу ли я позвонить firstAddress.Row или я лаю неправильное дерево?

Вот фрагмент кода:

g = .Find(Range("G" & i).Text, LookIn:=xlValues) 
      If Not g Is Nothing Then 
       firstAddress = g.Address 
       dupRow = firstAddress.Row 

И вот весь код ниже. Любая помощь приветствуется!

Sub FindCpy() 
Dim lw As Long 
Dim i As Integer 
Dim sh As Worksheet 
Dim dupRow As Integer 
Dim g As Integer 
Dim firstAddress As Integer 


'Used for the new worksheet we are pasting into 
Dim objNewSheet As Worksheet 
Dim rngNextAvailbleRow As Range 

'Used to narrow down the logical operators for duplicates 
Dim rngFirst As Range 

'Set the ranges 
rngFirst = Range("G" & 1, "G" & lw) 

Set sh = Sheets("Completed") 
lw = Range("A" & Rows.Count).End(xlUp).Row 

For i = 1 To lw 'Find duplicates from the list. 
    If Application.CountIf(Range("A" & i & ":A" & lw), Range("A" & i).Text) = "Complete" Then 

    'if COMPLETE, check the rest of the sheet for any 'in progress' duplicates... 
    With Worksheets("Still In Progress").rngFirst 
     g = .Find(Range("G" & i).Text, LookIn:=xlValues) 
     If Not g Is Nothing Then 
      firstAddress = g.Address 
      dupRow = firstAddress.Row 
      If Range("H" & dupRow).Text = Range("H" & i).Text _ 
      And Range("I" & dupRow).Text = Range("I" & i).Text _ 
      And Range("J" & dupRow).Text = Range("J" & i).Text Then 

     'select the entire row 
     Range.EntireRow.Select 

     'copy the selection 
     Selection.Cut 

     'Now identify and select the new sheet to paste into 
     Set objNewSheet = ThisWorkbook.Worksheets("Completed") 
     objNewSheet.Select 

     'Looking at your initial question, I believe you are trying to find the next  available row 
     Set rngNextAvailbleRow = objNewSheet.Range("A1:A" & objNewSheet.Cells(Rows.Count, "A").End(xlUp).Row) 

     Range("A" & rngNextAvailbleRow.Rows.Count + 1).Select 
     ActiveSheet.Paste 

     'delete the initial row 
     rngCell.EntireRow.Delete 

     Set g = .FindNext(g) 
      Loop While Not g Is Nothing And g.Address <> firstAddress 
     End If 
    End With 
Next i 
End Sub 
+0

Попробуйте добавить параметр Явно перед Sub и Dim g как Range, а не Integer. – pnuts

+0

спасибо, pnuts, это здорово. Я думал, что g будет возвращать целое число, но вы правы, диапазон действительно то, что он ищет. СЕЙЧАС, это говорит мне, что Range.EntireRow.Select недействителен, потому что аргумент не является обязательным ... Эта строка кода работала до ... Любые мысли? – user2674568

+0

Может быть, Range (R, 1). а не Range. ? – pnuts

ответ

0

Я внимательно просмотрел ваш код. Был ряд проблем. Некоторые из них, я думаю, я смог исправить - был один, где я догадался, что вы намеревались сделать, но для одного из них я только что отметил это; Вы должны объяснить, что вы пытаетесь сделать, как вы удаляете диапазон, который вы никогда не определен ...

Первая проблема с линией:

If Application.CountIf(Range("A" & i & ":A" & lw), Range("A" & i).Text) = "Complete" Then 

CountIf функция возвращает число; вы сравниваете это число со строкой «Complete». Я не думаю, что вы можете пройти мимо этой строки, так что остальная часть кода (правильная или нет) не будет выполнена. Не совсем понятно, что вы пытаетесь сделать в этой строке, так как я не уверен, когда строка будет отмечена как «Полная», но если вы заинтересованы в выполнении остальной части кода, если ячейка в A & i имеет строку «Complete» в нем, то вы, вероятно, хотите сделать

If Range("A" & i).Text = "Complete" Then 

Существовали ряд If - Then, With и Loop структур, которые не были должным образом завершаться соответствие End. Я попытался исправить это - убедитесь, что я сделал это правильно. Обратите внимание, что использование правильного отступа действительно помогает найти такие проблемы. Бар пространство является вашим другом ...

Поскольку метод Find возвращает объект, правильный способ использования функции является

Set g = .Find(Range("G" & i).Text, LookIn:=xlValues) 

Помимо этого - использовать Option Explicit в верхней части кода, и определите переменные с наиболее ограничительным (правильным) типом, который вы можете. Когда я это сделал, я обнаружил ошибку, которую я не мог исправить - с переменной rngCell, которая не была объявлена ​​и никогда не была установлена ​​... Она показывает, насколько она может быть полезной.Также хорошо для ловли опечаток - VBA счастливо позволит вам писать такие вещи, как

MYVAR = 1 MsgBox myVra + 1

Сообщение будет 1, не 2, из-за опечатки ... Тот факт, что Explicit должен быть даже вариант является одним из многих необъяснимых дизайнерских решений, сделанных командой VBA.

Вот ваш код «с большей частью исправленных ошибок». По крайней мере, это будет скомпилировано, но вы должны выяснить, что делать с оставшейся ошибкой (и я не могу быть уверен, что правильно догадался, что вы хотели сделать с ячейкой с надписью «Complete»).

Комментарии приветствуются.

Option Explicit 

Sub FindCpy() 
Dim lw As Long 
Dim i As Integer 
Dim sh As Worksheet 
Dim dupRow As Integer 
Dim g As Range 
Dim firstAddress As Range 

'Used for the new worksheet we are pasting into 
Dim objNewSheet As Worksheet 
Dim rngNextAvailbleRow As Range 

'Used to narrow down the logical operators for duplicates 
Dim rngFirst As Range 

'Set the ranges 
rngFirst = Range("G" & 1, "G" & lw) 

Set sh = Sheets("Completed") 
lw = Range("A" & Rows.Count).End(xlUp).Row 

For i = 1 To lw 'Find duplicates from the list. 
' If Application.CountIf(Range("A" & i & ":A" & lw), Range("A" & i).Text) = "Complete" Then 
    If Range("A" & i).Text = "Complete" Then 
    'if COMPLETE, check the rest of the sheet for any 'in progress' duplicates... 
    With Worksheets("Still In Progress").rngFirst 
     Set g = .Find(Range("G" & i).Text, LookIn:=xlValues) 
     If Not g Is Nothing Then 
      firstAddress = g.Address 
      dupRow = firstAddress.Row 
      If Range("H" & dupRow).Text = Range("H" & i).Text _ 
      And Range("I" & dupRow).Text = Range("I" & i).Text _ 
      And Range("J" & dupRow).Text = Range("J" & i).Text Then 

      'select the entire row 
      g.EntireRow.Select 

      'copy the selection 
      Selection.Cut 

      'Now identify and select the new sheet to paste into 
      Set objNewSheet = ThisWorkbook.Worksheets("Completed") 
      objNewSheet.Select 

      'Looking at your initial question, I believe you are trying to find the next  available row 
      Set rngNextAvailbleRow = objNewSheet.Range("A1:A" & objNewSheet.Cells(Rows.Count, "A").End(xlUp).Row) 

      Range("A" & rngNextAvailbleRow.Rows.Count + 1).Select 
      ActiveSheet.Paste 

      'delete the initial row 
      rngCell.EntireRow.Delete ' <<<<<< the variable rngCell was never defined. Cannot guess what you wanted to do here! 

      Do 
       Set g = .FindNext(g) 
       Loop While Not g Is Nothing And g.Address <> firstAddress 

      End If ' entire row matched 
     End If ' Not g Is Nothing 
     End With ' With Worksheets("Still in Progress") 
    End If  ' CountIf = "Complete" 

    Next i 

End Sub 

Еще один удобный трюк: когда вы «вставить в следующей строке», как вы делаете с Range("A" & rngNextAvailbleRow.Rows.Count + 1).Select, я обычно нахожу это удобно, чтобы сделать что-то вроде этого, вместо:

Dim destination As Range 
Set destination = Worksheets("Sheetname").Range("A1") 

И когда вы нужно вставить что-то:

destination.Select 
ActiveSheet.Paste 
Set destination = destination.Offset(1,0) 

Таким образом, destination всегда указывает на «следующее место, где я могу вставить». Я считаю это полезным и чистым.

Смежные вопросы