2012-06-05 5 views
6

In Excel Ctrl +[ oder ] wird manchmal direkt auf ein anderes Blatt schalten die Präzedenzfälle oder Familienangehörige in diesem Blatt zu zeigen.wählen Programmatically anderen Blatt Präzedenzfälle oder Familienangehörige in Excel

Ich möchte das programmatisch, weil ich die Präzedenzfälle (oder abhängigen) einer Auswahl von Zellen erhalten möchte.

Range.Dependents und Range.Precedents haben other issues, aber die Lösung dort löst nicht das Extra-Blatt-Problem.

Antwort

3

Nach einem guten Stück Googeln fand ich, dass es in 2003 gelöst wurde.

Aber ich habe den Code von here verwendet. Das Problem ist, dass Dependents und PrecedentsRange Eigenschaften sind, die sich nicht auf mehrere Arbeitsblätter beziehen können.

Die Lösung verwendet NavigateArrow, um die Querbogendellen zu lokalisieren.

Hier ist mein Code:

Option Explicit 

Private Sub GetOffSheetDents(ByVal doPrecedents As Boolean) 

Dim c As Range 
Dim results As Range 
Dim r As Range 
Dim sheet As Worksheet 
Dim extra As Boolean 

For Each c In Application.Intersect(ActiveSheet.UsedRange, Selection) 
    Set r = oneCellDependents(c, doPrecedents) 
    If Not r Is Nothing Then 
     If r.Worksheet Is ActiveSheet Then 
      ' skip it 
     ElseIf sheet Is Nothing Then 
      Set sheet = r.Worksheet 
      Include results, r 
     ElseIf Not sheet Is r.Worksheet Then 
      If Not extra Then 
       extra = True 
       MsgBox "More than one external sheet in " & IIf(doPrecedents, "Precedents", "Dependents") & ". Only displaying first sheet." 
      End If 
     Else 
      Include results, r 
     End If 
    End If 
Next 

If results Is Nothing Then 
    Beep 
Else 
    results.Worksheet.Activate 
    results.Select 
End If 
End Sub 

Sub GetOffSheetDependents() 

GetOffSheetDents False 

End Sub 

Sub GetOffSheetPrecedents() 

GetOffSheetDents True 

End Sub 

Private Function Include(ByRef ToUnion As Range, ByVal Value As Range) As Range 
If ToUnion Is Nothing Then 
    Set ToUnion = Value 
Else 
    Set ToUnion = Application.Union(ToUnion, Value) 
End If 
Set Include = ToUnion 
End Function 

Private Function oneCellDependents(ByVal inRange As Range, Optional doPrecedents As Boolean) As Range 

Dim inAddress As String, returnSelection As Range 
Dim i As Long, pCount As Long, qCount As Long 

If inRange.Cells.Count <> 1 Then Error.Raise 13 

Rem remember selection 
Set returnSelection = Selection 
inAddress = fullAddress(inRange) 

Application.ScreenUpdating = False 
With inRange 
    .ShowPrecedents 
    .ShowDependents 
    .NavigateArrow doPrecedents, 1 
    Do Until fullAddress(ActiveCell) = inAddress 
     pCount = pCount + 1 
     .NavigateArrow doPrecedents, pCount 
     If ActiveSheet.Name <> returnSelection.Parent.Name Then 

      Do 
       qCount = qCount + 1 
       .NavigateArrow doPrecedents, pCount, qCount 
       Include oneCellDependents, Selection 
       On Error Resume Next 
       .NavigateArrow doPrecedents, pCount, qCount + 1 
       If Err.Number <> 0 Then _ 
        Exit Do 
       On Error GoTo 0 
      Loop 
      On Error GoTo 0 
      .NavigateArrow doPrecedents, pCount + 1 
     Else 
      Include oneCellDependents, Selection 
      .NavigateArrow doPrecedents, pCount + 1 
     End If 
    Loop 
    .Parent.ClearArrows 
End With 

Rem return selection to where it was 
With returnSelection 
    .Parent.Activate 
    .Select 
End With 
Application.ScreenUpdating = True 

End Function 

Private Function fullAddress(inRange As Range) As String 
With inRange 
    fullAddress = .Parent.Name & "!" & .Address 
End With 
End Function 
5

Mark einen guten Job gemacht, aber das Makro ging insgesamt nicht auf ‚Beulen im gleichen Blatt und ausgefallen ist, als es noch‘ Beulen aus mehreren Blättern, da die Auswahl kann nicht aus mehreren Blattzellen erstellt werden.

Ich persönlich brauchte alle diese Funktionalität, um die "Strg + [" und "Strg +]" Schnellverknüpfungsfunktionalität für den Sprung zu Präzedenzfälle und Abhängigen zu ersetzen. Leider sind diese Shortcuts auf der internationalen Tastatur völlig unbrauchbar, da diese eckigen Klammern unter der AltGr (rechte Alt) -Kombination verborgen sind und Excel weder Strg + AltGr + 8 noch Strg + AltGr + 8 erlaubt, dasselbe Ergebnis zu erhalten und auch dort keine Möglichkeit, die Standard-Verknüpfungen neu zu ordnen.

Also habe ich den Code von Mark etwas verbessert, um diese Probleme zu beheben und die Popup-Nachricht aus dem Code entfernt, da ich mich selbst wissen sollte, wenn ich nicht alle 'Dellen auswählen kann, aber ich möchte die Funktion reibungslos ohne mich haben Klicken Sie die ganze Zeit auf OK. Die Funktion springt also einfach auf das Blatt, das in der Formel zuerst verknüpft ist.

Ich hoffe, dass dies auch für andere nützlich ist.

Die einzige Sache, die mich noch stört, ist, dass während Application.ScreenUpdating = False verhindert, springt um das Blatt und die Arbeitsmappe, die Pfeile immer noch blinken. Kann ich das vermeiden?

Option Explicit 

Private Sub GetOffSheetDents(ByVal doPrecedents As Boolean) 
'Main function, calling for separate function to find links to all cells to one of the input cells. Works for finding precedents for a whole selection (group of cells) 
'doPrecedents is TRUE, if we are searching for precedents and FALSE, if looking for dependents 
Dim InputCell As Range 
Dim results As Range 
Dim r As Range 
Dim sheet As Worksheet 

Application.ScreenUpdating = False 

For Each InputCell In Application.Intersect(ActiveSheet.UsedRange, Selection) 
'Cycle to go over all initially selected cells. If only one cell selected, then happens only once. 
    Set r = oneCellDependents(InputCell, doPrecedents) 
    ' r is resulting cells from each iteration of input cell to the function. 
    If Not r Is Nothing Then  'if there were precedents/dependents 
     If sheet Is Nothing Then 'if this is the first time. 
      Set sheet = r.Worksheet 
      Include results, r 
     ElseIf Not sheet Is r.Worksheet Then 'if new precedent/dependent is on another worksheet, don't add to selection (gets lost) 
     Else 
      Include results, r 
     End If 
    End If 
Next 
Application.ScreenUpdating = True 

If results Is Nothing Then 
    Beep 
Else 
    results.Worksheet.Activate 
    results.Select 
End If 
End Sub 

Sub GetOffSheetDependents() 
'Function defines, if we are looking for Dependents (False) or Precedents (True) 
GetOffSheetDents False 

End Sub 

Sub GetOffSheetPrecedents() 
'Function defines, if we are looking for Dependents (False) or Precedents (True) 
GetOffSheetDents True 

End Sub 

Private Function Include(ByRef ToUnion As Range, ByVal Value As Range) As Range 
If ToUnion Is Nothing Then 
    Set ToUnion = Value 
    ElseIf Value.Worksheet Is ToUnion.Worksheet Then 'if new precedent/dependent is on the same worksheet, then add to selection 
      'if new precedent/dependent is on another worksheet, don't add to selection (gets lost) 
     Set ToUnion = Application.Union(ToUnion, Value) 
End If 
Set Include = ToUnion 
End Function 

Private Function oneCellDependents(ByVal inRange As Range, Optional doPrecedents As Boolean) As Range 
'Function finds dependents for one of the selected cells. Happens only once, if initially only one cell selected. 
Dim inAddress As String, returnSelection As Range 
Dim i As Long, pCount As Long, qCount As Long 
Application.ScreenUpdating = False 
If inRange.Cells.Count <> 1 Then Error.Raise 13 'seems to check, that only one cell is handled, but does not seem to be necessary step. 

'remember selection 
Set returnSelection = Selection ' to keep initial selection for GetOffSheetDents function. 
inAddress = fullAddress(inRange) ' takes address of starting cell what is analyzed. 
pCount = 1 

With inRange 'all functions apply to this initial cell. 
    .ShowPrecedents 
    .ShowDependents 
    .NavigateArrow doPrecedents, 1 ' go to first precedent (if first argument is true)/dependent. But why required? 
    Do Until fullAddress(ActiveCell) = inAddress 
     .NavigateArrow doPrecedents, pCount 'go to first precedent, then second etc. 
     If ActiveSheet.Name <> returnSelection.Parent.Name Then ' checks, if the precedent is NOT on the same sheet 

      Do 
       qCount = qCount + 1 'qCount follows external references, if arrow is external reference arrow. 
       .NavigateArrow doPrecedents, pCount, qCount 'go to first exteranl precedent, then second etc. 
       Include oneCellDependents, Selection 
       On Error Resume Next 
       .NavigateArrow doPrecedents, pCount, qCount + 1 'could remove this step and check for error before Include? 
       If Err.Number <> 0 Then Exit Do 
       On Error GoTo 0 ' not sure if this is used, since if there is error, then already Exit Do in previous step. 
      Loop 
      On Error GoTo 0 'not sure, if necessary, since just asked in loop. 
     Else ' if precedent IS ON the same sheet. 
      Include oneCellDependents, Selection 
     End If 
     pCount = pCount + 1 
     .NavigateArrow doPrecedents, pCount 
    Loop 
    .Parent.ClearArrows 
End With 

'return selection to where it was 
With returnSelection 
    .Parent.Activate 
    .Select 
End With 

End Function 

Private Function fullAddress(inRange As Range) As String 
'Function takes a full address with sheet name 

With inRange 
    fullAddress = .Parent.Name & "!" & .Address 
End With 
End Function 
+0

+1, wie Sie eine bessere allgemeine Lösung für ein größeres Problem haben, als ich hatte, aber ich habe das grüne Häkchen nicht eingeschaltet, weil ich wissen will _do_, wenn ich nicht alle ‚Beulen gesehen habe. –

+0

In Ihren hinzugefügten Kommentaren fragen Sie nach 'On Error GoTo 0'. Dadurch wird die Fehlermeldung "On Error Resume Next" deaktiviert, und Sie müssen feststellen, ob ein Fehler vorliegt oder nicht, also an zwei Stellen. –

+0

Und der 'inRange.Cells.Count <> 1' Check ist nur defensive Programmierung. –

0

Ich fand Kaidobors Version von Mark Hurds Code genau, was ich brauchte. Ich habe einen Wrapper geschrieben, um alle Abhängigkeiten in den ausgewählten Zellen zu dokumentieren und sie in ein neues Blatt einzufügen. Mein Code ruft nur den Code von Kaidobor auf und speichert die Ergebnisse.

Mein Anwendungsfall: Ich habe eine komplexe Tabelle (von jemand anderem geschrieben), die ich aufräumen muss. Ich möchte einige Blätter löschen, die unnötig erscheinen, aber wissen wollen, wo ich Formeln brechen werde, bevor ich die Blätter lösche. Dadurch wird ein Index erstellt, der alle Zellen anzeigt, auf die in anderen Blättern verwiesen wird.

Sub FindDependentsForThisSheet() 
' Find all cells in the selection that have dependents on some other sheet 
' Calls code by kaidobor 
' January 9, 2017 
Dim rCurrent As String, strNoDependents As String, strDependents As String, strCurrrentParent As String 
Dim aDependents(1000, 4) As String ' Starting sheet, starting cell, referenced sheet, referenced cell 
Dim intArrayRows As Long 
strNoDependents = "No Dependents" & vbCrLf 
strDependents = "Dependents" & vbCrLf 
intArrayRows = 0 
Application.ScreenUpdating = False 

'Step through each cell in the current sheet (for each…) 
For Each cell In Selection.Cells 
    ' improvement: step through just the cells that are selected in case I know some are not worth bothering with 
    Range(cell.Address).Select 
    rCurrent = ActiveCell.Address 
    strCurrrentParent = ActiveCell.Parent.Name 
    'Run GetOffSheetDependents() for each cell 
    GetOffSheetDependents 
    'GetOffSheetPrecedents 
    'When GetOffSheetDependents() is done, if the ActiveCell.Address is not changed, 
    'If (rCurrent = ActiveCell.Address And strCurrrentParent = ActiveCell.Parent.Name) Then ' We do care about links on the current sheet 
    If (strCurrrentParent = ActiveCell.Parent.Name) Then ' Do not care about links on the current sheet 
     'then nothing 
     strNoDependents = strNoDependents & ActiveCell.Parent.Name + " - " + ActiveCell.Address & vbCrLf 
    Else 
     ' Stuff the array 
     aDependents(intArrayRows, 0) = strCurrrentParent 
     aDependents(intArrayRows, 1) = rCurrent 
     aDependents(intArrayRows, 2) = ActiveCell.Parent.Name 
     aDependents(intArrayRows, 3) = ActiveCell.Address 
     intArrayRows = intArrayRows + 1 
     strDependents = strDependents + strCurrrentParent + "!" + rCurrent + " referenced in " + ActiveCell.Parent.Name + "!" + ActiveCell.Address & vbCrLf 
     '1 record ActiveCell.Address + parent. 
     '2 return to home sheet and 
     Sheets(strCurrrentParent).Select 
     '3 record the address of the active cell 
    End If 
    If intArrayRows > 999 Then 
     MsgBox "Too many cells, aborting" 
     Exit Sub 
    End If 
Next 
'Debug.Print strDependents 
'Debug.Print strNoDependents 

' Store results in a new sheet 
If intArrayRows > 0 Then 
    varReturn = NewSheetandPaste(aDependents) 
    MsgBox ("Finished looking for dependencies. Created sheet with results. Found this many: " & intArrayRows) 
Else 
    MsgBox ("Finished looking for dependencies, found none.") 
End If 
Application.ScreenUpdating = True 
End Sub 
' ************************************************************************************************ 

Function NewSheetandPaste(aPasteThis As Variant) '(strSheetName As String) 
' Create new sheet and past strDependents 
Dim strName As String, strStartSheetName As String, n As Long 
'strName = strSheetName + "Dependents" 
strStartSheetName = ActiveSheet.Name 
strName = strStartSheetName + "Dependents" 
Sheets.Add After:=ActiveSheet 
ActiveSheet.Name = strName 
'Sheets("Sheet4").Name = "Sheet1Dependents" 
Range("A1").Value = "Dependents from " + strStartSheetName 
'ActiveCell.FormulaR1C1 = "Dependents from Sheet1" 
'Range("A2").Value = strPasteThis 
Range("A2").Value = "Starting Sheet" 
Range("B2").Value = "Starting Sheet Cell" 
Range("C2").Value = "Dependent Sheet" 
Range("D2").Value = "Dependent Sheet Cell" 

Range("A3").Select 
intLengthArray = UBound(aPasteThis) - LBound(aPasteThis) + 1 
n = 0 
'For n = 0 To intLengthArray 
While aPasteThis(n, 0) <> "" 
    ActiveCell.Value = aPasteThis(n, 0) 
    ActiveCell.Offset(0, 1).Select 
    ActiveCell.Value = aPasteThis(n, 1) 
    ActiveCell.Offset(0, 1).Select 
    ActiveCell.Value = aPasteThis(n, 2) 
    ActiveCell.Offset(0, 1).Select 
    ActiveCell.Value = aPasteThis(n, 3) 
    ActiveCell.Offset(1, -3).Select 
    n = n + 1 
Wend 

NewSheetandPaste = True 
End Function 
Verwandte Themen