Excel 将图像和数据从多个源工作簿复制到单个工作簿的有效方法

Excel 将图像和数据从多个源工作簿复制到单个工作簿的有效方法,excel,vba,Excel,Vba,我有以下代码将图像从一个工作簿复制到另一个工作簿。代码打开源工作簿/工作表,复制图像,然后关闭工作簿。此过程重复多次。有没有更有效的方法?也许绕过剪贴板 我只需要为每个源工作簿/工作表复制1个图像(名为“图片4”)和2-3个单元格值。我有7-8个源工作簿 Set srcWB = Workbooks.Open(ThisWorkbook.Path & "\testWS1.xlsx", True, True) Set srcWS = srcWB.Sheets("s

我有以下代码将图像从一个工作簿复制到另一个工作簿。代码打开源工作簿/工作表,复制图像,然后关闭工作簿。此过程重复多次。有没有更有效的方法?也许绕过剪贴板

我只需要为每个源工作簿/工作表复制1个图像(名为“图片4”)和2-3个单元格值。我有7-8个源工作簿

Set srcWB = Workbooks.Open(ThisWorkbook.Path & "\testWS1.xlsx", True, True)
Set srcWS = srcWB.Sheets("sheetwithimage")     

srcWS.Pictures(4).Copy         
dstWS.Range("B7").PasteSpecial

Set srcWB = Workbooks.Open(ThisWorkbook.Path & "\testWS2.xlsx", True, True)
Set srcWS = srcWB.Sheets("sheetwithimage")     

srcWS.Pictures(4).Copy         
dstWS.Range("G8").PasteSpecial
创建报告
  • 我假设目标工作簿和包含此代码的工作簿是相同的
  • 调整常量部分中的值
  • 仅运行
    createReport
    过程。它正在调用函数
    getFilePathsInFolder
  • 由于
    此工作簿
    将没有扩展名
    “xlsx”
    ,因此语句
    如果StrComp(filepath(fp)、dstFilePath、vbTextCompare)0那么
    是多余的,但我将离开它,因为有一天,当代码可能造成一些损坏时,您可能会将文件扩展名更改为
    “xls*”
摘要

  • 它将在指定的文件夹中查找并将所有
    .xlsx
    文件写入数组。它将循环遍历数组并打开每个工作簿,将其索引指定的图片复制到目标工作簿的指定位置,然后将其粘贴并写入指定的单元格值,然后关闭每个源工作簿
代码

Option Explicit

Sub createReport()
    
    Const ProcName As String = "createReport"
    On Error GoTo clearError

    ' Source
    Const Extension As String = "xlsx"
    Const srcName As String = "sheetwithimage"
    Const srcList As String = "A1,A2,A3" ' add more
    Const picIndex As Long = 1
    ' Destination
    Const dstName As String = "Sheet1"
    Const dstList As String = "B1,B2,B3" ' add more
    Const picAddress As String = "B7"
    Const colOffset As Long = 5
    
    ' Write file paths from Source Folder Path to File Paths array.
    Dim wbDst As Workbook: Set wbDst = ThisWorkbook
    Dim srcFolderPath As String: srcFolderPath = wbDst.Path
    Dim FilePaths As Variant
    FilePaths = getFilePathsInFolder(srcFolderPath, Extension)
    
    
    Dim srcCells() As String: srcCells = Split(srcList, ",")
    Dim dstCells() As String: dstCells = Split(dstList, ",")
    ' Use a variable for lower and upper if inside another loop.
    ' Split ensures that lower is 0, so no need for lower variable.
    Dim CellsUB As Long: CellsUB = UBound(srcCells) ' or 'Ubound(dstCells)'
    Dim dst As Worksheet: Set dst = wbDst.Worksheets(dstName)
    Dim dstFilePath As String: dstFilePath = wbDst.FullName
    
    ' Declare new variables occurring in the following loop.
    Dim wbSrc As Workbook
    Dim src As Worksheet
    Dim srcCount As Long
    Dim fp As Long
    Dim n As Long
    
    Application.ScreenUpdating = False
    
    ' We don't care if 'FilePaths' is zero, one or five-based, since we
    ' cannot use fp because of 'ThisWorkbook'; hence 'srcCount'.
    For fp = LBound(FilePaths) To UBound(FilePaths)
        ' We have to skip 'ThisWorkbook'. Using 'StrComp' with 'vbTextCompare'
        ' is a great way for comparing strings case-insensitively i.e. 'A=a'.
        ' '0' means it is a match.
        If StrComp(FilePaths(fp), dstFilePath, vbTextCompare) <> 0 Then
            Set wbSrc = Workbooks.Open(FilePaths(fp), True, True)
            Set src = wbSrc.Worksheets(srcName)
            src.Pictures(picIndex).Copy
            dst.Range(picAddress).Offset(, srcCount * colOffset).PasteSpecial
            For n = 0 To CellsUB ' 'Split'
                dst.Range(dstCells(n)).Offset(, srcCount * colOffset).Value _
                    = src.Range(srcCells(n)).Value
            Next n
            wbSrc.Close SaveChanges:=False
            srcCount = srcCount + 1
        End If
    Next fp
    
    ' Save and/or inform user.
    If srcCount > 0 Then
        dst.Range("A1").Select
        wbDst.Save
        Application.ScreenUpdating = True
        If srcCount = 1 Then
            MsgBox "Data from 1 workbook transferred.", vbInformation, "Success"
        Else
            MsgBox "Data from " & srcCount & " workbooks transferred.", _
                vbInformation, "Success"
        End If
    Else
        MsgBox "No matching workbooks found in folder '" & srcFolderPath _
            & "'!", vbCritical, "Fail"
    End If

ProcExit:
    Exit Sub

clearError:
    Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
              & "    " & "Run-time error '" & Err.Number & "':" & vbLf _
              & "        " & Err.Description
    Resume ProcExit
    
End Sub

Function getFilePathsInFolder( _
    FolderPath As String, _
    Optional ByVal ExtensionPattern As String = "", _
    Optional ByVal FirstIndex As Long = 0) _
As Variant
    
    Const ProcName As String = "listFilePathsInFolder"
    On Error GoTo clearError
    
    With CreateObject("Scripting.FileSystemObject")
        Dim fsoFolder As Object
        Set fsoFolder = .GetFolder(FolderPath)
        Dim FilesCount As Long
        FilesCount = fsoFolder.Files.Count
        If FilesCount > 0 Then
            Dim n As Long
            n = FirstIndex - 1
            Dim OneD As Variant
            ReDim OneD(FirstIndex To FilesCount + n)
            Dim fsoFile As Object
            If ExtensionPattern = "" Then
                For Each fsoFile In fsoFolder.Files
                    n = n + 1
                    OneD(n) = fsoFile.Path
                Next fsoFile
                getFilePathsInFolder = OneD
            Else
                For Each fsoFile In fsoFolder.Files
                    If LCase(.GetExtensionName(fsoFile)) _
                            Like LCase(ExtensionPattern) Then
                        n = n + 1
                        OneD(n) = fsoFile.Path
                    End If
                Next fsoFile
                If n > FirstIndex - 1 Then
                    ReDim Preserve OneD(FirstIndex To n)
                    getFilePathsInFolder = OneD
                Else
                    Debug.Print "'" & ProcName & "': " _
                        & "No '" & ExtensionPattern & "'-files found."
                End If
            End If
        Else
            Debug.Print "'" & ProcName & "': " _
                & "No files found."
        End If
    End With

ProcExit:
    Exit Function

clearError:
    Debug.Print "'" & ProcName & "': Unexpected error!" & vbLf _
        & "    " & "Run-time error '" & Err.Number & "':" & vbLf _
        & "        " & Err.Description
    Resume ProcExit

End Function
选项显式
子报表()
Const ProcName As String=“createReport”
关于错误转到clearError
"来源:
常量扩展名为String=“xlsx”
Const srcName As String=“sheetwithimage”
Const srcList As String=“A1、A2、A3”'添加更多
常量picIndex的长度=1
“目的地
常量dstName为String=“Sheet1”
Const dstList As String=“B1、B2、B3”'添加更多
Const picAddress As String=“B7”
长度=5时的常数列偏移
'将文件路径从源文件夹路径写入文件路径数组。
将wbDst设置为工作簿:设置wbDst=ThisWorkbook
将srcFolderPath设置为字符串:srcFolderPath=wbDst.Path
变暗文件路径作为变量
filepath=getFilePathsInFolder(srcFolderPath,扩展名)
Dim srccell()作为字符串:srccell=Split(srcList,“”)
Dim dstCells()作为字符串:dstCells=Split(dstList,“”)
'如果在另一个循环内,则为lower和upper使用一个变量。
'拆分确保lower为0,因此不需要lower变量。
将CellsUB设置为长:CellsUB=UBound(SRCCell)或UBound(DSTCell)
将dst设置为工作表:设置dst=wbDst.Worksheets(dstName)
Dim dstFilePath作为字符串:dstFilePath=wbDst.FullName
'声明发生在以下循环中的新变量。
将wbSrc设置为工作簿
Dim src As工作表
我认为只要
尽可能长
长
Application.ScreenUpdating=False
我们不在乎“文件路径”是零、一还是五,因为我们
'无法使用fp,因为'ThisWorkbook';因此“srcCount”。
对于fp=LBound(文件路径)到UBound(文件路径)
“我们必须跳过“此工作簿”。将“StrComp”与“vbTextCompare”一起使用
'是比较字符串大小写不敏感的好方法,即'a=a'。
“”0表示它是匹配项。
如果StrComp(filepath(fp)、dstFilePath、vbTextCompare)为0,则
设置wbSrc=Workbooks.Open(文件路径(fp)、True、True)
Set src=wbSrc.Worksheets(srcName)
src.图片(picIndex).复制
dst.Range(picAddress).Offset(,srcCount*colOffset).PasteSpecial
对于n=0的CellsUB“拆分”
dst.Range(dstcell(n)).Offset(,srcCount*colOffset).Value_
=src.Range(srccell(n)).Value
下一个
wbSrc.Close SaveChanges:=False
srcCount=srcCount+1
如果结束
下一个fp
'保存和/或通知用户。
如果srcCount>0,则
dst.范围(“A1”)。选择
wbDst.Save
Application.ScreenUpdating=True
如果srcCount=1,则
MsgBox“已传输1个工作簿中的数据”,vbInformation,“成功”
其他的
MsgBox“数据来自”&srcCount和“已传输工作簿”_
VBA信息,“成功”
如果结束
其他的
MsgBox“在文件夹“”中找不到匹配的工作簿(&srcFolderPath)_
&“!”,vbCritical,“失败”
如果结束
程序出口:
出口接头
clearError:
Debug.Print“”&ProcName&“:意外错误!”&vbLf_
&“&”运行时错误“&”错误编号&“:”&vbLf_
&“”错误描述(&R)
恢复程序退出
端接头
函数getFilePathsInFolder(_
FolderPath作为字符串_
可选的ByVal扩展模式为String=“”_
可选的ByVal FirstIndex(长度=0)_
作为变体
Const ProcName As String=“listFilePathsInFolder”
关于错误转到clearError
使用CreateObject(“Scripting.FileSystemObject”)
作为对象的模糊文件夹
设置fsoFolder=.GetFolder(FolderPath)
我认为时间很长
filescont=fsoFolder.Files.Count
如果FileCount>0,则
长
n=第一索引-1
作为变体
重新定义(第一个索引到filescout+n)
作为对象的Dim fsoFile
如果ExtensionPattern=“”,则
对于fsoFolder.Files中的每个fsoFile
n=n+1
OneD(n)=f文件路径
下一个文件
getFilePathsInFolder=OneD
其他的
对于fsoFolder.Files中的每个fsoFile
如果是LCase(.GetExtensionName(fsoFile))_
就像LCase(ExtensionPattern)那样
n=n+1
OneD(n)=f文件路径
Option Explicit

Sub copy_images_original()

Dim dstWS As Worksheet
Set dstWS = ThisWorkbook.Sheets(1)
Dim srcWB As Workbook
Dim srcWS As Worksheet

Set srcWB = Workbooks.Open(ThisWorkbook.Path & "\testWS1.xlsx", True, True)
Set srcWS = srcWB.Sheets("sheetwithimage")

srcWS.Pictures(4).Copy
dstWS.Range("B7").PasteSpecial
srcWB.Close

Set srcWB = Workbooks.Open(ThisWorkbook.Path & "\testWS2.xlsx", True, True)
Set srcWS = srcWB.Sheets("sheetwithimage")

srcWS.Pictures(4).Copy
dstWS.Range("G8").PasteSpecial
srcWB.Close
End Sub

Sub CalculateRunTime_Seconds()
'PURPOSE: Determine how many seconds it took for code to completely run
'SOURCE: www.TheSpreadsheetGuru.com/the-code-vault

Dim StartTime As Double
Dim SecondsElapsed As Double

'Remember time when macro starts
  StartTime = Timer

'*****************************
Call turn_app_off
Call copy_images_original
Call turn_app_on
'*****************************

'Determine how many seconds code took to run
  SecondsElapsed = Round(Timer - StartTime, 2)

'Notify user in seconds
  MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation

End Sub

Sub turn_app_off()
With Application
    .ScreenUpdating = False
    .EnableEvents = False
    .DisplayAlerts = False
End With
End Sub
Sub turn_app_on()
With Application
    .ScreenUpdating = True
    .EnableEvents = True
    .DisplayAlerts = True
End With
End Sub