如何从动态生成超链接(通过公式)的单元格中获取地址(Link)?

How to a get Address (Link) from cell where Hyperlink dynamically generated (by formulas)?

在 excel 中,您可以 link 一个 hyperlink(到一个单元格,到一个绘图等)

我们可以说这link分为两种:

  1. 困难Link 此功能通过直接编辑单元格或 object 实现,即通过 right-clicking 和 linking link(到文档中的某个位置,到网页等),或在 VBA 中调用 Hyperlinks object
  2. 的添加函数

所以这个 link 在单元格属性中可见,并且!在 Hyperlinks collection

中可见
  1. 动态生成的 hyperlink 是一种单元格具有本着
  2. 精神的公式的情况

=超级链接(B2;A2)

A2 包含显示名称,例如“Trade Minipigs”,B2 包含实际地址

对于用户来说,一切都与项目 1 的情况大致相同,但在 Hyperlinks 中不再可见 collection

但是!让我们假设公式依赖于另一个 sheet 上的单元格,它们仍然存在于某个地方,有一大堆支票和其他东西,通常很复杂,我们需要将这个 sheet 和最后的 links(但不是这些生成的 links 所指的 sheets)

在这种情况下,如果您将 sheet 复制到新文件,公式中的单元格引用将更正并指向从中复制 sheet 的文件

很明显,接收者没有这样的文件,这些link对他不起作用(但是,在hyperlink本身的部分,它不起作用即使到位,但与显示名称关联的部分按预期工作)

“复制和粘贴”(值)操作将无济于事,因为在这种情况下公式将在显示名称的部分进行计算,但结果 link 将不会被插入(当新文件和旧文件之间的 link 被破坏时,也会发生同样的情况)

就是这样,这个公式在其中的单元格的“值”只是一个显示名称,而不是超级link,而且它也不在单元格属性中 单元格 属性 hyperlink 是一个硬 hyperlink

我想肯定在 Excel object 模型的深处哪里可以买到这个 link 毕竟,当你将光标悬停在这样一个单元格上时,然后是,window 弹出这个 hyperlink。然而这是显而易见的。

是否可以通过软件以某种方式提取这个生成的 link,以便稍后可以通过 Hyperlinks object 的添加功能将其绑定到所需位置?

要查找所有通过公式添加的超链接,您可以使用 VBA 中的查找功能。以下例程将遍历所有超链接公式并调用子例程 'replaceHyperlink':

Sub replaceHyperlinks(Optional ws As Worksheet = Nothing)
    If ws Is Nothing Then Set ws = ActiveSheet
    
    Dim firstHit As Range, hit As Range
    Set hit = ws.Cells.Find(What:="=Hyperlink", LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
    Do While Not hit Is Nothing
        Call replaceHyperlink(hit)
        Set hit = ws.Cells.FindNext(after:=hit)
    Loop
End Sub

现在变得棘手了,我们需要创建一个函数来获取地址 (url) 和 Hyperlink-公式中的文本。获取文本很容易,您可以使用 Value2-属性 获取它。对于地址,我想除了分析公式文本之外别无他法。以下例程针对 3 个简单情况执行此操作:
- url 在引号中 ("https\www.whosebug.com")
- url 是单元格引用(指向相同的 sheet),例如 B2.
- url 是对另一个 sheet 的单元格引用(例如 Sheet2!B2

如果 url 本身是由公式创建的(例如 "https:\" & B2),它将失败。

有了 URL 和文本,单元格的公式将被替换为文本,并创建一个真正的超链接:

Sub replaceHyperlink(cell As Range)
    Const FormulaStart = "=HYPERLINK("
    If UCase(Left(cell.formula, Len(FormulaStart))) <> FormulaStart Then Exit Sub
    
    Dim formula As String, url As String, p As Long, text As String
    ' Search for the link address
    formula = Mid(cell.formula, Len("=Hyperlink(") + 1)
    p = InStr(formula, ",")
    If p > 0 Then
        formula = Left(formula, p - 1)
    Else
        formula = Left(formula, Len(formula) - 1)
    End If
    
    If Left(formula, 1) = """" And Right(formula, 1) = """" Then
        url = Mid(formula, 2, Len(formula) - 2)
    ElseIf InStr(formula, "!") = 0 Then
        url = cell.Parent.Range(formula)
    Else
        url = Evaluate(formula)
    End If
    
    text = cell.Value2
    cell.Value = text
    cell.Hyperlinks.Add Anchor:=cell, Address:=url, textToDisplay:=text
End Sub

更新 如果得到url的公式比较复杂,也许你可以把这个公式部分暂时写到单元格中。这样做之后,Value2-属性 应该将公式解析为 url。将最后几行替换为

text = cell.Value2            ' Save the friendly text
cell.formula = "=" & formula  ' Write the URL-part temporarily into cell as formula
url = cell.Value2             ' Get the result of that temp. formula 

cell.Value = text
cell.Hyperlinks.Add Anchor:=cell, Address:=url, textToDisplay:=text

我找到了复制这个的方法,或者更确切地说是获取了这样一个动态 link 的地址。它在于必须将单元格复制到 Word (多么高兴——通过这个操作,Word 计算出 link 的实际地址并将其变成固定地址),然后检查 Word 对象的 Hyperlinks 集合 already

当然,在这种形式下它运行起来很慢,但是如果你愿意,你可以改进它,例如,将 wdApp 对象设为静态而不是每次都 create/destroy 它,这样会加快如果你需要处理很多细胞,工作得非常体面。

2019 年 Excel/Word 测试(不要忘记连接 Microsoft Object Library

Function GetLink(r As Long, c As Long) As String
    
    Dim wdApp As Word.Application
    Dim wdDoc As Word.Document
    
    If Cells(r, c).Value = Empty Then
      GetLink = ""
      Exit Function
    End If
    
    Cells(r, c).Copy
    
    Set wdApp = CreateObject("Word.Application")
    wdApp.Documents.Add
    Set wdDoc = wdApp.Documents(1)
    
    wdApp.Visible = False
    wdDoc.Range.PasteExcelTable False, False, False
    
    If wdDoc.Hyperlinks.Count = 0 Then
        GetLink = ""
      Else
        GetLink = wdDoc.Hyperlinks(1).Name
     End If
    wdDoc.Close (wdDoNotSaveChanges)
    wdApp.Quit (wdDoNotSaveChanges)
    
End Function