Excel 循环工作表和传输数据

Excel 循环工作表和传输数据,excel,vba,Excel,Vba,我的大脑被炸了,这对于通常的嫌疑犯来说是很容易的div是一个包含工作表名称的数组。我在母版手册中循环浏览图纸,如果其中一张母版图纸与div数组中的一张图纸匹配,我想将一些数据从母版图纸传输到此工作簿中的一张图纸 如果此工作簿中不存在该工作表,请在主工作表后添加一个工作表并将其命名。最有效的方法是什么?我觉得嵌套循环是个坏主意-也许是一个集合 For i = 0 To UBound(div()) For Each s In book.Worksheets wsName

我的大脑被炸了,这对于通常的嫌疑犯来说是很容易的
div
是一个包含工作表名称的数组。我在母版手册中循环浏览图纸,如果其中一张母版图纸与
div
数组中的一张图纸匹配,我想将一些数据从母版图纸传输到
此工作簿中的一张图纸

如果此工作簿中不存在该工作表,请在主工作表后添加一个工作表并将其命名。最有效的方法是什么?我觉得嵌套循环是个坏主意-也许是一个集合

For i = 0 To UBound(div())

    For Each s In book.Worksheets

        wsName = Left(s.Name, 5)

        If div(i) = wsName Then
        If wsExists(wsName) Then
            Set ws = ThisWorkbook.Worksheets(wsName)
            Exit For
            'Debug.Print "true " & ws.name
        Else
            Set ws = ThisWorkbook.Worksheets.Add
            ws.Name = Left(s.Name, 5)
            'Debug.Print "false " & ws.name
        End If
        end if
    Next

    With ws
    .Columns(Start).Resize(, 2).Value = s.Columns("A:B").Value
    .Columns(Start + label).Resize(, cols).Value = s.Columns(Start + label).Resize(, cols).Value
    End With

Next
我是否需要检查工作表是否存在?密码是从你的电脑里偷来的

编辑:我从一个单独的例程调用循环

Call drop(thisWB, thisRange, ccArr)
其中
ccArr

Dim ccArr() As Variant
ccArr = Array("30500", "30510", "30515", "30530", "30600", "30900", "40500")
上述循环所在的例程将以

Sub drop(book As Workbook, cols As Integer, div As Variant, Optional startCol As Integer)

但是我在试图通过数组时遇到了一个
byref
错误;\

嵌套循环是多余的。您可以从
div
直接对照要检查的工作簿检查工作表名称,然后根据需要添加工作表名称

请参阅下面的代码,它也解决了编辑OP时的问题。我修改了
wsExists
函数,以包含对特定工作簿的集合引用,我认为这使它更具动态性

'assumes thisWB  and thisRange set above

Dim ccArr() As String, sList As String
sList = "30500,30510,30515,30530,30600,30900,40500"
ccArr = Split(sList, ",")

drop thisWB, thisRange, ccArr 'assumes thisWb and thisRange are set already

' rest of code
'==================================================

Sub drop(book As Workbook, cols As Integer, div() As String, Optional startCol as Integer)

For i = 0 To UBound(div())

    If wsExists(ThisWorkbook, div(i)) Then
        Set ws = ThisWorkbook.Worksheets(div(i))
        Exit For
        'Debug.Print "true " & ws.name
    Else
        Set ws = ThisWorkbook.Worksheets.Add
        ws.Name = div(i)
    End If

    'i think you need this here, otherwise, it will only work on the last worksheet in your loop
    With ws
        Dim s As Worksheet
        Set s = book.Sheets(div(i))
        .Columns(Start).Resize(, 2).Value = s.Columns("A:B").Value
        .Columns(Start + Label).Resize(, cols).Value = s.Columns(Start + Label).Resize(, cols).Value
    End With

Next

End Sub

Function wsExists(wb As Workbook, sName As String) As Boolean
Dim sht As Worksheet

On Error Resume Next
Set sht = wb.Sheets(sName)
On Error GoTo 0
wsExists = Not sht Is Nothing

End Function

与重新调整大小代码相关:

此语句
ws.Columns(1).Resize(,2)
转换为“第1列和第2列的200多万行”

您找到的解决方案运行良好,但它不是动态的(硬编码的最后一行)

以下是我设置列副本的方式:

Option Explicit

Public Sub copyCols()
    Dim ws1 As Worksheet, ws2 As Worksheet, rng1 As Range, rng2 As Range
    Dim cols As Long, lr As Long

    Dim col1 As Long    'renamed from "Start" (VBA keyword - property)
    Dim lbl As Long     'renamed from "label" (VBA keyword - Control object)

    Set ws1 = Sheet1    'ws
    Set ws2 = Sheet2    'book.Worksheets(wsName & "-F")

    col1 = 1
    cols = 2
    lbl = 1

    lr = ws2.Cells(ws2.UsedRange.Row + ws2.UsedRange.Rows.Count, "A").End(xlUp).Row

    Set rng1 = ws1.Range(ws1.Cells(1, col1), ws1.Cells(lr, col1 + 1))
    Set rng2 = ws2.Range("A1:B" & lr)

    rng1.Value2 = rng2.Value2

    Set rng1 = ws1.Range(ws1.Cells(1, col1 + lbl), ws1.Cells(lr, col1 + lbl + cols))
    Set rng2 = ws2.Range(ws2.Cells(1, col1 + lbl), ws2.Cells(lr, col1 + lbl + cols))

    rng1.Value2 = rng2.Value2 
End Sub

如果你不检查它的存在会发生什么?如果已经存在某个“表”名称,它是否会出错。您可以处理该错误。但没有理由不检查它。如果您的表数合理,则应该是有效的。将一些测试与示例结合在一起,但我必须运行。出于好奇,时间的百分比是多少(大致)
div
中的一个元素是否与现有的工作表名称不匹配?这是一个很好的问题。这个工作簿一开始实际上是空的。但我将使用第二本母版手册再次运行它,其中90%以上的工作表将匹配。编辑:这两本母版手册可容纳300多张工作表。数组的容纳量永远不会超过,比如说30ish。编辑2:我意识到我可以做到这一点更聪明的是,我不能问关于SO=Pah的广泛问题…因为你的div(I)是变量类型,函数需要一个字符串…你可以将
div(I)更改为string
,或者
Cstr(div(I))
将起作用(未测试)。我想我需要将
s.Columns(“a:B”).Value
更改为
book.Worksheets(wsName)。Columns(“A:B).Value
是吗?被否决并被标记。编辑:你还杀了
。我不应该思考。我希望得到交钥匙答案。我会要求你被禁止这么做。lolol I kid=P被否决。问题,它有效,但速度很慢?编辑:哦,你设置了
s
。我猜这也有效。编辑2:事实上,还是没有
,所以还是fail=P没什么大不了的。更重要的是,
split
强制执行一个字符串,我猜可能是列的大小调整……你可以通过注释该代码并查看在没有这些行的情况下运行需要多长时间来测试。我会帮你研究这个问题,看看我是否能帮上忙。让我知道我是否应该删除这个我不应该删除那个字符串估计。这是一个令人惊讶的答案。我很高兴它有帮助,我认为其他人应该知道默认参数有多么棘手。我认为如果你愿意,你可以取消删除它,但我不确定。我也在那里复制了答案
Option Explicit

Public Sub copyCols()
    Dim ws1 As Worksheet, ws2 As Worksheet, rng1 As Range, rng2 As Range
    Dim cols As Long, lr As Long

    Dim col1 As Long    'renamed from "Start" (VBA keyword - property)
    Dim lbl As Long     'renamed from "label" (VBA keyword - Control object)

    Set ws1 = Sheet1    'ws
    Set ws2 = Sheet2    'book.Worksheets(wsName & "-F")

    col1 = 1
    cols = 2
    lbl = 1

    lr = ws2.Cells(ws2.UsedRange.Row + ws2.UsedRange.Rows.Count, "A").End(xlUp).Row

    Set rng1 = ws1.Range(ws1.Cells(1, col1), ws1.Cells(lr, col1 + 1))
    Set rng2 = ws2.Range("A1:B" & lr)

    rng1.Value2 = rng2.Value2

    Set rng1 = ws1.Range(ws1.Cells(1, col1 + lbl), ws1.Cells(lr, col1 + lbl + cols))
    Set rng2 = ws2.Range(ws2.Cells(1, col1 + lbl), ws2.Cells(lr, col1 + lbl + cols))

    rng1.Value2 = rng2.Value2 
End Sub