用VBA实现把多个Excel文件合并到一个Excel文件的多个工作表(Sheet)里

通过VBA宏代码实现将多个Excel工作簿中的第一个工作表合并到一个新的工作簿中,每个工作表以原文件名命名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自: http://blog.sina.com.cn/s/blog_700659d40100mobg.html

打开一空白xls, 按Alt+F11 进入宏编辑界面 —> 插入模块, 在右边粘贴上如下代码, 按F5 即可运行。

 

'功能:把多个工作簿的第一个工作表合并到一个工作簿的多个工作表,新工作表的名称等于原工作簿的名称
Sub Books2Sheets()
    '定义对话框变量
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogFilePicker)
    
    '新建一个工作簿
    Dim newwb As Workbook
    Set newwb = Workbooks.Add
    
    With fd
        If .Show = -1 Then
            '定义单个文件变量
            Dim vrtSelectedItem As Variant
            
            '定义循环变量
            Dim i As Integer
            i = 1
            
            '开始文件检索
            For Each vrtSelectedItem In .SelectedItems
                '打开被合并工作簿
                Dim tempwb As Workbook
                Set tempwb = Workbooks.Open(vrtSelectedItem)
                
                '复制工作表
                tempwb.Worksheets(1).Copy Before:=newwb.Worksheets(i)
                
                '把新工作簿的工作表名字改成被复制工作簿文件名,这儿应用于xls文件,即Excel97-2003的文件,如果是Excel2007,需要改成xlsx
                newwb.Worksheets(i).Name = VBA.Replace(tempwb.Name, ".xls", "")
                
                '关闭被合并工作簿
                tempwb.Close SaveChanges:=False
                
                i = i + 1
            Next vrtSelectedItem
        End If
    End With
    
    Set fd = Nothing
End Sub

<think>我们面临的问题是将多个包含图片的Excel文件合并一个工作表中。注意,每个Excel文件中都包含图片,且我们希望将这些文件的内容(包括图片)合并到单个工作表多个位置,而不是多个工作表。但是,根据之前的引用和问题描述,之前的代码示例是将每个文件工作表复制到当前工作簿的多个工作表中(即每个文件成为新工作表)。而用户现在要求是合并到“一个工作表中。因此,我们需要调整策略:将多个Excel文件中的内容(包括图片)复制到同一个工作表的连续位置(如连续行)。但需要注意的是,图片的处理比数据复杂,因为图片是浮动对象(FloatingShapes)。思路:1.遍历指定文件夹中的所有Excel文件。2.打开每个文件,将其第一个工作表中的内容(数据、格式、图片等)复制到目标工作表中。3.将每个文件的内容按顺序排列,即第一个文件的内容复制到目标工作表的第一行,第二个文件的内容复制到第一个文件内容的下方(避免重叠),以此类推。然而,复制图片需要注意:-图片的位置:需要调整图片的位置,使其在目标工作表中位于正确的单元格区域。-图片的锚定:在Excel中,图片可以锚定在某个单元格。我们需要将图片锚定在目标位置。具体步骤:a.在目标工作表中,记录下一个可用的行号(初始为1)。b.打开一个文件,复制第一个工作表中所有单元格的内容(包括格式)到目标工作表的当前行开始的位置。c.复制所有图片(Shapes),并调整这些图片的Top位置(加上目标行所在的位置的高度偏移量)。d.更新下一个可用行号(当前已用行数加上源文件工作表中的已用行数,并加上适当的行间距)。e.关闭源文件,继续下一个文件。但要注意:直接调整图片的Top属性是以点为单位的,而我们需要根据行的位置调整。可以通过获取目标行的高度(以点为单位)来计算偏移量。不过,这个方法有个难点:源文件中的图片可能跨多个行,所以无法简单根据当前内容行数来精确计算偏移。我们可以采用另一种方法:先复制源工作表中的所有内容(包括图片)到目标工作表的临时位置(比如一个空白区域),然后整体移动图片到目标位置(通过计算偏移量),然后再删除临时复制的部分。然而,这种方法容易造成混乱。我们采用另一种思路:步骤:1.将源文件整个工作表复制到一个新的工作簿中,这样我们可以在新的工作簿中操作。2.获取该工作表中已使用的区域(UsedRange)的行高(注意,行高是以点为单位的)和总行数。3.记录源文件中每个图片的位置(Top、Left、Width、Height)以及锚定的单元格(但ExcelVBA中图片并没有直接锚定到某个单元格的概念,而是通过位置来定位的。在复制图片时,我们可以通过调整其Top属性来移动图片位置)。4.在目标工作表中,我们复制源工作表的UsedRange(数据部分)到目标工作表的当前行开始的位置。同时,我们也要复制行高,以保留原布局。5.遍历源工作表中的每个图片,将其复制到目标工作表,并将其Top属性调整为:目标工作表中当前行顶部的Top值(即目标行上方所有行的高度之和)加上源图片的Top(相对于源工作表顶部的位置)减去源工作表中第一行的顶部位置(因为源图片的Top是相对于源工作表的A1单元格的)。具体代码实现步骤:假设目标工作表为当前工作簿的Sheet1,我们按以下步骤操作:1.设置文件夹路径,获取所有Excel文件。2.在目标工作表中,初始化当前行号(currentRow)为1。3.循环处理每个文件:a.打开文件。b.选择第一个工作表(假设每个文件只处理第一个工作表)。c.获取源工作表已用区域的行数(rowCount)和列数(colCount)。d.计算源工作表从第一行到rowCount行的总高度(即从第1行到rowCount行的高度之和,单位为点),用totalHeight示。e.将源工作表的已用区域复制到目标工作表(当前行currentRow,第一列)。f.复制源工作表中的所有图片到目标工作表,并调整图片的位置:新Top=目标工作表中第currentRow行的顶部位置+图片在源工作表中的Top。注意:实际上,图片在源工作表中的Top是相对于源工作表第一行顶部的偏移。而目标工作表中第currentRow行的顶部位置可以用`Worksheets("目标工作表").Rows(currentRow).Top`来获取。g.更新当前行号:currentRow=currentRow+rowCount+1(+1是留一个空行作为分隔)h.关闭源文件。但是,直接使用`Worksheets("目标工作表").Rows(currentRow).Top`获取的是第currentRow行顶部到工作表顶部的距离(以点为单位)。而我们在复制数据时,是将源工作表的区域复制到了目标工作表的第currentRow行,那么目标工作表的第currentRow行开始的行高应该是和源工作表相同的(因为复制了行高?)。但实际上,我们复制的是整个区域,包括行高。所以目标工作表中的行高已经复制过来了,那么图片相对于目标工作表顶部的偏移量应该是:目标工作表中第currentRow行的顶部位置+源图片的Top。因此,我们可以这样复制图片:代码示例:```vbaSubMergeExcelFilesWithPictures()DimtargetSheetAsWorksheetSettargetSheet=ThisWorkbook.Worksheets("Sheet1")'设置目标工作表targetSheet.Cells.Clear'清空目标工作表(可选)DimfolderPathAsStringfolderPath="C:\Your\Folder\Path\"'设置包含文件文件夹路径DimfileNameAsStringfileName=Dir(folderPath&"*.xls*")'获取第一个Excel文件DimcurrentRowAsLongcurrentRow=1'目标工作表起始行DimsourceWorkbookAsWorkbookDimsourceSheetAsWorksheetDimsourceRangeAsRangeDimpictureAsShapeDimtargetTopAsDoubleDimrowCountAsLongApplication.ScreenUpdating=FalseDoWhilefileName<>""SetsourceWorkbook=Workbooks.Open(folderPath&fileName)SetsourceSheet=sourceWorkbook.Worksheets(1)'假设每个文件只处理第一个工作表'获取源工作表已用区域的行数rowCount=sourceSheet.UsedRange.Rows.CountIfrowCount=0ThenrowCount=1'避免没有数据时出错'计算目标工作表当前行顶部的位置(点)targetTop=targetSheet.Rows(currentRow).Top'复制源工作表的已用区域到目标工作表sourceSheet.UsedRange.CopytargetSheet.Cells(currentRow,1).PasteSpecialxlPasteAll'包括值和格式,但注意:这样粘贴也会粘贴列宽,但是不会复制行高(行高需要另外复制)'另外,如果源区域中有合并单元格,这样粘贴可能会破坏目标工作表的布局'为了保持行高,我们复制行高DimiAsLongFori=1TorowCounttargetSheet.Rows(currentRow+i-1).RowHeight=sourceSheet.Rows(i).RowHeightNexti'复制图片ForEachpictureInsourceSheet.Shapespicture.CopytargetSheet.PasteWithtargetSheet.Shapes(targetSheet.Shapes.Count).Top=targetTop+picture.Top.Left=picture.Left'注意:如果图片跨行,则以上调整仅根据当前行顶部位置加上原图片相对于源工作表顶部的偏移,这样能保证图片在目标工作表的相对位置不变EndWithNextpicture'更新当前行(包括数据行和额外的分隔行)currentRow=currentRow+rowCount+1sourceWorkbook.CloseSaveChanges:=FalsefileName=Dir'获取下一个文件LoopApplication.ScreenUpdating=TrueMsgBox"合并完成!"EndSub```注意:此代码可能存在以下问题:1.当源工作表中存在多个图片时,复制图片的顺序可能影响布局(通常不会)。2.复制区域时,如果源工作表的已用区域包括多个行和列,但可能不连续,这会影响UsedRange的范围。3.粘贴操作可能会覆盖目标工作表的格式。另外,如果复制区域很大,可能会占用大量内存和时间。4.图片的位置调整是相对于目标工作表当前行的顶部。但是,如果源工作表中图片的位置超出了已用区域的范围,那么它在目标工作表中也会被复制到相同偏移的位置(可能会超出目标工作表的当前区域)。此外,我们复制行高是为了保持行的高度和源工作表一致,这样图片在行内能保持相对位置。但注意,如果源工作表中行高不一致,则我们逐行复制行高。另一个潜在问题:在粘贴图片时,我们使用`targetSheet.Paste`,这会将图片粘贴到目标工作表的中心位置,然后我们立即调整其位置。但注意,这样可能会在调整位置前发生屏幕闪烁(虽然已经设置了ScreenUpdating=False,但VBA在执行粘贴时可能会短暂更新屏幕)。改进:我们可以先获取目标工作表当前所有图片的计数,然后粘贴图片,再找到新粘贴的图片(即从旧计数+1到当前计数的所有图片),然后调整位置。不过,在循环中复制和粘贴,每次只复制一个图片,并且立即调整位置,可以保证新粘贴的图片就是最后一张。但是,还有一个问题:如果图片在源工作表中是锚定在某个单元格,当目标工作表中对应行的行高发生变化时,图片位置可能不会自动调整。所以,我们这直接设置图片的Top和Left,将其固定位置。因此,此方法适用于行高在目标工作表中与源工作表保持一致的情况。注意:如果源文件中有很多图片,此操作可能会很慢。最后,由于每个文件之间我们增加了一个空行(+1),这会使不同文件的数据分开。如果不想要空行,可以去掉加1。但是,请注意:在复制每个文件的数据时,我们是连续复制,所以文件之间不会重叠。但为了区分,加一个空行是比较好的。另外,如果希望图片跟随单元格移动,我们可以尝试在粘贴时使用更高级的方式(如锚定),但是VBA中并没有直接的方法将图片锚定到单元格,我们只能通过设置图片的Top和Left来模拟。最后提醒:请在实际使用前备份数据,避免数据丢失。参考文献:[^1]使用VBA合并多个Excel文件Sheet页。[^2]vba批量合并指定的sheet_用VBA实现多个Excel文件合并一个Excel文件多个工作表Sheet...[^3]多个独立的excel文件合并一个excel文件多个工作表Sheet中。</think> ### 通过VBA宏将多个包含图片的Excel文件合并到单个工作表的方法 以下是一个完整的VBA解决方案,可以将多个Excel文件的内容(包括图片)合并到目标工作簿的单个工作表中: ```vba Sub MergeFilesWithPictures() Dim TargetSheet As Worksheet Dim SourceWorkbook As Workbook Dim SourceSheet As Worksheet Dim FolderPath As String Dim FileName As String Dim Pic As Shape Dim CurrentRow As Long Dim TotalRows As Long ' 设置目标工作表和起始位置 Set TargetSheet = ThisWorkbook.Worksheets("合并结果") ' 目标工作表名称 Application.ScreenUpdating = False TargetSheet.Cells.Clear CurrentRow = 1 ' 选择源文件所在的文件夹 With Application.FileDialog(msoFileDialogFolderPicker) .Title = "选择包含Excel文件文件夹" If .Show <> -1 Then Exit Sub FolderPath = .SelectedItems(1) & "\" End With ' 获取文件夹中的所有Excel文件 FileName = Dir(FolderPath & "*.xls*") Do While FileName <> "" ' 打开源文件 Set SourceWorkbook = Workbooks.Open(FolderPath & FileName) Set SourceSheet = SourceWorkbook.Worksheets(1) ' 处理每个文件的第一个工作表 ' 获取数据区域的行数 TotalRows = SourceSheet.UsedRange.Rows.Count ' 复制数据区域(保留格式) SourceSheet.UsedRange.Copy TargetSheet.Cells(CurrentRow, 1).PasteSpecial xlPasteValuesAndNumberFormats TargetSheet.Cells(CurrentRow, 1).PasteSpecial xlPasteFormats ' 复制图片 For Each Pic In SourceSheet.Shapes Pic.Copy TargetSheet.Paste Destination:=TargetSheet.Cells(CurrentRow, 1) With TargetSheet.Shapes(TargetSheet.Shapes.Count) ' 调整图片位置(基于单元格) .Top = TargetSheet.Cells(CurrentRow, 1).Top .Left = TargetSheet.Cells(CurrentRow, 1).Left ' 可选:设置图片随单元格移动和调整大小 .Placement = xlMoveAndSize End With Next Pic ' 更新目标工作表的行位置 CurrentRow = CurrentRow + TotalRows + 2 ' 数据行+空行分隔 ' 关闭源文件 SourceWorkbook.Close SaveChanges:=False FileName = Dir() Loop Application.ScreenUpdating = True MsgBox "成功合并了 " & ThisWorkbook.Sheets(1).Shapes.Count & " 张图片和所有数据!" End Sub ``` ### 关键功能说明 1. **图片处理技术**: - 使用 `Shapes` 集合遍历所有图片对象 - 通过 `.Copy` 和 `.Paste` 方法复制图片 - 设置 `Placement = xlMoveAndSize` 使图片随单元格移动和调整大小[^1] - 精确计算图片位置:`.Top = Cells(CurrentRow, 1).Top` 2. **数据合并流程**: - 使用 `UsedRange` 自动检测数据区域 - 通过 `xlPasteValuesAndNumberFormats` 保留数值和格式 - 添加行间隔 (+2) 分隔不同文件的数据 3. **用户友好设计**: - 文件夹选择对话框 (FileDialog) - 进度反馈和结果统计 - 屏幕更新控制提高性能 ### 使用步骤 1. 创建一个新工作簿,将目标工作表命名为"合并结果" 2. 按 `Alt+F11` 打开VBA编辑器 3. 插入新模块并粘贴上述代码 4. 运行宏并选择包含要合并文件文件夹 5. 查看合并结果,包含所有数据和图片 > **注意事项**: > - 图片位置基于A列单元格定位,可根据需要调整 > - 大型文件处理时建议关闭其他应用程序 > - 确保目标工作簿有足够的行容纳所有数据[^2] ### 进阶优化技巧 1. **图片尺寸控制**: ```vba ' 在复制图片后添加 With TargetSheet.Shapes(TargetSheet.Shapes.Count) .Height = Pic.Height ' 保持原始高度 .Width = Pic.Width ' 保持原始宽度 End With ``` 2. **错误处理**: ```vba On Error Resume Next ' 跳过错误文件 Set SourceWorkbook = Workbooks.Open(FileName) If SourceWorkbook Is Nothing Then Debug.Print "无法打开: " & FileName GoTo NextFile End If ``` 3. **性能优化**: ```vba Application.Calculation = xlCalculationManual ' 手动计算 Application.EnableEvents = False ' 禁用事件 ' ...合并过程... Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值