excel vba activating a tab by name using a variable string - vba

Can someone please help? I have a feeling that this type of issue is a simple one and has been answered many times but I can't seem to find a solution that works. Getting hit by error 9: subscript out of range.
A good part of the frustration is due to the simplicity of the code that works. I have a spreadsheet with tabs named like "Dist.12345-Store.67890". I have VBA code that will successfully open that tab if I use:
Sub test()
Worksheets("Dist.12345-Store.67890").visible = true
End sub
But rather than hard code this string in the code 31 times in 31 different subs I want to put a string together as a variable storeselect2, and refer to this string as the worksheet to appear. But I get that error 9...
Sub test()
Dim storeselect2 As String
storeselect2 = "Dist." & ActiveCell.Offset(0, -1).Value & "-Store." & ActiveCell.Value
` the storeselect2 is now = "Dist.12345-Store.67890" `
Sheets(storeselect2).Visible = True `this is where error 9 occurs`
End Sub
How can I get an existing tab to come up when using a string to refer to the tab name in the code? Is it due to the string coming from one tab and trying to open another?
Thanks!!

This what you need to write
Dim storeselect2 As String
Dim pig, dog, cat, bird As String
pig = "Dist."
dog = ActiveCell.Offset(0, -1).Value
cat = "-Store."
bird = ActiveCell.Value
storeselect2 = pig & dog & cat & bird
Sheets(storeselect2).Visible = False

For those arriving at this question (from Google?) seeking the straight-forward answer for how to activate a tab by name using a variable string:
Sheets(23).Activate
or
Worksheets(1).Select
or
Sheets("mytabname").Activate
It is not necessary to activate a worksheet in order to manipulate it programmatically, you can also just select it:
Sheets("mytabname").Select
This answer explains that it is not necessary to either select or activate a worksheet before manipulating it. Doing either one slows down the code. However, I (and others) have run into situations where first selecting or activating the sheet we want to manipulate seems to be necessary to avoid an error.
References:
https://www.automateexcel.com/vba/activate-select-sheet/
Excel Select vs Activate

Related

Workbook variable name from drop down box

I have 10 workbooks with near identical names "???????? Service Planner.xlsm" where ???????? is a place name. They all have identical tab names and identical column headers. Instead of going into the files 1 by 1 i'd like to have a seperate file that will lookup the information that i need. I'd like to have a drop down box with the "????????" part of the file name, when selected the correct file would open and my seperate file would populate by using vlookup.
I've used worksheet change before and have target.value as a sheet name, i thought i could do the same and use it as part of the workbook name but no matter what i try i can't get it to work. Can anyone give me some tips or point me in the right direction?
Below is the formula i use when it's different sheets i want to look up.
With Range("F5:L" & lRow)
.Formula = "=IF($C5=""Night"",VLOOKUP($A5,'\\server\drive name\Folder\[filename.xlsm]" & Target.Value & "'!$A:$I,F$1,0)
.Value = .Value
End With
Any help would be appreciated.
If you make a specific custom function, excluding some part of the name of your application, it could look like this:
Option Explicit
Sub TestMe()
Debug.Print getApplicationName(" Service Planner.xlsm - Excel")
End Sub
Public Function getApplicationName(nameToExclude As String) As String
Dim length As Long
length = Len(Application.Caption) - Len(" Service Planner.xlsm - Excel")
getApplicationName = Left(Application.Caption, length)
End Function
The property used is Application.Caption which returns the whole name of the file + - Excel at the end.

Button to add column?

In excel 2013 I was hoping if someone can make a code for adding 1 blank column to a spreadsheet based on the user input after they click this button that is an activex control. The column will end based on how many rows there are in my table, meaning if there are 10 rows I should not see a column on line 11 of the spreadsheet.
I keep getting an error saying application defined or object error after I put in the column I want to add, I even tried both caps an lowercase and the same error comes up.
Private Sub CommandButton2_Click()
Dim x As String
x = InputBox("Enter a column that you want to add: ", "What column?")
If x = "" Then Exit Sub
ColumnNum = x
Columns(ColumnNum & ":" & ColumnNum).Insert shift:=xlShiftRight
Columns(ColumnNum - 1 & ":" & ColumnNum - 1).Copy Range("A1" & ColumnNum)
Columns(ColumnNum & ":" & ColumnNum).ClearContents
End Sub
This will get you started:
Dim x As Variant
Dim ColumnNum%
x = InputBox("Enter a column that you want to add: ", "What column?")
If x = "" Then Exit Sub
ColumnNum = x
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum).Insert shift:=xlRight
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum - 1).Copy
'THe line above doesnt make any sense whatsoever.
'Im not going to try and trouble shoot it but it seems like you dont understand how to
' properly scuplt things. Youll notice i changed how you strucutred the .copy part.
'THe part that doesnt make sense to me is the Range section.
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum).ClearContents
There were a few things wrong with your code.
You need to put Option Explicit at the top of your code. You didnt declare your variables.
you inpout box needs to be declared as variant
When i played around with this its clear you didnt fully reference what columns in what sheets need to be inserted. Notice my "ThisWorkbook....."
Your if statement is structured incorrectly as well.
I suggest you spend some time reading up on the basics some more :)

VB, excel macro pause and resume working if possible

I cannot figure out the best way to do the following problem. Basically my macro (excel, VB) is checking several (100+) worksheets for correct values, if wrong value is found, I want it to stop, give me a warning, then I could have a look into the reason why the value is wrong, correct it manually and then I want to resume the macro, or remember the last value checked so if I return, it remembers where to continue (resume).
My current problem is that it finds the wrong value, then I can either make it stop so I check the problem, or it goes through all the sheets and then I have to remember which sheets had the wrong value.
What I thought of is make a list where the name of sheet is added every time a wrong value is found. The problem is that usually there is more than 1 wrong value in the same sheet if there is a wrong value at all and this added the same sheet name several times to the list. Another problem with that is that I cannot correct the values straight away.
I'm very inexperienced with programming and so would appreciate your idea on how to best approach this problem (I don't want to spend a long time on coding something which wouldn't be efficient for such a "simple" problem).
When the error is found (I'm assuming you've already been able to identify this), you can use the Application.InputBox function to prompt you for a new value.
For example, if rng is a Range variable that represents the cell being checked, and you have some logic to determine where the error happens, then you can just do:
rng.Value = Application.InputBox("Please update the value in " & rng.Address, "Error!", rng.Value)
The inputbox function effectively halts execution of the procedure, while waiting for input from the user.
If InputBox isn't robust enough, then you can create a custom UserForm to do the same sort of thing. But for modifying single range values, one at a time, the InputBox is probably the easiest to implement.
I believe you can handle this task by using one or two static local variables in your macro. A variable declared with "static" rather than "dim" will remember its value from the last time that procedure was run. This can hold where you left off so you can resume from there.
One thing that could be a problem with this solution would be if the macro gets recompiled. That would probably cause VBA to clear the value that the static variable was holding. Just doing a data edit in Excel should not cause a recompile, but you will want to watch for this case, just to make sure it doesn't come up. It almost certainly will if you edit any code between executions.
Create a public variable that stores the cell address of the last checked cell and use a conditional statement to see if it's "mid-macro" for want of a better phrase. here is a very crude example...
Public lastCellChecked As String
Sub Check_Someting()
Dim cell As Excel.Range
Dim WS As Excel.Worksheet
If Not lastCellChecked = vbNullString Then Set cell = Evaluate(lastCellChecked)
'// Rest of code...
'// Some loop here I'm assuming...
lastCellChecked = "'" & WS.Name & "'!" & cell.Address
If cell.Value > 10 Then Exit Sub '// Lets assume this is classed as an error
'// Rest of loop here...
lastCellChecked = vbNullString
End Sub
The best way to do this is to create a userform and as mentioned by prior users create a public variable. When the program finds an error store the cell and initiate the userform. Your code will stop on the userform. When you're done checking the problem have a button on the userform that you can click to continue checking. Your loop can be something like the below.
public y as integer
sub temp1 ()
rw1= range("a500000").end(xlup).row 'any method to create a range will do
if y = null then y=1
for x = y to rw1
cells(x,1).select
'check for the problem your looking for
if errorX=true then
userform1.show
y = activecell.row
exit sub
end if
next x
end sub
What about inserting a button (on the sheet or in a menubar) for stopping?
Insert the code below:
'This at the top of the module
Public mStop As Boolean
'This in the module
Sub MyBreak()
mStop = True
End Sub
'This is your macro
Sub YourMacro()
'This at the top of your code
mStop = False
'Your code
'...
'This code where you want to break
DoEvents '<<<< This makes possible the stop
If mStop Then
mCont = MsgBox("Do you want to continue?", vbYesNo)
If mCont = vbNo Then
Exit Sub
Else
mStop = False
End If
End If
'Your code
'...
End Sub
Now you need to create a button and link it to the macro called "MyBreak".

Excel 2010 VBA: .Names.Add does not work after .Hyperlinks.Add

I have run into a problem in Excel 2010 VBA on Windows 7 64-bit version which I have not been able to solve. The issue can easily be recreated by pasting the code below in a module in a new workbook and run it.
What I want to do is to loop through a number of sheets and add a defined name and a hyperlink on each sheet.
Sub Test()
Dim i As Integer
Dim ws As Worksheet
Dim defName As String
For i = 1 To 2
Set ws = Sheets(i)
defName = "Name_" & ws.Name
ws.Names.Add Name:=defName, RefersToR1C1:="=OFFSET(Sheet3!R1C1,0,0,1)"
ws.Hyperlinks.Add Anchor:=ws.Range("A1"), _
Address:="", SubAddress:="=Sheet3!A1"
Next i
End Sub
Running the code gives the following error on the second iteration, on the ws.Names.Add call: Run-time error '1004: The formula you typed contains an error.
Doing any of the following makes the error disappear:
Change the for iteration to "i = 1 To 1" or "i = 2 To 2"
Put a debug breakpoint inside the for loop and pressing F5 when it has stopped
Change the cell reference to
ws.Names.Add Name:=defName, RefersToR1C1:="=Sheet3!R1C1", i.e. removing the OFFSET command
Adding DoEvents to the first line of the for loop or setting Application.EnableEvents = False does not solve the problem.
Does anyone know the cause of this error or how to get around it? I am thankful for any help.
Edit: The issue occurs no matter what the hyperlink links to. Changing the hyperlink to the following does not solve the issue
ws.Hyperlinks.Add Anchor:=ws.Range("A1"), Address:="http://www.google.com"
Edit2: Managed to recreate the issue with an even simpler code:
Sub Test()
With Sheets(1)
.Hyperlinks.Add Anchor:=.Range("A1"), Address:="http://www.google.com"
.Names.Add Name:="myDefName", RefersToR1C1:="=OFFSET(Sheet1!R1C1,0,0,1)"
End With
End Sub
I solved this by separating the for loops into two loops, one for the .names.add calls and one for the hyperlinks.add calls. This way all the names get defined before the first hyperlink is created.
Sorry if it is not correct of me to post this as an answer.

Type Mismatch error in function using DateValue(), how to troubleshoot?

Warning: I'm a noob.
I've written a Sub to find cells with red text and alter them.
#ThinkerIV gave me a great function to put in a cell and drag the formula out into adjoining cells, but that won't work due to the number of sheets to work on.
So I wrote my Sub, calling his function (see code below). I passed it a Range of one cell, so it seems to me it should work?
But, it keeps throwing out Type Mismatch (run-time error code 13) on the line where the function calls the DateValue()! The passed range shows a value of 1 (which is the number in the cell it refers to) when I hover over it in the editor, but I don'rt know if that's the cell's contents or some other value 1 being shown.
So, I really don't know how to find out exactly why this is happening. Is it that the range I passed is somehow not the right kind? Please inform me of why this code won't work!
I tried to change that line to the comment line below it (and a couple other blind-guess changes), but that has the same error.
Thanks in advance!
Sub redTextToRealDates()
Dim dateTemp As Date
Dim redCell As Range
Dim foundCell As Range
Dim thisSheetsRange As Range
Dim busyCell As Range
Dim redTextCells As Range
Set thisSheetsRange = ActiveSheet.usedRange
'Build a range containing all the cells in a sheet containing red text.
' well... all cells formatted to HAVE red text, anyway.
' Anyone want to tell me how to write this to skip empty cells?
' Because I don't need to grab empty cells into this range...
For Each busyCell In thisSheetsRange
If (busyCell.Font.ColorIndex()) = 3 Then
If redTextCells Is Nothing Then
Set redTextCells = busyCell
Else: Set redTextCells = Union(redTextCells, busyCell)
End If
End If
Next busyCell
'Change unknown format cells to date cells populated with concantenated
'string of original contents and the active sheet's name.
For Each foundCell In redTextCells
foundCell.NumberFormat = "#"
foundCell = GetConcantDate(foundCell)
Next foundCell
redTextCells.NumberFormat = "dd/mm/yy"
On Error Resume Next
End Sub
Function GetConcantDate(rng As Range) As Date
'Original code supplied by ThinkerIV on StackOverflow.com
Dim dtTemp As Date
dtTemp = DateValue(rng.Range("A1").Value & " " & rng.Parent.Name)
'dateTemp = DateValue(foundCell.Value & " " & ActiveSheet.Name)
GetConcantDate = dtTemp
End Function
EDIT
I cant post my own answer yet, so I am adding this solution:
When feeding data to Format(), the contents of the first cell formatted for red were NOT in text form. I had not put in place any way to ensure that I passed the proper data type. So, the line to format the cell as text (foundCell.NumberFormat = "#") before passing it to the function is what fixed it.
The solution was actually already written when I copy/pasted the code into the question - I just wasn't aware that it had fixed it because of another error on a different Sub. (I'm a noob and was confused dealing with multiple errors in multiple subs) I thought I had tried it again with that new line, but HADN'T, so still thought it was not working.
Thanks to all who helped. I feel a bit of a fool now, having found it like that. Hope you forgive me for my rookie flubber - too many Subs and Functions in a huge list in the editor and I got 'dizzy'... At least I can post a solution in case some other noob needs it!
Ok, I think there are two things here. Firstly, the DateValue function takes a string representation of a date, e.g. "01/01/2013", when you pass through an excel date from a range, you are passing through a number, like 41275. This throws the run time error 13.
However, if you already have a date, why bother converting it? You seem to want all red cells to be converted to a date + the sheetname. To do this you'll have to have strings e.g. "01/01/2013 Sheet1", so you couldn't use DateValue here. Instead perhaps try something like this:
Public Function GetConcatDate(rng As Range) As String
Dim dtTemp As String
dtTemp = Format(rng.Range("A1").Value, "dd/mm/yyyy") & " " & rng.Parent.Name
GetConcatDate = dtTemp
End Function