【问题标题】:Return multiple column headers based on the color of the cells within a row根据行内单元格的颜色返回多个列标题
【发布时间】:2019-03-20 20:50:31
【问题描述】:

我的数据表(“srData”)是一个使用用户表单填充的数据透视表。所有数据在数据表的 A 列中都有一个唯一的 ID。 在用户表单中选中复选框,这将更改单元格,在 K:AA 列中,内部颜色为白色(2),否则内部颜色为灰色(15)

我需要做的是在另一个工作表(“Formulier”)上,基于选择唯一 ID 的下拉框 (C6) 的值(即 SR-1、SR-2、 SR-3 等...),对表执行查找以返回单元格内部颜色为 colorindex=2 的标题。此查找的结果需要放置在 A 列中的 sheet("Formulier") 上,从第 19 行到第 28 行。根据复选框,不会超过 10 行。

例如,根据上表,如果从下拉列表中选择了 SR-2,则返回的标题应放在 A 列,第 19 行 = pH,第 20 行 = NO2-IC

如果从下拉列表中选择了 SR-4,则返回的标题应放在 A 列,第 19 行 = OBD,第 20 行 = F-CFA,第 21 行 =NO3-CFA,第 22 行 = NO2-CFA

我已经使用this post 尝试了代码,但这并不是我想要的。由于此代码将标题 allin 放在单元格上,并且它基于值而不是颜色。

我希望有人能够帮助我。

【问题讨论】:

  • 颜色有一个值。您可以通过检查单元格的背景颜色来测试单元格,例如 Cells(1,1).interior.color=rgb(121,121,121)

标签: excel vba


【解决方案1】:

颜色搜索

在标准模块中(转到 VBE >> 插入 >> 模块)

Option Explicit

Public Const CriteriaCell As String = "C6"    ' Criteria Cell Range Address

Sub ColorSearch()

    ' Source
    Const cSource As Variant = "srData"       ' Worksheet Name/Index
    Const cCriteriaColumn As Variant = "A"    ' Criteria Column Letter/Number
    Const cColumns As String = "K:AA"         ' Columns Range Address
    Const cHeaderRow As Long = 1              ' Header Row Number
    Const cColorIndex As Long = 2             ' Criteria Color Index (2-White)
    ' Target
    Const cTarget As Variant = "Formulier"    ' Worksheet Name/Index
    Const cFr As Long = 19                    ' First Row Number
    Const cCol As Variant = "A"               ' Column Letter/Number

    Dim rng As Range      ' Source Found Cell Range
    Dim vntH As Variant   ' Header Array
    Dim vntC As Variant   ' Color Array
    Dim vntT As Variant   ' Target Array
    Dim i As Long         ' Source/Color Array Column Counter
    Dim k As Long         ' Target Array Row Counter
    Dim sRow As Long      ' Color Row
    Dim SVal As String    ' Search Value
    Dim Noe As Long       ' Source Number of Elements

    ' Write value from Criteria Cell Range to Search Value.
    SVal = ThisWorkbook.Worksheets(cTarget).Range(CriteriaCell)

    ' In Source Worksheet
    With ThisWorkbook.Worksheets(cSource)
        ' Search for Search Value in Source Criteria Column and create
        ' a reference to Source Found Cell Range.
        Set rng = .Columns(cCriteriaColumn) _
                .Find(SVal, , xlValues, xlWhole, , xlNext)
        ' Check if Search Value not found. Exit if.
        If rng Is Nothing Then Exit Sub
        ' Write row of Source Found Cell Range to Color Row.
        sRow = rng.Row
        ' Release rng variable (not needed anymore).
        Set rng = Nothing
        ' In Source Columns
        With .Columns(cColumns)
            ' Copy Header Range to Header Array.
            vntH = .Rows(cHeaderRow)
            ' Copy Color Range to Color Array.
            vntC = .Rows(sRow)
            ' Write number of columns in Source Columns to Source Number
            ' of Elements.
            Noe = .Columns.Count
            ' Loop through columns of Color Range/Array.
            For i = 1 To Noe
                ' Write current ColorIndex of Color Range to current
                ' element in Color Array.
                vntC(1, i) = .Cells(sRow, i).Interior.ColorIndex
            Next
        End With
    End With
    ' Resize Target Array to Number of Elements rows and one column.
    ReDim vntT(1 To Noe, 1 To 1)
    ' Loop through columns of Color Array.
    For i = 1 To Noe
        ' Check if current value in Color Array is equal to Criteria
        ' Column Index.
        If vntC(1, i) = cColorIndex Then
            ' Count row in Target Array.
            k = k + 1
            ' Write value of current COLUMN in Header Array to
            ' element in current ROW of Target Array.
            vntT(k, 1) = vntH(1, i)
        End If
    Next

    ' Erase Header and Color Arrays (not needed anymore).
    Erase vntH
    Erase vntC

    ' In Target Worksheet
    With ThisWorkbook.Worksheets(cTarget)
        ' Calculate Target Range by resizing the cell at the intersection of
        ' Target First Row and Target Column, by Number of Elements.
        ' Copy Target Array to Target Range.
        .Cells(cFr, cCol).Resize(Noe) = vntT
    End With

End Sub

在 Worksheet Formulier 中(在 VBE 中双击 Formulier)

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Cells.Count = 1 Then
        If Not Intersect(Target, Range(CriteriaCell)) Is Nothing Then
            ColorSearch
        End If
    End If
End Sub

白色单元格值版本

  • 添加了将白色单元格的值写入工作表的 D 列 Formulier.
  • *** 表示必须添加的内容。
  • ColorSearch2 更改为ColorSearch
Sub ColorSearch2()

    ' Source
    Const cSource As Variant = "srData"       ' Worksheet Name/Index
    Const cCriteriaColumn As Variant = "A"    ' Criteria Column Letter/Number
    Const cColumns As String = "K:AA"         ' Columns Range Address
    Const cHeaderRow As Long = 1              ' Header Row Number
    Const cColorIndex As Long = 2             ' Criteria Color Index (2-White)
    ' Target
    Const cTarget As Variant = "Formulier"    ' Worksheet Name/Index
    Const cFr As Long = 19                    ' First Row Number
    Const cCol As Variant = "A"               ' Column Letter/Number
    Const cColVal As Variant = "D"            ' *** Value Column Letter/Number

    Dim rng As Range      ' Source Found Cell Range
    Dim vntH As Variant   ' Header Array
    Dim vntC As Variant   ' Color Array
    Dim vntV As Variant   ' *** Value Array
    Dim vntT As Variant   ' Target Array
    Dim vntTV As Variant  ' *** Target Value Array
    Dim i As Long         ' Source/Color Array Column Counter
    Dim k As Long         ' Target Array Row Counter
    Dim sRow As Long      ' Color Row
    Dim SVal As String    ' Search Value
    Dim Noe As Long       ' Source Number of Elements

    ' Write value from Criteria Cell Range to Search Value.
    SVal = ThisWorkbook.Worksheets(cTarget).Range(CriteriaCell)

    ' In Source Worksheet
    With ThisWorkbook.Worksheets(cSource)
        ' Search for Search Value in Source Criteria Column and create
        ' a reference to Source Found Cell Range.
        Set rng = .Columns(cCriteriaColumn) _
                .Find(SVal, , xlValues, xlWhole, , xlNext)
        ' Check if Search Value not found. Exit if.
        If rng Is Nothing Then Exit Sub
        ' Write row of Source Found Cell Range to Color Row.
        sRow = rng.Row
        ' Release rng variable (not needed anymore).
        Set rng = Nothing
        ' In Source Columns
        With .Columns(cColumns)
            ' Copy Header Range to Header Array.
            vntH = .Rows(cHeaderRow)
            ' Copy Color Range to Color Array.
            vntC = .Rows(sRow)
            ' *** Copy Color Range to Value Array.
            ' Note: The values are also written to Color Array, but are
            '       later overwritten with the Color Indexes.
            vntV = .Rows(sRow)
            ' Write number of columns in Source Columns to Source Number
            ' of Elements.
            Noe = .Columns.Count
            ' Loop through columns of Color Range/Array.
            For i = 1 To Noe
                ' Write current ColorIndex of Color Range to current
                ' element in Color Array.
                vntC(1, i) = .Cells(sRow, i).Interior.ColorIndex
            Next
        End With
    End With
    ' Resize Target Array to Number of Elements rows and one column.
    ReDim vntT(1 To Noe, 1 To 1)
    ' *** Resize Target Value Array to Number of Elements rows and one column.
    ReDim vntTV(1 To Noe, 1 To 1)
    ' Loop through columns of Color Array.
    For i = 1 To Noe
        ' Check if current value in Color Array is equal to Criteria
        ' Column Index.
        If vntC(1, i) = cColorIndex Then
            ' Count row in Target Array.
            k = k + 1
            ' Write value of current COLUMN in Header Array to
            ' element in current ROW of Target Array.
            vntT(k, 1) = vntH(1, i)
            ' *** Write value of current COLUMN in Value Array to
            ' element in current ROW of Target Value Array.
            vntTV(k, 1) = vntV(1, i)
        End If
    Next

    ' Erase Header and Color Arrays (not needed anymore).
    Erase vntH
    Erase vntC
    Erase vntV '***

    ' In Target Worksheet
    With ThisWorkbook.Worksheets(cTarget)
        ' Calculate Target Range by resizing the cell at the intersection of
        ' Target First Row and Target Column, by Number of Elements.
        ' Copy Target Array to Target Range.
        .Cells(cFr, cCol).Resize(Noe) = vntT
        ' *** Calculate Target Value Range by resizing the cell at the
        ' intersection of Target First Row and Value Column, by Number of
        ' Elements.
        ' Copy Target Value Array to Target Value Range.
        .Cells(cFr, cColVal).Resize(Noe) = vntTV
    End With

End Sub

【讨论】:

  • 非常感谢您的帮助。这完全符合我的需要。非常感谢您的帮助。
  • 我还有一个问题,如果我必须为此使用一个新问题,请告诉我。我想知道在这个 sub 中是否也可以在输入后返回白色单元格中的值?该值将始终是一个数字,并且必须在“Formulier”的 D 列中。如果做一个新的子更好,我会试一试。如果我问这个超出了我的界限,我很抱歉。
  • @Bellandra:添加了白色单元格值版本。
  • 非常感谢您的快速回答。一个小时后会看,我有约会。
  • 效果很好。不能感谢你!也很高兴您解释了代码的作用,这样我可以了解更多信息。为了解决这个问题,我花了数周的时间寻找。
猜你喜欢
  • 1970-01-01
  • 2019-06-17
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多