我是Excel中的新手,我需要创建一个宏来从所选工作簿中的多个工作表中获取数据。
到目前为止,我有这段代码来选择一个文件并从表1中获取数据,但我希望它能够从所选文件中的所有工作表中获取信息。
Sub MergeSelectedWorkbooks()
Dim SummarySheet As Worksheet
Dim FolderPath As String
Dim SelectedFiles() As Variant
Dim NRow As Long
Dim FileName As String
Dim NFile As Long
Dim WorkBk As Workbook
Dim SourceRange As Range
Dim DestRange As Range
' Create a new workbook and set a variable to the first sheet.
Set SummarySheet = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
' Modify this folder path to point to the files you want to use.
FolderPath = "C:\Users\My\Desktop\Path"
' Set the current directory to the the folder path.
ChDrive FolderPath
ChDir FolderPath
' Open the file dialog box and filter on Excel files, allowing multiple files
' to be selected.
SelectedFiles = Application.GetOpenFilename( _
filefilter:="Excel Files (*.xl*), *.xl*", MultiSelect:=True)
' NRow keeps track of where to insert new rows in the destination workbook.
NRow = 1
' Loop through the list of returned file names
For NFile = LBound(SelectedFiles) To UBound(SelectedFiles)
' Set FileName to be the current workbook file name to open.
FileName = SelectedFiles(NFile)
' Open the current workbook.
Set WorkBk = Workbooks.Open(FileName)
' Set the source range to be A9 through C9.
' Modify this range for your workbooks. It can span multiple rows.
Set SourceRange = WorkBk.Worksheets(1).Range("A1:G5")
' Set the destination range to start at column B and be the same size as the source range.
Set DestRange = SummarySheet.Range("A" & NRow)
Set DestRange = DestRange.Resize(SourceRange.Rows.Count, _
SourceRange.Columns.Count)
' Copy over the values from the source to the destination.
DestRange.Value = SourceRange.Value
' Increase NRow so that we know where to copy data next.
NRow = NRow + DestRange.Rows.Count
' Close the source workbook without saving changes.
WorkBk.Close savechanges:=False
Next NFile
' Call AutoFit on the destination sheet so that all data is readable.
SummarySheet.Columns.AutoFit
End Sub
答案 0 :(得分:3)
要使用Excel Automation执行此操作,请首先使用概述here概述的技术定义以下函数,该函数将获取工作表中最后使用的单元格:
Function LastUsedCell(wks As Excel.Worksheet) As Excel.Range
With wks
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
Set LastUsedCell = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
End If
End With
End Function
和这个辅助函数,用于确定从每个工作表开始复制数据的位置:
Function GetNextRowStart(wks As Excel.Worksheet) As Excel.Range
Dim lastCell As Excel.Range
Dim nextRow As Integer
nextRow = 1
Set lastCell = LastUsedCell(wks)
If Not lastCell Is Nothing Then nextRow = lastCell.Row + 1
Set GetNextRowStart = wks.Cells(nextRow, 1)
End Function
然后您可以使用以下代码:
Dim outputWorkbook As Excel.Workbook
Dim outputWorksheet As Excel.Worksheet
Dim filepath As Variant
Set outputWorkbook = Workbooks.Open("D:\Zev\Clients\stackoverflow\outputMultipleWokrbooksWithADO\output.xlsx")
Set outputWorksheet = outputWorkbook.Sheets("Sheet1")
For Each filepath In Application.GetOpenFilename(FileFilter:="Excel Files (*.xl*), *.xl*", MultiSelect:=True)
Dim wkbk As Excel.Workbook
Dim wks As Excel.Worksheet
Set wkbk = Workbooks.Open(filepath, , True)
For Each wks In wkbk.Sheets
Dim sourceRange As Excel.Range
Dim outputRange As Excel.Range
With wks
Set sourceRange = .Range(.Cells(1, 1), LastUsedCell(wks))
End With
Set outputRange = GetNextRowStart(outputWorksheet)
sourceRange.Copy outputRange
Next
Next
outputWorksheet.Columns.AutoFit
之前的方法使用Excel自动化 - 打开工作簿,获取工作表,操作源和输出工作表上的范围。
您还可以使用ADODB读取Excel工作表,就好像工作簿是数据库而工作表是其表格一样;然后发出INSERT INTO
语句将原始记录复制到输出工作簿。它具有以下优点:
Value
对象的Range
属性,该对象返回一个二维数组。这可以很容易地分配/粘贴到任何需要这样一个数组的东西,包括Value
属性本身。但是,它受到以下限制:
INSERT INTO
要求源和目标具有相同数量的字段,具有相同的数据类型。 (在这种情况下,可以修改SQL以插入到不同的目标字段集或顺序,并使用不同的源字段)。INSERT INTO
。.xls
输入和输出,没有.xlsx
。'Sheet1$'
,将'Sheet1$'FilterDatabase
(或Sheet1$_
时使用Jet提供商)。向 Microsoft ActiveX数据对象添加引用(工具 - &gt; 引用... )。 (选择最新版本;通常为6.1)。
输出工作簿和工作表应该存在。此外,在运行此代码时,应关闭输入和输出工作簿。
Dim filepath As Variant
Dim outputFilePath As String
Dim outputSheetName As String
'To which file and sheet within the file should the output go?
outputFilePath = "c:\path\to\ouput.xls"
outputSheetName = "Sheet1"
For Each filepath In Application.GetOpenFilename(FileFilter:="Excel Files (*.xl*), *.xl*", MultiSelect:=True)
Dim conn As New ADODB.Connection
Dim schema As ADODB.Recordset
Dim sql As String
Dim sheetname As Variant
With conn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=""" & filepath & """;" & _
"Extended Properties=""Excel 12.0;HDR=No"""
'To use the old Microsoft Jet provider:
'.Provider = "Microsoft.Jet.OLEDB.4.0"
'.ConnectionString = "Data Source=""" & filepath & """;" & _
' "Extended Properties=""Excel 8.0;HDR=No"""
.Open
End With
Set schema = conn.OpenSchema(adSchemaTables)
For Each sheetname In schema.GetRows(, , "TABLE_NAME") 'returns a 2D array of one column
'This appends the data into an existing worksheet
sql = _
"INSERT INTO [" & outputSheetName & "$] " & _
"IN """ & outputFilePath & """ ""Excel 12.0;"" " & _
"SELECT * " & _
"FROM [" & sheetname & "]"
'To create a new worksheet, use SELECT..INTO:
'sql = _
' "SELECT * " & _
' "INTO [" & outputSheetName & "$] " & _
' "IN """ & outputFilePath & """ ""Excel 12.0;"" " & _
' "FROM [" & sheetname & "]"
conn.Execute sql
Next
Next
Dim wbk As Workbook
Set wbk = Workbooks.Open(outputFilePath)
wbk.Worksheets(outputSheetName).Coluns.AutoFit
另一种方法是使用ADODB将数据读入记录集,然后使用CopyFromRecordset方法将其粘贴到输出工作簿中:
Dim filepath As Variant
Dim outputFilePath As String
Dim outputSheetName As String
Dim sql As String
Dim wbk As Workbook, wks As Worksheet
Dim rng As Excel.Range
Dim sheetname As Variant
'To which file and sheet within the file should the output go?
outputFilePath = "c:\path\to\ouput.xlsx"
outputSheetName = "Sheet1"
For Each filepath In Application.GetOpenFilename(FileFilter:="Excel Files (*.xl*), *.xl*", MultiSelect:=True)
Set schema = conn.OpenSchema(adSchemaTables)
For Each sheetname In schema.GetRows(, , "TABLE_NAME") 'returns a 2D array of one column
sql = sql & _
"UNION ALL SELECT F1 " & _
"FROM [" & sheetname & "]" & _
"IN """ & filepath & """ ""Excel 12.0;"""
Next
Next
sql = Mid(sql, 5) 'Gets rid of the UNION ALL from the first SQL
Dim conn As New ADODB.Connection
Dim rs As ADODB.Recordset
With conn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=""" & filepath & """;" & _
"Extended Properties=""Excel 12.0;HDR=No"""
.Open
Set rs = .Execute(sql)
Set wbk = Workbooks.Open(outputFilePath, , True)
Set wks = wbk.Sheets(outputSheetName)
wks.Cells(2, 1).CopyFromRecordset rs
wks.Columns.AutoFill
.Close
End With
Jet SQL:
ADO:
另请参阅this回答,这是做类似的事情。
答案 1 :(得分:1)
你可以试试这个: https://msdn.microsoft.com/en-us/library/office/gg549168(v=office.14).aspx 我不知道它是否有帮助。