VBA 代码将工作表拆分为多个工作簿,同时还保存格式和工作表保护/锁定单元格

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

我是 VBA 新手,希望得到任何帮助。也希望这可以通过 VBA 实现。

我在模块中有一些现有代码,用于根据 A 列中的值将工作表选项卡中的数据拆分到新工作表中(见下文)。这看起来效果很好。

但是,我们还需要(1)复制工作表保护/锁定单元格并(2)复制格式(即标题颜色),以便在拆分新工作表时将其拉到新工作表中。否则,拆分功能很有帮助,但我们将手动为 50 多个工作表添加工作表保护和着色标题。

是否可以调整下面的代码以合并上面的第 1 点和第 2 点,如果可以,如何调整?

提前非常感谢。

亲切的问候

阿克斯

这是现有的代码,但我不确定如何添加上面的第 1 点和第 2 点 - 如果可能的话?


Sub SplitSheetIntoMultipleWorkbooksBasedOnColumn()
    Dim objWorksheet As Excel.Worksheet
    Dim nLastRow, nRow, nNextRow As Integer
    Dim strColumnValue As String
    Dim objDictionary As Object
    Dim varColumnValues As Variant
    Dim varColumnValue As Variant
    Dim objExcelWorkbook As Excel.Workbook
    Dim objSheet As Excel.Worksheet
    Set objWorksheet = ActiveSheet
    nLastRow = objWorksheet.Range("A" & objWorksheet.Rows.Count).End(xlUp).Row
    Set objDictionary = CreateObject("Scripting.Dictionary")
    For nRow = 2 To nLastRow
        strColumnValue = objWorksheet.Range("A" & nRow).Value
        If objDictionary.Exists(strColumnValue) = False Then
           objDictionary.Add strColumnValue, 1
        End If
    Next
    varColumnValues = objDictionary.Keys
    For i = LBound(varColumnValues) To UBound(varColumnValues)
        varColumnValue = varColumnValues(i)
        Set objExcelWorkbook = Excel.Application.Workbooks.Add
        Set objSheet = objExcelWorkbook.Sheets(1)
        objSheet.Name = objWorksheet.Name
        objWorksheet.Rows(1).EntireRow.Copy
        objSheet.Activate
        objSheet.Range("A1").Select
        objSheet.Paste
        For nRow = 2 To nLastRow
            If CStr(objWorksheet.Range("A" & nRow).Value) = CStr(varColumnValue) Then
               objWorksheet.Rows(nRow).EntireRow.Copy
               nNextRow = objSheet.Range("A" & objWorksheet.Rows.Count).End(xlUp).Row + 1
               objSheet.Range("A" & nNextRow).Select
               objSheet.Paste
               objSheet.Columns("A:F").AutoFit
            End If
        Next
    Next
End Sub
excel vba formatting spreadsheet-protection
1个回答
0
投票

将工作表导出到多个工作簿

  • 按原样运行此代码并根据消息框中的信息进行操作。如果你不明白,请随时在下面留言。
  • 只要您不将
    IS_IN_TEST_MODE
    设置为
    False
    ,即不会创建 2 个新工作簿(不保存),并且您必须手动关闭它们。
Sub SplitSheetIntoMultipleWorkbooksBasedOnColumn()
' Use something shorter and more user-friendly like 'ExportByName'.
    
    ' Define constants.
    
    Const CRITERIA_COLUMN As String = "A"
    Const DST_SUBFOLDER_NAME As String = "Items"
    ' The following two have to be 'in sync'!
    Const DST_FILE_EXTENSION As String = ".xlsx"
    Dim DST_FILE_FORMAT As XlFileFormat: DST_FILE_FORMAT = xlOpenXMLWorkbook
    Const IS_IN_TEST_MODE As Boolean = True ' Careful! There is no Undo!
    
    ' Reference the source objects.
    
    Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
    ' If it's not, use 'ActiveWorkbook' instead.
    If Len(swb.Path) = 0 Then
        MsgBox "The workbook """ & swb.Name & """ was never saved!", _
            vbExclamation
        Exit Sub
    End If
    
    Dim sws As Worksheet: Set sws = swb.ActiveSheet ' improve!
    Dim sName As String: sName = sws.Name
    Dim srg As Range: Set srg = sws.Range("A1").CurrentRegion
    
    Dim sRowsCount As Long: sRowsCount = srg.Rows.Count
    If sRowsCount < 2 Then Exit Sub ' no data
    
    Dim scrg As Range:
    On Error Resume Next
        Set scrg = Intersect(srg, sws.Columns(CRITERIA_COLUMN))
    On Error GoTo 0
    If scrg Is Nothing Then
        MsgBox "The source range is ""'" & sName & "'!" & srg.Address(0, 0) _
            & """. The criteria column """ & CRITERIA_COLUMN _
            & """ is out of bounds!", vbExclamation
        Exit Sub
    End If
    
    Dim ColumnsCount As Long: ColumnsCount = srg.Columns.Count
    
    ' Return the source data in arrays.
    
    ' If there are formulas that need to be preserved,
    ' use '.Formula' (or 'Formula2') instead of '.Value'!
    Dim sData() As Variant: sData = srg.Value
    ' Here you need values!
    Dim scData() As Variant: scData = scrg.Value
    
    ' Return the distinct values from the criteria array in the keys
    ' of a dictionary. Each corresponding item will hold a collection
    ' of the source rows.
    ' Also, calculate the maximum number of rows per value.
    
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    dict.CompareMode = vbTextCompare
    
    Dim sKey As Variant, sRow As Long, dRowsCount As Long
    
    For sRow = 2 To sRowsCount
        sKey = scData(sRow, 1)
        If Not IsError(sKey) Then
            sKey = CStr(sKey)
            If Len(sKey) > 0 Then
                If Not dict.Exists(sKey) Then
                    dict.Add sKey, New Collection
                End If
                dict(sKey).Add sRow
                If dict(sKey).Count > dRowsCount Then
                    dRowsCount = dict(sKey).Count
                End If
            End If
        End If
    Next sRow
    
    If dict.Count = 0 Then
        MsgBox "There are only errors or blanks in the criteria range ""'" _
            & sName & "'!" & scrg.Address(0, 0) & """!", vbExclamation
        Exit Sub
    End If
    
    ' Create a copy of the source worksheet in a new single-sheet workbook
    ' and clear the 'excessive' rows i.e. keep as many data rows
    ' as the maximum number of rows per value.
    ' This helper workbook with fewer rows will be repeatedly copied
    ' so fewer rows will have to be cleared.
    
    Application.ScreenUpdating = False
    
    sws.Copy
    Dim cwb As Workbook: Set cwb = Workbooks(Workbooks.Count)
    Dim cws As Worksheet: Set cws = cwb.Sheets(1)
    cws.Range(srg.Address).Resize(sRowsCount - dRowsCount - 1) _
        .Offset(dRowsCount + 1).Clear
    
    ' For each key in the dictionary, create a copy of the helper workbook
    ' (the copy becomes the destination workbook),
    ' copy the matching rows from the source array to the destination array,
    ' copy the values from the destination array to the destination range,
    ' clear excessive rows and save and close the destination workbook.
    
    ' Define the destination array.
    Dim dData() As Variant: ReDim dData(1 To dRowsCount, 1 To ColumnsCount)
    
    Dim dwb As Workbook, dws As Worksheet, drg As Range
    Dim RowItem As Variant, c As Long
    Dim dRow As Long, dFolderPath As String, dFilePath As String
    
    For Each sKey In dict.Keys ' distinct criteria
        ' Return the matching rows at the top of the destination array.
        dRow = 0
        For Each RowItem In dict(sKey) ' source row numbers in collection
            sRow = RowItem
            dRow = dRow + 1
            For c = 1 To ColumnsCount
                dData(dRow, c) = sData(sRow, c)
            Next c
        Next RowItem
        ' Create a copy of the helper workbook,...
        cws.Copy
        ' ... and reference this copy, the destination workbook.
        Set dwb = Workbooks(Workbooks.Count)
        Set dws = dwb.Sheets(1)
        'dws.Name = sName
        ' Return the values from the destination array in the destination range.
        Set drg = dws.Cells(1).Offset(1).Resize(dRow, ColumnsCount)
        drg.Value = dData
        ' Clear below.
        If dRow < dRowsCount Then
            drg.Resize(dRowsCount - dRow + 1).Offset(dRow).Clear
        End If
        ' Build the destination file path.
        dFolderPath = swb.Path & Application.PathSeparator _
            & IIf(Len(DST_SUBFOLDER_NAME) = 0, "", DST_SUBFOLDER_NAME _
            & Application.PathSeparator)
        If Len(Dir(dFolderPath, vbDirectory)) = 0 Then MkDir dFolderPath
        dFilePath = dFolderPath & sKey & DST_FILE_EXTENSION
        ' Save and close the destination workbook.
        If IS_IN_TEST_MODE Then
            Dim dCount As Long: dCount = dCount + 1
            dwb.Saved = True
            MsgBox "File " & dCount & " would have been saved as """ _
                & dFilePath & """!", vbExclamation
            If dCount = 2 Then
                MsgBox "Adjust the constants to get the desired paths." _
                    & vbLf & "Once they're satisfactory, set the " _
                    & """IS_IN_TEST_MODE"" constant to `False`!", _
                    vbCritical
                Exit For
            End If
        Else
            ' To overwrite without confirmation, ...
            ' prevent dialog if different format,... and whatnot.
            Application.DisplayAlerts = False
                dwb.SaveAs dFilePath, DST_FILE_FORMAT
            Application.DisplayAlerts = True
            dwb.Close SaveChanges:=False ' just got saved
        End If
    Next sKey
    
    ' Close the helper workbook.
    cwb.Close SaveChanges:=False

    Application.ScreenUpdating = True
    
    ' Inform.
    
    MsgBox "Workbooks created.", vbInformation

End Sub
© www.soinside.com 2019 - 2024. All rights reserved.