How to cycle through borders in Excel and change their color?

白昼怎懂夜的黑 提交于 2020-07-22 21:25:12

问题


I am trying to cycle through active borders in Excel and to change their colors to "next one".

Here is the code I have:

Dim Color1 As Variant
Dim Color2 As Variant
Dim Color3 As Variant
Dim Color4 As Variant
Dim Color5 As Variant

Color_default = RGB(0, 0, 0)
Color1 = RGB(255, 0, 0)
Color2 = RGB(0, 255, 0)
Color3 = RGB(0, 0, 255)
Color4 = RGB(222, 111, 155)
Color5 = RGB(111, 111, 111)

Dim cell As Range
Dim positions As Variant
Dim i As Integer

positions = Array(xlDiagonalDown, xlDiagonalDown, xlEdgeLeft, xlEdgeTop, xlEdgeBottom, xlEdgeRight, xlInsideVertical, xlInsideHorizontal)

For Each cell In Selection
    For i = LBound(positions) To UBound(positions)
        If cell.BORDERS(positions(i)).LineStyle <> xlNone Then
            If cell.BORDERS(positions(i)).Color = Color_default Then
                cell.BORDERS(positions(i)).Color = Color1
            ElseIf cell.BORDERS(positions(i)).Color = Color1 Then
                cell.BORDERS(positions(i)).Color = Color2
            ElseIf cell.BORDERS(positions(i)).Color = Color2 Then
                cell.BORDERS(positions(i)).Color = Color3
            ElseIf cell.BORDERS(positions(i)).Color = Color3 Then
                cell.BORDERS(positions(i)).Color = Color4
            ElseIf cell.BORDERS(positions(i)).Color = Color4 Then
                cell.BORDERS(positions(i)).Color = Color5
            Else
                cell.BORDERS(positions(i)).Color = Color_default
            End If
        End If
    Next i
Next cell

It works. It does not change the weight of the borders and it does not add new borders (only changes the existing ones).

The issue is that when two cells are nearby, the outer borders are changes to "next+1" color, and the inner borders are changed to "next+2" color, as they are looped through two times.

EDIT: The code should check if the existing border colors are the ones I want to use. Secondly, the colors should be unified first, to avoid multiple border colors within selection.

A picture of the problem

I want to unify the borders and then be able to cycle through their colors, regardless what their weight is and without adding NEW borders.


回答1:


This code should do what you want. It reads the existing color from a framed cell within the selection, determines which is the next color to set and sets all colours accordingly.

Sub CycleBorderColors(Optional ByVal Reset As Boolean)

    Dim BorderColor As Variant
    Dim BorderPos As Variant
    Dim CurrentColor As Long
    Dim ColorIndex As Long
    Dim Cell As Range
    Dim i As Integer


    BorderPos = Array(xlDiagonalDown, xlDiagonalUp, xlEdgeLeft, xlEdgeTop, _
                      xlEdgeBottom, xlEdgeRight, xlInsideVertical, xlInsideHorizontal)
    BorderColor = Array(RGB(0, 0, 0), RGB(255, 0, 0), RGB(0, 255, 0), _
                        RGB(222, 111, 155), RGB(111, 111, 111))

    If Reset Then
        ColorIndex = Reset
    Else
        CurrentColor = xlNone
        ' read the border color of the first selected cell with a border
        For Each Cell In Selection.Cells
            For i = LBound(BorderPos) To UBound(BorderPos)
                With Cell
                    If .Borders(BorderPos(i)).LineStyle <> xlNone Then
                        CurrentColor = .Borders(BorderPos(i)).Color
                        Exit For
                    End If
                End With
            Next i
            If CurrentColor <> xlNone Then Exit For
        Next Cell
        If CurrentColor = xlNone Then
            MsgBox "The selection includes no cells with borders.", _
                   vbInformation, "Inapplicable selection"
            Exit Sub
        End If

        For ColorIndex = UBound(BorderColor) To 0 Step -1
            If BorderColor(ColorIndex) = CurrentColor Then Exit For
        Next ColorIndex
        ' ColorIndex will be -1 if not found
    End If
    ColorIndex = ColorIndex + 1                 ' set next color
    If ColorIndex > UBound(BorderColor) Then ColorIndex = 0

    For Each Cell In Selection
        For i = LBound(BorderPos) To UBound(BorderPos)
            If Cell.Borders(BorderPos(i)).LineStyle <> xlNone Then
                Cell.Borders(BorderPos(i)).Color = BorderColor(ColorIndex)
            End If
        Next i
    Next Cell
End Sub

The procedure has an optional argument which, if set to True, causes a reset. The current program sets the border color to default. In hindsight the idea isn't so hot because you could cause a reset by running the code 4 or fewer times. But when I started it seemed like a good idea. Now you may prefer to remove the feature. The easiest way would be to remove the argument from the declaration, add Dim Reset As Boolean to the variable declarations and leave the rest to itself.

While you do have the the option to reset use an intermediary to call the procedure. Any of the three variants shown below will work.

Sub CallCycleBorderColors()
    CycleBorderColors
  ' CycleBorderColors True
  ' CycleBorderColors False
End Sub

Call the sub CallCycleBorderColors from the worksheet.




回答2:


Here's one approach - note I removed some of your border enums - if you're cycling over each cell then you can likely ignore the "outer" borders.

It first loops to find what needs to change, but doesn't set any border colors in that first loop. In the second loop it updates, but won't change a border that's already been changed as part of a previous cell's updates.

Sub BorderColor()

    Dim cell As Range
    Dim positions As Variant
    Dim i As Long, clrNow As Long, clrNext As Long, Pass As Long
    Dim col As New Collection, arr

    positions = Array(xlEdgeLeft, xlEdgeTop, xlEdgeBottom, xlEdgeRight)

    For Each cell In Range("C4:F11").Cells
        For i = LBound(positions) To UBound(positions)
            If cell.Borders(positions(i)).LineStyle <> xlNone Then
                With cell.Borders(positions(i))
                    'store the cell, border position, current color and new color
                    col.Add Array(cell, positions(i), .Color, NextColor(.Color))
                End With
            End If
        Next i
    Next cell
    'now loop and set the new color if needed
    For Each arr In col
        Set cell = arr(0)
        With cell.Borders(arr(1))
            'only change the color if it hasn't already been changed
            If .Color = arr(2) Then .Color = arr(3)
        End With
    Next


End Sub

'get next color (cycles through array)
Function NextColor(currentColor As Long) As Long
    Dim arr, i As Long, rv As Long
    arr = Array(RGB(0, 0, 0), RGB(255, 0, 0), _
                RGB(0, 255, 0), RGB(0, 0, 255), _
                RGB(222, 111, 155), RGB(111, 111, 111))
    rv = -1
    For i = LBound(arr) To UBound(arr)
        If currentColor = arr(i) Then
            If i < UBound(arr) Then
                rv = arr(i + 1)
            Else
                rv = arr(LBound(arr))
            End If
            Exit For
        End If
    Next
    If rv = -1 Then rv = RGB(0, 0, 0) 'default next
    NextColor = rv
End Function



回答3:


You don't upload u's image showing cell.border so I can't figure out how you want to work.

I assume that in selection, the border colors are initially the same and they are in the colors you give. try this:

Sub Test()
    Dim color As Variant, cell As Range
    Dim arr_Color, Arr_Border, Index, item
    'black-> red -> green -> blue -> pink-> Brown-> black
    arr_Color = Array(RGB(0, 0, 0), RGB(255, 0, 0), RGB(0, 255, 0), _
                      RGB(0, 0, 255), RGB(222, 111, 155), RGB(111, 111, 111), RGB(0, 0, 0))
    Arr_Border = Array(xlEdgeLeft, xlEdgeTop, xlEdgeRight, xlEdgeBottom)
    Dim origin As Range: Set origin = selection
    For Each item In Arr_Border
            If item = xlEdgeRight Then
                Set selection = selection.Resize(selection.Rows.Count, 1).Offset(0, selection.Columns.Count - 1)
            End If
            If item = xlEdgeBottom Then
                Set selection = origin.Resize(1, origin.Columns.Count).Offset(origin.Rows.Count - 1, 0)
            End If
        For Each cell In selection.Cells
        color = cell.Borders(item).color
        Index = Application.Match(color, arr_Color, 0)
            If Not (IsError(Index)) Then
            color = arr_Color(Index)
                If cell.Borders(item).LineStyle <> xlLineStyleNone Then
                     cell.Borders(item).color = color
                End If
            End If
        Next cell

    Next item
End Sub

Notes:

-Unnecessary xlInsideVertical, xlInsideHorizontal when looping through the cells.

-I will loop through the edge types before iterating through each cell



来源:https://stackoverflow.com/questions/60582649/how-to-cycle-through-borders-in-excel-and-change-their-color

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!