根据条件将行复制到另一个工作表的 VBA 代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44742564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-12 12:46:33  来源:igfitidea点击:

VBA Code to copy rows based on criteria to another sheet

vbaexcel-vbaexcel

提问by Sreeni Vasan

I am trying to write a simple VBA code to pick up complete rows from one sheet and copy them to another sheet based o certain criteria

我正在尝试编写一个简单的 VBA 代码来从一张纸中提取完整的行,然后根据某些标准将它们复制到另一张纸上

For example if the first cell in a row contains the text "Cricket" (case insensitive), the system will create a worksheet with the name Cricket, and will copy all rows that fit the criteria to the new worksheet

例如,如果一行中的第一个单元格包含文本“Cricket”(不区分大小写),系统将创建一个名为 Cricket 的工作表,并将所有符合条件的行复制到新工作表中

Below is my attempt, however it's not working as expected

以下是我的尝试,但它没有按预期工作

Sub officetest()
    Worksheets("Sheet1").Activate
    If Range("A1,A10000") = "Cricket" Then
        Sheets.Add
        Sheets(2).Name = "Cricket"
        Worksheets("Sheet1").Range("A1, A10000").Copy 
        Worksheets("Sheet2").Range("A1")
    End If
End Sub

tried this as well..but not working:

也试过这个..但不起作用:

Sub officetest()
    Worksheets(1).Activate
    If Range("A1,A10000") = "Cricket" Then
        Sheets.Add Sheets(1).Name = "Cricket"
        Worksheets("Cricket").Range("A, AD").Copy Worksheets(2).Range("A1")
    End If
End Sub

回答by jsotola

this is a recorded macro:

这是一个录制的宏:

i filled first few cells in column A with text (on a blank worksheet)

我用文本填充了 A 列中的前几个单元格(在空白工作表上)

made one of the cells "cricket"

使其中一个细胞“蟋蟀”

started macro recorder

启动宏记录器

selected top left cell ... searched for "cricket" (searched by columns)

选定的左上角单元格...搜索“板球”(按列搜索)

created a new worksheet and named it "cricket"

创建了一个新工作表并将其命名为“板球”

returned to first sheet selected row with "cricket" ... hit ctrl-c (copy)

使用“板球”返回到第一张选定的行...点击 ctrl-c(复制)

selected cricket worksheet ... hit ctrl-v (paste)

选定的板球工作表...点击 ctrl-v(粘贴)

stopped macro recorder

停止宏记录器

this is the resulting macro:

这是由此产生的宏:

Sub Macro2()

    Cells.Find(What:="cricket", After:=ActiveCell, LookIn:=xlValues, LookAt _
        :=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:= _
        False, SearchFormat:=False).Activate
    Selection.Copy
    Sheets.Add After:=ActiveSheet
    Sheets("Sheet2").Select
    Sheets("Sheet2").Name = "cricket"
    Sheets("Sheet1").Select
    Rows("9:9").Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("cricket").Select
    ActiveSheet.Paste

End Sub


here is a quick range addressing example

这是一个快速范围寻址示例

there are sooooo many ways to refer to a cell and to cell ranges in excel

有很多方法可以在excel中引用单元格和单元格范围

i included it because, in the rewritten code, the found cell row is referred to as row one

我包含它是因为在重写的代码中,找到的单元格行被称为第一行

Sub lesson()

' note: use F8 to single-step through code

    ' quick example of ranges "inside" other ranges

    Range("b3").Select                     ' cell at B3 is selected
    Range("b3").Range("a2").Select         ' cell at B4 is selected because range(B3) is now a top corner for range(a2)
    Range("b3").Range("a1", "b2").Select   ' range(b3:c4) is selected

End Sub

'  _A_ _B_ _C_                
'1|   |   |   |                
' |_ _|_ _|_ _|
'2|   |   |   |
' |_ _|_ _|_ _|
'3|   |A1 |B1 | <<<<<  range("B3").Range("A1", "B2")
' |_ _|_ _|_ _|
'4|   |A2 |B2 |        cell "B3" is the top left corner of Range("A1", "B2")
' |_ _|_ _|_ _|
'5|   |   |   |
' |_ _|_ _|_ _|


here is the recorded macro that has been rewritten to make it shorter

这是已被重写以使其更短的录制宏

the code has no error checking, so it will crash if search text is not found

代码没有错误检查,所以如果没有找到搜索文本,它会崩溃

you can uncomment the "select" methods then single-step through the code and see which cells are highlighted by the select statement

您可以取消对“select”方法的注释,然后单步执行代码并查看 select 语句突出显示了哪些单元格

note of caution: "foundHere.Select" method will fail if you do not have the first sheet selected (a select method will fail if you try to select a range that is not on an active worksheet

注意事项:如果您没有选择第一个工作表,“foundHere.Select”方法将失败(如果您尝试选择不在活动工作表上的范围,选择方法将失败

Sub findAndCopy()

    Dim wb As Workbook
    Set wb = ThisWorkbook

    Dim foundHere As Range

    Dim findMe As String
    findMe = "cricket"

    Set foundHere = Cells.Find(What:=findMe, After:=Sheets("sheet1").Range("a1"), LookIn:=xlValues, _
        LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:= _
        False, SearchFormat:=False)

'    foundHere.Select               ' use during debugging only to see if correct cell is being acted on
'    foundHere.Range("1:1").Select

    wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name = findMe

    ' note: range("1:1") is first row of range(foundHere) ... see above

    foundHere.Range("1:1").Copy Sheets(findMe).Rows(5) ' copy to row 5 (adjust to your liking)


End Sub

i hope that this helps you get started

我希望这可以帮助您入门

回答by paul bica

Copy both of these procedures in a new VBA module and execute "CopyRows()"

将这两个过程复制到新的 VBA 模块中并执行“CopyRows()”

First sub will filter all rows using Cricket as the criteria in the first column

First sub 将使用 Cricket 作为第一列中的条件过滤所有行

Then it will copy all visible rows to the new Sheet named Cricket

然后它将所有可见行复制到名为 Cricket 的新工作表



Option Explicit

Public Sub CopyRows()
    Const ITEM1 As String = "Cricket"
    Dim wsFrom As Worksheet, wsDest As Worksheet

    Set wsFrom = Sheet1                             '<--- Update this
    Application.ScreenUpdating = False
        Set wsDest = CheckNamedSheet(ITEM1)
        With wsFrom.UsedRange
            .AutoFilter Field:=1, Criteria1:="=" & ITEM1
            .Copy   'Copy visible data
        End With
        With wsDest.Cells
            .PasteSpecial xlPasteColumnWidths
            .PasteSpecial xlPasteAll
            .Cells(1, 1).Copy
        End With
        Application.CutCopyMode = False
        wsFrom.UsedRange.AutoFilter
    Application.ScreenUpdating = True
End Sub


This function checks if a previous Sheet named Cricket exists, deletes it and creates a new one

此函数检查之前名为 Cricket 的工作表是否存在,将其删除并创建一个新工作表

Private Function CheckNamedSheet(ByVal sheetName As String) As Worksheet
    Dim ws As Worksheet, result As Boolean, activeWS As Worksheet

    Set activeWS = IIf(ActiveSheet.Name = sheetName, Worksheets(1), ActiveSheet)
    For Each ws In Worksheets
        If ws.Name = sheetName Then
            Application.DisplayAlerts = False
            ws.Delete   'delete sheet if it already exists
            Application.DisplayAlerts = True
            Exit For
        End If
    Next
    Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count))    'create a new one
    ws.Name = sheetName
    activeWS.Activate
    Set CheckNamedSheet = ws
End Function


回答by jsotola

this is just an experiment. i included it because i used it when i needed to figure out "offset" addressing

这只是一个实验。我包含它是因为我在需要找出“偏移”寻址时使用它

it may help someone in the future

它可能会在未来帮助某人

    Sub see_how_offset_works()

        Range("c5").Select                ' C5
        Range("c5").offset(-1).Select     ' C4   previous row
        Range("c5").offset(0).Select      ' C5   same row
        Range("c5").offset(1).Select      ' C6   next row
        Range("c5").offset(1, 1).Select   ' D6   next row and next column

    End Sub


here is code that may work for you

这是可能对您有用的代码

i have not thoroughly tested the code, and there may be issues because i have not "destroyed" any of the created objects eg. set wb = Nothing

我没有彻底测试代码,可能会出现问题,因为我没有“破坏”任何创建的对象,例如。 设置 wb = 无

there is no check for sheet name duplication

没有检查工作表名称重复

the program assembles all the data ranges of interest into one range and then does a single copy command to put the data where it is needed

该程序将所有感兴趣的数据范围组装到一个范围内,然后执行单个复制命令将数据放在需要的地方

enjoy

请享用



                                   '
    Sub testFind()                 ' !!!!!!!!!!!! run me !!!!!!!!!!!!

        If findData("cricket") Then
            MsgBox "success"
        Else
            MsgBox "text not found"
        End If

    End Sub

    ' ----------------------------------------------------

    Function findData(findme As String) As Boolean      ' returns True if search is successful

        Dim wb As Workbook
        Set wb = ThisWorkbook

        Dim start As Range
        Dim fini As Range
        Dim oneFound As Range
        Dim allFound As Range

        Set start = Range("a1")            ' top of the search range     (must be one column)
        Set fini = Range("a20")            ' bottom of the search range  (must be one column)

    '    Range(start, fini).Select         ' highlight initial search area (debug only ... comment out after debug done)

        Dim indx As Integer
        indx = 0                           ' how far down within the search range do we start the next search

        Dim i As Integer                   ' loop counter
        Dim foundAt As Integer             ' row number where text has been found (this is relative to search range, not relative to worksheet)

        Dim numFinds As Integer            ' how many times is the search text repeated
        numFinds = Application.WorksheetFunction.CountIf(Range(start, fini), findme)  ' count occurences

    '    Debug.Print numFinds
        findData = False                   ' preload the "failure" status

        If numFinds > 0 Then

            For i = 1 To numFinds

                foundAt = Application.WorksheetFunction.Match(findme, Range(start.offset(indx), fini), 0)

                indx = indx + foundAt - 1        ' indx is the offset from "original top of search range" to the "current found cell"

                start.offset(indx).Select        ' for debugging ... "start.offset(indx)" is the "current found cell"

                Set oneFound = Rows(start.offset(indx).Row)       ' whole row
        '        Set oneFound = start.offset(indx).Range("b1:f1")  ' cells in columns B:F

        '        oneFound.Select                 ' for debugging only

                If i = 1 Then
                    Set allFound = oneFound
                Else
                    Set allFound = Union(allFound, oneFound)  ' assemble all ranges into one range
                End If

        '        allFound.Select                 ' for debugging only
                indx = indx + 1                  ' point to next cell after the "current found cell"
            Next

        '    allFound.Select                     ' for debugging only

        '    allFound.Copy Rows(22)              ' copy selected ranges into row 22 of the current worksheet


            wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name = findme  ' this new sheet will have focus

            allFound.Copy Sheets(findme).Rows(5) ' copy to row 5 (change to your liking)

            findData = True                      ' success status

        End If


    End Function