I am getting a RunTime 13 error when trying to use a variable for a sheetname as per below:
Sub inputdata()
Set asheet1 = ThisWorkbook.Worksheets("input").Range("D12")
Set rangeDate = ThisWorkbook.Worksheets("input").Range("inputdate")
Range("F12:M12").Copy
Sheets(asheet1).Select
It is erroring on the line Sheets(asheet1).Select
Any help would be great thanks!
The asheet1 is not a string, you are asigning a range object to it . You should declare asheet1 as string and the change this line to
Dim asheet1 as string
asheet1 = ThisWorkbook.Worksheets("input").Range("D12").Value
That should make it work!
Edit
removed the Set keyword from the string var.
Option Explicit
Sub inputdata()
dim inputSheet as WorkSheet
dim aCellOnInputSheet as Range
dim inputDateCell as Range
dim userSheetName as String
Set inputSheet = ThisWorkbook.Worksheets("input")
Set aCellOnInputSheet = inputSheet.Range("D12")
userSheetName = aCellOnInputSheet.Value
Set inputDateCell = inputSheet.Range("inputdate")
Range("F12:M12").Copy
Sheets(userSheetName).Select
End Sub
EDIT: A couple of points
1) Option Explicit is a must.
2) Define variables and name it appropriately. i.e. define variable which refers to a cell/Range with the name range instead of aSheet - it confuses the reader
Related
Context: I am writing a function which returns words/numbers present in a string which are enclosed by parenthesis.
Example: Calling ExtractParenthesis("This {should} work. But {doesnt}.") should return a collection containing two items, should and doesnt.
Error: The error I receive from the code below is
Run-time error '450': Wrong number of arguments or invalid property
assignment
It doesn't appear on a particular line and I just receive an error message with "OK" and "Help" as options.
Code:
Public Function ExtractParenthesis(strText As String) As Collection
Dim i As Long
Dim RegExp As Object
Dim Matches As Object
Dim Output As New Collection
Set Output = Nothing
Set RegExp = CreateObject("vbscript.regexp")
RegExp.Pattern = "{(.*?)}"
RegExp.Global = True
Set Matches = RegExp.Execute(strText)
For i = 0 To (Matches.count - 1)
Output.Add Matches(i).submatches(0)
Next i
Set ExtractParenthesis = Output
End Function
It works exactly the way you want it for me:
Option Explicit
Public Sub TestMe()
Dim myColl As New Collection
Set myColl = ExtractParenthesis("This {should} work. But {doesnt}.")
Debug.Print myColl(1)
Debug.Print myColl(2)
End Sub
Public Function ExtractParenthesis(strText As String) As Collection
Dim i As Long
Dim RegExp As Object
Dim Matches As Object
Dim Output As New Collection
Set Output = Nothing
Set RegExp = CreateObject("vbscript.regexp")
RegExp.Pattern = "{(.*?)}"
RegExp.Global = True
Set Matches = RegExp.Execute(strText)
For i = 0 To (Matches.Count - 1)
Output.Add Matches(i).submatches(0)
Next i
Set ExtractParenthesis = Output
End Function
I receive "should" and "doesnt" on the immediate window (Ctrl+G). Probably you are not aware that you are returning a collection. It should be used with the Set keyword.
To run it from the immediate window, try like this:
?ExtractParenthesis("This {should} work. But {doesnt}.")(1)
?ExtractParenthesis("This {should} work. But {doesnt}.")(2)
From what I understand of your comment to Vityatas answer you mean you want to run it as a worksheet function - running it directly
The changes I've made to your code will let you use it as a function:
In A1:B1 this will work: {=ExtractParenthesis("This {should} work. But {doesnt}.")}
In A1:A2 use it like this: {=TRANSPOSE(ExtractParenthesis("This {should} work. But {doesnt}."))}
NB: The curly brackets are added by Excel when you enter the formula using Ctrl+Shift+Enter rather than Enter on its own.
The one problem with the code is that you must select the correct number of cells first - if it should return three words, but you've only selected two then you'll only see the first two.
Public Function ExtractParenthesis(strText As String) As Variant
Dim i As Long
Dim RegExp As Object
Dim Matches As Object
Dim Output As Variant
Set Output = Nothing
Set RegExp = CreateObject("vbscript.regexp")
RegExp.Pattern = "{(.*?)}"
RegExp.Global = True
Set Matches = RegExp.Execute(strText)
ReDim Output(1 To Matches.Count)
For i = 1 To (Matches.Count)
Output(i) = Matches(i - 1).submatches(0)
Next i
ExtractParenthesis = Output
End Function
I have various settings tables in Excel, each with two column headings Parameter and Value.
I want to pass a specific table's name to a function getParameter that looks up a specific parameter's name in that table, returns the associated parameter's value, and performs all error handling, e.g. with the following code segment:
Function getParameter(....
...
Dim paramterValue as Variant
With Application
parameterValue = .Index([tableName[Value], .Match("parameterName", [tableName[Parameter], 0))
If Not IsError(parameterValue) then
...
Else
...
End If
End With
End Function
How do I define the appropriate function arguments and call the function?
Tables are in VBA selectable as ListObject Object. But those objects are on worksheet scope only. So we must know the worksheet on which the table is placed on to get it using wrksht.ListObjects(tableName).
To be more flexible, we could using Evaluate to evaluate the structured references:
Public Function getParameter(tableName As String, parameterName As Variant) as Variant
Dim parameterValue As Variant
Dim oRangeTValues As Range
Dim oRangeTParameters As Range
Set oRangeTValues = Evaluate("" & tableName & "[Value]")
Set oRangeTParameters = Evaluate("" & tableName & "[Parameter]")
With Application
parameterValue = .Index(oRangeTValues, .Match(parameterName, oRangeTParameters, 0))
If Not IsError(parameterValue) Then
getParameter = parameterValue
Else
getParameter = CStr(parameterValue)
End If
End With
End Function
This will be usable on all worksheets since the table names are on workbook scope in reality.
This is supposed to be used as User Defined Function using a cell formula like =getParameter("TableName","Parameter").
I'll try like this, identifying the sheet and the ListObject corresponding to your TableName :
Function getParameter(ByVal tableName As String, ByVal parameterName As String) As Variant
Dim parameterValue As Variant
Dim RgVal As Range
Dim wS As Worksheet
Dim LOTable As ListObject
Application.Volatile
Set wS = Evaluate(tableName).Parent
Set LOTable = wS.ListObjects(tableName)
Set RgVal = LOTable.DataBodyRange
With Application.WorksheetFunction
parameterValue = .Index(RgVal.Columns(2), .Match(parameterName, RgVal.Columns(1), 0))
End With 'Application.WorksheetFunction
If Not IsError(parameterValue) Then
getParameter = parameterValue
Else
'...
DoEvents
getParameter = CStr(parameterValue)
End If
End Function
Call in VBA :
Sub test_GetParameter()
Debug.Print getParameter("Table1", "testParam")
End Sub
Call in Excel :
= getParameter("Table1", "testParam")
#R3uk Axel Richter's code is sufficient, but yours also works.
I have a need to refer to a seriescollection by name. The MSDN object model page for seriescollection states either an index or a name can be used. However when I try to use a string variable I get error 1004 'Invalid parameter':
Dim sSeriesName As String
dim aRootCats() as string
Dim cSeriesCol As SeriesCollection
For x = 0 To UBound(aRootCats)
sSeriesName = aRootCats(x)
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(sSeriesName)
Next x
I've tried the following too:
sSeriesName = CStr(aRootCats(x)) ' just in case, because I filled this array with variant data type earlier
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(sSeriesName)
and
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(aRootCats(x))
and
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection("Product Support")
UPDATE: I'm also experiencing the same error when looping on the seriescollection:
For c = 1 To cChart.ChartGroups(1).SeriesCollection.Count
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(c)
Next c
Any ideas?
Many thanks.
Because you are using a ChartGroup not a Chart, you have to use the Item property of the SeriesCollection and you have to pass a variant. Use either:
cChart.ChartGroups(1).SeriesCollection.Item(1)
or:
cChart.ChartGroups(1).SeriesCollection.Item(CVar(sSeriesName))
(or declare the variable as Variant rather than String)
Can I convert the following declaration and assignment into one line:
Dim clientToTest As String
clientToTest = clientsToTest(i)
or
Dim clientString As Variant
clientString = Split(clientToTest)
There is no shorthand in VBA unfortunately, The closest you will get is a purely visual thing using the : continuation character if you want it on one line for readability;
Dim clientToTest As String: clientToTest = clientsToTest(i)
Dim clientString As Variant: clientString = Split(clientToTest)
Hint (summary of other answers/comments): Works with objects too (Excel 2010):
Dim ws As Worksheet: Set ws = ActiveWorkbook.Worksheets("Sheet1")
Dim ws2 As New Worksheet: ws2.Name = "test"
You can sort-of do that with objects, as in the following.
Dim w As New Widget
But not with strings or variants.
You can define and assign a value in one line, as shown below. I have given an example of two variables declared and assigned in a single line. If the data type of multiple variables are the same:
Dim recordStart, recordEnd As Integer: recordStart = 935: recordEnd = 946
in fact, you can, but not that way.
Sub MySub( Optional Byval Counter as Long=1 , Optional Byval Events as Boolean= True)
'code...
End Sub
And you can set the variables differently when calling the sub, or let them at their default values.
In some cases the whole need for declaring a variable can be avoided by using With statement.
For example,
Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogSaveAs)
If fd.Show Then
'use fd.SelectedItems(1)
End If
this can be rewritten as
With Application.FileDialog(msoFileDialogSaveAs)
If .Show Then
'use .SelectedItems(1)
End If
End With
Is there anyway to convert a string value to a Range object ? I'm having a function which takes a Range object as a argument and need to pass a single string parameter to it
Thank You
A string with a cell address? if so:
Dim r As Range: Set r = Range("B3")
MsgBox r.ColumnWidth
I don't like this one bit, but if you can't change the function that requires a range, you could create a function that converts a string to a range. You'd want to be sure that the only thing the first function cares about is the Value or Text properties.
Function FuncThatTakesRange(rng As Range)
FuncThatTakesRange = rng.Value
End Function
Function ConvertStringToRange(sInput As String) As Range
Dim ws As Worksheet
Set ws = Workbooks.Add.Sheets(1)
ws.Range("A1").Value = sInput
Set ConvertStringToRange = ws.Range("A1")
Application.OnTime Now + TimeSerial(0, 0, 1), "'CloseWB """ & ws.Parent.Name & """'"
End Function
Sub CloseWb(sWb As String)
On Error Resume Next
Workbooks(sWb).Close False
End Sub
Use in the Immediate Window like
?functhattakesrange(convertstringtorange("Myvalue"))
Here is my solution that involves no need for a new function.
1.Make dynamic string variable first
2.Then finalize it by creating a range object out of this string via a range method: Set dynamicrange= range (dynamicstring)
You can manipulate dynamicstring as you want to, I just kept it simple so that you can see that you can make range out of a string variable.
Sub test()
Dim dynamicrangecopystring As String
Dim dynamicrangecopy As range
dynamicrangecopystring = "B12:Q12"
Set dynamicrangecopy = range(dynamicrangecopystring)
End Sub
Why not change the function argument to a variant and then in the function determine Using VarType etc) if you have been passed a Range and use error handling to check for a string which can be converted to a range or a string that cannot be converted to a range ?
This simple function will convert string arguments into a range object, usable in other excel functions.
Function TXT2RNG(text) As Variant
Set TXT2RNG = Range(text)
End Function
Let's say Sheet1!A1 has the text value "Sheet1!B1" and Sheet1!B1 has the value "1234". The following code will use the range address stored as text in A1 as an input and copy the range B1 to A2:
Sub Tester()
Sheet1.Range(Range("A1")).Copy
Sheet1.Range("A2").PasteSpecial xlPasteAll
End Sub