Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 将多个工作簿的行复制到一个主工作簿中_Excel_Vba - Fatal编程技术网

Excel 将多个工作簿的行复制到一个主工作簿中

Excel 将多个工作簿的行复制到一个主工作簿中,excel,vba,Excel,Vba,我想打开只包含一张工作表的工作簿, 将数据复制到列AC,直到列A中最后一行可用, 将数据粘贴到工作簿“Mergedsheet.xlsx”A列的第一个空行中 我想循环查看特定文件夹中的所有工作簿,但会出现很多错误 Sub MergeNew() Dim WorkBk As Workbook Dim MergedSheet As Worksheet Dim SourceData As Range Dim DestinationData As Range Dim

我想打开只包含一张工作表的工作簿,
将数据复制到列AC,直到列A中最后一行可用,
将数据粘贴到工作簿“Mergedsheet.xlsx”A列的第一个空行中

我想循环查看特定文件夹中的所有工作簿,但会出现很多错误

Sub MergeNew()
    Dim WorkBk As Workbook
    Dim MergedSheet As Worksheet
    Dim SourceData As Range
    Dim DestinationData As Range
    Dim lastRow As Long
    Dim NextRow As Range
    Dim FolderPath As String
    Dim FileNames As String 

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

    FolderPath = "E:\Jan to March 2019\Bharuch 31\"
    FileNames = Dir(FolderPath & "*.xls*")
    Do While FileNames <> ""
        Set WorkBk = Workbooks.Open(FolderPath & FileNames)
        Range("A1:AC1").Select
        Range(Selection, Selection.End(xlDown)).Select
        Selection.Copy
        Workbooks.Open Filename:="E:\Jan to March 2019\Bharuch 31\MergedSheet.xlsx"
        lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
        Range("A" & lastRow).Select
        ActiveSheet.Paste
        'ActiveWindow.Close SaveChanges:=True
        'ActiveWindow.Close SaveChanges:=False
        Application.CutCopyMode = False

        FileNames = Dir()
    Loop
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub
Sub-MergeNew()
将WorkBk设置为工作簿
以工作表的形式显示合并表
将SourceData设置为范围
模糊目标数据作为范围
最后一排一样长
下一步变暗为范围
将FolderPath设置为字符串
将文件名设置为字符串
Application.ScreenUpdating=False
Application.DisplayAlerts=False
FolderPath=“E:\2019年1月至3月\Bharuch 31”
FileNames=Dir(FolderPath&“*.xls*”)
当文件名为“”时执行此操作
设置WorkBk=Workbooks.Open(文件夹路径和文件名)
范围(“A1:AC1”)。选择
范围(选择,选择。结束(xlDown))。选择
选择,复制
工作簿。打开文件名:=“E:\2019年1月至3月\Bharuch 31\MergedSheet.xlsx”
lastRow=ActiveSheet.Cells(Rows.Count,“A”).End(xlUp).行+1
范围(“A”&最后一行)。选择
活动表。粘贴
'ActiveWindow.Close SaveChanges:=True
'ActiveWindow.Close SaveChanges:=False
Application.CutCopyMode=False
FileNames=Dir()
环
Application.ScreenUpdating=True
Application.DisplayAlerts=True
端接头

您正在一个文件夹中循环,并将每个工作簿的第一页数据复制粘贴到工作簿a。但是,工作簿a也在该文件夹中。所以你应该注意跳过它(当循环时)

(或者,您可以为
DIR
函数提供不同的参数(例如,一些通配符条件,如果可能的话,排除工作簿a),这样您就不必经常检查循环内部。)

未经测试

Option Explicit

Private Sub MergeNew()
    'Application.ScreenUpdating = False 'Uncomment this when you know code is working.
    'Application.DisplayAlerts = False 'Uncomment this when you know code is working.

    Dim folderPath As String
    folderPath = GetFolderPath(titleToShow:="Select the folder containing the files to loop through.")

    Dim Filename As String
    Filename = Dir$(folderPath & "*.xls*")

    If Len(Filename) = 0 Then
        MsgBox "Could not find a relevant file in '" & folderPath & "'. Code will stop running now."
        Exit Sub ' No point in carrying on in such a case.
    End If

    Dim destinationFolderPath As String
    destinationFolderPath = GetFolderPath(titleToShow:="Select the folder to save the 'MergedSheet.xlsx' file to.")

    Dim destinationWorkbook As Workbook
    Set destinationWorkbook = Application.Workbooks.Add

    ' This line may throw an error
    destinationWorkbook.SaveAs Filename:=destinationFolderPath & "MergedSheet.xlsx", FileFormat:=xlOpenXMLWorkbook

    Dim destinationSheet As Worksheet
    Set destinationSheet = destinationWorkbook.Worksheets(1) ' I assume there's only 1 sheet in there, but change as necessary.

    Do Until Len(Filename) = 0
        Dim fullFilePathToOpen As String
        fullFilePathToOpen = folderPath & Filename

        If fullFilePathToOpen <> destinationWorkbook.FullName Then ' Probably could have just compared filename since directory is the same, but this is more explicit
            Dim sourceWorkbook As Workbook
            Set sourceWorkbook = Application.Workbooks.Open(Filename:=fullFilePathToOpen, ReadOnly:=True) ' If you don't make changes to the workbook you open, better to open as read-only

            Dim sourceSheet As Worksheet
            Set sourceSheet = sourceWorkbook.Worksheets(1) ' You say there's only one worksheet in there, so referring by index should be okay (for now)

            Dim lastSourceRow As Long
            lastSourceRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row ' Assume last row can be determined from column A alone

            Dim lastDestinationRow As Long
            lastDestinationRow = destinationSheet.Cells(destinationSheet.Rows.Count, "A").End(xlUp).Row + 1

            If destinationSheet.Rows.Count < (lastDestinationRow + lastSourceRow) Then
                MsgBox "Ran out of rows (in sheet '" & sourceSheet.Name & "' of workbook '" & destinationWorkbook.Name & "')"
                Exit Sub
            End If

            sourceSheet.Range("A1", sourceSheet.Cells(lastSourceRow, "AC")).Copy Destination:=destinationSheet.Cells(lastDestinationRow, "A")

            sourceWorkbook.Close False
        End If
        Filename = Dir$()
    Loop

    'Application.ScreenUpdating = True 'Uncomment this when you know code is working.
    'Application.DisplayAlerts = True 'Uncomment this when you know code is working.
End Sub

Private Function GetFolderPath(Optional ByVal titleToShow As String = vbNullString) As String
    With Application.FileDialog(msoFileDialogFolderPicker)
        If Len(titleToShow) > 0 Then .Title = titleToShow
        .AllowMultiSelect = False ' Only one is allowed.
        .Show
        If .SelectedItems.Count = 0 Then
            MsgBox "Folder selection appears to have cancelled. Code will stop running now"
            End
        End If
        GetFolderPath = .SelectedItems(1) & "\"
    End With
End Function
选项显式
私人分公司(新)
“Application.ScreenUpdating=False”在您知道代码正在工作时取消注释。
“Application.DisplayAlerts=False”当您知道代码正在工作时,取消对此的注释。
将folderPath设置为字符串
folderPath=GetFolderPath(titleToShow:=“选择包含要循环通过的文件的文件夹。”)
将文件名设置为字符串
Filename=Dir$(folderPath&“*.xls*”)
如果Len(Filename)=0,则
MsgBox“在'&folderPath&'中找不到相关文件。代码将立即停止运行。”
退出Sub“在这种情况下进行没有意义。
如果结束
Dim destinationFolderPath作为字符串
destinationFolderPath=GetFolderPath(标题显示:=“选择要将“MergedSheet.xlsx”文件保存到的文件夹。”)
将目标工作簿设置为工作簿
设置目标工作簿=Application.Workbooks.Add
“这条线可能会出错
destinationWorkbook.SaveAs文件名:=destinationFolderPath&“MergedSheet.xlsx”,文件格式:=xlOpenXMLWorkbook
将目的表设置为工作表
Set destinationSheet=destinationWorkbook.Worksheets(1)'我假设其中只有一张工作表,但根据需要进行更改。
直到Len(文件名)=0为止
Dim fullFilePathToOpen为字符串
fullFilePathToOpen=folderPath&Filename
如果fullFilePathToOpen destinationWorkbook.FullName,则“可能只是比较了文件名,因为目录是相同的,但这更明确。”
将源工作簿设置为工作簿
设置source工作簿=Application.Workbooks.Open(文件名:=fullFilePathToOpen,只读:=True)’如果不更改打开的工作簿,最好以只读方式打开
将源表设置为工作表
Set sourceSheet=source工作簿.Worksheets(1)'您说其中只有一个工作表,所以按索引引用应该可以(目前)
将lastSourceRow设置为长
lastSourceRow=sourceSheet.Cells(sourceSheet.Rows.Count,“A”).End(xlUp)。Row'假定最后一行可以单独从列A确定
将最后一个目的地排成一行
lastDestinationRow=destinationSheet.Cells(destinationSheet.Rows.Count,“A”)。结束(xlUp)。行+1
如果destinationSheet.Rows.Count<(lastDestinationRow+lastSourceRow),则
MsgBox“在工作表“&”sourceSheet.Name&“工作簿的”&“目标工作簿.Name&”中的行数不足”
出口接头
如果结束
sourceSheet.Range(“A1”,sourceSheet.Cells(lastSourceRow,“AC”))。复制目标:=目标Sheet.Cells(lastDestinationRow,“A”)
sourceWorkbook.Close为False
如果结束
Filename=Dir$()
环
“Application.ScreenUpdate=True”在您知道代码正在工作时取消注释。
“Application.DisplayAlerts=True”当您知道代码正在工作时,取消对此的注释。
端接头
私有函数GetFolderPath(可选ByVal titleToShow As String=vbNullString)作为字符串
使用Application.FileDialog(msoFileDialogFolderPicker)
如果Len(titleToShow)>0,则.Title=titleToShow
.AllowMultiSelect=False“只允许一个”。
显示
如果.SelectedItems.Count=0,则
MsgBox“文件夹选择似乎已取消。代码将立即停止运行”
终点
如果结束
GetFolderPath=.SelectedItems(1)和“\”
以
端函数

您正在一个文件夹中循环,并将每个工作簿的第一页数据复制粘贴到工作簿a。但是,工作簿a也在该文件夹中。所以你应该注意跳过它(当循环时)

(或者,您可以为
DIR
函数提供不同的参数(例如,一些通配符条件,如果可能的话,排除工作簿a),这样您就不必经常检查循环内部。)

未经测试

Option Explicit

Private Sub MergeNew()
    'Application.ScreenUpdating = False 'Uncomment this when you know code is working.
    'Application.DisplayAlerts = False 'Uncomment this when you know code is working.

    Dim folderPath As String
    folderPath = GetFolderPath(titleToShow:="Select the folder containing the files to loop through.")

    Dim Filename As String
    Filename = Dir$(folderPath & "*.xls*")

    If Len(Filename) = 0 Then
        MsgBox "Could not find a relevant file in '" & folderPath & "'. Code will stop running now."
        Exit Sub ' No point in carrying on in such a case.
    End If

    Dim destinationFolderPath As String
    destinationFolderPath = GetFolderPath(titleToShow:="Select the folder to save the 'MergedSheet.xlsx' file to.")

    Dim destinationWorkbook As Workbook
    Set destinationWorkbook = Application.Workbooks.Add

    ' This line may throw an error
    destinationWorkbook.SaveAs Filename:=destinationFolderPath & "MergedSheet.xlsx", FileFormat:=xlOpenXMLWorkbook

    Dim destinationSheet As Worksheet
    Set destinationSheet = destinationWorkbook.Worksheets(1) ' I assume there's only 1 sheet in there, but change as necessary.

    Do Until Len(Filename) = 0
        Dim fullFilePathToOpen As String
        fullFilePathToOpen = folderPath & Filename

        If fullFilePathToOpen <> destinationWorkbook.FullName Then ' Probably could have just compared filename since directory is the same, but this is more explicit
            Dim sourceWorkbook As Workbook
            Set sourceWorkbook = Application.Workbooks.Open(Filename:=fullFilePathToOpen, ReadOnly:=True) ' If you don't make changes to the workbook you open, better to open as read-only

            Dim sourceSheet As Worksheet
            Set sourceSheet = sourceWorkbook.Worksheets(1) ' You say there's only one worksheet in there, so referring by index should be okay (for now)

            Dim lastSourceRow As Long
            lastSourceRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row ' Assume last row can be determined from column A alone

            Dim lastDestinationRow As Long
            lastDestinationRow = destinationSheet.Cells(destinationSheet.Rows.Count, "A").End(xlUp).Row + 1

            If destinationSheet.Rows.Count < (lastDestinationRow + lastSourceRow) Then
                MsgBox "Ran out of rows (in sheet '" & sourceSheet.Name & "' of workbook '" & destinationWorkbook.Name & "')"
                Exit Sub
            End If

            sourceSheet.Range("A1", sourceSheet.Cells(lastSourceRow, "AC")).Copy Destination:=destinationSheet.Cells(lastDestinationRow, "A")

            sourceWorkbook.Close False
        End If
        Filename = Dir$()
    Loop

    'Application.ScreenUpdating = True 'Uncomment this when you know code is working.
    'Application.DisplayAlerts = True 'Uncomment this when you know code is working.
End Sub

Private Function GetFolderPath(Optional ByVal titleToShow As String = vbNullString) As String
    With Application.FileDialog(msoFileDialogFolderPicker)
        If Len(titleToShow) > 0 Then .Title = titleToShow
        .AllowMultiSelect = False ' Only one is allowed.
        .Show
        If .SelectedItems.Count = 0 Then
            MsgBox "Folder selection appears to have cancelled. Code will stop running now"
            End
        End If
        GetFolderPath = .SelectedItems(1) & "\"
    End With
End Function
选项显式
私人分公司(新)
“Application.ScreenUpdating=False”在您知道代码正在工作时取消注释。
“Application.DisplayAlerts=False”当您知道代码正在工作时,取消对此的注释。
暗淡的