Excel VBA Runtime Error 1004 when renaming ActiveSheet - vba

I'm at a loss when trying to figure out where this code is tripping up. I am looking to rename the activesheet by using a concat of two ranges on the activesheet and some static text. When only one worksheet is in the workbook, the code works great. As soon as a second worksheet is added, I get a Runtime Error 1004. I'll highlight the line of code where it is breaking. This code currently resides in a normal module.
Option Explicit
Sub updateName()
Dim fNumber
Dim pCheckNumber
Dim asName As String
Dim tempASName As String
Dim worksheetName As Object
If ActiveSheet.Name = "Launch Page" Then Exit Sub
fNumber = ActiveSheet.Range("FlightNumber").Value
pCheckNumber = ActiveSheet.Range("PerformanceCheckNumber").Value
If fNumber <> "" And pCheckNumber <> "" Then
tempASName = "Flight " & fNumber & " | Run " & pCheckNumber & " (0.0%)"
asName = tempASName
MsgBox ActiveSheet.Name & vbCr & asName
ActiveSheet.Name = asName
worksheetName.Caption = asName
Else
Exit Sub
End If
End Sub
I'm in the process of adding error checking to ensure that I don't have duplicate sheet names. However, due to the nature of the field names, this will never occur.
I appreciate all of the insights!

The error you are reporting is, most likely, provoked because of trying to rename a Worksheet by using a name already in use. Here you have a small code to avoid this kind of situations:
Dim newName As String: newName = "sheet1"
Dim addition As String: addition = "_2"
Do While (Not sheetNameFree(newName))
newName = newName & addition
Loop
Where sheetNameFree is defined by:
Function sheetNameFree(curName As String) As Boolean
sheetNameFree = True
For Each Sheet In ActiveWorkbook.Sheets
If (LCase(Sheet.Name) = LCase(curName)) Then
sheetNameFree = False
Exit Function
End If
Next Sheet
End Function
You can adapt this code to your specific needs (for example, by converting addition into a number which grows after each wrong name).
In your code I see one other problem (although it shouldn't be triggering a 1004 error): you are accessing the property Caption from an non-instantiated object (worksheetName), whose exact functionality is not too clear. Just delete this line.
NOTE: good point from KazJaw, you might be using an illegal character. If fNumber and pCheckNumber are numbers or letters, it would be OK.
NOTE2: if with worksheetName you want to refer to an ActiveX Label in your workSheet, better do: ActiveSheet.Label1.Caption (where Label1 is the name of the Label). You cannot define worksheetName as a Label, because it is not a "conventional Label".

Related

why does my VBA code that works in module not work as expected when assigned to a worksheet and a button

I have a workbook that is essentially an automated test, marking and feedback tool for end of topic tests for students. On the '701Test' sheetThey input their teaching group via a drop down list and the select their from subsequent list. They answer the multiple choice questions and press a button when finished. The button takes them to a 'results' page which gives their marks for each question, give feedback for incorrect answers and gives a total score. They then hit the finish button which generates a PDF copy of the mark sheet in their my documents folder and then emails a copy to themselves and the Schools email account. At this point I also wanted to post the final score to the students record on a central registry using a loop through the student list to find the name and offset to post the Score value from the 'Results' page and finally return to the test page. This last bit I wrote the code for in a module and it executes perfectly, but when added to the main code and run from the button the loop part fails to execute but the return to the test page does work, but no error is recorded for the loop failure.
Here is the 'Results' page code in full the 'With Central reg' bit at the bottom is the problem, any help is greatly appreciated.
Private Sub CommandButton1_Click()
Dim IsCreated As Boolean
Dim PdfFile As String, Title As String
Dim OutlApp As Object
Dim cell As Range
Dim Students As Range
Title = Range("D1").Value
sname = Range("B2").Value
PdfFile = CreateObject("WScript.Shell").SpecialFolders("MyDocuments") & "\" & sname & Title & ".pdf"
With ActiveSheet
.ExportAsFixedFormat Type:=xlTypePDF, Filename:=PdfFile, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
End With
On Error Resume Next
Set OutlApp = GetObject(, "Outlook.Application")
If Err Then
Set OutlApp = CreateObject("Outlook.Application")
IsCreated = True
End If
OutlApp.Visible = True
On Error GoTo 0
With OutlApp.CreateItem(0)
.Subject = Title
.to = Range("B2").Value ' <-- Put email of the recipient here"
.CC = "" ' <-- Put email of 'copy to' recipient here
.Body = "Hi," & vbLf & vbLf _
& "Yr 7 701 EOT test attached in PDF format." & vbLf & vbLf _
& "Regards," & vbLf _
& "KDS ICT Dept" & vbLf & vbLf
.Attachments.Add PdfFile
Application.Visible = True
.Display
End With
If IsCreated Then OutlApp.Quit
Set OutlApp = Nothing
With CentralReg
For Each cell In Range("A2:A250")
If cell = Range("Results!B2").Value Then
cell.Offset(0, 4).Activate
ActiveCell.Value = Range("Results!B27").Value
End If
Next
End With
End Sub
I believe you are trying to refer to CentralReg which is a worksheet, which means you should qualify it as such.
Also, you should not dim variables that are similar to defined objects/properties in VBE. Try MyCell instead of cell (good practice, not required).
I am assuming you want to see if the value on sheet CentralReg in Column A is equal to sheet Result B2. If this condition is met, your MyCell will take on the value equal sheet Result B27
Dim MyCell As Range
Dim Result, NewValue as Variant
Result = ThisWorkbook.Sheets("Result").Range("B2")
NewValue = ThisWorkbook.Sheets("Result").Range("B27")
With ThisWorkbook.Sheets("CentralReg")
For Each MyCell In .Range("A2:A250")
If MyCell = Result Then MyCell.Offset(, 4) = NewValue
Next MyCell
End With
That with statement is useless as nothing actually uses it within the construct.
Delete with CentralReg and End with and it will work.
alternatively if CentralReg IS something like a sheet then you need to precede your code with a . so this: Range("A2:A250") becomes this: .Range("A2:A250") and so on, the . tells the code that it is related to whatever your with construct surrounds

formatting codes for footer not being applied and page orientation data mismatch

I have a worksheet(adHoc) where cell b28 contains
"&9 2014 YTD Financial Data for PP" & Chr(10) & " &D &T" & Chr(10) & " Version 1.0" & Chr(10) & " &F"
When I use the above to update the footer of another worksheet in a different workbook. I don't get the embedded formatting - it displays exactly what is contained in the cell b28.For example excel should see &9 and make the font 9 points.
I am also getting a datatype mismatch error with the page orientation. The contents of cell b36 is xlLandscape.
I posted a copy of this question last week on another board but did not get any answers. I hope someone here has answer.
http://www.mrexcel.com/forum/excel-questions/919033-updating-pagesetup-using-cells-master-worksheet-orientation-formatting-footer-excel-visual-basic-applications.html
This is the code I am using.
Sub page_setup()
Dim reportWB As Excel.Workbook
Dim sheet As Excel.Worksheet
'open report workbook - name of workbook is in cell b4
Set reportWB = Workbooks.Open(Workbooks("macros.xlsm").Sheets("adHoc").Range("b4").Value)
Dim leftFooter
leftFooter = Workbooks("macros.xlsm").Sheets("adHoc").Range("b28").Value
For Each sheet In reportWB.Sheets
With sheet
.PageSetup.leftFooter = leftFooter
.PageSetup.Orientation = Workbooks("macros.xlsm").Sheets("adHoc").Range("b36").Value
End With
Next
End Sub
Reading in your footer definitions like that they are treated as literal string, not code. You need to resolve the code to valid footer strings somehow.
For the LeftFooter string, you can use Evaluate to resolve it, but it will need to be written as if it's a Excel Formula, not VBA, so use
"&9 2014 YTD Financial Data for PP" & Char(10) & " &D &T" & Char(10) & " Version 1.0" & Char(10) & " &F"
Note the I use Char rather than Chr, the Excel formula equivalent.
For Orientation you are using a named constant, which won't work. Either put the value on your Excel sheet (2 in this case) or write your own code to resolve the name to its value
Working version (with corrected source data on sheet as descibed above)
Sub page_setup()
Dim reportWB As Excel.Workbook
Dim sheet As Excel.Worksheet
Dim wsSource As Worksheet
'open report workbook - name of workbook is in cell b4
Set wsSource = Workbooks("macros.xlsm").Sheets("adHoc")
Set reportWB = Workbooks.Open(wsSource.Range("b4").Value)
Dim leftFooter
leftFooter = wsSource.Range("b28").Value
For Each sheet In reportWB.Sheets
With sheet
.PageSetup.leftFooter = Evaluate(leftFooter)
.PageSetup.Orientation = wsSource.Range("b36").Value
End With
Next
End Sub
To handle the constants you could add a UDF that resolves the string names to values and call that from your settings sheet
Eg
Function GetConst(s As String) As Variant
Select Case s
Case "xlLandscape"
GetConst = xlLandscape
Case "xlPortrait"
GetConst = xlPortrait
' etc
End Select
End Function
Put in cell B36 GetConst("xlLandscape") (as a string, not formula), and change your Orientation line of code to
.PageSetup.Orientation = Evaluate(wsSource.Range("b36").Value)
Add any other named constants you want to the Select Case statement.
AFAIK, there is no (straightforward) way to do what you're trying to do. When you put code in a cell, and then call that cell's value in place of actual code, what VBA is trying to run is not:
.PageSetup.Orientation = xlLandscape
but rather:
.PageSetup.Orientation = "xlLandscape"
which will produce the errors and behavior you're seeing.
As rule of thumb, if your VBA code needs a string (ie, something in ""), or a number, you can do that calculation on the sheet and have the code pull in the value.
For everything else (there's Mastercard) put it in the code. For example:
leftfooter = cell1.value & Chr(10) & cell2.value & Chr(10) & cell3.value
(As a side note, I'm not familiar with the formatting it seems you're trying to do in that string... Those are generally set up through things like
With sheet.PageSetup.leftFooter.
.Font.Size = 9
'etc...
)

How to use a variable as one of the values in Excel VBA VLOOKUP

I'm using VBA in Excel and I'm assigning a VLOOKUP as a formula to a cell. It works fine, but I would like to use a variable that refers to the last cell that contains a value in the column.
In the example below, I would the value for $B$269 to change depending on the number of elements in the closed document.
"=VLOOKUP(B2,'Macintosh HD:Users:myself:Documents:[Master_Terms_Users.xlsm]Master_Terms_Users.csv'!$A$1:$B$269,2,FALSE)"
I know I want to use something along the lines of:
Range("B" & Rows.Count).End(xlUp).Address
With that said, I haven't been able to figure out how to incorporate the result, which is something like $B$269 into the VLOOKUP. I know that those formulas return the correct address because I've used it in Debug.Print.
I tried to do something like this:
"=VLOOKUP(B2,'Macintosh HD:Users:myself:Documents:[Master_Terms_Users.xlsm]Master_Terms_Users.csv'!$A$1:"&GetLastRowFunct&",2,FALSE)"
But that didn't work.
Here is my current code:
Sub GetLastRow()
Debug.Print GetLastRowFunct
End Sub
Function GetLastRowFunct() As String
Dim openNwb As Workbook
Const MasterPath = "Macintosh HD:Users:myself:Documents:"
Dim strNewFileName As String
strNewFileName = "Master_Terms_Users.xlsm"
Set openNwb = Workbooks.Open(MasterPath & strNewFileName)
Dim openNws As Worksheet
Set openNws = openNwb.Worksheets(1)
GetLastRowFunct = openNws.Range("B" & Rows.Count).End(xlUp).Address
openNwb.Close
End Function
Any recommendations would be appreciated.
I would rewrite that function to return the entire range address, including worksheet, workbook and path.
Function GetLastRowFunct() As String
Const MasterPath = "Macintosh HD:Users:myself:Documents:"
Dim openNwb As Workbook, strNewFileName As String
strNewFileName = "Master_Terms_Users.xlsm"
Set openNwb = Workbooks.Open(MasterPath & strNewFileName)
with openNwb.Worksheets(1)
GetLastRowFunct = .Range(.cells(1, 1), .cells(rows.count, "B").End(xlUp)).Address(1, 1, external:=true)
end with
openNwb.Close
End Function
The formula construction and assignment becomes simpler to deal with.
rng.formula = "=VLOOKUP(B2, " & GetLastRowFunct & ", 2, FALSE)"
tbh, I'm not sure if you have to supply your own square brackets or not on a Mac.

VBA Directory Referencing

I'm trying to reference data from another workbook and I found that (correct me if I'm wrong) inserting the worksheet formulas directly into the cells (see code below) is the only way to do this without actually opening the workbook I'm referring to. Now my dilemma is I'm trying to make the directory portion of this code variable such that the user can do something like:
Path = Application.GetOpenFilename
Right now the path is fixed at 'S:\SN\SN\2015-S[2015SNL.xlsx]2015'
Sub Formulation()
Application.ScreenUpdating = False
Sheets("Data").Activate
Range("A1").FormulaR1C1 = _
"=IF(ISBLANK('S:\SN\SN\2015-S\[2015SNL.xlsx]2015'!RC), _
""-"",'S:\SN\SN\2015-S\[2015SNL.xlsx]2015'!RC)"
Application.ScreenUpdating = True
End Sub
It is also referencing to a specific sheet as you can see the ...2015'!
Any ideas? Thank you in advanced for your assistance
A form not prone to errors is
Dim dirn as String, tabn as String, refs as String
dirn = "S:\SN\SN\2015-S\" ' Change this line
tabn = dirn & "[2015SNL.xlsx]2015"
refs = "'" & tabn &"'!" & "RC"
Dim ws as Worksheet
Set ws = ActiveWorkbook.Sheets("Data")
ws.Range("A1").FormulaR1C1 = "=IF(ISBLANK(" & refs & "),""-""," & refs & ")"
Remember to qualify your Ranges, see this.
To add in variables into a string in VA, you need to close the quotes, and follow with and ampersand: &.
Like so:
Range("A1").FormulaR1C1 = "=IF(ISBLANK('" & Path & "2015'!RC),""-"",'" & Path & "2015'!RC)"
Make sure to add a space between the quotes, the ampersand and the variable name.

Concatenation yields error with underscore

I am trying to create a macro that brings in the name of the sheet and combine it with text. For example, for sheet one, I want it to say "ThisIs_Sheet1_Test" in I5 of Sheet1. There are several sheets but it should work for all of them.
What is wrong with my code? I think the underscore might be ruining it all. Here's what I have:
Dim SheetName As String
Public Sub CommandButton1_Click()
SheetName = ActiveSheet.Name
Sheets("Sheet1").Range("I5", "I5") = ThisIs_" & SheetName.text & "_Test
Sheets("Sheet2").Range("H5", "H5") = ThisIs_" & SheetName.text & "_Test
Sheets("Sheet3").Range("G5", "G5") = ThisIs_" & SheetName.text & "_Test
End Sub
This question has been forwarded to Pull in Earlier Value Using Concatenation
looks like a quoting problem. ThisIs_ and _Test are strings, right? So the quotes should be around them, not around & SheetName.text &
Sheets("Sheet1").Range("I5", "I5") = "ThisIs_" & SheetName.text & "_Test"
In addition to the missing quotes, SheetName is a string, not an object, so it won't have a Text property. Did you want the name of the sheet to change as the sheet changes? You need this:
Private Sub CommandButton1_Click()
Dim ws As Worksheet
For Each ws In Me.Parent.Worksheets
ws.Range("I5").Value = "ThisIs_" & ws.Name & "_Test"
Next ws
End Sub
I am able to get it to work...sort of.
Now, it displays ThisIS_Sheet1_Test in Sheet1, etc.
However, I have it set up to pull data from a listbox into a function which I called ThisIS_Sheet1_Test. I figured that once I got it to display the name, it would pull the function in. Here's what I have above:
Public Sub ListBox2_LostFocus()
ListBox2.Height = 15
With ListBox2
ThisIS_Sheet1_Test = "'"
For i = 0 To .ListCount - 1
If .Selected(i) Then
ThisIS_Sheet1_Test = ThisIS_Sheet1_Test & .List(i) & "','"
End If
Next i
End With
ThisIS_Sheet1_Test = Left(ThisIS_Sheet1_Test, Len(ThisIS_Sheet1_Test) - 2)
End Sub
How come when I get the text I want it doesn't translate into the function I thought it would.
can you take few minutes to compile your code (in VBA Window, Debug->Compile VBA Project) before looking for other's help?? That would have screamed about your missing quotes, using .Text on a string variable etc.
Public Sub dummy()
Dim SheetName As String
SheetName = ActiveSheet.Name
Sheets("Sheet1").Range("I5", "I5") = "ThisIs_" & SheetName & "_Test"
Sheets("Sheet2").Range("H5", "H5") = "ThisIs_" & SheetName & "_Test"
Sheets("Sheet3").Range("G5", "G5") = "ThisIs_" & SheetName & "_Test"
End Sub
Underscore carries a special meaning in VBA/VB world. Its code concatination (meaning if your code is too long and you want to split it across two lines then you put a space underscore ( _) and continue with next line. And also Dick Kusleika is right about object/string. Only for objects you will have differnt peopreties (.Text means you are asking for Text property of that object), and usually that Text property would be of String type. here you already have a String, and you just use it as it is.