根据工作表标题列表复制并保存工作表(如果存在)

问题描述 投票:0回答:2

我的组织发布了 Excel 格式的每周报告,其中包含 60 多个工作表,每个工作表的标题都有一个活动缩写。目前,我手动将特定工作表复制到新工作簿中。

发现的 VBA 解决方案似乎需要数组中预定义的工作表名称。这在我的情况下不起作用,因为当没有活动时,标题为活动代码的工作表不包含在工作簿中。

我正在寻求:

  • 根据名称中的特定活动代码识别工作表(我有完整的列表)
  • 当工作表不在工作簿中时跳过名称
  • 将识别的工作表复制并保存到新工作簿中 理想情况下,最终用户会选择保存新工作簿的目的地,而不是自动保存在原始工作簿的路径中。

我合并了在网上找到的多个代码。

在测试中,我使用了三个工作表名称。真正的运行会拉 20。标题为“BBA”和“BBB”的工作表在工作簿中,而“BBV”不在工作簿中。我愿意走不同的方向,因为我确信有一种更干净的方法。

Sub TwoSheetsAndYourOut()
    Dim NewName As String
    Dim nm As Name
    Dim ws As Worksheet
    Dim MyArr, j As Long
     
    If MsgBox("Copy specific sheets to a new workbook" & vbCr & _
      "New sheets will be pasted as values, named ranges removed" _
      , vbYesNo, "NewCopy") = vbNo Then Exit Sub
     
    Application.ScreenUpdating = False
         
    '       Copy specific sheets
    '       *SET THE SHEET NAMES TO COPY BELOW*
    '       Array("Sheet Name", "Another sheet name", "And Another"))
    '       Sheet names go inside quotes, seperated by commas
    On Error GoTo ErrCatcher
    MyArr = Array("BBA", "BBV", "BBB")

    For j = 0 To UBound(MyArr)
        Set ws = Nothing

        On Error Resume Next
        Set ws = Worksheets(MyArr(j))
        On Error GoTo 0

        If Not ws Is Nothing Then
        'Your copying code goes here

        '       Paste sheets as values
        '       Remove External Links, Hperlinks and hard-code formulas
        '       Make sure A1 is selected on all sheets
            ws.Select
            ws.Cells.Copy
            ws.[A1].PasteSpecial Paste:=xlValues
            ws.Cells.Hyperlinks.Delete
            Application.CutCopyMode = False
            Cells(1, 1).Select
            ws.Activate
        End If
    Next
    '       Remove named ranges
    For Each nm In ActiveWorkbook.Names
        If nm.Visible Then nm.Delete
    Next nm
         
    '       Input box to name new file
    NewName = InputBox("Please Specify the name of your new workbook", "New Copy")
         
    '       Save it with the NewName and in the same directory as original
    ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & Application.PathSeparator & "myFile.xlsm", FileFormat:=52
                
    Application.ScreenUpdating = True
    Exit Sub
     
ErrCatcher:
    MsgBox "Specified sheets do not exist within this workbook"
End Sub
excel vba
2个回答
0
投票

概念上:

  • 使用 For-Next 循环遍历工作簿中的所有工作表
  • 将每个工作表名称与关键字列表进行比较
  • 当工作表名称满足条件时,执行复制

此网站和其他网站上有许多代码示例,介绍如何循环工作簿中的所有工作表、如何在另一个字符串中查找字符串以及如何在工作簿之间复制工作表。


0
投票

将指定工作表导出到新工作簿

Sub ExportSheetsByActivityCodes()
    Const PROC_TITLE As String = "Export Sheets By Activity Codes"
    Dim dwb As Workbook ' to be closed if error
    Dim WasSuccess As Boolean
    On Error GoTo ClearError ' start error-handling routine
    
    ' Define constants.
    
    Const DST_FILE_BASE_NAME As String = "New File"
    ' The following two constants have to be in 'sync'.
    Const DST_FILE_EXTENSION As String = ".xlsm"
    Const DST_FILE_FORMAT As Long = xlOpenXMLWorkbookMacroEnabled
    Const DST_FILE_FILTER_LEFT As String = "Excel macro-enabled files"
    Const ORDER_BY_WORKSHEET_POSITION As Boolean = False
    
    Dim ActivityCodes() As Variant: ActivityCodes = VBA.Array( _
        "BBA", "BBV", "BBB") ' add more
     
    ' Ask to proceed.
     
    ' Return the values of the array in a delimited string (for the messages).
    Dim ActivityCodesList As String:
    ActivityCodesList = Join(ActivityCodes, ", ")
     
    If MsgBox("Do you want to copy the worksheets named after activity " _
        & "codes """ & ActivityCodesList & """ to a new workbook?" _
        & vbLf & "The worksheets in the new workbook will be without " _
        & "formulas and hyperlinks, and named ranges will be removed!", _
        vbYesNo + vbQuestion, PROC_TITLE) = vbNo Then GoTo ProcExit
     
    ' Return the names of the worksheets to be exported in a 1D one-based array.
    
    Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
     
    ' Define an array of the size of the number of activity codes.
    Dim dwsMax As Long: dwsMax = UBound(ActivityCodes) + 1
    Dim dwsNames() As Variant: ReDim dwsNames(1 To dwsMax)
     
    Dim sws As Worksheet, dwsCount As Long, n As Long
    
    If ORDER_BY_WORKSHEET_POSITION Then
        For Each sws In swb.Worksheets
            If IsNumeric(Application.Match(sws.Name, ActivityCodes, 0)) Then
                dwsCount = dwsCount + 1
                dwsNames(dwsCount) = sws.Name
            End If
            If dwsCount = dwsMax Then Exit For ' all found
        Next sws
    Else ' order by activity code
        For n = 1 To dwsMax
            On Error Resume Next ' defer error handling (sheet doesn't exist)
                Set sws = swb.Worksheets(ActivityCodes(n - 1))
            On Error GoTo ClearError ' restart error-handling routine
            If Not sws Is Nothing Then
                dwsCount = dwsCount + 1
                dwsNames(dwsCount) = sws.Name
                Set sws = Nothing ' reset for the next iteration
            End If
        Next n
    End If
    
    If dwsCount = 0 Then
        MsgBox "No worksheets named after activities """ & ActivityCodesList _
            & """ found!", vbExclamation, PROC_TITLE
        GoTo ProcExit
    End If
    
    If dwsCount < dwsMax Then ReDim Preserve dwsNames(1 To dwsCount)
    
    ' Copy the worksheets whose names are in the array to a new workbook
    ' and reference this workbook.
    ' Note that when copying multiple sheets to a new workbook,
    ' the order of the sheets is always the same as their order
    ' in the source workbook (no matter their order in the array).
    ' Note that this will fail if there is no visible worksheet,
    ' and very hidden worksheets will not be copied.
    swb.Sheets(dwsNames).Copy
    Set dwb = Workbooks(Workbooks.Count)
    
    ' Process the destination workbook.
    
    Dim dws As Worksheet, nm As Name
    
    ' Process worksheets.
    For Each dws In dwb.Worksheets
        With dws.UsedRange
            .Hyperlinks.Delete ' delete hyperlinks
            .Value = .Value ' formulas to values
            Application.Goto Reference:=.Cells(1), Scroll:=True
        End With
    Next dws
    
    ' Process workbook.
    For Each nm In dwb.Names
        If nm.Visible Then nm.Delete '???
    Next nm
    
    ' Move sheets to correct positions when ordering by activity code required.
    If Not ORDER_BY_WORKSHEET_POSITION And dwsCount > 1 Then
        For n = 1 To dwsCount
            dwb.Sheets(dwsNames(n)).Move After:=dwb.Sheets(dwsCount)
        Next n
    End If
    
    ' Let the user choose the location and name of the destination file.
    
    Dim dFileFilter As String:
    dFileFilter = DST_FILE_FILTER_LEFT & ",*" & DST_FILE_EXTENSION
    
    Dim dFilePath As Variant: dFilePath = Application.GetSaveAsFilename( _
        InitialFileName:=swb.Path & Application.PathSeparator & _
            DST_FILE_BASE_NAME, _
        FileFilter:=dFileFilter, _
        Title:=PROC_TITLE)
    
    If dFilePath = False Then
        MsgBox "File save canceled.", vbExclamation, PROC_TITLE
        GoTo ProcExit
    End If
    
    ' Prevent error if file (or file with same name) is open
    ' Note that the error-handling routine could cover this instead!
    ' Note that you cannot change the given file extension.
    
    Dim dFileName As String: dFileName = Right(dFilePath, _
        Len(dFilePath) - InStrRev(dFilePath, Application.PathSeparator))
    
    Dim cwb As Workbook
    
    On Error Resume Next ' defer error handling (file (workbook) exists)
        Set cwb = Workbooks(dFileName)
    On Error GoTo ClearError ' restart error-handling routine
    
    If Not cwb Is Nothing Then
        If StrComp(dFilePath, cwb.FullName, vbTextCompare) = 0 Then
            MsgBox "The destination file """ & cwb.FullName & """ is open!", _
                vbExclamation, PROC_TITLE
        Else
            MsgBox "Another file """ & cwb.FullName _
                & """ with the same name is open!", vbExclamation, PROC_TITLE
        End If
        GoTo ProcExit
    End If
        
    ' Save and close.
        
    Application.DisplayAlerts = False ' overwrite without confirmation
        dwb.SaveAs Filename:=dFilePath, FileFormat:=DST_FILE_FORMAT
    Application.DisplayAlerts = False
    dwb.Close SaveChanges:=False ' just got saved
                
    Application.ScreenUpdating = True
    
    WasSuccess = True
    
    ' Inform.
    
    MsgBox "The following " & IIf(dwsCount <> 1, dwsCount & " ", "") _
        & "sheet" & IIf(dwsCount = 1, " was", "s were") & " exported to """ _
        & dFilePath & """:" & vbLf & vbLf & Join(dwsNames, vbLf), _
        vbInformation, PROC_TITLE
    
ProcExit:
    On Error Resume Next ' prevent endless loop if error in continuation
        If Not WasSuccess Then
            If Not dwb Is Nothing Then dwb.Close SaveChanges:=False
        End If
    On Error GoTo 0
    Exit Sub
ClearError: ' continue error-handling routine (e.g. invalid file name)
    MsgBox "Run-time error '" & Err.Number & "':" & vbLf & vbLf _
        & Err.Description, vbCritical, PROC_TITLE
    Resume ProcExit
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.