Попытка создать код поиска / копирования / вставки VBA - PullRequest
0 голосов
/ 11 июня 2018

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

У меня есть два листа, и я хочу посмотреть на столбец L Листа1 и для всех ячеек, в которых есть "НЕТ"для значения я хочу скопировать значение в столбце A той же строки и вставить его в последнюю строку Sheet2 в столбце A.

Звучит довольно просто, но я не могу разобраться с кодом.

Что не так с кодом ниже?

    Sub SearchMacro()

    Dim wb As Workbook
    Dim ws As Worksheet
    Set wb = ActiveWorkbook
    Set ws = Sheets("Sheet1")
    wb.Activate
    ws.Select

RowCount = Cells(Cells.Rows.Count, "A").End(xlUp).Row
For i = 1 To RowCount
    Range("L" & i).Select
    If ActiveCell = "NO" Then
        ActiveCell.Range("A").Copy
        Sheets("Sheet2").Select
        RowCount = Cells(Cells.Rows.Count, "A").End(xlUp).Row
        Range("A" & RowCount + 1).Select
        ActiveSheet.Paste
        Sheets("Sheet1").Select
    End If
Next

End Sub

Ответы [ 3 ]

0 голосов
/ 11 июня 2018

У меня возникает соблазн пометить этот вопрос как дубликат, потому что ежедневно существует множество вопросов о копировании и вставке данных, ну да ладно ..

  1. Не используйте Select/ActiveCell/Activesheet/Activeworkbook/.. период !! Это плохая vba-excel практика, которую всегда можно избежать.Кроме того, просто потому, что ваш цикл через RowCount не означает, что ячейка активна.Вероятно, это также причина, по которой вы продолжаете получать ошибки: Application.ActiveCell в соответствии с определением MSDN выглядит следующим образом:

    Возвращает объект Range, представляющий активную ячейку в активном окне (окно сверху) или в указанном окне. Если в окне не отображается рабочий лист, это свойство не работает .Только для чтения.

    (для получения дополнительной информации о том, как избежать их использования, обращайтесь к этому stackoverflow вопросу)

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

    Private Sub copy_paste()
    
    Dim ws_source As Worksheet: Set ws_source = Sheets("Sheet1")
    Dim ws_target As Worksheet: Set ws_target = Sheets("Sheet2")
    
    Dim last_row As Long
    last_row = ws_source.Cells(ws_source.Rows.Count, "L").End(xlUp).Row
    Dim next_paste As Long
    
    For i = 1 To last_row
        If ws_source.Cells(i, "L") = "NO" Then
            ws_source.Rows(i).EntireRow.Copy
            next_paste = ws_target.Cells(ws_target.Rows.Count, "A").End(xlUp).Row + 1
            ws_target.Rows(next_paste).PasteSpecial xlPasteValues
        End If
    Next i
    
    End Sub
    

С данными: enter image description here

Ожидаемый результат: enter image description here

0 голосов
/ 11 июня 2018

Вы можете использовать FIND.Это найдет NO , но не Нет или nO (измените значение на MatchCase=False, чтобы найти все случаи).

Public Sub SearchAndCopy()

    Dim wb As Workbook
    Dim ws As Worksheet
    Dim ws1 As Worksheet
    Dim last_row As Long
    Dim rFound As Range
    Dim sFirstAdd As String

    Set wb = ThisWorkbook 'ActiveWorkbook
                          'Workbooks("SomeWorkbook.xlsx")
                          'Workbooks.Open("SomePath/SomeWorkbook.xlsx")

    Set ws = wb.Worksheets("Sheet1")
    Set ws1 = wb.Worksheets("Sheet2")

    With ws.Columns("L")
        Set rFound = .Find(What:="NO", _
                           LookIn:=xlValues, _
                           LookAt:=xlWhole, _
                           SearchDirection:=xlNext, _
                           MatchCase:=True)

        If Not rFound Is Nothing Then
            sFirstAdd = rFound.Address
            Do
                'Find next empty row on destination sheet.
                    'Only really need to give worksheet reference when
                    'counting rows if you have 2003 & 2007+ files open - "ws.Rows.Count"
                last_row = ws1.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1

                'Copy the figure from source to target sheet.
                'You could also use Copy/Paste if you want the formatting as well.
                ws1.Cells(last_row, 1) = ws.Cells(rFound.Row, 1)

                'Look for the next matching value in column L.
                Set rFound = .FindNext(rFound)
            Loop While rFound.Address <> sFirstAdd
        End If
    End With

End Sub  

Я добавил объяснение вашего кода ниже - главное, что неправильно с вашим кодом - ActiveCell.Range("A").Copy.Нет диапазона A, но есть A1, A2 и т. Д.

Sub SearchMacro()

    'You didn't declare these two which
    'indicates you haven't got Option Explicit
    'at the top of your module.
    Dim RowCount As Long
    Dim i As Long

    Dim wb As Workbook
    Dim ws As Worksheet

    'I'll only comment that you set
    'wb to be the ActiveWorkbook and you then
    'activate the active workbook which is already active.....
    Set wb = ActiveWorkbook
    Set ws = Sheets("Sheet1")
    wb.Activate
    ws.Select

    'Looks at the active sheet as you just activated it.
    'Generally better to say "the cells in this named worksheet, even if it isn't active, or
    'in the active book... just reference the damn thing."
    'Something like "ws.cells(ws.cells.rows.count,"A").End(xlUp).Row"
    'Note it references the correct worksheet each time.
    RowCount = Cells(Cells.Rows.Count, "A").End(xlUp).Row
    For i = 1 To RowCount
        Range("L" & i).Select
        If ActiveCell = "NO" Then

            'Your code falls over here - you can't have range A.
            'You can have range A1, which is the first cell in your referenced range.
            'So ActiveCell.Range("A1") will return the ActiveCell - "L1" probably.
            ActiveCell.Range("A1").Copy

            'This will copy from column A using your method:
            'ws.Cells(ActiveCell.Row, 1).Copy

            'If you get the above line correct this will all work.
            Sheets("Sheet2").Select
            RowCount = Cells(Cells.Rows.Count, "A").End(xlUp).Row
            Range("A" & RowCount + 1).Select
            ActiveSheet.Paste

            'You've already called it "ws" so just "ws.Select" will work.
            Sheets("Sheet1").Select
        End If
    Next

End Sub
0 голосов
/ 11 июня 2018

Я думаю, что вы можете использовать автофильтр вместо зацикливания.

RowCount = Cells(Cells.Rows.Count, "A").End(xlUp).Row
Cells.AutoFilter ' set an filter on the sheet
With Sheets("Sheet1").Range("A1:L" & RowCount) ' filter on NO column L
    .AutoFilter Field:=12, Criteria1:="NO"
End With
Sheets("Sheet1").Range("A2:L" & Range("A2").End(xlDown)).Copy 'Copy the filtered data
Sheets("Sheet2").Select
RowCount = Cells(Cells.Rows.Count, "A").End(xlUp).Row
Range("A" & RowCount + 1).Select
ActiveSheet.Paste
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...