.Paste works in 'If' portion of statement, but not 'Else' - vba

I'm automating a process to import data from a worksheet, though for data integrity (and to eventually append to a database), I do not want the identifier entered twice. My code works to import the data if the identifier (SHC_No) is not in column A, and to prompt if you would like to replace the entries because something has changed. It will delete the entries, and find the next blank row, but the .paste function will not operate. (Even though it is on the cell I want to paste into and I can see the data in the clipboard.)
I have gotten Run Time Error 1004 "Paste method of worksheet class failed," and "PasteSpecial Method of Range class failed," as well as 438 "Object doesn't support this property or method."
I'm relatively new to Excel VBA. I have tried different variations of .paste and .pastespecial and nothing seems to work. I have tried With statements, and defining the range. I'm at a loss.
Any ideas or suggestions, would be greatly appreciated.
Sub ImportAPDR()
Dim wbImport As Workbook
Dim wbCurrent As Workbook
Dim strSHC As String
Set wbImport = Workbooks("ImportPhase2.xlsm") 'Ensure name of the workbook... and don't change it.
Set wbCurrent = ActiveWorkbook
'On Error GoTo Handler:
Application.ScreenUpdating = False 'Prevents flickering screen.
'Activate Page 3 of the APDR
Worksheets("Page 3").Activate
strSHC = Range("A11").Value
Range("A11").Activate
Do
If ActiveCell.Value = "" Then Exit Do
ActiveCell.Offset(1, 0).Activate
Loop
'Selects All data from A11 until the EOR
ActiveCell.Offset(-1, 12).Activate
Range("A11", ActiveCell).Select
Selection.Copy
'Find the first blank cell in the Import workbook.
wbImport.Activate
Worksheets("Import").Activate
FindSHC (strSHC) 'Must send a variable or the other subroutine will not work.
Application.ScreenUpdating = True
Exit Sub
'Handler:
'MsgBox ("Ensure to run the macro on the APDR workbook, not the import workbook.")
End Sub
Sub FindSHC(strSHC As String)
Dim foundSHC As String
Dim Rng As Range
Dim StartRange As Range
Dim PasteRng As Range
FindString = strSHC
If Trim(strSHC) <> "" Then
With Sheets("Import").Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Rng Is Nothing Then
Range("A1").Activate
Do
If ActiveCell.Value = "" Then Exit Do
ActiveCell.Offset(1, 0).Activate
Loop
ActiveSheet.Paste
Application.CutCopyMode = False
MsgBox ("The Tenant/Unit Details have been copied for import.")
Else
Application.Goto Rng, True
Set StartRange = ActiveCell
Answer = MsgBox("This APDR looks like it has already been imported." & vbNewLine & "Do you want to reimport and replace?", vbYesNo)
If Answer = vbYes Then
'Finds the values that have previously been entered and loops to select them all for deletion.
Do
If ActiveCell.Value <> strSHC Then Exit Do
ActiveCell.Offset(1, 0).Activate
Loop
ActiveCell.Offset(-1, 0).Activate
Range(StartRange, ActiveCell).Select
Selection.EntireRow.Delete Shift:=xlUp
'Find the next open row
Range("A1").Activate
Do
If ActiveCell.Value = "" Then Exit Do
ActiveCell.Offset(1, 0).Activate
Loop
ActiveSheet.Paste '<-----This is where I get my error.
Application.CutCopyMode = False
MsgBox ("The Tenant/Unit Details have been replaced.")
Else
Application.CutCopyMode = False
MsgBox ("Import has been cancelled.")
End If
End If
End With
End If
End Sub

Here are some tips to avoid getting stuck in such moments.
Always try to emulate what macro does by manually performing all the actions, wherever it is possible to. In your case you can choose 2 identifiers for QA - one which is not present and another which is present. You won't have any trouble with the first one, but with the second - as soon as you delete any cell content after you have copied some range, your selection and copied range would be lost from clipboard. And that's actually what makes a trouble.
Do proper debugging. As soon as you go into strange exception - debug what brought your code to this point. And again - in your case you can see that as soon as you delete contents the "dashed border" around copied range will disappear, meaning you have no copied range anymore which you could paste.
This one goes directly to copy-paste combination. Whenever you are in need to use Copy & Paste build up your code so that these two go one after another. Avoid any range interaction between these two functions. If you need to do some calculations just save the range parameters(like range rectangle dimensions, starting row+column, ending row+column) to other variables and Copy only when you've done with everything using those saved parameters.
Good luck with this one.

Related

How to stop Loop If current cell selection is empty?

I want to stop my loop if the current selection is empty. I have tried the following:
If (IsEmpty(Sheets("Sheet3").ActiveCell)) Then Exit Do
If Sheets("Sheet3").Selection.Value = "" Then Exit Do ;tried to replace "" with Empty and Nothing but didn't work either
If Sheets("Sheet3").Activecell.Value is Empty Then Exit Do
If Sheets("Sheet3").Selection is blank Then Exit Do
The issue is if I don't stop the loop somehow it will carry on forever.
I was hoping somebody can help me here.
EDIT :
This is my code:
Public Sub CopyFilteredData()
Do
Sheets("Sheet4").Select
ActiveSheet.Range("$A$1:$R$25239") _
.AutoFilter _
Field:=5, _
Criteria1:=Sheets("Sheet3").Application.Selection.Value
Range("A1").Select
ActiveCell.CurrentRegion.Select
Selection.Copy
Sheets("Sheet5").Select
Range("A1").Select
ActiveCell.End(xlDown).Select
Selection.Offset(1, 0).Select
ActiveSheet.Paste
Range("A1").Select
ActiveCell.End(xlDown).Select
Selection.Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "+"
Sheets("Sheet3").Select
Selection.Offset(1, 0).Select
' This is where the code to stop the loop needs to go
Loop
End Sub
This question is a classic case of the XY Problem.
Y Solution
The main reason none of your four attempts to detect an empty cell work, is a lack of understanding on what Selection and ActiveCell actually are. They are properties of the Application object and return the following
Selection - the selected object of the active sheet (the top most sheet)
ActiveCell - the active cell of the active sheet (the top most sheet)
You can't use Sheets("Sheet3").ActiveCell or Sheets("Sheet3").Selection as the Sheet object doesn't have these properties.
What you can use is Application.ActiveCell and Application.Selection or, more simply, ActiveCell and Selection. Of course, this will only work after activating Sheet3.
My preferred way of doing this is:
Sheets("Sheet3").Activate
If (IsEmpty(ActiveCell)) Then Exit Do
Your code also contains a similar problem with this bit:
Criteria1:=Sheets("Sheet3").Application.Selection.Value
While the code correctly gets the Selection object, it doesn't actually activate Sheet3 and is exactly the same as writing:
Criteria1:=Application.Selection.Value or Criteria1:=Selection.Value
Fixing this issue by storing the Sheet3 selection value in a variable leads to the following working code:
Option Explicit
'(v0.2)
Public Sub Y_Fixed_BUT_VERY_VERY_VERY_BAD_CODE()
' Added three lines and changed a fourth to fix the incorrect usage of "Selection" for the criteria
' Changed a fifth line to add the correct loop exit code
Sheets("Sheet3").Activate ' Fix#1 Not necessary if the code is always run from Sheet3
Dim varSheet3ActiveCellValue As Variant ' Fix#2
Do
varSheet3ActiveCellValue = ActiveCell.Value2 ' Fix#3
Sheets("Sheet4").Select
ActiveSheet.Range("$A$1:$R$25") _
.AutoFilter _
Field:=5, _
Criteria1:=varSheet3ActiveCellValue ' Fix#4
Range("A1").Select
ActiveCell.CurrentRegion.Select
Selection.Copy
Sheets("Sheet5").Select
Range("A1").Select
ActiveCell.End(xlDown).Select
Selection.Offset(1, 0).Select
ActiveSheet.Paste
Range("A1").Select
ActiveCell.End(xlDown).Select
Selection.Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "+"
Sheets("Sheet3").Select
Selection.Offset(1, 0).Select ' Fix#5
If IsEmpty(ActiveCell) Then Exit Do
Loop
End Sub
X Solution
As mentioned in response to your first posted question, you really, really need to learn how to avoid using .Select. This Stack Overflow post is a good place to start.
The following code is the equivalent to the above, without using a single .Select, .Activate, Selection, or ActiveCell. It also includes a better way to find the last value in a column. (Your method fails unless there is a least one cell containing a value after the first cell.)
A useful way to work out how the code works is to select a word in it, for example With and pressing F1. This will bring up the Excel Help related to that word, with explanations and examples.
'============================================================================================
' Module : <in any standard module>
' Version : 1.0
' Part : 1 of 1
' References : N/A
' Source : https://stackoverflow.com/a/47468132/1961728
'============================================================================================
Option Explicit
Public Sub X__GOOD_CODE()
Dim rngFilterCriteriaList As Range
With Sheets("Sheet3").Range("A3")
Set rngFilterCriteriaList = Range(.Cells(1), .EntireColumn.Cells(Rows.Count).End(xlUp))
End With
Dim rngCell As Range
For Each rngCell In rngFilterCriteriaList
Sheets("Sheet4").Range("A1:R25239") _
.AutoFilter _
Field:=Range("E:E").Column, _
Criteria1:=rngCell.Value2
Sheets("Sheet4").Range("A1").CurrentRegion.Copy _
Destination:=Sheets("Sheet5").Range("A:A").Cells(Rows.Count).End(xlUp).Offset(1)
Sheets("Sheet5").Range("A:A").Cells(Rows.Count).End(xlUp).Offset(1).Value2 = "+"
Next rngCell
Sheets("Sheet4").Cells.AutoFilter
End Sub
if u cannot specify the range then have to activated sheet3 then its works refer below:
ThisWorkbook.Worksheets("Sheet3").Activate
If ActiveCell = "" Then
Exit Do
End If
Your selection will not change if you are not changing the cell by using .select in the code and therefore will likely result in infinite loop. But using .select in the code is not considered as good practice as it slows down the process.
I'd suggest using For...each Loop like below.
Dim rng as Range
For each rng in selection
If Len(rng.Value) = 0 then Exit Sub '\\ Exit at first blank cell
'\\ Do process here
Next rng
selection can contain 1 or more cells. If you want to check if all the cells in the selection are empty you can use the worksheet function countblank which returns the number of empty cells. If the number of empty cells in the selection equals the number of cells in the selection then all the cells in the selection are empty. your test can be adapted like this
If Application.WorksheetFunction.CountBlank(Selection) = Selection.Count Then Exit Do
Your solution is here.
Credits to mvptomlinson from MrExcel.com
The right code is
'Your code to loop through copying sheets
If ActiveSheet.Range("A1").Value = "" Then Exit Sub
'Your code to continue if A1 isn't empty

Error when referring to a previous dimmed activecell (Run-time Error '1004')

I am currently in the process of re-purposing some older code to function as a loop rather then as 160 different macros (literally).
Anecdotally, I have committed the cardinal sin of selecting ranges and using active cell (partially due to my ignorance of how this would work otherwise), I have attempted to rebuild this using by assigning cell = cell etc, however I was unsure how this would work, I have returned to what I know.
The code is as follows:
Sub Refined_Code()
' Turn off the usual system hogs.
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
ActiveWorkbook.ForceFullCalculation = False
' Dim some ranges for use later on.
Dim BU As Range
Set BU = Sheets("Control").Range("C3")
Dim PorT As Range
Set PorT = Sheets("Control").Range("C8")
Dim BUStart As Range
Set BUStart = Sheets("Control").Range("D3")
Dim MasterData As Range
Set MasterData = Sheets("Parent and Child view").Range("Y6:Y180")
Dim MasterPaste As Range
Set MasterPaste = Sheets("Parent and Child view").Range("F6")
Dim BUlist As Range
Set BUlist = Sheets("Parent and Child view").Range("I106:AR116")
Dim PrevCell As Range
' Selects sheet "parent and child view" clears the data from the range, then selects the "Control' sheet.
Sheets("Parent and Child view").Select
Range("F6:R1000").Select
Selection.ClearContents
Sheets("Parent and Child view").Range("G6") = "G6"
Sheets("Control").Select
' Look up the datavalidated cell in D3 and find the right column
Range("G106:AR106").Select
Selection.Find(What:=BUStart.Value, After:=ActiveCell).Activate
ActiveCell.Select
Selection.Offset(1, 0).Select
' This will lookup the Range in D3, and commence running the macro chain.
Do While (Selection.Offset(1, 0) <> "")
Application.Calculation = xlCalculationManual
Sheets("Control").Select
BU.Value = ActiveCell.Value
Set PrevCell = ActiveCell
Application.Calculation = xlCalculationAutomatic
If InStr(1, ActiveCell, " ") = 1 Then
PorT.Value = "Target"
Else
PorT.Value = "Plan"
End If
Sheets("Parent and Child view").Select
MasterData.Copy
MasterPaste.Select
ActiveCell.End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.PasteSpecial xlPasteValues
PrevCell.Select
Selection.Offset(1, 0).Select
Loop
MsgBox "Finished"
End Sub
The code appears to crash on the line
PrevCell.Select
with a run-time error '1004' select method of range class failed.
I have tried following previous 'solved' guides for people who have used select, including placing the worksheet name and re-selecting this etc, but to no avail.
Any help or workaround would be GREATLY appreciated.
Warm regards,
RB.
[Update]
Thanks for the help guys, the solution was simple once the problem was identified, the range error was the result of trying to select the activecell on the incorrectly selected sheet.
Moral is, don't use select, but if you have to, atleast make your code tight.
The issue is here:
MasterPaste.Select
ActiveCell.End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.PasteSpecial xlPasteValues
PrevCell.Select
You've set MasterPaste as Sheets("Parent and Child view").Range("F6"). But in this section of the loop...
Sheets("Control").Select
BU.Value = ActiveCell.Value
Set PrevCell = ActiveCell
...you set PrevCell to the ActiveCell, which is on the "Control" Worksheet (see 2 lines prior). Then, 7 lines later, you do this:
Sheets("Parent and Child view").Select
Now, the ActiveSheet is "Parent and Child view", which doesn't change before you call PrevCell.Select. PrevCell is (see above) a Range on Worksheet "Control" which isn't the active sheet. Excel will throw a 1004 if you try to select a Range that isn't on the active Worksheet.
Your instinct toward a top-down re-write is well warranted - it's close to impossible to decipher what you intend that this code does with all of the references to active objects and navigation through selection. I'd suggest a top down re-write without using Select, Active* or any of the other global objects.

How to loop through rows, save these as variables and use them as variables VBA

I'm trying to store values in sheets as a variable, and then go on to reference a sheet using that variable as well as use it to filter by.
This will be looped through until the program reaches the first empty cell.
The relevant code I have so far is:
Sub Program()
Dim i As Integer
i = 2
Do Until IsEmpty(Cells(i, 1))
Debug.Print i
Sheets("Button").Activate
Dim First As String
First = Cells(i, 1).Value
Debug.Print First
Dim Second As String
Second = Cells(i, 2).Value
Debug.Print Second
'Filters my Data sheet and copies the data
Sheets("DATA").Activate
Sheets("DATA").Range("A1").AutoFilter _
Field:=2, _
Criteria1:=First 'Filters for relevant organisation
Sheets("DATA").Range("A1").AutoFilter _
Field:=6, _
Criteria1:="=" 'Filters for No Response
Sheets("DATA").Range("A1:H6040").Copy
'This should loop through for each separate group
Sheets(CStr(Second)).Select
Range("A1").Select
ActiveSheet.Paste
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Loop
Worksheets("DATA").AutoFilterMode = False
End Sub
I have changed the program significantly trying to add notation such as 'CStr' as there was an error at this line:
Sheets(CStr(Second)).Select when it used to say Sheets(Second)).Select
and the debug.print's to see if it is actually working but it isn't logging to the Immediate Window.
Additionally, when I actually run it, no error comes up but nothing seems to happen.
Not sure what else to add, or what else to try. Cheers!
As a first remark, using (at least the first) sheet activation within the loop seems unnecessary, because the start of the loop is what determines which sheet is being used to control the flow of the loop.
Furthermore, I would argue that it is better to remove the sheet activation altogether, re: the discussion about .Select (the cases aren't the same, but the solution discussed herein works better for both .Select and .Activate in almost all instances): How to avoid using Select in Excel VBA macros.
Let's also see if we can refer to the table in the "DATA" sheet in a more direct manner, as well as do some errorchecking.
My suggestion:
Sub Program()
Dim i As Integer
Dim First, Second As String
Dim secondWs As Worksheet
Dim dataTbl As ListObject
i = 2
Set dataTbl = Worksheets("DATA").Range("A1").ListObject.Name
' The above can be done more elegantly if you supply the name of the table
Sheets("DATA").Activate
Do Until IsEmpty(Cells(i, 1))
Debug.Print i
First = Sheets("Button").Cells(i, 1).Value
Debug.Print First
Second = Sheets("Button").Cells(i, 2).Value
Debug.Print Second
'Filters my Data sheet and copies the data
dataTbl.AutoFilter _
Field:=2, _
Criteria1:=First 'Filters for relevant organisation
dataTbl.AutoFilter _
Field:=6, _
Criteria1:="=" 'Filters for No Response
Sheets("DATA").Range("A1:H6040").Copy
'This should loop through for each separate group
On Error Resume Next
Set secondWs = Worksheets(Second)
On Error GoTo 0
If Not secondWs Is Nothing Then
secondWs.Range("A1").PasteSpecial Paste:=xlPasteValues
Else
Debug.Print "Sheet name SECOND was not found"
End If
i = i + 1
Loop
Worksheets("DATA").AutoFilterMode = False
End Sub
If you get any errors, please state which line it appears on and what the error message actually is.
Ref:
http://www.mrexcel.com/forum/excel-questions/3228-visual-basic-applications-check-if-worksheet-exists.html#post13739

How To Paste My Formula In A Cell With Specific Text Instead Of A Column?

I pretty much have an already working macro for me but for the future it may cause problems because the macro i have finds the column i gave it and then starts to input the formula there. Now my data may change in the future and in that column i might have something new so the macro would obviously run the formulas to the wrong column. Changing it manually is possible but hectic and a lot of work. Is there any possible way i can select a cell with a specific text in it instead of the column? since the text will never change this will me much easier for me to work with. Because doing this the formulas will always be posted in the correct column.
EDIT! I added the whole code to the post so you can see it more clearly and understand what i mean more clearly.
Sub HW_Copy_RawData_Formulas()
Dim intChoice As Integer
Dim strPath As String
Dim I As Integer
Dim filePath As String
Dim SourceWb As Workbook
Dim TargetWb As Workbook
Dim Lastrow As Long
Dim Nrow As Long
Set TargetWb = ActiveWorkbook
' Delete Rows
On Error Resume Next
TargetWb.Worksheets("Raw Data").Activate
Range("A2:AL2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
Range("A2:AL2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
'Copy Formulas
Range("AF2").Formula = "=IF([#ServDt]<DATE(2013,1,1), DATE(YEAR([#ServDt]),12,31),EOMONTH([#ServDt],0))"
Range("AG2").Formula = "=IF([#Amount]>1,[#Quantity],0)"
Range("AH2").Formula = "=IF([#Amount]<>0,[#Amount]-[#Adj]-[#[Adjustment ]],0)"
Range("AI2").Formula = "=IF(AND([#Department]=""HH"",[#Pay]=0),[#Amount]/2,0)"
Range("AJ2").Formula = "=IF([#Amount]<>0,[#Bal]-[#[Adjustment ]],[#Bal]+[#Adj])"
Range("AK2").Formula = "=VLOOKUP([Department],Service[#All],2,FALSE)"
Range("AL2").Formula = "=VLOOKUP([#Entity],Site,3,FALSE)"
MSG1 = MsgBox("Add Raw Data", vbYesNo)
If MSG1 = vbYes Then
'only allow the user to select one file
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogOpen).Show
'determine what choice the user made
If intChoice <> 0 Then
'get the file path selected by the user
strPath = Application.FileDialog( _
msoFileDialogOpen).SelectedItems(1)
Else: GoTo endmsg
End If
'Setting source of data
Set SourceWb = Workbooks.Open(strPath)
Lastrow = SourceWb.Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
SourceWb.Worksheets(1).Range("A2:BJ" & Lastrow).SpecialCells(xlCellTypeVisible).Select
Selection.Copy Destination:=TargetWb.Sheets("Raw Data").Range("A2")
' Close the source workbook without saving changes.
SourceWb.Close savechanges:=False
Else
endmsg:
MsgBox "Complete"
End If
Range("AF2:AL2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Range("AF2").PasteSpecial xlPasteValues
End Sub
The following code snippet might be of use to you. It acquires the range of the cell given a specific value. It can also be used to search a specific row with .Rows() instead.
Dim *YOURCELL* As Range
Set *YOURCELL*= .Columns(1).Find(What:= *WHATYOUWANTTOFIND*, LookAt:=xlWhole, MatchCase:=False, searchformat:=False)
If, however, you do not know where the last used cell is located, then consider reading this other post.
EDIT:
The while loop runs as long as the currently selected cell is not empty. In this loop, it selects the next cell to the right and increments a count. After the loop has finished, the currently selected cell is the first empty cell in the second row. Count has found the column number of it by incrementing alongside the loop, so it can then be used as needed. I used cells instead of range afterwards because it can use the column number.
Range("A2").Select
Dim count As Integer
count = 1
'skip all used cells in the row
Do While Not (ActiveCell.value = None)
ActiveCell.Offset(0, 1).Range("A1").Select
count = count + 1
Loop
Cells(count, 2).Formula = your_formula
Cells(count + 1, 2).Formula = your_formula ' next cell to the right
Cells(count + 2, 2).Formula = your_formula ' next cell to the right

How to create proper loops in VB (macro)

I have recorded and polished the following macro which should create an extra sheet with hypertext links pointing on a starting cell of each table within the original sheet called "All_tables". In this sheet, every single table is separated by a hash symbol (#). See a screenshot:
Sub Create_list_of_tables()
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = "list of tables"
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:="", SubAddress:= _
"All_Tables!A22", TextToDisplay:="some variable pointing at the table name"
Range("A2").Select
End Sub
Now I would like to put it into a loop which would repeat itself ten (or more) times. I tried to use the hash symbol as a reference point for a program to find out at which cell he should point the hyperlink. Here is the result:
Sub Create_list_of_tables()
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = "list of tables"
Const cStrDivider As String = "#"
Dim rMyCell As Range
Dim table_number As Long
table_number = 0
Do Until table_number = 10
Set rMyCell = Range("cStrDivider").Select
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:="", SubAddress:= _
"All_Tables!&rMyCell", TextToDisplay:="some variable pointing at the table name"
ActiveCell.Offset(1, 0).Select
table_number = table_number + 1
Loop
End Sub
And it doesn't work. I am totally new to macro and VB programming so I'd be really happy if you could at least show me the direction. Is my approach is completely wrong?
Thank you so much
I'm not sure exactly where you want your hyperlink pointing but this should get you a good start. Things to look out for:
Don't use Select or Selection statements. They are slow and can produce undesirable effects. Instead use very explicit statements that do not depend on cursor position but rater the absolutle position of where you know things are.
Use the Find and FindNext method of a range object to locate strings. When FindNext can't find anything more it returns nothing. Good to check for instead of doing your table_number loop.
updated
Sub Create_list_of_tables()
Const cStrDivider As String = "#"
Dim sht As Worksheet, rMyCell As Range, rSearchRange As Range
Dim testSht As Worksheet, firstMyCell As Range
Set sht = ActiveSheet
On Error Resume Next
Set testSht = ActiveWorkbook.Sheets("All_Tables")
If Err.Number <> 9 Then
Application.DisplayAlerts = False
testSht.Delete
Application.DisplayAlerts = True 'important to set back to true!
End If
On Error GoTo 0
ActiveWorkbook.Sheets.Add After:=Sheets(Sheets.Count)
ActiveWorkbook.Sheets(Sheets.Count).Name = "All_Tables"
Set rSearchRange = sht.Range("A:A")
'do initial "Find"
Set rMyCell = rSearchRange.Find(cStrDivider)
Set firstMyCell = rMyCell
Do
sht.Hyperlinks.Add Anchor:=rMyCell.Offset(0, 1), Address:="All_Tables!" & rMyCell.Address, _
TextToDisplay:="Link"
'get the next "MyCell" to use from the master range to search
Set rMyCell = rSearchRange.FindNext(rMyCell)
'increment your table counter (if you want to do this you can still
table_number = table_number + 1
Debug.Print firstMyCell.Address
Debug.Print rMyCell.Address
Loop While firstMyCell.Address <> rMyCell.Address
End Sub
See how that works an move on from there.