VBA Excel Detect #REF! в трудовой книжке и сообщить об этом - PullRequest
2 голосов
/ 06 августа 2020

Добрый день,

Я хотел бы быстро проверить свою рабочую книгу, чтобы определить потенциальный #REF! значения.

Я нашел здесь хорошее решение:

Найти все совпадения в книге с помощью Excel VBA

, но когда я его применяю, он меняет все найдены значения.

Мне нужно что-то, что проинформирует меня, что появляется нежелательное значение.

В этом случае я изменил следующий код:

 Sub FindAndExecute()

 Dim Sh As Worksheet
 Dim Loc As Range

 For Each Sh In ThisWorkbook.Worksheets
 With Sh.UsedRange
    Set Loc = .Cells.Find(What:="#REF!")
    If Not Loc Is Nothing Then
        Do Until Loc Is Nothing
            If Loc = True Then
            MsgBox ("Error found")
            End If
            'Loc.Value = "Answered!"
            Set Loc = .FindNext(Loc)
        Loop
    End If
   End With
   Set Loc = Nothing
 Next

End Sub

Но я не вижу реакции. Есть ли способ открыть окно сообщения, когда значение #REF встречается во всей книге?

Ответы [ 6 ]

6 голосов
/ 10 августа 2020

Я уже давно использую FindLink от Bill Manville Associates, и он всегда был весьма полезен.

введите описание изображения здесь

Он выдает предупреждения, как вы имеете в виду. Вы можете использовать его как есть. Я не уверен, что вы можете получить доступ к его коду.

4 голосов
/ 06 августа 2020

Если ячейка в Excel содержит формулу с ошибкой, это означает, что это не #NAME?, #REF! или что-то в этом роде - только так excel отображает таких ошибок. Следовательно, поиск строки #REF! ничего не найдет.

Существует простая команда, которая позволяет вам найти все ячейки, содержащие ошибки - см. Следующий код (при условии, что sh установлен на лист, который вы хотите посмотрите)

Dim cell As Range
For Each cell In sh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors)
    Debug.Print cell.Address, cell.Formula
Next cell

Обновление : Как указывает BigBen, я ошибся с текстовым поиском для #REF, на самом деле вы можете использовать Find для поиска недействительных ссылок.

Если ваш код ничего не находит, возможно, вам нужно указать параметр LookAt :=xlPart.

Однако метод Find не обнаружит никаких других типов ошибок, таких как #NAME? или #DIV/0, в то время как SpecialCells найдет все типы ошибок очень простым способом.

Update2 Следующий код будет l oop на всех листах и перечислить все ячейки с ошибкой. Я также добавил код, чтобы проверить, есть ли на листе какая-либо ячейка с ошибкой - в противном случае SpecialCells вызовет ошибку времени выполнения - чтобы избежать этого, я поместил оператор в On Error Resume Next -statement.

Sub FindAndExecute()
    Dim Sh As Worksheet
    For Each Sh In ThisWorkbook.Worksheets
        Dim cell As Range, allCellsInError As Range
        Set allCellsInError = Nothing
        On Error Resume Next
        Set allCellsInError = Sh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors)
        On Error Goto 0
        If Not allCellsInError Is Nothing Then
            For Each cell In allCellsInError
               Debug.Print Sh.Name; cell.Address; cell.Formula
            Next cell
        End If
    Next
End Sub
2 голосов
/ 10 августа 2020

Ваш текущий код на самом деле настолько эффективен, насколько это возможно, ему просто нужно несколько дополнений, чтобы показать вам, где были обнаружены ошибки.

 Sub FindAndExecute()

 Dim Sh As Worksheet, errorSheet As Worksheet
 Dim Loc As Range
 Dim i As Integer
 Dim lastFound As String

 ThisWorkbook.Worksheets.add after:=Sheets(Sheets.Count)
 Set errorSheet = Sheets(Sheets.Count)
 errorSheet.Name = "Errors " & Format(Now(), "hh_mm_ss")
 i = 1
 
 For Each Sh In ThisWorkbook.Worksheets
 With Sh.UsedRange
    Set Loc = .Cells.Find(What:="#REF!")
    If Not Loc Is Nothing Then
        Do
            Set Loc = .FindNext(Loc)
            If Not Loc Is Nothing Then
                errorSheet.Cells(i, 1) = "Error on sheet " & Loc.Parent.Name & _
                    " in cell " & Replace(Loc.Address, "$", "")
               i = i + 1
               lastFound = Loc.Address
            End If
        Loop While Not Loc Is Nothing And lastFound <> Loc.Address
    End If
   End With
   Set Loc = Nothing
 Next

 If i = 1 Then errorSheet.Cells(1, 1) = "No errors were found"
 
End Sub

Итак, сначала мы добавляем лист ThisWorkbook.Worksheets.add для хранения списка ошибок.

Мы используем счетчик i As Integer для отслеживания количества найденных ошибок If i = 1 Then errorSheet.Cells(1, 1) = "No errors were found", а также для отслеживания следующей свободной строки в списке ошибок errorSheet.Cells(i, 1).

Наконец, мы используем свойство address класса Range, чтобы указать, в какой ячейке находится метод Find: Loc.Address. Я использовал метод Replace , чтобы избавиться от абсолютных квалификаторов $, поскольку свойство адреса будет префиксом ячейки и строки с ними, например, $ A $ 1.

0 голосов
/ 18 августа 2020

Мне было скучно, спокойнее (настолько!), И у меня было время сделать что-то полезное / продуктивное (это то, ради чего я живу, не могу работать, по крайней мере, не пытаясь сделать что-то хорошее). Итак, я сделал что-то, чтобы улучшить свой последний код:

Изменил массив, (gosh так приятно иметь немного времени и места без насильственной музыки c от соседей, чтобы иметь возможность сосредоточиться. что-то не в спешке или травма / беспокойство *!), чтобы оно функционировало должным образом. Также получает 1-й элемент (который отсутствовал на листе вывода предыдущего кода), а также получает текущую позицию значения ref, для которой пользователь остановил его.

Это слишком приятно. ! :) Если бы только вчера у меня был такой уровень спокойствия без стресса. Я вижу гораздо яснее. !!

Также добавлен сегмент в коде в начале, чтобы не скрывать любые скрытые столбцы, которые могут быть на листах книги (как это делает и ответ / инструмент победителя конкурса. Инструмент не может показать их, но он может обнаружить их, даже если они находятся в скрытых столбцах. Один из способов сделать это с помощью VBA - это vba-показать эти столбцы прямо вверх).

Sub FindAndExecuteVersion2()
            Dim Sh As Worksheet
            Dim answer As VbMsgBoxResult
            Dim myCell As Range 'this had to be declared to make the activations work (not for the loops ! which uses cell)
            
            Set DataRange = ActiveSheet.UsedRange 'I think you can remove this
            
            Dim myArray() As Variant
            Dim x As Long
            
Set starting_ws = ActiveSheet
For Each Sh In ThisWorkbook.Worksheets
Sh.Activate
Columns.EntireColumn.Hidden = False
Rows.EntireRow.Hidden = False
Next
starting_ws.Activate
         
            
           refcount = 0
            
            For Each Sh In ThisWorkbook.Worksheets
                Dim cell As Range, allCellsInError As Range
                Set allCellsInError = Nothing
                On Error Resume Next
                Set allCellsInError = Sh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors)
                On Error GoTo 0
                If Not allCellsInError Is Nothing Then
                    For Each cell In allCellsInError
                    If cell.Text = "#REF!" Then ''only printong the refs (igniring all other errors)
                    
                    
                    Set myCell = cell 'You need this for real time in the loop activations-selections of said cell
                    
                    Sh.Activate 'I think you can live without this.
                    myCell.Select
                    
                    ReDim Preserve myArray(x)
                     myArray(x) = Sh.Name & cell.Address
                    'x = x + 1
                    refcount = refcount + 1 '' moved it up here 18/08/2020 20:15 (below to get the 1st. start from 0 . proper)
                    'x = x + 1
                    
                   '' MsgBox "Ref Found in " & cell.Address & " " & Sh.Name
                       Debug.Print Sh.Name; cell.Address; cell.Formula
                       
                       answer = MsgBox("Do you want to go to cell " & Sh.Name & cell.Address & " and fix?", vbYesNo)
                        
                        If answer = vbYes Then
                        
                        Sh.Activate
                        cell.Select
                        GoTo Line1
                        Exit Sub
                            Else
                          'MsgBox "No"
                          'GoTo Line1
                        End If 'must thank also -  https://www.automateexcel.com/vba/yes-no-message-box/ - for this
                        
                       x = x + 1
                       End If
                       
                    Next cell
                    
                End If
            Next
  
    
Line1:

      'This section outputs the array of found refs upto the point you got to in the message boxes (either the whole thing if you say no to all, or from where you said ok yes deal with) on a sheet after all the other sheets. Basically its a screen dump of the console.
    
            
         Dim sheet As Worksheet
         Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
          
           For y = LBound(myArray) To UBound(myArray)
            Debug.Print myArray(y)
    
          Next y
          
          With ActiveSheet
          For Z = 1 To UBound(myArray) + 1 
        
          Cells(Z, 1).Value = myArray(Z - 1)  
         
          Next Z
           End With
            
     End Sub

Очень доволен этой версией. * Может это то, что либералы стремятся сделать нормализовать - переходить к и другим.!? Кто знает?. Это могло быть единственным объяснением снижения уценки.

0 голосов
/ 17 августа 2020

Но реакции не вижу. Есть ли способ открыть окно сообщения, когда значение #REF находится во всей книге?

Предоставляет окна сообщений и выбирает / активирует каждую найденную ссылку и спрашивает вас по каждой, если вы sh, с которым нужно иметь дело.

Когда одна из ячеек с ошибкой является вашим заданным c значением ("#REF!" В вашем случае), то активирует его.

См. версия 2 ниже, которая является лучшей версией (даже если она использует goto для текущих обработанных ссылок)

 For Each cell In allCellsInError
          If cell.Text = "#REF!"
            Set myCell = cell
            Sh.Activate 'I think you can live without this.
            myCell.Select

Эта часть делает это. Когда одна из ошибочных ячеек является вашим значением c ("#REF!"), Она активируется.

На протяжении всего выполнения кода, когда обнаруживается конкретное значение (Ref в вашем случае), он сопровождается окном сообщения и выбором вопроса-ответа, если вы хотите иметь дело (что фактически завершит программу и активирует указанную ячейку, содержащую эту ссылку).

  Sub FindAndExecute11()
    Dim Sh As Worksheet
    Dim answer As VbMsgBoxResult
    Dim myCell As Range 'this had to be declared to make the activations work (not for the loops ! which uses cell)
    
    Set DataRange = ActiveSheet.UsedRange 'I think you can remove this
    
    Dim myArray() As Variant
    Dim x As Long
 
    
   refcount = 0
    
    For Each Sh In ThisWorkbook.Worksheets
        Dim cell As Range, allCellsInError As Range
        Set allCellsInError = Nothing
        On Error Resume Next
        Set allCellsInError = Sh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors)
        On Error GoTo 0
        If Not allCellsInError Is Nothing Then
            For Each cell In allCellsInError
            If cell.Text = "#REF!" Then ''only printong the refs (igniring all other errors)
            
            Set myCell = cell 'You need this for real time in the loop activations-selections of said cell
            
            Sh.Activate 'I think you can live without this.
            myCell.Select
            
            refcount = refcount + 1
            ReDim Preserve myArray(x)
             myArray(x) = Sh.Name & cell.Address
            x = x + 1
            
            
            
            MsgBox "Ref Found in " & cell.Address & " " & Sh.Name
               Debug.Print Sh.Name; cell.Address; cell.Formula
               
               answer = MsgBox("Do you want to go to cell" & cell.Address & " and fix?", vbYesNo)
                
                If answer = vbYes Then
                Sh.Activate
                cell.Select
                Exit Sub
                    Else
                  'MsgBox "No"
                End If 'must thank also -  https://www.automateexcel.com/vba/yes-no-message-box/ - for this
                
               
               End If
               
            Next cell
        End If
    Next
    
    
    
    
    'the following creates a new sheet after your sheets, and dumps contents of array (the Ref locations found) into it. It will only do this if all the Ref's are worked through and youve said "no" to dealing with them. In my 2nd version (to come) I will attempt to get a worksheet dump of all ref's no matter where you are in the procedure/process.


    
    Dim sheet As Worksheet
 Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
  'Range("A1:A" & UBound(myArray)).Value = myArray(x)
  
   For x = LBound(myArray) To UBound(myArray)
    Debug.Print myArray(x)
'With sheet
'End With
  Next x
  
  With ActiveSheet
  For x = 1 To UBound(myArray)

  Cells(x, 1).Value = myArray(x)
 
  Next x
   End With
    
    
    
    
End Sub

Более доволен приведенным выше кодом, работающим адаптировано из версии пользователя @FunThomas.

Но здесь (ниже версия 2 ) я занимаюсь сбором и распечатываю ссылки ДО ТОЧКИ вы выполняете программу (поэтому, когда вы сказали «да», он останавливает код и распечатывает найденные ссылки до этого момента, если вы никогда не скажете «да», он распечатает все найденные ссылки по завершении). С «ужасными» ярлыками goto. (Известно, что СООБЩЕСТВО ПРОГРАММАТОРОВ говорит, что никогда не используйте операторы GOTO или лог c. Использование GOTO (или подпрограмм) они говорят, что это признак плохо спроектированной программы и кодирования [Я не согласен. Не всегда .] - Однако время ограничено). Тем не менее, единственный способ I мог получить обработанные ссылки, в Листе вывода для печати, В СРЕДНЕМ ПРОЦЕССЕ (окна сообщений) (так что он также распечатывает ссылки, найденные до этого момента ) должен был использовать GOTO в коде:

Также удалено одно из окон сообщений в этой версии, поскольку в этом не было необходимости, так что у вас есть только один. Мне больше нравится эта версия, поскольку она, кажется, делает все, что вы и все, с sh.

версия 2: , где все действия происходят вокруг / внутри / из-за:

answer = MsgBox("Do you want to go to cell " & Sh.Name & cell.Address & " and fix?", vbYesNo)

answer переменная, определенная ранее как VbMsgBoxResult

Но в обеих версиях я использовал счетчик для подсчета определенных c ссылок и array для хранения их позиций (таким образом вы можете распечатать значения массива, как это делается на последнем листе) внутри вложенных ifs в для каждого sh l oop.

           Sub FindAndExecuteVersion2() 
            Dim Sh As Worksheet
            Dim answer As VbMsgBoxResult
            Dim myCell As Range 'this had to be declared to make the activations work (not for the loops ! which uses cell)
            
            Set DataRange = ActiveSheet.UsedRange 'I think you can remove this
            
            Dim myArray() As Variant
            Dim x As Long
         
            
           refcount = 0
            
            For Each Sh In ThisWorkbook.Worksheets
                Dim cell As Range, allCellsInError As Range
                Set allCellsInError = Nothing
                On Error Resume Next
                Set allCellsInError = Sh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors)
                On Error GoTo 0
                If Not allCellsInError Is Nothing Then
                    For Each cell In allCellsInError
                    If cell.Text = "#REF!" Then ''only printong the refs (igniring all other errors)
                    
                    Set myCell = cell 'You need this for real time in the loop activations-selections of said cell
                    
                    Sh.Activate 'I think you can live without this.
                    myCell.Select
                    
                    refcount = refcount + 1
                    ReDim Preserve myArray(x)
                     myArray(x) = Sh.Name & cell.Address
                    x = x + 1
                    
                   '' MsgBox "Ref Found in " & cell.Address & " " & Sh.Name
                       Debug.Print Sh.Name; cell.Address; cell.Formula
                       
                       answer = MsgBox("Do you want to go to cell " & Sh.Name & cell.Address & " and fix?", vbYesNo)
                        
                        If answer = vbYes Then
                        Sh.Activate
                        cell.Select
                        GoTo Line1
                        Exit Sub
                            Else
                          'MsgBox "No"
                          'GoTo Line1
                        End If 'must thank also -  https://www.automateexcel.com/vba/yes-no-message-box/ - for this
                        
                       
                       End If
                       
                    Next cell
                    
                End If
            Next
  
    
         Line1:

      'This section outputs the array of found refs upto the point you got to in the message boxes (either the whole thing if you say no to all, or from where you said ok yes deal with) on a sheet after all the other sheets. Basically its a screen dump of the console.
    
            
         Dim sheet As Worksheet
         Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
          
           For y = LBound(myArray) To UBound(myArray)
            Debug.Print myArray(y)
    
          Next y
          
          With ActiveSheet
          For Z = 1 To UBound(myArray)
        
          Cells(Z, 1).Value = myArray(Z)
         
          Next Z
           End With
            
     End Sub
0 голосов
/ 12 августа 2020

Вот как я это сделал. Я бы и близко не подошел к этому сегодня вечером, если бы не mrfluff в MrExcel.

Для справки см. мой вопрос в Mr Excel Я написал с просьбой о помощи по поводу: цикл по столбцам и строкам любого конкретного листа в более ранней версии кода, который я разработал, который стал «использовать usedrange» благодаря отличной помощи, которую я получил от замечательного @mrfluff.

Находит all refs и активирует каждый по ходу и дает вам возможность для каждого найденного ref остановить программу и обработать ее тут же в этой ячейке. Вы можете перезапустить снова после работы.

    Sub FindRefsandErrorsinWorkbookBySheets24()
    Dim lastColumn As Integer

    Dim myCell As Range
    Dim LastRow As Long
    
    Dim myArray() As Variant
    Dim x As Long
   'Determine the data you want stored
  Set DataRange = ActiveSheet.UsedRange

'Resize Array prior to loading data
  'nope - ReDim myArray(DataRange.Cells.Count)
  
refcount = 0
Dim ws As Worksheet
'Dim starting_ws As Worksheet
'Set starting_ws = ActiveSheet 'remember which worksheet is active in the beginning
       
   For Each ws In ThisWorkbook.Worksheets
      ws.Activate
      For Each myCell In ws.UsedRange 'ws.UsedRange.SpecialCells(xlFormulas, xlErrors) 'ws.UsedRange
         If myCell.Text = "#REF!" Then
         refcount = refcount + 1
         myCell.Select '' 1. COMMENT OUT FOR SPEED
            myCell.Offset(0, 1) = "This was a ref in " & myCell.Address
            ReDim Preserve myArray(x)
            myArray(x) = myCell.Address
            x = x + 1
            MsgBox "Ref Found in " & myCell.Address ''2. COMMENT OUT FOR SPEED
            If MsgBox("do you want to edit? - press cancel", vbOKCancel) = vbCancel Then Exit Sub ''3. COMMEMT OUT FOR SPEED
            
         ElseIf IsError(myCell.Value) Then
            myCell.Offset(0, 1) = "Do you know you had different tyoe of error in " & myCell.Address & "???"
         End If
      Next myCell
      'MsgBox ws.Name
      
   Next ws
   
   MsgBox "Finished Checking. There where " & refcount & "ref errors! and they were in"
   
   Dim sheet As Worksheet
 Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
  'Range("A1:A" & UBound(myArray)).Value = myArray(x)
  
   For x = LBound(myArray) To UBound(myArray)
    Debug.Print myArray(x)
'With sheet
'End With
  Next x
  
  With ActiveSheet
  For x = 1 To UBound(myArray)

  Cells(x, 1).Value = myArray(x)
 
  Next x
   End With
   
  ''Dim sheet As Worksheet
 ''Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
  'Range("A1:A" & UBound(myArray)).Value = myArray(x)
End Sub

Он также находит все ссылки и дает вам список в конце, где они находятся.

Я предполагал, что вы хотите их по одному one, и вы можете остановить макрос на определенном, чтобы исправить это. Но если вы этого не сделаете, закомментируйте все 3 строки, относящиеся к окнам сообщений, где я написал COMMENT OUT THIS ENTIRE LINE IF YOU WANT SPEED . Каждая из них - '1,' 2 и '3.

Я вставил их в начала, но как только я убедился, что они работают, я удалил их для ускорения моего тестирования, прежде чем вставлять их обратно только сейчас.

Итак, эти 3 раздела имеют в себе комментарий «1 ...» 2 ... '3 ... полностью закомментируйте эти 3 строки, и у вас будет гораздо более быстрый макрос с только заключительным окном сообщения с общим количеством ссылок и выводом всех ссылок в немедленном окне и новым созданным листом в конце.

Я предпочитаю макрос без этих трех строк внутри, так как он работает более плавно и быстро. Но сначала вы размышляли, было бы хорошо редактировать-исследовать ссылки по ходу / по мере их нахождения. Вот почему я только что вернул их обратно. Но вы можете удалить эти 3 строки для гораздо более быстрой и менее прерывистой подпрограммы (и вы все равно получите массив - итого и распечатайте все местоположения ссылок в конце, так что на вашем месте я бы жил без этих 3 строк).

Надеюсь, я помог. У меня это сработало. :)

Вот макрос (я предпочитаю, даже если он не показывает вам ссылки во время выполнения или дает вам варианты остановки.) Без окон сообщений или активации и без вставки смещений (который у меня был только в первом, потому что я нашел их полезными при разработке):

    Sub FindRefsandErrorsinWorkbookBySheets245()
        Dim lastColumn As Integer
    
        Dim myCell As Range
        Dim LastRow As Long
        
        Dim myArray() As Variant
        Dim x As Long
       'Determine the data you want stored
      Set DataRange = ActiveSheet.UsedRange
    
    'Resize Array prior to loading data
      'nope - ReDim myArray(DataRange.Cells.Count)
      
    refcount = 0
    Dim ws As Worksheet
           
       For Each ws In ThisWorkbook.Worksheets
          ws.Activate
          For Each myCell In ws.UsedRange 'ws.UsedRange.SpecialCells(xlFormulas, xlErrors) 'ws.UsedRange
             If myCell.Text = "#REF!" Then
             refcount = refcount + 1
            ' myCell.Select '' 1. COMMENT OUT FOR SPEED
              '  myCell.Offset(0, 1) = "This was a ref in " & myCell.Address
                ReDim Preserve myArray(x)
                myArray(x) = myCell.Address(, , , 1) '' THIS GETS YOU THE SPECIFICS (SHEET NUMBER TOO)
                x = x + 1
              '  MsgBox "Ref Found in " & myCell.Address ''2. COMMENT OUT FOR SPEED
              '  If MsgBox("do you want to edit? - press cancel", vbOKCancel) = vbCancel Then Exit Sub ''3. COMMEMT OUT FOR SPEED
                
        '     ElseIf IsError(myCell.Value) Then
         '       myCell.Offset(0, 1) = "Do you know you had different tyoe of error in " & myCell.Address & "???"
            End If
          Next myCell
      
          
       Next ws
       
       MsgBox "Finished Checking. There where " & refcount & "ref errors! and they were in"
       
       Dim sheet As Worksheet

     Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
    
      
       For x = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(x)

      Next x
      
      With ActiveSheet
      For x = 1 To UBound(myArray)
    
      Cells(x, 1).Value = myArray(x)
        
      Next x
       End With
     
    End Sub

Они идентичны. Единственная разница - это ' строк, которые меняют поведение.

Это только что пришло мне в голову (фраза на вашем языке: обнаружить их и активировать ячейки, Где они появляются (optionally one by one) Это меня достало размышляя, как бы у вас могла быть возможность активировать ячейку, не зная, где эта опция видна, кроме списка, данного вам или окна сообщения (т.е. как вам может быть предоставлена ​​возможность активировать или не активировать, не видя ее?)

Но, строго следуя вашим словам, я переписал исходный макрос (в котором есть эти ненужные и потенциально возможные смещения перезаписи данных), чтобы сделать это именно так.

Ссылка сообщается вам в окне сообщения, а затем второе окно сообщения спрашивает, будете ли вы sh обрабатывать эту ссылку (с адресом) или продолжить. Да, выберите ячейку и завершите макрос / подпункт. Нет, просто продолжите.

SO Это one не активирует какую-либо ячейку или какой-либо рабочий лист, пока вы не решите. Вы получаете свои сообщения одно за другим для каждой ссылки, а любое окно сообщений с определенной ссылкой вас интересует тот, который вы решили активировать - выбрать эту ячейку ref и работать с ней или нет. немного отличается. Лист и ячейка только `` активируются '' (выбираются), и программа останавливается, когда вы решаете, основываясь на сообщении msgbox (я думаю, у вас есть хорошая мысленная карта того, где эти ячейки находятся на ваших листах, и вы уже знаете, какая из них важнее!?).

Благодаря go парню (Джону) в excelcampus и людям из automateexcel здесь

Этот тоже работает. Все 3 делают, немного по-разному, в зависимости от того, как вы читаете свои слова.

Sub FindRefsandErrorsinWorkbookBySheets26()
        Dim lastColumn As Integer
    
        Dim myCell As Range
        Dim LastRow As Long
        
        Dim myArray() As Variant
        Dim x As Long
        
        'excel campus - https://www.youtube.com/watch?v=rCh7ki9yVsM
        Dim Answer As VbMsgBoxResult
        
       'Determine the data you want stored
      Set DataRange = ActiveSheet.UsedRange
    
    'Resize Array prior to loading data
      'nope - ReDim myArray(DataRange.Cells.Count)
      
    refcount = 0
    Dim ws As Worksheet
    'Dim starting_ws As Worksheet
    'Set starting_ws = ActiveSheet 'remember which worksheet is active in the beginning
           
       For Each ws In ThisWorkbook.Worksheets
          ''' ws.Activate 'you could comment this out too if you dont need or want to see the sheets, and put it back in the "yes portion" of "i wasnt to deal with" - as you kinda implied you want to be chooser of what ref to activate
          For Each myCell In ws.UsedRange 'ws.UsedRange.SpecialCells(xlFormulas, xlErrors) 'ws.UsedRange
             If myCell.Text = "#REF!" Then
             refcount = refcount + 1
             '''''myCell.Select '' deleted because your wording kind of suggests you want to choose when to select/activate the cell.
                myCell.Offset(0, 1) = "This was a ref in " & myCell.Address
                ReDim Preserve myArray(x)
                myArray(x) = myCell.Address
                x = x + 1
                MsgBox "Ref Found in " & myCell.Address ''2. COMMENT OUT FOR SPEED
                ''''If MsgBox("do you want to edit? - press cancel", vbOKCancel) = vbCancel Then Exit Sub ''3. COMMEMT OUT FOR SPEED
                
           Answer = MsgBox("Do you want to go to cell" & myCell.Address & " and fix?", vbYesNo)
                
                If Answer = vbYes Then
                ws.activate
                myCell.Select
                Exit Sub
                    Else
                  'MsgBox "No"
                End If 'must thank also -  https://www.automateexcel.com/vba/yes-no-message-box/ - for this
                
             ElseIf IsError(myCell.Value) Then
                myCell.Offset(0, 1) = "Do you know you had different type of error in " & myCell.Address & "???"
             End If
          Next myCell
          'MsgBox ws.Name
          
       Next ws

       If refcount = 0 Then
       MsgBox "Finished Checking. There were " & refcount & " Ref Errors!"
       Exit Sub
       End If

       
       MsgBox "Finished Checking. There where " & refcount & "ref errors! and they were in"
       
       Dim sheet As Worksheet
     Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
      'Range("A1:A" & UBound(myArray)).Value = myArray(x)
      
       For x = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(x)
    'With sheet
    'End With
      Next x
      
      With ActiveSheet
      For x = 1 To UBound(myArray)
    
      Cells(x, 1).Value = myArray(x)
     
      Next x
       End With
       
      ''Dim sheet As Worksheet
     ''Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
      'Range("A1:A" & UBound(myArray)).Value = myArray(x)
    End Sub

Самый быстрый / самый простой способ imo обработать последнюю или единственную потенциальную ошибку в этом коде и завершить работу чисто (то есть, если myarray был пустым или он не нашел ссылок) и учитывать пустой массив myarray / null, без ошибки ref ситуации, было If refcount = 0 Then, иначе определение того, является ли массив пустым (myarray) = true, оказалось слишком сложной дополнительной работой и сложным в его время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...