.Value does not read whole string - excel

In my macro I need to read a value out of a Cell. The values always start with an ' followed by a number like '1 or '1001.
When I attempt to read the cell like s = wsout.Cells(headerVal(6, 1) + i, 1).Value, I only get 1 instead of '1.
wsout is a worksheet and s is defined as a String.
How do I read the actual contents of the cell?

You need the Range.PrefixCharacter Property whih returns the prefix character for the cell.
Here is an example
s = wsout.Cells(headerVal(6, 1) + i, 1).PrefixCharacter & _
wsout.Cells(headerVal(6, 1) + i, 1).Value
Debug.Print s
If the cell has '1 then s above will have '1

Related

Left Function Compile Error: Argument not optional (VBA)

I am trying to do a few things with this subroutine.
First i need to insert a row after every 18th row
Then i need to insert a string in column A based on the string in the above row (i.e. 17th row in the first iteration).
Finally i need to insert a string in column B of the ith row again based on the previously established string.
So in Layman's terms, row 17 will say 120F_CASH
i want to find "_ " and take the characters in the string from the left of the "_ ", then in row 18 i want to put 120F & "_MULTI_STRAT" in column A
in column B of row 18, i want to insert "SSELECT PERF.IMST.INDEX WITH ENTITY = " & "120F" & "AND WITH CATEGORY1 = ""01"""
here's my code:
Option Explicit
Sub InsertRowEveryXrows()
Dim r As Long, lr As Long
Dim code As String
lr = Range("A" & Rows.Count).End(xlUp).Row
For r = 18 To lr Step 18
Rows(r).Insert Shift:=xlDown
Set code = Left(Range(Cells(r - 1, "A"), InStr(1, "_", Cells(r, "A")) - 1))
Cells(r, "A") = code & "_MULTI_STRAT"
Cells(r, "B") = "SSELECT PERF.IMST.INDEX WITH ENTITY = " & code & "AND WITH CATEGORY1 = ""01"""
Next r
End Sub
i am getting a compile error: Wrong number of arguments or invalid property assignments on this line:
Set code = Left(Range(Cells(r - 1, "A"), InStr(1, "_", Cells(r, "A"))
- 1))
the string's location is in row 17 (r-1) in column A & the number of characters is found by looking for "_"
What am i missing?
*fyi i had to add a space after the underscore for it to show up properly here, however, there SHOULD NOT be a space after the underscore.
Set code = Left(Range(Cells(r - 1, "A"), InStr(1, "_", Cells(r, "A")) - 1))
The Left function wants a string and an integer, but you haven't provided the integer. Here's the same expression, without the outer Left function call:
Set code = Range(Cells(r - 1, "A"), InStr(1, "_", Cells(r, "A")) - 1)
Notice anything? The result of InStr is being passed as the 2nd argument to the (unqualified) Range property, and that isn't what you intended.
In fact, you don't need that Range call at all. This should be closer to your intent:
Set code = Left(Cells(r - 1, "A"), InStr(1, "_", Cells(r, "A")) - 1)
Note that there is quite a bit of implicit code going on here; made explicit, reads like this:
Set code = Left(ActiveSheet.Cells(r - 1, "A").Value, InStr(1, "_", ActiveSheet.Cells(r, "A").Value) - 1)
Do you really intend to be working of just whatever worksheet happens to be active? Most likely not, but if so, consider explicitly qualifying these Cells calls with ActiveSheet. If you mean to be working with a specific sheet, use that sheet object as a qualifier instead.
Now, you're using Set for this assignment, but code is not an object reference, and that is another problem.
Strings are not objects in VBA, they're assigned with the regular value assignment syntax. That is, without a Set keyword (you could have the legacy Let keyword there if you wanted, but it's not needed):
code = Left(ActiveSheet.Cells(r - 1, "A").Value, InStr(1, "_", ActiveSheet.Cells(r, "A").Value) - 1)
Now, Range.Value (explicit here, implicit in your code) will be a Variant, not a String. In most cases, it won't matter.
Until one cell has a Variant/Error subtype (think #N/A, or #VALUE! worksheet errors); then everything blows up with a type mismatch error. To avoid this, you can use the Text of the cell instead of its Value, or you can pull that value into its own local Variant variable, and only proceed to treat it like a string when IsError returns False for it.
You could use something like so
Function Pop_String(strInput As String, strDelim As String, Optional lngInstance = 1)
Dim aTemp() As String
aTemp = Split(strInput, strDelim, lngInstance + 1)
Pop_String = aTemp(lngInstance - 1)
End Function
Calling like so
Pop_String("a-b-c-d-e-f","-",4) returns d
Pop_String("a-b-c-d-e-f","-",2) returns b
I would add some error checking too, the default (without 3rd argument) is the first section, so
Pop_String("test-string","-") would return test and
Pop_String("test-string","-",2) would return string.

VBA - How to output a variable to a particular row and column in excel?

This code should find the correct cell (in the column corresponding to it's 'length' and the next empty row) in which to output a variable.
I'm getting the error message:
method range of object _worksheet failed
on lines 13 onward containing "outputcolumn"
In the MsgBox lines, the correct column and row number are being displayed, so I am not sure why it is not happy with my outputcolumn in particular.
Private Sub OutputRowAndColumn()
'Choose correct column: Find the length column and name this outputcolumn
Dim cell As Range, outputcolumn As Integer
Set cell = Range("FindLength").Find(Range("Length").Value, LookIn:=xlValues)
If Not cell Is Nothing Then
outputcolumn = cell.Column
End If
MsgBox "Output column is number " & outputcolumn & "."
'Choose correct row: If the cell to the left of "cell" is empty then this is the first row of output otherwise find next empty cell down
If Sheet1.Range(outputcolumn & "4").Offset(0, 1).Value = "" Then
outputrow = 4 ''' error msg '''
ElseIf Sheet1.Range(outputcolumn & "5").Offset(0, 1).Value = "" Then
outputrow = 5
Else
outputrow = Sheet1.Range(outputcolumn & "4").Offset(0, 1).End(xlDown).Row + 1
End If
MsgBox "Output row is number " & outputrow & "."
'Copy values 1, 2 and 3 from sheet 2 to sheet 1
Sheet1.Range(outputcolumn & outputrow).Offset(0, 1).Value = Sheet2.Range("Value1").Value ''' error msg '''
Sheet1.Range(outputcolumn & outputrow).Offset(0, 2).Value = Sheet2.Range("Value2").Value
Sheet1.Range(outputcolumn & outputrow).Offset(0, 3).Value = Sheet2.Range("Value3").Value
End Sub
outputcolumn is a numeric value (you defined it as Integer, but you always should define variables holding row or column numbers as long to avoid overflow errors).
So let's say outputcolumn gets the number 2 (column B). You write Sheet1.Range(outputcolumn & "4"). To access a range by it's address, You would have to write something like Range("B4"), but what you write is Range(2 & "4"), which means Range("24"), and that is an invalid address for a Range.
You could try to translate the column number 2 to a B, but there is an easier way to access a cell when you know the row and column number: Simply use the cells-property:
If Sheet1.Cells(4, outputcolumn).Offset(0, 1).Value = "" Then
' (or)
If Sheet1.Cells(4, outputcolumn+1).Value = "" Then
Just note that the order of the parameters is row, column.
"outputcolumn" is numeric in your case and when using .Range(), it needs to be a proper alphanumeric cell reference like "C5", not all numeric.
I haven't tried it directly but changing this ...
If Not cell Is Nothing Then
outputcolumn = cell.Column
End If
... to this ...
If Not cell Is Nothing Then
outputcolumn = Split(cell.Address, "$")(1)
End If
... will go a long way to helping you.

sum number of a string of a cell that meet certain conditions

I just wonder how to calculate this in vba:
Calculate the first amount of money if it is yes but not calculate the amount if it is no. Imagine there are four cells:
(cell 1) abcbc bcbcbcb cbcbcbc $1000/kskskksks/$2000//1222/1221/11/yes
(cell 2) any words will be here $2300/heyhey hey/ //3232//3232/no
(cell 3) kakjsak dsdsk kdjskj 2323/ $23232/hhehe 22/33/333/yes
(cell 4) kakaka kjsdkj ksjskjds kdjsjkdj 11 223 222/ $1121/ $2121/yes
The algorithm is to check whether is yes or no. Then, on each line, find the first money, beginning with $, the second money on the same line would not take into account.
In this example, the program will take $1000 into account, because it is yes, second line would not be executed since it is no. And the third cell would take the first money (first $), $23232. So, the program will sum $1000+$23232+$1121=$25353
I guess that this is what you want, considering that you are using the first column to place each value and your sheet's name is "Sheet1"
Sub SumFirstAmountIfYes()
Dim AmountSum As Variant ' Declares the AmountSum
lastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row ' Finds the last used row on the first column
For i = 1 To lastRow ' Iterates over the rows to the last row
StringValue = Sheets("Sheet1").Cells(i, 1).Value2 ' Gets the value to a variable
If StringValue Like "*yes" Then ' Checks if the string terminates with "yes"
FirstDollar = InStr(StringValue, "$") ' Finds first dollar symbol "$"
FirstSlashAfterDollar = InStr(FirstDollar, StringValue, "/", 0) ' Finds first slash "\" after the first dollar symbol
FirstAmount = Mid(StringValue, FirstDollar + 1, FirstSlashAfterDollar - FirstDollar - 1) ' Gets the amount of each row
AmountSum = AmountSum + CDec(FirstAmount) ' Adds to the sum variable each found amount
End If
Next
MsgBox (AmountSum) ' Shows the final sum of the amounts
End Sub
This uses split to isolate yes/no and InStr to locate the first currency symbol.
Sub sumYes()
Dim i As Long, str As String, dbl As Double
With Worksheets("Sheet10")
For i = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
str = LCase(.Cells(i, "A").Value2)
If Split(str, "/")(UBound(Split(str, "/"))) = "yes" Then
If CBool(InStr(1, str, Chr(36))) Then
dbl = dbl + Val(Mid(str, InStr(1, str, Chr(36)) + 1))
End If
End If
Next i
.Cells(2, "B") = dbl
End With
End Sub
Slightly different approach which uses excel array formula assuming your cell values doesn't contain trailing spaces ,
=SUM(IF(RIGHT(A1:A4,1)="s",MID(A1:A4,SEARCH("$",A1:A4)+1,SEARCH("/",A1:A4,SEARCH("$",A1:A4))-SEARCH("$",A1:A4)-1)*1,""))

Cell reference based on FOR loop index

Here is some of my code:
Dim wbX As Workbook
Dim wbY As Workbook
Set wbX = Application.Workbooks.Open("C:\Converter\aaa.xls")
Set wbY = Application.Workbooks.Open("C:\Converter\bbb.xlsx")
For i = 1 To wbX.Sheets.Count
wbY.Sheets(1).Activate
Range("Y" & i + 2).Select
ActiveSheet.Range("Y" & i + 2).Formula = "=RIGHT(("S" & i + 2); 4)"
The problem is that ("S" & i + 2) is not recognized as a cell - VBA spits out syntax errors.
Your expression "Y" & i + 2 does not yield a valid cell reference because you concatenate a number to a string. You must convert the numeric expression to a string:
"Y" & Str(i + 2)
What I understand from your comment, the assignment should be written as:
"=LEFT(S" & Trim(Str(i + 2)) & "; 4)" ' yields e.g.: =LEFT(S3; 4)
(The LEFT function gets the first characters from a string. This assumes the cells you reference contains strings, or that VB converts the value to a string first. And here you must use Trim(Str(i + 2)) because you are constructing a string to place as a formula in the cell.)
Maybe this example helps you:
Option Explicit
Sub test()
Dim rngC As Range
For Each rngC In Range("C2:C100")
rngC.Offset(0, 4) = Right(rngC, 4)
Next
End Sub

Select range of rows to delete in Excel 2007. Runtime error 1004?

I'm trying to write a code that deletes all rows between the 3rd and last data row on a worksheet. I have some short lines of code that first looks for the last row containing data, returns that row number. Subtracts 1 from it. And selects the data range from 3rd row to the 2nd to last row and attempts to delete them. But I run into error every time I run this code. Any suggestions?
Sheets("Sheet1").Activate
lastrow = (Sheet1.Range("A1").Offset(Sheet1.Rows.Count - 1, 0).End(xlUp).Row) - 1
Range("3: lastrow").Select 'Error 1004: method range of object _global failed
Selection.Delete Shift:=xlUp
Using the SpecialCells property of the range:
Range("A3:" & Range("A1").SpecialCells(xlCellTypeLastCell).Address).Select
This will select the block up until the last used cell.
Edit:
To incorporate it into your program to get the second to last, do some string manipulations on the last cell.
Dim str, str1, str2, add As String
Dim index, num As Integer
str = Range("A1").SpecialCells(xlCellTypeLastCell).Address 'returns say $j$20
index = InStr(2, str, "$") 'find the second dollar sign
str1 = Left(str, index) 'gets the string "$j$"
str2 = Mid(str, index + 1) 'get the string "20"
num = CInt(str2) 'convert "20" to 20
num = num - 1
add = str1 & CStr(num) 'reattach to form "$j$19"
Range("A3:" & add).Select

Resources