Count characters between two empty space to dashes() in vba - vba

How do I get the length of character between beginning with space and ending with * Here is the image. Column B shows the total len before dasher(-) and my code
Sub xn()
Dim x As Integer
x = 1
If Worksheet("Sheet1").Range("A"& x).len(Right," ") Or _
Worksheet("Sheet1").Range("A"&x)len(Left,"-") Then
len(totallen)
End If
x = x + 1
End Sub

The code posted has multiple issues:
Worksheet is not a valid object - you need to use Worksheets.
.len is not a property of a Range object.
Even in .len was a property of a Range, you would need a
de-reference operator (aka '.') in here: Range("A"&x)len(Left,"-")
If you intend to use the function Len(), it only takes one argument.
You apparently are trying to loop, but you need to use either a For
or For Each loop - it won't loop automatically when you increment x
at the bottom of the sub.
Right is a function, but you're calling it without arguments and they are not optional.
Similarly, Left is a function, but you're also calling it without
the required arguments.
totallen is not declared anywhere, so Len(totallen) will assume
that totallen is a Variant (default for undeclared variables), then
cast it to a String, and then always return 0 because it has never
been given a value.
Anything else I may have missed.
The solution is to use the InStr function. It returns the location in a string of a given sub-string.
Sub xn()
Dim x As Long
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Worksheets("Sheet1")
For x = 1 To sheet.Range("A" & sheet.Rows.Count).End(xlUp).Row
sheet.Cells(x, 2) = InStr(1, sheet.Cells(x, 1), "-") - 1
Next x
End Sub
I'd also recommend taking a look at the MSDN article on Looping Through a Range of Cells (2003 vintage, but still valid), and Error Finding Last Used cell In VBA.

Related

vba: lbound error on dates array

I have a "Datevarie" dynamic matrix which contains many dates.
At some point in the routine I have to extract from DateVarie the lowest value.
The problem is that when I use the Lbound function, I always return the value 1 instead of the date (for example "01/01/2018").
I think the data in the array is entered correctly as I debugged it step by step several times.
How can I resolve without having to report data on a sheet and order them? Do I have to use FOR ... NEXT? The dates can be 2-3 but also several tens
Type interventi
...
data as date
...
public Intervento as interventi
public rs1 as adodb.recordset
...
Sub TheSubWithProblem(...)
...
dim Datevarie() as date
..
redim preserve etc..
DateVarie(k)=format(RS1!DataI,"dd/mm/yyyy") '<<<< correct
...
Intervento.data=lbound(datevarie) '<<<< always return 1
...
The problem is that when I use the Lbound function, I always return the value 1 instead of the date (for example "01/01/2018").
LBOUND and UBOUND functions return the lower- and upper bounds of the array, not the lowest and highest values within the array.
Arrays in VBA are base-0 by default, so an initialized array should typically have LBound of 0.
If you want to get the lowest or highest value, then you need to implement your own algorithm to do so (e.g., a for/next loop), or if this is a single-dimensional array we can potentially make use of an ArrayList object which has (among other things) a Sort method:
Set d = CreateObject("System.Collections.ArrayList")
Dim dateVarie As Variant
Dim i As Long, m As Long, day As Long
For i = 1 To 100
m = Application.WorksheetFunction.RandBetween(1, 12)
day = Application.WorksheetFunction.RandBetween(1, 30)
d.Add (DateValue(DateSerial(2018, m, day)))
Next
'Preserve your un-sorted array, if needed:
ReDim dateVarie(d.Count - 1)
dateVarie = d.ToArray()
Msgbox "The first value is: " & dateVarie(0)
d.Sort ' Sorts the arraylist:
MsgBox "The lowest value is: " & (d(0))
Arrays start at 0. This is why the below returns 0:
Sub TestMe()
Dim datevarie(2) As Date
Debug.Print LBound(datevarie)
End Sub
And it does not matter, whether you put values in the array or not.
If you want an array to start at 1, in VBA write Option Base 1 and make sure that noone sees the code, because you may have problems with your colleagues/peers:
Option Explicit
Option Base 1
Sub TestMe()
Dim datevarie(2) As Date
Debug.Print LBound(datevarie)
End Sub

Passing arrays to UDF; UBound

It's quite frustrating that I already seem to be doing something wrong in the first line of my first VBA project. In essence my project has already been stalled because I can't figure out why this works:
Function TestF(Values As Variant, Dates As Variant)
TestF = Values(2)
End Function
But this does:
Function TestF(Values As Variant, Dates As Variant)
TestF = UBound(Values)
End Function
(I just want to see that UBound works. So, I removed everything from the project that is not related.)
Where Values and Dates are each supposed to be a 1-dimensional array. (Or ranges? Or is that the issue?)
How do I fix the first bit of code?
I Googled and I Googled, but I haven't found my answer.
The (Excel) 'error' is get is #VALUE! from =testf(A2:A10,B2:B10), where the ranges are like:
-1000 31-Dec-13
-10 31-Dec-14
30 13-Mar-15
1200 17-Mar-15
-40 30-Jun-15
1300 30-Sep-16
1200 31-Oct-17
1250 30-Nov-18
1500 31-Dec-18
The problem in your passing of array to UDF is your understanding about array and ranges. In general, ranges are presented as a two dimensional array even when they are with single row or column.
To make your code work, try the "Double Transpose Trick" which is pretty much the following:
Public Sub TestMe()
Dim k As Variant
k = Range("A2:F2")
Debug.Print k(1)
With WorksheetFunction
k = .Transpose(.Transpose(k))
Debug.Print k(1)
End With
End Sub
The code above will hopefully result as an error in the Debug.Print k(1) part. This is because k is a two-dimensional array, although it is on one row only:
Comment this part or change it to Debug.Print k(1, 1) and continue with the .Transpose It will change your array to a single dimension and it will be working.
Thus, if you want your non-working formula to work, this is a possible way to do it:
Public Function TestFormula(myValues As Variant) As String
Dim myArr As Variant
With WorksheetFunction
myArr = .Transpose(.Transpose(myValues))
TestFormula = myArr(UBound(myArr))
End With
End Function
Some important notes: the "Double Transpose Trick" works on one row ranges, when these should be transfered to array. If you are having a one column range, use "Single Transpose":
myArr = .Transpose(myValues)
With more than 1 column or 1 row, do not use transpose as it cannot be mapped to a 1 dimensional array.
Furthermore, if you pass a range of once cell, it will not work. But you will find some way to go around it.
As mentioned by #cyboashu in the comments, the myArr() array would take values up to column 65536, because the Transpose() is made this way, probably for compatibility reasons with Excel 2003. To make a bigger array - Put entire column (each value in column) in an array?
You need to pass the right parameters to your UDF.
Both parameters are Range.
Function TestF(Rng1 As Range, DatesRng As Range) As Long
Dim C As Range
Dim x As Long
For Each C In Rng1
If Trim(C.Value) <> "" Then ' make sure there isn't a blank cell in the middle of your Range
x = x + 1
End If
Next C
TestF = x - 1
End Function
If you don't have empty cells in the middle of your Range, then the following code will be sufficient:
Function TestF(Rng1 As Range, DatesRng As Range) As Long
Dim C As Range
TestF = Rng1.Cells.Count - 1
End Function
You probably wanted:
TestF=Values(Ubound(Values))
also, you should declare what your function is suppose to return, like
Function TestF(Values As Variant, Dates As Variant) as String

Type Mismatch that is normally matched [duplicate]

In some of my column's cells there appear #VALUE! words and formulas inside are as follows example:
=IF(VALUE(RIGHT(CELL("nome.arquivo";A1);LEN(CELL("nome.arquivo";A1))-SEARCH("]";CELL("nome.arquivo";A1))))=1;1;1+INDIRECT(ADDRESS(329;COLUMN();;;VALUE(RIGHT(CELL("nome.arquivo";A1);LEN(CELL("nome.arquivo";A1))-SEARCH("]";CELL("nome.arquivo";A1))))-1)))
Mentioned column is CT. Now when i am trying to loop through the cells when it comes to first occurence of #VALUE! i get an error:
Run Time Error 13, Type mismatch on this line:
L = 9
Do While Cells(L, "CT").Value <> "" '<========= HERE AN ERROR
L = L + 8
Loop
How to fix that?
Cells doesn't take any String parameter, the type mismatch error you're getting has nothing to do with #VALUE / the data being processed - because the code never gets to evaluate the data, since Cells wants two Integer parameters: dang this bites me everytime - apparently you can use string parameters in the Cells function. Ugh.
So the problem is with comparing the value to "" - a string. #VALUE! isn't a valid string function so you need to account for it:
Dim theCell As Range
Set theCell = Cells(L, "CT")
If Not IsError(theCell.Value) Then
Do While Not IsEmpty(theCell.Value)
'...
L = L + 8
Loop
End If
You might also want to correctly qualify that function call:
Do While Not IsEmpty(ActiveSheet.Cells(L, "CT").Value)
That way it's explicit that you're looking at a cell in the active worksheet; an unqualified call is implicitly doing that, and anything implicit is potentially confusing and bug-prone.
Make sure the top of the module says Option Explicit and that L is properly declared:
Dim L As Long
"L" being a meaningless identifier, you should consider naming it after what you're using it for:
Dim currentRow As Long
currentRow = 9
Do While Not IsEmpty(ActiveSheet.Cells(currentRow, "CT"))
That way your code becomes much easier to read, follow and understand.

VBA Run Time Error 13 Type Mismatch #VALUE

In some of my column's cells there appear #VALUE! words and formulas inside are as follows example:
=IF(VALUE(RIGHT(CELL("nome.arquivo";A1);LEN(CELL("nome.arquivo";A1))-SEARCH("]";CELL("nome.arquivo";A1))))=1;1;1+INDIRECT(ADDRESS(329;COLUMN();;;VALUE(RIGHT(CELL("nome.arquivo";A1);LEN(CELL("nome.arquivo";A1))-SEARCH("]";CELL("nome.arquivo";A1))))-1)))
Mentioned column is CT. Now when i am trying to loop through the cells when it comes to first occurence of #VALUE! i get an error:
Run Time Error 13, Type mismatch on this line:
L = 9
Do While Cells(L, "CT").Value <> "" '<========= HERE AN ERROR
L = L + 8
Loop
How to fix that?
Cells doesn't take any String parameter, the type mismatch error you're getting has nothing to do with #VALUE / the data being processed - because the code never gets to evaluate the data, since Cells wants two Integer parameters: dang this bites me everytime - apparently you can use string parameters in the Cells function. Ugh.
So the problem is with comparing the value to "" - a string. #VALUE! isn't a valid string function so you need to account for it:
Dim theCell As Range
Set theCell = Cells(L, "CT")
If Not IsError(theCell.Value) Then
Do While Not IsEmpty(theCell.Value)
'...
L = L + 8
Loop
End If
You might also want to correctly qualify that function call:
Do While Not IsEmpty(ActiveSheet.Cells(L, "CT").Value)
That way it's explicit that you're looking at a cell in the active worksheet; an unqualified call is implicitly doing that, and anything implicit is potentially confusing and bug-prone.
Make sure the top of the module says Option Explicit and that L is properly declared:
Dim L As Long
"L" being a meaningless identifier, you should consider naming it after what you're using it for:
Dim currentRow As Long
currentRow = 9
Do While Not IsEmpty(ActiveSheet.Cells(currentRow, "CT"))
That way your code becomes much easier to read, follow and understand.

#VALUE error with Excel VBA Function

In my Excel spreadsheet I have two columns.
A contains strings with the values 'Yes', 'No' or 'Maybe'.
B contains strings with a year in.
I need a function to determine the number of occurrences of a year in column B, where the equivalent value in column A is 'Yes'.
I currently have the following code:
Function CountIfYearAndValue(Rng As Range, YNM As String, Year As String) As Integer
Dim count As Integer
count = 0
For Each c In Rng.Cells
If (StrComp(Abs(c.Value), Year, vbTextCompare) = 0) And (StrComp(Cells(c.Row, A), YMN, vbTextCompare) = 0) Then count = count + 1
Next
CountIfYearAndValue = count
End Function
The idea of this code is that we iterate through every cell in the range given (a range on column B) and check if the year is equal to the Year parameter. And if the equivalent cell on column A is equal to the YNM parameter we increment the count variable.
For some reason this code does not work when I use the following parameter:
=CountIfYearAndValue('Years'!B1:B7,"Yes","Year 7")
It just does the #VALUE error and refuses to display any outcome.
Any help would be much appreciated.
Edit: All of the values in both cells are on of an unformatted datatype ('General') and no cells are blank.
It sounds like you are reinventing the wheel... There already is a built in function (advantage: being much faster than a UDF) that does exactly what you are after. It is called COUNTIFS()
All YESes for Year 7 in rows 1 to 10.
=COUNTIFS(B1:B10, "Year 7",A1:A10, "Yes")
I just had a quick look at your code and I think there are possibly a few reasons why your original code is not working as expected.
YNM is a valid column name therefore it should not be used as a variable name. You should avoid naming your variables like that - give it a more meaningful name
YNM != YMN as you had it in your code (see function definition and then the misspelled version in the StrComp() function)
Year is a valid VBA built in function, therefore once again you should avoid using it as a variable name as you're exposing yourself to a naming collision.
Add Option Explicit at the top of your module. This requires you to Dimension all you variables. It's always recommended for many many reasons.
rng variable is of Range type therefore you do not need to explicitly add the .Cells property to it. Even though it may help in some cases - at a bit more advanced level you may face some runtime type compatibility issues. ( runtime may convert your rng Range variable to a 2D array etc )
Added an explicit conversion in the second StrComp() function around the c.Offset(0, -1) as you don't want the runtime to (rare but still possible) convert your Yes to a Boolean data type. Explicit conversion to a String just gives you that extra protection ;p (lol)
therefore, something like this returns the correct value
Function CountIfYearAndValue(rng As Range, choice As String, myYear As String) As Long
Dim count As Long
count = 0
Dim c As Range
For Each c In rng
If (StrComp(c, myYear, vbTextCompare) = 0) And (StrComp(CStr(c.Offset(0, -1)), choice, vbTextCompare) = 0) Then
count = count + 1
End If
Next c
CountIfYearAndValue = count
End Function
Right, I hope this helps you understand bits and pieces :) any questions please leave a comment