How to convert string to Workbook name in VBA - excel

Sub openwb()
Dim x260path As String
x260path = "E:\sarath\PTMetrics\20131002\D8 L538-L550 16MY\D8 L538-L550_16MY_Powertrain Metrics_" & Format(Date, "YYYYMMDD") - 1
Workbooks("x260path").Activate
ActiveWorkbook.SaveAs ["E:\sarath\PTMetrics\20131002\D8 L538-L550 16MY\D8 L538-L550_16MY_Powertrain Metrics_" & Format(Date, "YYYYMMDD")]
Debug.Print x260path
End Sub
Here, when i execute, an error says "subscript out of Range". And it appears on 4th line.when i use 'workbook' to declare 'x260path' instead of string, It shows another error saying "Object variable or with block variable not set" on line 3. Can u help?Why is this happening?

In VBA the equivalent function to =Today() is Date() (*or Date)
x260path = CONCATENATE("..." & Date)
Alternatively, use Now() function ( that includes a time stamp as well though )
x260path = CONCATENATE("..." & Now)
debug.print Date
02/10/2013
and
debug.print Now
02/10/2013 08:39:20
some of the spreadsheet functions are available to use with the WorksheetFunction class. For example
Sub Main()
Dim sum As Double
sum = WorksheetFunction.sum(10, 20)
MsgBox sum
End Sub
Note: when you type the sum = WorksheetFunction. as soon as you type in the . you should get the VBA's Intelli-sense help. It is a list of all available functions you can use with the WorksheetFunction class.
In your case the =Concatenate function is equivalent to & operator in VBA. Therefore the easiest way would be to join two string using the &
x260path = "C:\..." & date
If a function you are trying to use doesn't exist in the Intelli-sense you can create your own UDF or you can do some online research on how the function works and how to overwrite it.

Related

Passing a sheets codename as a parameter in the range function

IN VBA
Function SNAME(number As String) As String
Dim WORD$
WORD = "Sheet" + number
' SNAME = Worksheets(1).CodeName
For i = 1 To ThisWorkbook.Worksheets.Count
If Worksheets(i).CodeName = WORD Then SNAME = Worksheets(i).Name
Next i
End Function
IN EXCEL
=SUMIFS((SNAME(19)!$T$2:$T$9962),(SNAME(19)!$A$2:$A$9962),"=31",(SNAME(19)!$C$2:$C$9962),"<="&EDATE(TODAY(),-12))
Purpose:
The idea here is that I want to pass the sheets name to the range function based on its code name. the VBA function SNAME seems functional and returns the worksheet's name based on the VBA object code name. When I try to combine that with the range function in the equation, there seems to be an error I'm unsure how to resolve. When I replace SNAME(19) with the sheet name the Equation executes properly.
Goal:
I need to be able to reference the sheet using its code name to avoid future errors of individuals changing the name of the sheets. I'd really appreciate any advice someone might have on the issue.
As far as I know, Excel automatically corrects the formula if any name used there has been changed. So I'm not sure whether you need this construction. Anyway, to make it work we have to change SNAME(19)!$T$2:$T$9962 to something like INDIRECT("'" & SNAME(19) & "'!$T$2:$T$9962").
To make this cleaner, let's put quoting inside the function SNAME. Also, I'd change the type of number to Variant and put Exit For on success:
Function SNAME(number) As String
Dim sh As Worksheet
Dim WORD$
WORD = "Sheet" & number
For Each sh In ThisWorkbook.Worksheets
If sh.CodeName = WORD Then
SNAME = "'" & sh.Name & "'"
Exit For
End If
Next sh
End Function
In the formula, I would use LET to ease editing the function call and to call it once:
=LET(sh, SNAME(19),
SUMIFS(
INDIRECT(sh & "!$T$2:$T$9962"),
INDIRECT(sh & "!$A$2:$A$9962"),
"=31",
INDIRECT(sh & "!$C$2:$C$9962"),
"<=" & EDATE(TODAY(),-12)
)
)

Open Excel Workbook based on formula

I am looking for a code that will open a workbook based on the output of a formula. I have files which are named by the date e.g. 20210807 in the format JJJJMMTT. What I need is that if I run the VBA on the file "20210807" then the workbook "20210806" shall be opened. The purpose of this is, because the VBA I run on a file always reference to the previous day and I cannot retrieve data if the workbook is not open.
Is that possible? I have tried it with that code, but it doesn't work and it looks very wrong to me, but I have no clue.
Workbooks.Open FileName:= _
"=INDIRECT(CONCATENATE(LEFT(CELL(""filename""),LEN(CELL(""filename""))-13),LEFT(RIGHT(CELL(""filename""),13),8)+1,"".xlsx"",)"
You need to evaluate the formula to get its result:
Workbooks.Open FileName:=Evaluate("=INDIRECT(CONCATENATE(LEFT(CELL(""filename""),LEN(CELL(""filename""))-13),LEFT(RIGHT(CELL(""filename""),13),8)+1,"".xlsx"",)")
And you should check if the file exists or put some error handling (see VBA Error Handling – A Complete Guide) so in case the file cannot be loaded your code can handle this.
For Example:
Option Explicit
Public Sub Example()
' your code goes here …
Dim OpenFileName As String
OpenFileName = Evaluate("=INDIRECT(CONCATENATE(LEFT(CELL(""filename""),LEN(CELL(""filename""))-13),LEFT(RIGHT(CELL(""filename""),13),8)+1,"".xlsx"",)"))
On Error Goto ERR_OPEN_FILE ' on error jump to error handler
Dim WbOpen As Workbook
Set WbOpen = Workbooks.Open(FileName:=OpenFileName)
On Error Goto 0 ' re-activate error reporting
' your code goes here …
' example:
WbOpen.Worksheets("Sheet1").Range("A1").Value = "Test"
WbOpen.Close SaveChanges:=False
Exit Sub ' exit here if no error occured.
ERR_OPEN_FILE:
MsgBox "File '" & OpenFileName & "' could not be opened:" & vbCrLf & Err.Description, vbCritical, "Error " & Err.Number
Err.Clear
End Sub
If your filename is 20210807.xlsm you can subtact 1 from the day 07. But what if the file name is 20210801 then this idea ob subtracting one does not work anymore.
You need to convert the string 20210807 into a real numeric date to be able to subtract one day and get the correct result as a date that you can use to build your new file name:
Public Function GetPreviousDayFileName(ByVal ThisFileName As String) As String
'ThisFileName = "20210807.xlsm"
Dim ThisYear As String
ThisYear = Left$(ThisFileName, 4) ' 2021
Dim ThisMonth As String
ThisMonth = Mid$(ThisFileName, 5, 2) ' 08
Dim ThisDay As String
ThisDay = Mid$(ThisFileName, 7, 2) ' 07
Dim ThisDate As Date
ThisDate = DateSerial(CInt(ThisYear), CInt(ThisMonth), CInt(ThisDay))
Dim PreviousDate As Date
PreviousDate = DateAdd("d", -1, ThisDate) ' subtract one day
' generate file name
GetPreviousDayFileName = Format$(PreviousDate, "YYYYMMDD") & ".xlsx"
End Function
And use it in the first example code like this:
OpenFileName = ThisWorkbook.Path & Application.PathSeparator & GetPreviousDayFileName(ThisWorkbook.Name)
I have tried, but I don't know if I understood it perfectly. I have an additional question. So I have built this Vlookup and now want to replace a part from it with your code.
This is the code: "=IF(ISNA(VLOOKUP(RC[-1],INDIRECT(CONCATENATE(""'"",LEFT(RIGHT(CELL(""Dateiname""),13),8)-1,"".xlsx'!$A:$AP"")),2,FALSE)),DATE(LEFT(LEFT(RIGHT(CELL(""Dateiname""),13),8),4),MID(LEFT(RIGHT(CELL(""Dateiname""),13),8),5,2),RIGHT(LEFT(RIGHT(CELL(""Dateiname""),13),8),2)),VLOOKUP(RC[-1],INDIRECT(CONCATENATE(""'"",LEFT(RIGHT(CELL(""Dateiname""),13),8)-1,"".xlsx'!$A:$AP"")),2,FALSE))"
Whereas the part:
CONCATENATE(""'"",LEFT(RIGHT(CELL(""Dateiname""),13),8)-1,"".xlsx'!$A:$AP"")
is equal to:
CONCATENATE(GetPreviousDayFileName, "$A:$AP")
But this is not working. What do I miss

How to Throw Error with Excel Prompt in VBA

I have some code which looks for a value with a given sheet name in two separate workbooks.
What I want to do is when the first workbook does not have the sheet, instead of the following prompt coming up, it cancels/throws an error and using the error handling goes to the second spreadsheet. How do I do this?
Currently I am using this code to achieve this:
fFormString1 = "'" & wkBookRef1 & firstShtName & "'!$L$6/1000"
fFormString2 = "'" & wkBookRef2 & firstShtName & "'!$L$6/1000"
Application.DisplayAlerts = False 'Does nothing to the prompt
On Error GoTo tryTwo 'Following only throws error when prompt is canceled
ThisWorkbook.Sheets("Place").Range("E53").Formula = "=" & fFormString1
GoTo endTen
tryTwo:
ThisWorkbook.Sheets("Place").Range("E53").Formula = "=IFERROR(" & fFormString2 & ","""")"
On Error Resume Next
endTen:
Application.DisplayAlerts = True 'Does nothing to the prompt
Note: I wish to do this with the spreadsheet closed ideally. Or visually not present to improve speed and smoothness of operation for my client.
ExecuteExcel4Macro will return a value from a closed workbook. If the worksheet doesn't exist it will throw an error 1004 'A formula in this worksheet contains one or more invalid references.
ExternalWorksheetExists uses this to test it the worksheet exist.
Function ExternalWorksheetExists(FilePath As String, FileName As String, WorksheetName As String) As Boolean
If Right(FilePath, 1) <> "\" Then FilePath = FilePath & "\"
On Error Resume Next
Call ExecuteExcel4Macro("'" & FilePath & "[" & FileName & "]" & WorksheetName & "'!R3C3")
ExternalWorksheetExists = Err.Number = 0
On Error GoTo 0
End Function
When using ExecuteExcel4Macro, all references must be given as R1C1 strings. Here is an example of a valid string:
ExecuteExcel4Macro("'C:\Users\tinzina\Documents\[Book1.xlsm]Sheet1'!R6C12")
Borrowing heavily from Thomas' answer (full credit is due). However it seems that this didn't work for you.
Use ExecuteExcel4Macro but ascribe the value to the variable val. Then check if this is the error you are looking for Error(2023).
Please find the code below:
'Check if the sheet exists in the workbook, used to check which forecast file one should look in
Function ExtSheetExists(formString) As Boolean 'Form string is a formula string with both the worksheet and the workbook
Dim val As Variant
'Tries to execute formula and throws error if it doesn't exist
On Error Resume Next
val = ExecuteExcel4Macro(formString)
ExtSheetExists = (val <> Error(2023)) 'Returns False if the sheet does not exist based on Error 2023
On Error GoTo 0
End Function

Error with Format function

I am having a problem with the Format() function in excel vba. I am trying to alter the formatting of a date formatted cell to change the way it is displayed. However, everytime i invoke Format to do that i get the error: "Compile Error: Wrong number of arguments or invalid property assignment."
here is the code:
Sub test()
Dim given
given = DateSerial(2012, 10, 11)
dateformat = Format(given, "dd/mm/yy")
MsgBox given & vbCrLf & dateformat
End Sub
This is just a test function and should function on its own and return "11/10/12". This code works on other computers. What could be wrong?
Had this problem with code I put in a Worksheet_Activate() today and was pulling my hair out. Resolved it by changing Format to VBA.Format
So try:
Sub test()
Dim given
given = DateSerial(2012, 10, 11)
dateformat = VBA.Format(given, "dd/mm/yy")
MsgBox given & vbCrLf & dateformat
End Sub
This is because you might also have some Sub named Format somewhere else in your project.Hence you get the error.
Currently you are declaring your given variable as a variant by default. Please declare it as Date data type. And to be safe, make sure you only send a Date using CDate() into the Format() to format as the date style you want.
Also DateSerial input should be in the following format. Which in your case alright. ;)
DateSerial(CInt(x), CInt(y), CInt(z)
Code snippet:
OPTION EXPLICIT '------------ please add this to your code to begin for better coding
Sub test()
Dim given as Date '-------- define given as Date type
Dim dateformat as Date
given = DateSerial(2012, 10, 11)
dateformat = Format(CDate(given), "dd/mm/yy") '--------- anyway wrap with CDate() to be sure
MsgBox given & vbCrLf & dateformat
End Sub

Excel VBA call function with variable name

I'm trying to call a function with a variable name that is generated at run time based upon a combo box value. This is straightforward in most languages but I can't seem to figure it out in Excel VBA, I suspect this is because I don't really understand how the compiler works. I've found several posts that are close but don't quite seem to do the trick. The code below is wrong but should give an idea of what I want.
Thanks
Sub main()
'run formatting macros for each institution on format button click
Dim fn As String
Dim x As Boolean
'create format function name from CB value
fn = "format_" & CBinst.Value
'run function that returns bool
x = Eval(fn)
...
End Sub
CallByName is what you'll need to accomplish the task.
example:
Code in Sheet1
Option Explicit
Public Function Sum(ByVal x As Integer, ByVal y As Integer) As Long
Sum = x + y
End Function
Code is Module1 (bas module)
Option Explicit
Sub testSum()
Dim methodToCall As String
methodToCall = "Sum"
MsgBox CallByName(Sheet1, methodToCall, VbMethod, 1, 2)
End Sub
Running the method testSum calls the method Sum using the name of the method given in a string variable, passing 2 parameters (1 and 2). The return value of the call to function is returned as output of CallByName.
You should write a function that accepts the CB value as a parameter and then uses a select case to call the appropriate formatting function.
Something similar to this
Function SelectFormatting(Name as String) As Boolean
Select Case CBinst.Value
Case "Text1":
SelectFormatting = Text1FormattingFunction()
Case "Text2":
.
.
.
End Select
End Function
The above will work but not with a large number of names
Use Application.Run(MacroName, Parameters)
You have to may sure that there is a macro but it is better than the above as there is no select statement.
With respect to my answer above you might also find this useful to check whether the macro exists
'=================================================================================
'- CHECK IF A MODULE & SUBROUTINE EXISTS
'- VBA constant : vbext_pk_Proc = All procedures other than property procedures.
'- An error is generated if the Module or Sub() does not exist - so we trap them.
'---------------------------------------------------------------------------------
'- VB Editor : Tools/References - add reference TO ......
'- .... "Microsoft Visual Basic For Applications Extensibility"
'----------------------------------------------------------------------------------
'- Brian Baulsom October 2007
'==================================================================================
Sub MacroExists()
Dim MyModule As Object
Dim MyModuleName As String
Dim MySub As String
Dim MyLine As Long
'---------------------------------------------------------------------------
'- test data
MyModuleName = "TestModule"
MySub = "Number2"
'----------------------------------------------------------------------------
On Error Resume Next
'- MODULE
Set MyModule = ActiveWorkbook.VBProject.vbComponents(MyModuleName).CodeModule
If Err.Number <> 0 Then
MsgBox ("Module : " & MyModuleName & vbCr & "does not exist.")
Exit Sub
End If
'-----------------------------------------------------------------------------
'- SUBROUTINE
'- find first line of subroutine (or error)
MyLine = MyModule.ProcStartLine(MySub, vbext_pk_Proc)
If Err.Number <> 0 Then
MsgBox ("Module exists : " & MyModuleName & vbCr _
& "Sub " & MySub & "( ) : does not exist.")
Else
MsgBox ("Module : " & MyModuleName & vbCr _
& "Subroutine : " & MySub & vbCr _
& "Line Number : " & MyLine)
End If
End Sub
'-----------------------------------------------------------------------------------

Resources