遍历工作表,并在所有其他工作表上仅应用一组条件格式

Loop through worksheets and apply ONLY (!) a set of conditional formatting on all other worksheets

提问人:2mas 提问时间:10/30/2023 更新时间:10/31/2023 访问量:65

问:

如何仅将一张纸的条件格式传输到所有其他工作表?xlPaste 和 xlPasteAllMergingConditionalFormats 等的任何技巧都不起作用,因为我的代码是通过字典复制范围的。

 Sub LoopSheets()

        
 Dim ws As Worksheet

         For Each ws In Worksheets

            ' Loop through all sheets after sheet 1, and Copy ONLY the conditional formatting rules from sheet 1 to the others.
            
            

         Next

      End Sub

代码不是我写的,但我从这个网站上的某个人那里得到了很多帮助。我尽力去理解它。我标记了我的一些想法。

Option Explicit

Sub ExtractCompanyData_NoComp()
    
    ' Define constants.
    
    Const SRC_SHEET_NAME As String = "MasterTable"
    Const DATA_COLUMNS As String = "A:K"
    Const DATE_COLUMN As Long = 6
'   Const COMPANY_COLUMN As Long = 8
    Const DST_FIRST_CELL As String = "A1"
    Const DST_DATE_FORMAT As String = "dd\/mm\/yyyy"
    Const DST_SHEET_NAME_DATE_FORMAT As String = "ddd dd.mm.yyyy"
    Const COPY_HEADERS As Boolean = True
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    
    ' Return the source data in an array ('sData').
    
    Dim sws As Worksheet: Set sws = wb.Sheets(SRC_SHEET_NAME)
    Dim srg As Range: Set srg = sws.UsedRange.Columns(DATA_COLUMNS)
    Dim srCount As Long: srCount = srg.Rows.Count
    Dim cCount As Long: cCount = srg.Columns.Count
    Dim sData() As Variant: sData = srg.Value
    
    ' An Incomplete Description of the Dictionary and the Collection
    ' A dictionary consists of two arrays: one is called 'Keys' and the other
    ' is called 'Items' ('Values'). Each key has an associated item
    ' and they form a so-called 'key-value pair'.
    ' Each key needs to be unique while its item can hold various data types,
    ' in this case, a collection ('object').
    ' A collection is similar but simpler.
    ' Each of a collection's 'item' needs to be unique.
    ' The collection is used because it is more efficient and you can simply
    ' add just an item to it while you need to add a value pair to a dictionary.
    
    ' Return the unique dates ('sDate') from the source array ('sData')
    ' in the 'keys' of a dictionary.
    ' Each key's corresponding 'item' will hold a collection whose 'items'
    ' will hold the rows ('sr') where each date ('sDate', key) was found.
    
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    
    Dim sDate As Variant, sr As Long
    
    For sr = 2 To srCount ' skip headers
        sDate = sData(sr, DATE_COLUMN)
        If IsDate(sDate) Then
            If Not dict.Exists(sDate) Then
                ' Create the 'sDate' key in the dictionary
                ' and add a new collection to the key's associated item.
                dict.Add sDate, New Collection
                ' or:
                'Set dict(sDate) = New Collection
            End If
            dict(sDate).Add sr ' add the row to the items of the collection
        End If
    Next sr

    ' Loop through the keys (dates) of the dictionary, and by applying
    ' the required logic, copy the data to the destination worksheet.

    Application.ScreenUpdating = False

    Dim dws As Worksheet, drg As Range, ddrg As Range
    Dim dData() As Variant, sRow As Variant
    Dim dr As Long, idr As Long, drCount As Long, c As Long
    Dim dwsName As String
'   Dim Company As String, IsCompanyFound As Boolean
    
    ' Loop through the keys (dates) of the dictionary.
    For Each sDate In dict.Keys
        
        ' Define the destination array.
        drCount = dict(sDate).Count - COPY_HEADERS
        ReDim dData(1 To drCount, 1 To cCount)
        
        ' Write the headers to the destination array.
        ' Also, determine the used destination array rows ('idr', 'dr')
        ' i.e. the inital row, the first row to be written to minus one.
        If COPY_HEADERS Then
            For c = 1 To cCount
                dData(1, c) = sData(1, c)
            Next c
            idr = 1
        Else
            idr = 0
        End If
        dr = idr
        
        ' Loop through the items ('sRow') of the collection ('dict(sDate)'),
        ' held by the current key's ('dDate') corresponding item ('dict(sDate)'),
        ' and write the values from each corresponding row ('sRow')
        ' of the source array ('sData') to the next row ('dr')
        ' of destination array ('dData') skipping the company column.
        ' Also, attempt to determine the company name.
        For Each sRow In dict(sDate)
            dr = dr + 1
            For c = 1 To cCount
                    dData(dr, c) = sData(sRow, c)
            Next c
        Next sRow

        
        ' Determine the destination worksheet name ('dwsName').
        dwsName = Format(sDate, DST_SHEET_NAME_DATE_FORMAT)
        
        ' Delete an existing same named sheet.
        Application.DisplayAlerts = False
            On Error Resume Next
                wb.Sheets(dwsName).Delete
            On Error GoTo 0
        Application.DisplayAlerts = True
        
        ' Add a new worksheet ('dws') and rename it accordingly.
        'insert right after all sheets
        Set dws = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
        
        
        ' Copy the values from the destination array ('dData')
        ' to the destination range ('drg').
        Set drg = dws.Range(DST_FIRST_CELL).Resize(drCount, cCount)
        drg.Value = dData
        
        ' Apply formatting to the destination (range, worksheet).
        With drg
            ' Format headers and reference the destination data range ('ddrg').
            If COPY_HEADERS Then
                With .Rows(1)
                    .Font.Bold = True
                End With
                Set ddrg = drg.Resize(drCount - 1).Offset(1)
            Else
                Set ddrg = drg
            End If
            ' Format the destination data range ('ddrg').
            With ddrg
                ' Format the destination date column.
                With ddrg.Columns(DATE_COLUMN)
                    .NumberFormat = DST_DATE_FORMAT
                End With
            End With
            ' Format the entire destination columns.
            .EntireColumn.AutoFit

       
'XYZ        'Copy Name to Header, delete second row
            .dws.Range("E1") = .dws.Range("E2")
            .Rows(2).EntireRow.Delete
'XYZ

    End With
        
    Next sDate
    
    'Additional Ideas
    
    'sws.Activate
    wb.Save

    Application.ScreenUpdating = True
    
    ' Inform.
    
    MsgBox "Daten wurden extrahiert", vbInformation
    
End Sub

标有“XYZ”的部分: 这没有用。我可以使用 .单元格(“E1”)。价值? 我该如何推断自己,范围是否可以使用 .cells 或 .value,我真的必须每次都自己尝试一下吗?

Excel VBA 格式

评论

0赞 FaneDuru 10/30/2023
你理解你粘贴的代码吗?是否要将条件格式应用于仅包含单元格?那么,你能更好地解释(用语言)你尝试做什么吗?讨论中的所有工作表是否都具有相同的使用范围?是否所有单元格都以相同的方式(使用相同的方式/规则)有条件地格式化?如果很难解释我上面的要求,至少,图片来显示你所拥有的和你需要的,也许会帮助我们理解你试图完成的事情......Date
0赞 2mas 10/30/2023
让我再试一次,我今天过得很糟糕。我基本上只有一个问题:如何将一张纸的条件格式规则应用于所有其他纸?我知道我可以做这样的事情:但是我怎么知道我在VBA中安装的格式公式是什么样子的?剩下的基本上就是:这是一堆我不理解的代码。如果您愿意,请为我插入它,但我更想表明我尝试过。这是试图说“我在这里,我想到达那里,引导我一点”。MyRange.FormatConditions.Add Type:=xlCellValue, Operator:=xlBetween, _ Formula1:="=100", Formula2:="=150"
1赞 Notus_Panda 10/31/2023
您的 XYZ 具有 drg (range) .dws (worksheet) 。Range(“E1”) (另一个范围),这将失败----尝试。至于你的另一个问题,我相信你也想吃蛋糕。代码(来自 vBasic2000)创建一个数组来一次性粘贴值而无需使用,但这正是使复制条件格式更加困难的确切原因。据我所知,使用新范围重新应用条件格式或不使用 vBasic 显示的方法会更容易。With dws.Range("E2") : .Offset(-1).Value = .Value : .EntireRow.Delete : End With.Copy
0赞 FaneDuru 10/31/2023
你想要什么,在你的问题标题中说明。你真正想要完成的事情与我的评论有关。尝试回答我的澄清问题有那么难吗?一个解决方案,一个快速的解决方案与你的答案有关。如果你只是开玩笑地问,恐怕只是猜测你有什么和你需要什么,我帮不了你。如果您只需要使用相同格式规则的条件格式化部分工作表单元格是一种方法,则使用相同条件格式的类似使用范围是另一种方法。恐怕你的代码没有任何帮助。你的解释可能是......
0赞 2mas 10/31/2023
@Notus_Panda 这也是我想通的。现在,我尝试遍历所有新生成的工作表(在主表之后开始循环),然后在我的尝试中应用条件格式,您基本上可以手动将规则放在工作表上。我尝试使用宏记录器,但后来我要求提供某种文档,如何有效地推断如何手动创建这些规则。

答:

1赞 taller 10/31/2023 #1
  • 将条件格式应用于另一个工作表的最快方法是复制并粘贴该格式。
  • 如果目标工作表上有无法覆盖的格式,则必须逐个复制条件格式规则。Sheet1
  • 条件格式有 10 多种类型,它们可能具有不同的属性。提供的代码是 的示例。xlExpression
  • 如果 上使用了更多格式(除了 Interior.Color 和 Font.Color 之外),则需要修改。Sheet1
Option Explicit

Sub CopyFC()
    Dim srcSht As Worksheet, Sht As Worksheet
    Dim targetRng As Range
    Dim oFC As FormatCondition, newFC As FormatCondition
    Set srcSht = Sheets("Sheet1")
    For Each Sht In Sheets
        If Not Sht.Name = srcSht.Name Then
            For Each oFC In srcSht.Cells.FormatConditions
                Select Case oFC.Type
                Case Is = xlExpression
                    Set newFC = Sht.Range(oFC.AppliesTo.Address).FormatConditions.Add(Type:=xlExpression, Formula1:=oFC.Formula1)
                    newFC.Interior.Color = oFC.Interior.Color
                    newFC.Font.Color = oFC.Font.Color
                    newFC.StopIfTrue = oFC.StopIfTrue
                Case Is = xlTextString
                    ' ..
                ' Case Is = <All XlFormatConditionType types which are implemented on sheet1>
                End Select
            Next
        End If
    Next
End Sub

Microsoft 文档:

XlPasteType 枚举 (Excel)

名字 价值 描述
xlAboveAverageCondition 12 高于平均水平的状况
xlBlanksCondition 10 空白条件
xlCell值 1 单元格值
xlColorScale(xl颜色比例) 3 色标
xl数据栏 4 数据栏
xlErrors条件 16 错误条件
xl表达式 2 表达
xlIconSet 6 图标集
xlNoBlanksCondition 13 无空白条件
xlNoErrorsCondition 17 无错误条件
xlTextString 9 文本字符串
xl时间周期 11 时间段
xlTop10的 5 十大价值
xlUniqueValues 8 唯一值

评论

0赞 Notus_Panda 10/31/2023
使用的公式不会因为范围与主表不同而扭曲吗?这就是为什么我不认为循环使用 CF 规则是一个可行的解决方案。
0赞 taller 10/31/2023
@Notus_Panda我同意。老实说,我不知道。提供的代码只是一个演示。可能需要微调。
0赞 2mas 11/6/2023
@Notus_Panda 我使用的规则很简单,例如“如果单元格中有一个唯一的代码字,如”_construction_site_owner“和”_construction_site_name“,则为单元格着色。这创造了一个漂亮的视觉方向。我现在的问题是:我怎样才能知道我的条件格式规则在 vba 中的样子,即确切的参数?
0赞 Notus_Panda 11/6/2023
在第二个 for 循环 (FormatConditions) 中,您可以使用用于将其设置为新工作表的 taller 检查公式:这应该是您要查找的,对吧?然而,如前所述,可能会有所不同。Debug.Print oFC.Formula1oFC.AppliesTo.Address