Trying to build a Select Case statement that does a similar job to a nested if function. Essentially I want to give a cell a value (in Column i + 1) based on values of two columns (column P and column I) and then apply it to a down the whole column of numbers down to the lastrow (hence lr variable)
Currently, I am getting type mismatch error on the select case line.
Dim i As Long
Dim RowNum As Long
Dim lr As Long
Set i = 10
RowNum = 2
lr = Worksheets("1").cells.Find("*", cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False).Row
Set tbl = ActiveSheet.ListObjects("1")
Do Until cells(RowNum, i + 1) = lr
Select Case cells(RowNum, "P") And cells(RowNum, "I").Value
Case Is = "1" And "Available"
cells(RowNum, i + 1).Value = "Purchase"
Case Is = "2" And "Not Available"
cells(RowNum, i + 1).Value = "Attempt Purchase"
Case Is = "3"
cells(RowNum, i + 1).Value = "Purchase Automatic"
Case Is = "4"
cells(RowNum, i + 1).Value = "Do not Purchase"
Case Else
cells(RowNum, i + 1).Value = "N/A"
End Select
RowNum = RowNum + 1
Loop
Any help is greatly appreciated. Thanks
Multi Select Case
Select Case needs one expression. Handle the other with an If statement.
Snippet
Select Case Cells(RowNum, "P")
Case Is = "1"
If Cells(RowNum, "I").Value = "Available" Then
Cells(RowNum, i + 1).Value = "Purchase"
End If
Case Is = "2"
If Cells(RowNum, "I").Value = "Not Available" Then
Cells(RowNum, i + 1).Value = "Attempt Purchase"
End If
Case Is = "3"
Cells(RowNum, i + 1).Value = "Purchase Automatic"
Case Is = "4"
Cells(RowNum, i + 1).Value = "Do not Purchase"
Case Else
Cells(RowNum, i + 1).Value = "N/A"
End Select
If you had read up on how the Select Case structure works you would realise that the way you are structuring your Select Case is not possible. In the VBA IDE put the cursor on Select and Press F1. This will bring up the help page of Select Case.
To achieve something similar to what you need to achieve you will need to concatenate the two values to give a single value and adjust the case values accordingly. The code below assumes that "CStr(Cells(RowNum, "I").Value" is equivalent to "" where necessary for the Case labels in the Case structure to work correctly.
You should also be aware that 'Set i' is incorrect as I is a value variable and not a reference variable. Use i=10.
Dim i As Long
Dim RowNum As Long
Dim lr As Long
i = 10
RowNum = 2
lr = Worksheets("1").Cells.Find("*", Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False).Row
Set tbl = ActiveSheet.ListObjects("1")
Do Until Cells(RowNum, i + 1) = lr
Select Case Trim$(CStr(Cells(RowNum, "P").Value) & CStr(Cells(RowNum, "I").Value))
Case "1Available"
Cells(RowNum, i + 1).Value = "Purchase"
Case Is = "2Not Available"
Cells(RowNum, i + 1).Value = "Attempt Purchase"
Case Is = "3"
Cells(RowNum, i + 1).Value = "Purchase Automatic"
Case Is = "4"
Cells(RowNum, i + 1).Value = "Do not Purchase"
Case Else
Cells(RowNum, i + 1).Value = "N/A"
End Select
RowNum = RowNum + 1
Loop
Related
I have a user Form through which I am able to upload transactions into a cashflow worksheet. By using cDbl in two controls I am able to ensure that amounts are added to the Worksheet in a format that can be used in calculations. However, by nature these fields are mutually exclusive (Credit & Debit). cDbl requires a value to be populated in each control so I am looking for a method that will check the value of each of the two relevant controls and to ignore them when the value is Null
Private Sub cmdAddRecord_Click()
'Used to add new transation records to the database
lastrow = Sheets("Spending Account").Range("A" & Rows.Count).End(xlUp).Row
Cells(lastrow + 1, "A").Value = DTPicker1
Cells(lastrow + 1, "B").Value = cboVendorDetails
Cells(lastrow + 1, "C").Value = cboTransactionType
Cells(lastrow + 1, "D").Value = CDbl(Me.txtTransactionAmountDebit)
Cells(lastrow + 1, "E").Value = CDbl(Me.txtTransactionAmountCredit)
Cells(lastrow + 1, "F").Value = cboTransactionStatus
With ActiveSheet
Application.Goto Reference:=.Cells(.Rows.Count, "A").End(xlUp).Offset(-20), Scroll:=True
End With
Unload Me
frmRegularTransactions.Show
End Sub
I would welcome any solution
Private Sub cmdAddRecord_Click()
'Used to add new transation records to the database
Dim r As Long, sCredit As String, sDebit As String
sDebit = Me.txtTransactionAmountDebit
sCredit = Me.txtTransactionAmountCredit
With Sheets("Spending Account")
r = 1 + .Cells(.Rows.Count, "A").End(xlUp).Row
.Cells(r, "A").Value = DTPicker1
.Cells(r, "B").Value = cboVendorDetails
.Cells(r, "C").Value = cboTransactionType
.Cells(r, "F").Value = cboTransactionStatus
' credit or debit
If Len(sDebit) > 0 Then
If Len(sCredit) > 0 Then
MsgBox "Warning - Both Credit and Debit", vbExclamation
Else
.Cells(r, "D").Value = CDbl(sDebit)
End If
ElseIf Len(sCredit) > 0 Then
.Cells(r, "E").Value = CDbl(sCredit)
End If
If r > 21 Then
Application.Goto Reference:=.Cells(r - 20, "A"), Scroll:=True
End If
End With
Unload Me
frmRegularTransactions.Show
End Sub
The code breaks here
ws.Cells(j, "M").Value = dict(ws.Cells(j, "H").Value).volume
ws.Cells(j, "N").Value = dict(ws.Cells(j, "H").Value).rate
I believe the issue is trying to retrieve the dictionary value when the key is dynamic so
dict(ws.Cells(j, "H").Value).volume errors out
but
dict(5455).volume
will work.
Am I correct that this is the issue and any solutions?
Sub RetrieveData()
Dim dict As New Dictionary
Dim group As clsgroup
Dim lrowRetrieve As Long, lrowLookup As Long
Dim ws As Worksheet
Dim i As Long, j As Long, name As String, rate As Long, volume As Long
lrowRetrieve = Cells(Rows.Count, "C").End(xlUp).Row
lrowLookup = Cells(Rows.Count, "H").End(xlUp).Row
Set ws = Sheets("Test")
dict.RemoveAll
For i = 1 To lrowRetrieve
'add criteria for month/year of reporting
If ws.Cells(i, "C").Value <> "" And ws.Cells(i, "C").Value <> 0 And ws.Cells(i, "G").Value <> "" And ws.Cells(i, "G").Value <> 0 Then
name = ws.Cells(i, "C").Value
If dict.Exists(name) = False Then
Set group = New clsgroup
group.name = name
dict.Add key:=group.name, Item:=group
Else
Set group = dict(name)
'dict(ws.Cells(i, "C").Value) = ws.Cells(i, "G").Value
End If
With group
.rate = .rate + ws.Cells(i, "F").Value
.volume = .volume + ws.Cells(i, "G").Value
End With
End If
Next i
Dim key As Variant
For Each key In dict
Set group = dict(key)
With group
Debug.Print .name, .rate, .volume
End With
Next key
For j = 25 To lrowLookup
Select Case ws.Cells(j, "H").Value
Case "5455"
If ws.Cells(j, "K").Value = "Medical" Then
ws.Cells(j, "M").Value = dict("5455/5456").volume
ws.Cells(j, "N").Value = dict("5455/5456").rate
Else
ws.Cells(j, "M").Value = dict("5455/5456 (non med)").volume
ws.Cells(j, "N").Value = dict("5455/5456 (non med)").rate
End If
Case Else
Debug.Print ws.Cells(j, "H").Value
ws.Cells(j, "M").Value = dict(ws.Cells(j, "H").Value).volume
ws.Cells(j, "N").Value = dict(ws.Cells(j, "H").Value).rate
End Select
Next j
End Sub
dict(5455) is not the same as dict("5455") - it matters what data type your keys have when they're added - reliable retrieval from the dictionary requires the same type be used....
You might find it best to always convert your keys to String before adding them, and always retrieve with String-type keys
Sub Tester()
Dim dict As Object
Set dict = CreateObject("scripting.dictionary")
dict(5455) = "Numeric"
dict("5455") = "String" '"5455" is a different key from 5455 !
Debug.Print dict(5455) '>> "Numeric"
Debug.Print dict("5455") '>> "String"
End Sub
I have rows in my Excel from RowA and RowX.
My intent is to find all items that start with "F" in ROWB and replace it with value 5 in ROWX, all others with have 31 in ROwX.
Sub ReplaceDashes()
Dim Cmcode As String
Dim Rownum As Long
Rownum = 6
With Range("B6")
Do Until Cells(Rownum, 2).Value = ""
Select Case Cells(Rownum, 2).Value
Case Left(.Text, 1) = "F"
Cells(Rownum, 24).Value = "5"
Case Else
Cells(Rownum, 24).Value = "31"
End Select
Rownum = Rownum + 1
Loop
End With
MsgBox ("DONE")
End Sub
The above does not work the way I wanted, it does not work for the first case, it replaces everything with "31" . Can some one suggest?
Edit: Found a solution. The select case has to be performed directly over left function:
Sub ReplaceDashes()
Dim Cmcode As String
Dim Rownum As Long
Dim mystr As String
Rownum = 6
With Cells(Rownum, 2)
Do Until Cells(Rownum, 2).Value = ""
mystr = Cells(Rownum, 2).Value
Select Case Left(mystr, 1)
Case "f"
Cells(Rownum, 24).Value = "5"
Case Else
Cells(Rownum, 24).Value = "31"
End Select
Rownum = Rownum + 1
Loop
End With
MsgBox ("DONE")
End Sub
I'm trying to compare data between two worksheets. Each Worksheet has three column: A is a concatenation of a Customer and a SKU, B is the sales volume and C is for measuring volume discrepancies. I aim to do two things, check Sheet1 for SKUs that are not in Sheet2 and then, if SKUs match on both sheets, check their volume for quantity differences. If Sheet 1 has a SKU not in Sheet2, I want the record highlighted. I've accomplished this in a primitive way, the entire row gets highlighted. I am, however, having trouble getting the code to check volumes if the Customer & SKU match. I was hoping VBA would retain the values of the cells it was checking, where have I gone wrong and what is the proper implementation? Sorry for being such a n00b.
Sub Again()
Dim lastRow As Integer
Dim rng As Range
lastRow = Sheets("Sheet1").Range("A65000").End(xlUp).Row
For i = 1 To lastRow
Set rng = Sheets("sheet2").Range("A:A").Find(Sheets("Sheet1").Cells(i, 1))
If rng Is Nothing Then
Sheets("Sheet1").Cells(i, 3) = "Item not in sheet2"
Sheets("Sheet1").Cells(i, 1).EntireRow.Interior.Color = vbRed
ElseIf Not rng Is Nothing Then
If Sheets("sheet1").Cells(i, 2).Value - Sheets("sheet2").Cells(i, 2).Value < -5 Then
Sheets("sheet1").Cells(i, 3) = "Sheet2 reports " & Sheets("sheet1").Cells(i, 2).Value - Sheets("sheet2").Cells(i, 2).Value & " more units of volume."
ElseIf Sheets("sheet1").Cells(i, 2) - Sheets("sheet2").Cells(i, 2) > 5 Then
Sheets("sheet1").Cells(i, 3) = "Sheet1 reports " & Sheets("sheet1").Cells(i, 2) - Sheets("sheet2").Cells(i, 2) & " more units of volume."
Else: Sheets("sheet1").Cells(i, 3) = "No or insignificant discrepancy"
End If
End If
Next
End Sub
I think you need to reuse rng like this:
rng.offset(2,0).value
in place of:
Sheets("sheet2").Cells(i, 2).Value
Because all your currently doing is assuming that the matching cell is in exactly the same row as in sheet1.
Your code should then look something like this:
Sub Again()
Dim lastRow As Integer
Dim rng As Range
lastRow = Sheets("Sheet1").Range("A65000").End(xlUp).Row
For i = 1 To lastRow
Set rng = Sheets("sheet2").Range("A:A").Find(Sheets("Sheet1").Cells(i, 1))
If rng Is Nothing Then
Sheets("Sheet1").Cells(i, 3) = "Item not in sheet2"
Sheets("Sheet1").Cells(i, 1).EntireRow.Interior.Color = vbRed
ElseIf Not rng Is Nothing Then
If Sheets("sheet1").Cells(i, 2).Value - rng.offset(0, 2).Value < -5 Then
Sheets("sheet1").Cells(i, 3) = "Sheet2 reports " & Sheets("sheet1").Cells(i, 2).Value - rng.offset(0, 2).Value & " more units of volume."
ElseIf Sheets("sheet1").Cells(i, 2) - rng.offset(0, 2).Value > 5 Then
Sheets("sheet1").Cells(i, 3) = "Sheet1 reports " & Sheets("sheet1").Cells(i, 2) - rng.offset(0, 2).Value & " more units of volume."
Else: Sheets("sheet1").Cells(i, 3) = "No or insignificant discrepancy"
End If
End If
Next
End Sub
Variables. ...If I understand your questions correctly.
dim myString as String
dim myFloat as Float
I need help fixing my code and adding in the cell ranges.
I am trying to change the values in the cells to being the correct values if they are spelt incorrectly. But the table will be added to so I need to make it a flexible code. The code currently stops at the beginning sub with error code 424. I am fairly new to VBA and am stuck.
Sub Consolidates()
Dim datasheet As Worksheet
Set datasheet = ThisWorkbook.Sheets("sheet1")
lr = datasheet.Cells(Rows.Count, 9).End(xlUp).Row
For x = 2 To lr
If cell.Value = "B" Or "BR" Or " Then
cell.Value = "BR"
ElseIf cell.Value = "CL" Or "CR" _
Then cell.Value = "CR"
ElseIf cell.Value = "" Then
End If
Next x
End Sub
you could use something like follows
Option Explicit
Sub Consolidates()
Dim stringsToSearch As String, stringToSubstitute As String
Dim stringsToSearchArr As Variant, stringToSubstituteArr As Variant
' here define the "table"
stringsToSearch = "B,CL" '<--| type here the strings to be searched for
stringToSubstitute = "BR,CR" '<--| type here the corresponding strings to change searched ones into
stringsToSearchArr = Split(stringsToSearch, ",") '<--| turn "stringsToSearch" into an array
stringToSubstituteArr = Split(stringToSubstitute, ",") '<--| turn "stringToSubstitute" into an array
With ThisWorkbook.Sheets("sheetTest") '<--| change "sheetTest" with your actual sheet name
With .Range("I2:I" & .Cells(.Rows.Count, 9).End(xlUp).Row) '<--| consider all cells in column "I" from row 2 to last non empty one
For i = LBound(stringsToSearchArr) To UBound(stringsToSearchArr) '<--| loop through the "table"
.Replace What:=stringsToSearchArr(i), Replacement:=stringToSubstituteArr(i), LookAt:=xlWhole, MatchCase:=True '<--| find current string and replace it with its corresponding replacement
Next i
End With
End With
End Sub
Cell needs a reference to which cell. Also you can't use the or statement like that. Below a simple way to get it done.
For x = 1 To lr
If Cells(x, 9).Value = "B" Or Cells(x, 9).Value = "BR" Then
Cells(x, 9).Value = "BR"
ElseIf Cells(x, 9).Value = "CL" Or Cells(x, 9).Value = "CR" Then
Cells(x, 9).Value = "CR"
End If
Next x
You should consider a select statement
For x = 1 To lr
Select Case Cells(x, 9).Value
Case "B", "BR"
Cells(x, 9).Value = "BR"
Case "CL", "CR"
Cells(x, 9).Value = "CR"
End Select
Next x
Since it is case sensitive you could add an Lcase which could save you some time
For x = 1 To lr
Select Case LCase(Cells(x, 9).Value)
Case "b", "br"
Cells(x, 9).Value = "BR"
Case "cl", "cr"
Cells(x, 9).Value = "CR"
End Select
Next x