【问题标题】:Identify references within same workbook vs references in other workbooks识别同一工作簿中的引用与其他工作簿中的引用
【发布时间】:2016-12-23 18:40:14
【问题描述】:

我想要 Excel VBA 代码根据以下参数为字体着色:

  • 蓝色:硬编码数字
  • 黑色:公式(例如 sum、vlookup、average 等)
  • 绿色:从同一文件中的另一个工作表链接的编号
  • 红色:从外部文件的另一张表链接的数字

我已经编写了下面的代码,但它没有区分来自同一文件中另一个单元格/工作表的引用与外部文件中的引用。任何帮助都可以完成最后一步。

谢谢

Dim rng As Range, rErr As Range

On Error Resume Next

For Each rng In Intersect(ActiveSheet.UsedRange, Selection)

    If rng.HasFormula Then

        Set rErr = Range(Mid(rng.Formula, 2, Len(rng.Formula) - 1))

        If CBool(Err) Then

            rng.Font.ColorIndex = 1 'black

        Else

            rng.Font.ColorIndex = 3 'red

        End If

        Err = 0

    ElseIf CBool(Len(rng.Value)) Then

        rng.Font.ColorIndex = 5 'blue

    Else

        rng.Font.ColorIndex = xlAutomatic 'default

    End If

Next rng

Set rErr = Nothing

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    你可以试试这个:

    Option Explicit
    
    Sub main()
        Dim cell As Range
    
        With Intersect(ActiveSheet.UsedRange, Selection)
            On Error Resume Next
            .SpecialCells(xlCellTypeConstants, xlNumbers).Font.ColorIndex = 5 'blue
    
            For Each cell In .SpecialCells(xlCellTypeFormulas, xlNumbers)
                Select Case True
                    Case InStr(cell.Formula, "[") > 0
                        cell.Font.ColorIndex = 3 'red
                    Case InStr(Replace(cell.Formula, cell.Parent.Name & "!", ""), "!") > 0
                        cell.Font.ColorIndex = 4  'green
                    Case Else
                        cell.Font.ColorIndex = 1 'black
                End Select
            Next
        End With
    End Sub
    

    【讨论】:

    • @antd,你通过了吗?
    【解决方案2】:

    对我来说,链接的单元格很难找到……但它们确实如此。

    您不能只搜索[],因为手动输入的链接可能会将它们排除在外,而该链接仍然可以使用。您不能只搜索文件名,因为两个同名文件可能存在于不同的文件夹中。您不能只搜索文件路径或\,因为如果链接的工作簿在同一个 Excel 应用程序中打开,则链接中会省略文件路径。

    内部链接会带来类似的问题。例如,您不能依赖搜索!,因为链接可能是Name

    前段时间,我必须识别内部和外部链接的单元格,因此我编写了一些粗略且现成的代码来执行此操作。这些函数包含在下面的示例中,但我毫不怀疑会有例外(例如,任何包含与 Name 名称相同的字符串的公式都将无法通过测试)。

    我将这些函数保留为单独的例程,因为它们可能对其他用户有用,但它确实使您的项目的代码效率稍低。不过,可能会证明是您可以解决的问题。

    您会注意到我刚刚使用 UsedRange 来定义目标范围 - 您可能需要修改它。

    Sub RunMe()
        Dim extLinkCells As Range
        Dim intLinkCells As Range
        Dim formulaCells As Range
        Dim numberCells As Range
        Dim cell As Range
    
        Set numberCells = Sheet1.UsedRange.SpecialCells(xlCellTypeConstants)
        Set extLinkCells = AllExternallyLinkedCells(Sheet1.UsedRange)
        Set intLinkCells = AllInternallyLinkedCells(Sheet1.UsedRange)
        'Pick up the remaining non-linked cells (ie must just be formulas)
        For Each cell In Sheet1.UsedRange.SpecialCells(xlCellTypeFormulas)
            If Intersect(cell, extLinkCells) Is Nothing And Intersect(cell, intLinkCells) Is Nothing Then
                If formulaCells Is Nothing Then
                    Set formulaCells = cell
                Else
                    Set formulaCells = Union(formulaCells, cell)
                End If
            End If
        Next
    
        numberCells.Font.Color = vbBlue
        formulaCells.Font.Color = vbBlack
        intLinkCells.Font.Color = vbGreen
        extLinkCells.Font.Color = vbRed
    End Sub
    
    Private Function AllInternallyLinkedCells(testRange As Range) As Range
    
        Dim result As Range, cell As Range
        Dim links() As String
        Dim fileName As String
        Dim wb As Workbook
        Dim ws As Worksheet
        Dim nm As Name
        Dim i As Long
    
        Set wb = testRange.Parent.Parent
    
        'Acquire all sheet names apart from this one
        i = 1
        For Each ws In wb.Sheets
            If ws.Name <> testRange.Worksheet.Name Then
                ReDim Preserve links(1 To i)
                links(i) = ws.Name
                Debug.Print "Internal Link"; i; links(i)
                i = i + 1
            End If
        Next
        'Acquire all names that don't refer to this sheet
        For Each nm In wb.Names
            If nm.RefersToRange.Worksheet.Name <> testRange.Worksheet.Name Then
                ReDim Preserve links(1 To i)
                links(i) = nm.Name
                Debug.Print "Internal Link"; i; links(i); " of "; nm.RefersToRange.Worksheet.Name
                i = i + 1
            End If
        Next
    
        'Test if cell formula matches our list
        For Each cell In testRange.SpecialCells(xlCellTypeFormulas)
            If Exists(cell.Formula, links) Then
                If result Is Nothing Then
                    Set result = cell
                Else
                    Set result = Union(result, cell)
                End If
            End If
        Next
    
        Set AllInternallyLinkedCells = result
    
    End Function
    
    Private Function AllExternallyLinkedCells(testRange As Range) As Range
    
        Dim result As Range, cell As Range
        Dim rawLinks As Variant
        Dim adjLinks() As String
        Dim fileName As String
        Dim wb As Workbook
        Dim i As Long
    
        'Acquire all the links
        rawLinks = ThisWorkbook.LinkSources(xlExcelLinks)
        ReDim adjLinks(1 To UBound(rawLinks) * 2)
        For i = 1 To UBound(rawLinks)
            fileName = Right(rawLinks(i), Len(rawLinks(i)) - InStrRev(rawLinks(i), "\"))
            Set wb = Nothing: On Error Resume Next
            Set wb = Workbooks(fileName): On Error GoTo 0
            adjLinks(i) = IIf(wb Is Nothing, rawLinks(i), fileName)
            adjLinks(i + 1) = Replace(adjLinks(i), fileName, "[" & fileName & "]")
            Debug.Print "External Link"; i; adjLinks(i + 1)
        Next
    
        For Each cell In testRange.SpecialCells(xlCellTypeFormulas)
            If Exists(cell.Formula, adjLinks) Then
                If result Is Nothing Then
                    Set result = cell
                Else
                    Set result = Union(result, cell)
                End If
            End If
        Next
    
        Set AllExternallyLinkedCells = result
    
    End Function
    
    Private Function Exists(item As String, arr As Variant) As Boolean
        Dim i As Long
    
        For i = LBound(arr) To UBound(arr)
            If InStr(item, arr(i)) > 0 Then
                Exists = True
                Exit Function
            End If
        Next
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 2013-08-16
      • 2018-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多