英文:
How to move and copy multiple sheets into a single workbooks
问题
我正在尝试使用VBA将一组工作表复制到新工作簿中。但是,一组中的工作表数量可以根据某个条件而变化。
例如:35100001-1、35100001-2、35100001-3是一个工作簿中的工作表名称。
现在我想要复制工作表,其工作表名称与这些相同的字符,并将它们放入一个新的Excel工作簿中,所以在这里我希望有一个包含这些工作表的新Excel工作簿:
35100001工作簿
- 35100001-1 35100001-2 35100001-3工作表
35100002工作簿
- 35100002-1 35100002-2 35100002-3工作表
35100003工作簿
- 35100003-1 35100003-2 35100003-3 35100003-4工作表
35100004工作簿
- 35100004-1 35100004-2工作表
我正在尝试使用VBA将一组工作表复制到新工作簿中。但是,一组中的工作表数量可以根据某个条件而变化。
感谢帮助,我真的很感激。
英文:
I'm trying to copy and groups of sheets to a new workbook using VBA.
But the number of sheets in a group can change depending on a criterion.
For example: 35100001-1, 35100001-2, 35100001-3 are sheet names in one workbook.
Now I want to copy sheets with sheet name having the character same these into a single workbook , so here I want a new excel workbook containing these sheets:
35100001 workbook
- 35100001-1 35100001-2 35100001-3 worksheets
35100002 workbook
- 35100002-1 35100002-2 35100002-3 worksheets
35100003 workbook
- 35100003-1 35100003-2 35100003-3 35100003-4 worksheets
35100004 workbook
- 35100004-1 35100004-2 worksheets
I'm trying to copy and groups of sheets to a new workbook using VBA.
But the number of sheets in a group can change depending on a criterion.
thanks for the help, i really appreciate it.
答案1
得分: 1
以下是您要翻译的代码部分:
Sub ExportSheets()
' Define constants.
Const DELIMITER As String = "-"
' Reference the workbook.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' In each 'key' of a dictionary, return a unique workbook name while
' adding each associated sheet name to a 'key' of another dictionary held
' in the associated 'item' of the initial dictionary.
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim sh As Object, DelPos As Long, wbName As String, shName As String
For Each sh In wb.Sheets
' Prevent 'mayhem' if the only sheet of a group is hidden or very hidden
' i.e. very hidden sheets will never get copied but either won't
' raise an error if at least one of the sheets is visible.
' To simplify, exclude both.
If sh.Visible = xlSheetVisible Then
shName = sh.Name
DelPos = InStr(shName, DELIMITER)
' Prevent error if the sheet name starts with the delimiter.
If DelPos > 1 Then
wbName = Left(shName, DelPos - 1)
If Not dict.Exists(wbName) Then
Set dict(wbName) = CreateObject("Scripting.Dictionary")
End If
dict(wbName)(shName) = Empty
End If
End If
Next sh
If dict.Count = 0 Then
MsgBox "No sheets found.", vbCritical
Exit Sub
End If
' Define the path: use the same path as the workbook (modify as required).
Dim wbPath As String: wbPath = wb.Path
' Using the 'keys' (the workbook names) and the 'items'
' (the 1D arrays of sheet names ('keys')), export each group of sheets
' to a new workbook, then save and close the workbook.
Application.ScreenUpdating = False
Dim Key, FilePath As String
For Each Key In dict.Keys
wb.Sheets(dict(Key).Keys).Copy ' return the sheets in a new workbook
With Workbooks(Workbooks.Count) ' reference this new workbook
' The following is all you need to save as a '.xlsx' file
' i.e. you don't need to specify the file extension.
FilePath = wbPath & Application.PathSeparator & Key
Application.DisplayAlerts = False ' overwrite without confirmation
.SaveAs FilePath
Application.DisplayAlerts = True
.Close SaveChanges:=False
End With
Next Key
Application.ScreenUpdating = True
' Inform.
MsgBox "Sheets exported.", vbInformation
End Sub
请注意,这是代码的翻译部分。如果您需要更多帮助或其他内容的翻译,请随时告诉我。
英文:
Export Groups of Sheets to New Workbooks
<!-- language: lang-vb -->
Sub ExportSheets()
' Define constants.
Const DELIMITER As String = "-"
' Reference the workbook.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' In each 'key' of a dictionary, return a unique workbook name while
' adding each associated sheet name to a 'key' of another dictionary held
' in the associated 'item' of the initial dictionary.
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim sh As Object, DelPos As Long, wbName As String, shName As String
For Each sh In wb.Sheets
' Prevent 'mayhem' if the only sheet of a group is hidden or very hidden
' i.e. very hidden sheets will never get copied but either won't
' raise an error if at least one of the sheets is visible.
' To simplify, exlude both.
If sh.Visible = xlSheetVisible Then
shName = sh.Name
DelPos = InStr(shName, DELIMITER)
' Prevent error if the sheet name starts with the delimiter.
If DelPos > 1 Then
wbName = Left(shName, DelPos - 1)
If Not dict.Exists(wbName) Then
Set dict(wbName) = CreateObject("Scripting.Dictionary")
End If
dict(wbName)(shName) = Empty
End If
End If
Next sh
If dict.Count = 0 Then
MsgBox "No sheets found.", vbCritical
Exit Sub
End If
' Define the path: use the same path as the workbook (modify as required).
Dim wbPath As String: wbPath = wb.Path
' Using the 'keys' (the workbook names) and the 'items'
' (the 1D arrays of sheet names ('keys')), export each group of sheets
' to a new workbook, then save and close the workbook.
Application.ScreenUpdating = False
Dim Key, FilePath As String
For Each Key In dict.Keys
wb.Sheets(dict(Key).Keys).Copy ' return the sheets in a new workbook
With Workbooks(Workbooks.Count) ' reference this new workbook
' The following is all you need to save as a '.xlsx' file
' i.e. you don't need to specify the file extension.
FilePath = wbPath & Application.PathSeparator & Key
Application.DisplayAlerts = False ' overwrite without confirmation
.SaveAs FilePath
Application.DisplayAlerts = True
.Close SaveChanges:=False
End With
Next Key
Application.ScreenUpdating = True
' Inform.
MsgBox "Sheets exported.", vbInformation
End Sub
答案2
得分: 0
这里是一个完整的示例代码。
原则:
- 计算我需要的所有工作簿的名称
- 创建这些工作簿
- 逐个遍历工作簿中的每个工作表并复制到其新位置
- 保存并关闭所有打开的工作簿
Option Explicit
Sub demo()
Dim ws As Worksheet, colSheets As Collection, wbName As String
Set colSheets = New Collection
'首先计算要创建的其他工作簿的名称
For Each ws In ThisWorkbook.Sheets
wbName = Left(ws.Name, InStr(ws.Name, "-") - 1)
On Error Resume Next '强制循环忽略重复的键
colSheets.Add wbName, wbName
On Error GoTo 0 '重置错误处理
Next
'现在创建这些工作簿 - 并保存在与当前工作簿相同的文件夹中
Dim x As Variant, wb As Workbook
For Each x In colSheets
Set wb = Workbooks.Add(1) '强制工作簿只有1个工作表
'关闭警告,以防这是重新运行
Application.DisplayAlerts = False
wb.SaveAs Filename:=ThisWorkbook.Path & "\" & x
Application.DisplayAlerts = True
Next
'现在只需将每个工作表复制到其相关的新位置
For Each ws In ThisWorkbook.Sheets
wbName = Left(ws.Name, InStr(ws.Name, "-") - 1) & ".xlsx"
ws.Copy After:=Workbooks(wbName).Sheets(Workbooks(wbName).Sheets.Count)
Next
'整理新工作簿
For Each x In colSheets
Set wb = Workbooks(x & ".xlsx")
Application.DisplayAlerts = False
wb.Sheets("Sheet1").Delete
Application.DisplayAlerts = True
wb.Close SaveChanges:=True
Next
End Sub
还有很多改进的空间 - 例如错误处理、跳过任何已知不想复制的工作表等等。
英文:
Here is a complete worked example.
Principle:
-
Work out the names of all the workbooks I will need
-
Create those workbooks
-
Step through every sheet in the workbook and copy to its new home
-
Save and close all the open workbooks
Option Explicit
Sub demo()
Dim ws As Worksheet, colSheets As Collection, wbName As String Set colSheets = New Collection 'First work out the names of other workbooks to create For Each ws In ThisWorkbook.Sheets wbName = Left(ws.Name, InStr(ws.Name, "-") - 1) On Error Resume Next 'force the loop to ignore duplicate keys colSheets.Add wbName, wbName On Error GoTo 0 'reset error handling Next 'Now go create those workbooks - and save in same folder as current workbook Dim x As Variant, wb As Workbook For Each x In colSheets Set wb = Workbooks.Add(1) 'forces the workbook to only have 1 sheet 'Turn off warnings in case this is a re-run Application.DisplayAlerts = False wb.SaveAs Filename:=ThisWorkbook.Path & "\" & x Application.DisplayAlerts = True Next 'Now just copy each sheet to it's relevant new home For Each ws In ThisWorkbook.Sheets wbName = Left(ws.Name, InStr(ws.Name, "-") - 1) & ".xlsx" ws.Copy After:=Workbooks(wbName).Sheets(Workbooks(wbName).Sheets.Count) Next 'Tidy up the new workbooks For Each x In colSheets Set wb = Workbooks(x & ".xlsx") Application.DisplayAlerts = False wb.Sheets("Sheet1").Delete Application.DisplayAlerts = True wb.Close SaveChanges:=True Next
End Sub
Plenty of room for improvement - e.g. error handling, skip any known sheets that you don't want to copy etc., etc.
答案3
得分: 0
由于您没有提供更多详细信息,无论您是要完全自动执行过程,还是要手动运行宏以查找特定工作表名称,或者您如何输入要查找的所需工作表名称,我简化了代码。提供的代码是一个可工作的示例。请根据您的具体需求进行调整。
方法CopySheets要求您提供您要查找的基本工作表名称(例如35100001等),并维护复制工作表的整个过程。
它调用方法GetSheetsArray,该方法在当前工作簿中搜索符合您的条件的工作表名称,并将它们作为“Variant数组”返回。
最后,它创建一个新工作簿,将所有相关工作表复制到其中,并将该工作簿保存在与当前工作簿相同的文件夹中。工作簿的名称始终与您要查找的工作表名称相同(例如35100001等)。
Public Sub CopySheets()
'要求提供您要查找的基本工作表名称(例如35100001等)
Dim BaseSheetName As String
BaseSheetName = InputBox(Prompt:="基本工作表名称")
'包含符合您条件的工作表名称的数组。
Dim SheetsArray As Variant
SheetsArray = GetSheetsArray(BaseSheetName)
Dim wbNew As Workbook
Set wbNew = Application.Workbooks.Add
'选择并复制工作表。
With ThisWorkbook
.Worksheets(SheetsArray).Select
.Activate
ActiveWindow.SelectedSheets.Copy After:=wbNew.Worksheets(1)
End With
'删除新创建的工作簿中的默认工作表。如果有3个默认工作表,请循环删除它们。
Application.DisplayAlerts = False
wbNew.Worksheets(1).Delete
Application.DisplayAlerts = True
'将新工作簿保存在与此工作簿相同的目录中,并为其命名
'您要查找的名称。根据您的首选项调整保存路径。
wbNew.SaveAs Filename:=ThisWorkbook.Path & "\" & BaseSheetName, _
FileFormat:=XlFileFormat.xlOpenXMLWorkbook
wbNew.Close
End Sub
以下函数中的输出数组实际上并不是必需的,可以直接使用GetSheetsArray。但我更喜欢这种方式,因为如果将来函数名称更改,只需在函数末尾修改它一次,这样可以简化程序员的工作。
Private Function GetSheetsArray(ByVal LookupName As String) As Variant
'输出数组的基本初始化。
Dim Output As Variant
ReDim Output(1)
Dim i As Long: i = 0
'将所有相关工作表名称存储在数组中。
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If InStr(1, ws.Name, LookupName, vbTextCompare) > 0 Then
ReDim Preserve Output(i)
Output(i) = ws.Name
i = i + 1
End If
Next ws
GetSheetsArray = Output
Erase Output
End Function
如果您想在与当前工作簿不同的工作簿中搜索符合您条件的工作表名称,可以通过将工作簿的引用作为输入参数添加到GetSheetsArray函数中来轻松修改该函数。
Private Function GetSheetsArray(ByVal LookupName As String, _
ByVal wb As Workbook) As Variant
然后在函数体内,您必须将ThisWorkbook替换为wb。
For Each ws In wb.Worksheets
'...
Next ws
英文:
Since you didn't provide more details whether you want to have the process fully automatic or you want to run the macro manually for particular sheet names or how you put in the desired sheet name you are looking for, I made it quite simple. Provided code is a working sample. Kindly adjust it by your specific needs.
Method CopySheets asks you for base sheet name you are looking for (35100001, etc.) and maintains the whole process of copying worksheets.
It calls the method GetSheetsArray which searches for sheet names which met your criteria in current workbook and return them as Variant array
.
Finally it creates new workbook where it will copy all relevant worksheets and saves the workbook in the same folder as current workbook. Name of the workbook is always identical with the sheet name you were looking for (35100001, etc.) .
Public Sub CopySheets()
'Ask for the base sheet name you are looking for (35100001, etc.)
Dim BaseSheetName As String
BaseSheetName = InputBox(Prompt:="Base sheet name")
'Array containing sheet names which fit your criteria.
Dim SheetsArray As Variant
SheetsArray = GetSheetsArray(BaseSheetName)
Dim wbNew As Workbook
Set wbNew = Application.Workbooks.Add
'Select and copy sheets.
With ThisWorkbook
.Worksheets(SheetsArray).Select
.Activate
ActiveWindow.SelectedSheets.Copy After:=wbNew.Worksheets(1)
End With
'Delete the default sheet in newly created workbook. In case you have 3 default sheets, delete them in cycle.
Application.DisplayAlerts = False
wbNew.Worksheets(1).Delete
Application.DisplayAlerts = True
'Save new workbook in same directory as this workbook and give it a name
'you were looking for. Adjust the saving path by your preferences.
wbNew.SaveAs Filename:=ThisWorkbook.Path & "\" & BaseSheetName, _
FileFormat:=XlFileFormat.xlOpenXMLWorkbook
wbNew.Close
End Sub
The Output array in following function is not really necessary and GetSheetsArray can be used directly. But I prefer to use it this way because if function name changes in the future, it needs to be modified only at one place, at the end of the function. It makes programmer's life easier.
Private Function GetSheetsArray(ByVal LookupName As String) As Variant
'Basic initialization of output array.
Dim Output As Variant
ReDim Output(1)
Dim i As Long: i = 0
'Store all relevant sheet names in array.
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If InStr(1, ws.Name, LookupName, vbTextCompare) > 0 Then
ReDim Preserve Output(i)
Output(i) = ws.Name
i = i + 1
End If
Next ws
GetSheetsArray = Output
Erase Output
End Function
If you want to search for worksheet names which met your criteria in workbook other then current workbok, you can easily modify the GetSheetsArray function by adding the reference to a workbook as an input parameter.
Private Function GetSheetsArray(ByVal LookupName As String, _
ByVal wb As Workbook) As Variant
Then within the function body you have to replace ThisWorkbook by wb.
For Each ws In wb.Worksheets
'...
Next ws
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论