【问题标题】:Cannot use hyperlink when protecting sheets without allowing user to select locked cells在不允许用户选择锁定单元格的情况下保护工作表时无法使用超链接
【发布时间】:2016-01-31 09:41:46
【问题描述】:

我有一个工作表,其中包含一组根据下拉菜单更改的动态超链接。只有带有下拉菜单的单元格被解锁。我未选中“选择锁定的单元格”,因此当我保护工作表时,用户只能选择下拉菜单。不幸的是,当我这样做时,超链接不再可用。

有人知道如何解决这个问题吗?

更新*

根据要求,我的动态超链接单元格的代码:

=IF(ISNA(MATCH(B4,'Data Sheet'!A2:A103,0)),"",HYPERLINK(VLOOKUP(B4,'Data Sheet'!A:S,7,FALSE),VLOOKUP(B4,'Data Sheet'!A:S,5,FALSE)&" - "&VLOOKUP(B4,'Data Sheet'!A:S,6,FALSE)))

1) 单元格 B4 是用户选择特定选项的下拉菜单。超链接会根据此选择而改变。

2) “数据表”是一个单独的表,其中包含一个数组中的所有参考数据。

这基本上是说:B4 中的值是否与我的数据图表中的第一列匹配?如果是这样,请使用 VLOOKUP 使用超链接公式将相应的 URL 插入到公式中。

【问题讨论】:

  • 你是如何生成超链接的?我认为最终你必须考虑用户与之交互的任何东西都必须被解锁。因此,现在我们开始着手减轻用户更改超链接所在位置的危险。如果您通过HYPERLINK 公式生成,那么用户可能会更改您的公式。如果您通过 VBA 生成它...似乎没什么大问题,因为它是在每次下拉列表更改时动态生成的,而用户没有机会更改脚本。
  • 我在 =hyperlink 公式中使用 VLOOKUP 来使超链接动态化。防止用户更改公式不是问题。包含超链接的单元格被锁定。我只想取消选中使锁定单元格可选的框。主要是出于审美原因。在我看来,它看起来更专业。如果您认为这更适合该论坛,我会询问超级用户。谢谢!
  • 你愿意使用VBA吗?
  • @EEM 当然,如果这是触发超链接的唯一方法,那将是一个有效的答案。至少对于赏金而言,不知道 OP 的要求。
  • 试图评估该问题还涉及哪些其他问题,因此遇到了一些问题:1)您有多少个超链接单元格? 2)这些超链接是否指向同一工作簿中的位置? 3) 这些地方是否没有受到保护? 4)当您说“防止用户更改公式不是问题”时。这是因为:“包含超链接的单元格被锁定。”? 5) 你能分享一下超链接的VLOOKUP 公式吗?

标签: excel hyperlink


【解决方案1】:

这是我对设置和要求的理解:

设置

  • 有一个带有下拉菜单的受保护工作表,用于更新包含 VLOOKUP\HYPERLINK 公式的其他单元格。

  • 工作表中的所有单元格(不包括下拉菜单)都受到保护。

  • 包含 VLOOKUP\HYPERLINK 公式的单元格的值可能等于 www 地址或空白,具体取决于下拉菜单的值。因此,所有超链接都指向网页或为空白。

  • 工作表EnableSelection 设置为xlUnlockedCells,这决定了一旦工作表受到保护,“只能选择未锁定的单元格”。

要求 - 需要保护工作表以保护包括 VLOOKUP\HYPERLINK 公式在内的所有内容。

  • 需要允许用户选择\仅激活未受保护的细胞,主要是出于美观原因并提供专业产品。

此解决方案使用以下资源

  • HYPERLINK 函数
  • UDF(用户定义函数)
  • 两个Public Variables
  • Worksheet_BeforeDoubleClick 事件

UDF 被包装到 HYPERLINK 函数中时,会导致 每次鼠标悬停在包含组合的单元格上时 HYPERLINK(UDF,[FriendlyName]) 的公式触发了UDF

我们将使用Public Variable 来保存LinkLocation,以便稍后根据用户决定使用超链接。

第二个Public Variable 设置LinkLocation 上次更新的时间。

我们将模仿“正常”激活超链接的方式:

  • 用户通过它选择一个单元格并单击所选单元格中的超链接。

  • 相反,用户将鼠标悬停在带有超链接 的单元格上(UDF 将 LinkLocation 和时间输入公共变量)DoubleClicks 单元格 (触发跟随超链接的工作表事件,首先验证上次更新 LinkLocation 的时间以确保它仍然是真实的并清除 LinkLocation 变量)

首先,我们需要确保工作表中用于生成动态超链接的公式具有适当的结构:

假设当前的 VLOOKUP\HYPERLINK 公式具有以下结构: (必须根据假设工作,因为没有提供实际公式)

=IFERROR( HYPERLINK( VLOOKUP( DropDownCell , Range , Column, False ), FriendlyName ), "" )

我们需要将该公式更改为以下结构:

=IFERROR( HYPERLINK( UDF( VLOOKUP( DropDownCell , Range , Column, False ) ), FriendlyName ), "" )

以下过程负责修改公式结构以使其适合所提出的解决方案。 建议将两者复制到一个名为“维护”的单独模块中。

Option Explicit

Private Sub Wsh_FmlHyperlinks_Reset()
Const kWshPss As String = "WshPssWrd"
Const kHypLnk As String = "HYPERLINK("
Dim WshTrg As Worksheet, rHyplnk As Range
Dim rCll As Range, sHypLnkFml As String
Dim sOld As String, sNew As String

    Rem Application Settings
    Application.EnableEvents = False
    Application.ScreenUpdating = False

    Rem Set & Unprotect Worksheet
    Set WshTrg = ActiveSheet
    WshTrg.Unprotect kWshPss

    Rem Find Hyperlink Formulas
    If Not (Rng_Find_Set(WshTrg.UsedRange, _
        rHyplnk, kHypLnk, xlFormulas, xlPart)) Then Exit Sub
    If rHyplnk Is Nothing Then Exit Sub

    Rem Add Hyperlinks Names
    For Each rCll In rHyplnk.Cells
        With rCll
            sHypLnkFml = .Formula
            sOld = "HYPERLINK( VLOOKUP("
            sNew = "HYPERLINK( Udf_HypLnkLct_Set( VLOOKUP("
                sHypLnkFml = Replace(sHypLnkFml, sOld, sNew)
            sOld = ", FALSE ),"
            sNew = ", FALSE ) ),"
                sHypLnkFml = Replace(sHypLnkFml, sOld, sNew)
            .Formula = sHypLnkFml
    End With: Next

    Rem Protect Worksheet
    WshTrg.EnableSelection = xlUnlockedCells
    WshTrg.Protect Password:=kWshPss

    Rem Application Settings
    Application.EnableEvents = True
    Application.ScreenUpdating = True

End Sub


Function Rng_Find_Set(rInp As Range, rOut As Range, _
    vWhat As Variant, eLookIn As XlFindLookIn, eLookAt As XlLookAt) As Boolean
Dim rFound As Range, sFound1st As String
    With rInp
        Set rFound = .Find( _
            What:=vWhat, After:=.Cells(1), _
            LookIn:=eLookIn, LookAt:=eLookAt, _
            SearchOrder:=xlByRows, SearchDirection:=xlNext, _
            MatchCase:=False, SearchFormat:=False)
        If Not (rFound Is Nothing) Then
            sFound1st = rFound.Address
            Do
                If rOut Is Nothing Then
                    Set rOut = rFound
                Else
                    Set rOut = Union(rOut, rFound)
                End If
                Set rFound = .FindNext(rFound)
            Loop While rFound.Address <> sFound1st
    End If:  End With
    Rem Set Results
    If Not (rOut Is Nothing) Then Rng_Find_Set = True
End Function

这些是公共变量和 UDF。 建议将它们复制到单独的模块中。

Option Explicit

Public psHypLnkLoct As String, pdTmeNow As Date

Public Function Udf_HypLnkLct_Set(sHypLnkFml As String) As String
    psHypLnkLoct = sHypLnkFml
    pdTmeNow = Now
End Function

并且将这个过程复制到受保护工作表的模块中,并带有动态生成的超链接。

Option Explicit

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    If Now = pdTmeNow And psHypLnkLoct <> Empty Then
        ThisWorkbook.FollowHyperlink Address:=psHypLnkLoct, NewWindow:=True
    End If
End Sub

【讨论】:

  • 优雅的解决方案!如果我错了,请纠正我,但这不会有一些问题吗? 1) 您需要取消双击,因为如果您双击锁定的单元格,Excel 将自动进入下一个可用的未锁定单元格。如果 OPs 表甚至包含一个未锁定的单元格,这可能会导致问题。 2)如果用户悬停单元格并立即双击,这不会触发吗?如果用户悬停单元格并等待几秒钟,pdTimeNow 变量会不会是多余的?我可能是错的,我现在不在 Excel 中,所以我无法运行它并检查
  • @AranDG 通过将取消变量设置为True 来取消双击事件应该是微不足道的,如果它会引起麻烦的话。也就是说,我也对 pdTimeNow 变量及其用途感到好奇。
  • @AranDG 1) 不需要取消双击,这样做是多余的。双击实际所做的(即未激活事件)是选择发生双击的单元格,因为该单元格受到保护,没有任何反应。 2a)我对这个问题感到惊讶,应该知道您帖子中使用的 Hyperlink\UDF 组合行为如何。 Hyperlink\Udf 组合导致每次鼠标移动到单元格上时都会触发 UDF。 2b) 每次用户将鼠标移动到单元格上时都会更新 pdTimeNow,包括双击移动。
  • @eirikdaude pdTimeNow 的目的是管理 psHypLnkLoct 变量的生命周期,并提供与标准单击超链接类似的行为。在激活超链接的正常环境中,用户单击链接所在的单元格,如果用户选择带有超链接的单元格然后移动到另一个单元格并单击,我们不希望超链接被触发。
  • @eirikdaude 在手头的情况下,一旦鼠标移动到带有超链接公式的单元格上,psHypLnkLoct 就会被加载,但用户可能只是在移动到另一个单元格时经过该单元格,或者只是意外地经过了在它之上,尽管如此,这一举动触发了 UDF,但由于 UDF 不是侵入性的,所以没有注意到这一点(相反的行为可以在 AranDG 帖子中清楚地看到)。因此,一旦触发双击事件,它就会使用 pdTimeNow 来验证上次加载 psHypLnkLoct 的时间,如果没有加载 NOW,那么 psHypLnkLoct 已经过时并被清除
【解决方案2】:

如果您乐于使用 VBA,您可以对相关工作表使用以下代码,这将复制超链接的点击事件并尝试以目标的本机格式打开

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If InStr(1, Target.Formula, "HYPERLINK", vbTextCompare) > 0 Then

    On Error Resume Next

    Target.Hyperlinks(1).Follow (True)

    On Error GoTo 0

End If

End Sub

更新

我想我有一些工作要做。我从here 中提取了一些代码,它允许翻转动作来触发一些vba。因此,假设您在单元格 A1 中有链接。将您的链接更改为以下内容:

=IFERROR(HYPERLINK(MyMouseOverEvent("http://www.google.com"),"Hover"),"Hover")

您可以动态更改您的链接,只要它返回一个字符串。现在创建一个新模块并粘贴以下内容:

Public Function MyMouseOverEvent(varLink As String)
    varResponse = MsgBox("Would you like to open link to: '" & varLink & "'?", vbYesNo, "Confirm")
    If varResponse = vbYes Then
        ActiveWorkbook.FollowHyperlink Address:=varLink, NewWindow:=True
    End If
End Function

唯一的缺点是它会在悬停而不是单击时触发代码,但是弹出框将允许用户决定是否要关注所述链接。我会继续查看它,看看我是否可以为点击找到一个工作区,但我认为它正在取得进展,因为即使在完全保护的情况下它也会触发。如果有帮助,我正在使用 Excel 2010。

【讨论】:

  • 嘿,如果这可行,那比我预期的答案要简单得多。如果单元格被锁定并且不允许选择锁定的单元格,SelectionChange-event 会触发吗?直到星期一回来工作我才能真正测试,但看起来不错! :)
  • 感谢您回复我未回答的问题。我通常可以将 VBA 融入其中,并会尝试使用代码。
  • 请接受我的歉意,看起来我在 Excel 2010 中偶然发现了一个怪癖。如果在保护过程中选择了包含超链接的单元格,则链接可以使用上面的代码工作,但是一旦选择了另一个单元格,代码就会失败。我会尝试另一种方法
  • @Jamiho 这项工作是否可以接受,还是您需要点击事件?
猜你喜欢
  • 2018-10-20
  • 1970-01-01
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
相关资源
最近更新 更多