Case Statement, for loop and if...else in VBA - excel

In the above column i have unique date.
I have a drop down list where anything can be selected.. so it has 8 permutation(2^3)..So i want to extract probable date based on the selection..Suppose if i select Year as 2020 and day as 19 then i will extract the probable date which match both the condition..Like above picture...
Right now i am using 8 if elseif-=...end if statment...and for loop..Is there any other way to do the same work?? I wanted to write a function which will take (day,month,year,lastrow) as parameter and based on probable date will be calculated..Can anyone give me any idea how to do it?
My code now:
Public Sub ProbableDate(CaseNo As Integer, lastrow As Long)
Dim sh As Worksheet, sh1 As Worksheet
Set sh1 = Worksheets("Dashboard")
Set sh = Worksheets("Logical operation")
Dim Y As String, M As String, D As String
Y = sh1.Cells(4, 1).Value
M = sh1.Cells(4, 2).Value
D = sh1.Cells(4, 3).Value
Dim L As Long, i As Long
L = 2
With sh
.Range("H2:H1048576").Clear
For i = 2 To lastrow
Select Case CaseNo
Case 1
If Year(.Cells(i, 2).Value) = Y Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case 2
If MonthName(Month(.Cells(i, 2).Value)) = M Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case 3
If Day(.Cells(i, 2).Value) = D Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case 4
If Year(.Cells(i, 2).Value) = Y And MonthName(Month(.Cells(i, 2).Value)) = M Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case 5
If Year(.Cells(i, 2).Value) = Y And Day(.Cells(i, 2).Value) = D Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case 6
If Day(.Cells(i, 2).Value) = D And MonthName(Month(.Cells(i, 2).Value)) = M Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case 7
If Day(.Cells(i, 2).Value) = D And MonthName(Month(.Cells(i, 2).Value)) = M And Year(.Cells(i, 2).Value) = Y Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
End If
Case Else
MsgBox "Wrong Info"
End Select
Next i
End With
End Sub

You can simplify your code using a binary lookup table. Each CaseNo matches with a particular set of true/false outcomes for the day, month and year check. These are different to your original mapping, here is the new map:
CaseNo DMY
0 fail
1 D
2 M
3 DM
4 Y
5 D Y
6 MY
7 DMY
And the code:
With sh
.Range("H:H").Clear
For i = 2 To lastrow
OK = 0
If Day(.Cells(i, 2).Value) = D Then OK = OK + 1
If MonthName(Month(.Cells(i, 2).Value)) = M Then OK = OK + 2
If Year(.Cells(i, 2).Value) = Y Then OK = OK + 4
If OK = CaseNo Then
.Cells(L, 8).Value = .Cells(i, 2).Value
L = L + 1
Else
MsgBox "Wrong Info"
End If
Next i
End With

Related

How to erase previous values of arrays when repeating in excel vba

Sub WriteToZeroBasedArray()
Dim E As Integer
Dim rCount As Long: rCount = Worksheets("0618").Cells.SpecialCells(xlLastCell).Row
For E = 9 To 11
Dim V() As Variant ' Note the parentheses!
Dim P() As Variant
Dim N() As Variant
Dim Index As Long
Dim Index_2 As Long
Dim Index_3 As Long
Dim cCount As Long: cCount = Worksheets("0618").Cells.SpecialCells(xlLastCell).Column ' e.g.
Dim c As Long '배열에 값 저장하기
For c = 7 To cCount
If 0 < Worksheets("0618").Cells(E, c).Value And Worksheets("0618").Cells(E, c).Value < 100 Then
ReDim Preserve V(Index)
' A safer way (Option Base related):
'ReDim Preserve V(0 To Index)
V(Index) = Worksheets("0618").Cells(2, c).Value
Index = Index + 1
ReDim Preserve P(Index_2)
P(Index_2) = Worksheets("0618").Cells(4, c).Value
Index_2 = Index_2 + 1
ReDim Preserve N(Index_3)
N(Index_3) = Worksheets("0618").Cells(E, c).Value
Index_3 = Index_3 + 1
End If
Next c
Dim K As Integer
Dim L As Integer
K = UBound(V) '배열의 값 차례로 Sheet2에 넣기
For L = 0 To K
If L < 5 Then
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 1).Value = V(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 2).Value = P(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 3).Value = N(L)
Else
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 5).Value = V(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 6).Value = P(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 7).Value = N(L)
End If
Next
Dim FP As Integer
Dim Sum As Integer
Sum = 0
'수량*단가 구하기
For FP = (6 + 14 * (E - 9)) To (10 + 14 * (E - 9))
Worksheets("sheet2").Cells(FP, 4).Value = Worksheets("sheet2").Cells(FP, 2).Value * Worksheets("sheet2").Cells(FP, 3).Value
Worksheets("sheet2").Cells(FP, 8).Value = Worksheets("sheet2").Cells(FP, 6).Value * Worksheets("sheet2").Cells(FP, 7).Value
'총액 구하기
Sum = Sum + Worksheets("sheet2").Cells(FP, 4).Value + Worksheets("sheet2").Cells(FP, 8).Value
'0 지우기
If Worksheets("sheet2").Cells(FP, 4).Value = 0 Then
Worksheets("sheet2").Cells(FP, 4).ClearContents
End If
If Worksheets("sheet2").Cells(FP, 8).Value = 0 Then
Worksheets("sheet2").Cells(FP, 8).ClearContents
End If
Next
'총액 구하기2
Worksheets("sheet2").Cells(12 + 14 * (E - 9), 8).Value = Sum
'받으실 분
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 2).Value = Worksheets("0618").Cells(E, 3).Value
'주소
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 5).Value = Worksheets("0618").Cells(E, 2).Value
'서식 복사'
Worksheets("sheet3").Range("A1:H13").Copy
Worksheets("sheet2").Range("A" & 15 + 14 * (E - 9)).PasteSpecial
If Index = 0 Then Exit Sub
Next
Debug.Print Join(V, vbLf)
End Sub
I expected this code to be like this
But the result is like this
When E = 9, the code runs exactly the same as I thought, but when E is over 10, it doesn't.
when E = 9, the V array's values and orders are like this [grape, apple], and that's what I wanted.
However, when E = 10, I want the V array's value to be like this [orange]
but the result says it is [ , , orange]
Could someone tell me what's wrong with my code?
For me, the two (different) pictures look like 'Chinese'... So, I cannot refer to them.
No need to use Index, Index2 and Index3. Use only Index and increment it at the second loop end;
'replace this line
Index_3 = Index_3 + 1
'with
Index = Index + 1
' and comment all the previous index incrementations
You must reinitialize the used arrays content and used Index at the first loop end:
'your code...
If Index = 0 Then Exit Sub 'after this existing code line
Erase V: Erase P: Erase N: Index = 0
Next
'Your code
Now, using Redim Preserve to often is bad from memory handling point of view. Please, try firstly ReDim to a value to exceed the necessary number of necessary elements (ReDim V(cCount)) and use only of the end: Redim Preserve V(Index -1). Do the same for the other two used arrays...

How to make an array empty in excel VBA

Sub WriteToZeroBasedArray()
Dim E As Integer
Dim rCount As Long: rCount =
Worksheets("0618").Cells.SpecialCells(xlLastCell).Row
For E = 9 To rCount
Dim V() As Variant ' Note the parentheses!
Dim P() As Variant
Dim N() As Variant
Dim Index As Long
Dim Index_2 As Long
Dim Index_3 As Long
Dim cCount As Long: cCount = Worksheets("0618").Cells.SpecialCells(xlLastCell).Column ' e.g.
Dim c As Long '배열에 값 저장하기
For c = 7 To cCount
If 0 < Worksheets("0618").Cells(E, c).Value And Worksheets("0618").Cells(E, c).Value < 100 Then
ReDim Preserve V(Index)
' A safer way (Option Base related):
'ReDim Preserve V(0 To Index)
V(Index) = Worksheets("0618").Cells(2, c).Value
Index = Index + 1
ReDim Preserve P(Index_2)
P(Index_2) = Worksheets("0618").Cells(4, c).Value
Index_2 = Index_2 + 1
ReDim Preserve N(Index_3)
N(Index_3) = Worksheets("0618").Cells(E, c).Value
Index_3 = Index_3 + 1
End If
Next c
Dim K As Integer
Dim L As Integer
K = UBound(V) '배열의 값 차례로 Sheet2에 넣기
For L = 0 To K
If L < 5 Then
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 1).Value = V(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 2).Value = P(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 3).Value = N(L)
Else
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 5).Value = V(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 6).Value = P(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 7).Value = N(L)
End If
Next
Dim FP As Integer
Dim Sum As Integer
Sum = 0
'수량*단가 구하기
For FP = (6 + 14 * (E - 9)) To (10 + 14 * (E - 9))
Worksheets("sheet2").Cells(FP, 4).Value = Worksheets("sheet2").Cells(FP, 2).Value * Worksheets("sheet2").Cells(FP, 3).Value
Worksheets("sheet2").Cells(FP, 8).Value = Worksheets("sheet2").Cells(FP, 6).Value * Worksheets("sheet2").Cells(FP, 7).Value
'총액 구하기
Sum = Sum + Worksheets("sheet2").Cells(FP, 4).Value + Worksheets("sheet2").Cells(FP, 8).Value
'0 지우기
If Worksheets("sheet2").Cells(FP, 4).Value = 0 Then
Worksheets("sheet2").Cells(FP, 4).ClearContents
End If
If Worksheets("sheet2").Cells(FP, 8).Value = 0 Then
Worksheets("sheet2").Cells(FP, 8).ClearContents
End If
Next
'총액 구하기2
Worksheets("sheet2").Cells(12 + 14 * (E - 9), 8).Value = Sum
'받으실 분
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 2).Value = Worksheets("0618").Cells(E, 3).Value
'주소
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 5).Value = Worksheets("0618").Cells(E, 2).Value
'서식 복사'
Worksheets("sheet3").Range("A1:H13").Copy
Worksheets("sheet2").Range("A" & 15 + 14 * (E - 9)).PasteSpecial
Erase V, P, N
If Index = 0 Then Exit Sub
Next
Debug.Print Join(V, vbLf)
End Sub
I used "Erase V, P, N" at the last part of this code to make V,P,N into empty arrays, because the code has to repeat from E = 9 to E = Column number and as it repeats, these arrays has to be continuously empty at the last part of the code, to use them again at the next repeat.
But when I run this code, these arrays doesn't become empty. The values are accumulated more and more as the code repeats. I think maybe the code "Erase V, P, N" is the wrong code.
So Could anybody please tell me how to make the the arrays empty?

How can I get a right order of data from previous sheets with VBA

Could someone help me out with the following code, I thought i figured it out but keep on stranding with the same problem:
Sub history()
nsheets = ActiveWorkbook.Worksheets.Count 'count sheets in workbook
nas_index = ActiveSheet.Index 'index of the activated sheet
nas_LR = Sheets(nas_index).Cells(Sheets(nas_index).Rows.Count, "A").End(xlUp).Row 'count rows of activesheet
For d = 1 To nsheets
If d < nas_index Then
pre_index = Sheets(nas_index - d).Index
pre_LR = Sheets(pre_index).Cells(Sheets(pre_index).Rows.Count, "A").End(xlUp).Row
oldtime = Sheets(d).Cells(1, 6).Value
newwknr = Sheets(nas_index).Cells(1, 7).Value
oldwknr = Sheets(pre_index).Cells(1, 7).Value
StrOldTime = Format(oldtime, "hh:mm:ss")
For n = 3 To nas_LR
prid_new = Sheets(nas_index).Cells(n, 1).Value
For o = 3 To pre_LR
prid_old = Sheets(pre_index).Cells(o, 1).Value
pre_am = Sheets(pre_index).Cells(o, 6).Value
pre_amw = CStr(pre_am) & "(" & StrOldTime & ")" & "(wk: " & oldwknr & ")"
If prid_new = prid_old Then
'Below is not working properly
'------------------------------
re = re & " " & pre_amw
Sheets(nas_index).Cells(n, 10).Value = re
'------------------------------
End If
Next o
Next n
Else
'MsgBox exit loop
Exit For
End If
Next d
'------------------nevermind below
Dim ntime As Date, nStrTime As String
If Not ThisWorkbook.ActiveSheet.Cells(1, 10).Value = "" Then
'-new time
ThisWorkbook.ActiveSheet.Cells(1, 12).Value = Time()
ntime = ThisWorkbook.ActiveSheet.Cells(1, 12).Value
mstrtime = Format(ntime, "hh:mm:ss:ms")
ThisWorkbook.ActiveSheet.Cells(1, 12).Value = mstrtime
'-old time
gettime = ThisWorkbook.ActiveSheet.Cells(1, 10).Value
ThisWorkbook.ActiveSheet.Cells(1, 11).Value = gettime
myStrTime = Format(gettime, "hh:mm:ss:ms")
ThisWorkbook.ActiveSheet.Cells(1, 11).Value = myStrTime
End If
End Sub
The image below is so far what I got (the text in red, is what i wish to have).
My goal is to have the following Check if I bought the same item before (ID). Collect data of this ID and store it in the column History. So that I can see if the product has been price changed over the previous weeks. I can't get the data properly of previous sheets. Instead of getting the following:
item: A B C D or
item: D C B A
I get something like this:
item: A A A A A A B B B B B B C C C C C C D D D D D D or
item: A B C D A B C D A B C D
I think I am failing here:
If prid_new = prid_old Then
'Below is not working properly
'------------------------------
re = re & " " & pre_amw
Sheets(nas_index).Cells(n, 10).Value = re
'------------------------------
End If
Can someone lent me a hand.
I tried looping the worksheets within a grocery item loop with some success.
Historical data is gathered from every worksheet prior to the current worksheet (ActiveSheet) onto the current worksheet.
Option Explicit
Sub costHistory()
Dim i As Long, w As Long, gro As Long, ndx As Long, g As Variant
Dim icost As Double, lcost As Double, dif As String
With ActiveSheet
ndx = ActiveSheet.Index
For i = 3 To .Cells(.Rows.Count, "A").End(xlUp).Row
gro = .Cells(i, "A").Value2
lcost = .Cells(i, "D").Value2
dif = vbNullString
For w = 1 To ndx - 1
With Worksheets(w)
g = Application.Match(gro, .Columns(1), 0)
If Not IsError(g) Then
If .Cells(g, "D").Value2 <> lcost Then
dif = Format(.Cells(g, "D").Value2, "0.00") & _
Format(.Cells(g, "F").Value2, " 0 ") & _
Format(.Cells(1, "F").Value2, "(hh:mm:ss)") & _
Format(.Cells(1, "G").Value2, " (\w\k\:0)") & _
Chr(124) & dif
End If
End If
End With
Next w
If CBool(Len(dif)) Then
.Cells(i, "J") = Left(dif, Len(dif) - 1)
End If
Next i
End With
End Sub

Adding a group of numeric value in a column based on another criteria from another column

I have table in Sheet1. I can sum up all numeric data of a certain Country.
However I wanted only to sum-up to numbers with the same date.
I have ComboBox for the date. So for example If I choose July 1, it will only add those numbers in July 1.
My desired result if I choose July 1 is the following:
America 24
Brazil 56
Canada 68
screenshot
My code:
Private Sub ComboBox1_Change()
Dim a As Long
Dim b As Long
Dim c As Long
Dim lastrow As Long
a = 0
b = 0
c = 0
lastrow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastrow
If Cells(i, 3) = "America" Then
a = Cells(i, 4) + a
ElseIf Cells(i, 3) = "Brazil" Then
b = Cells(i, 4) + b
ElseIf Cells(i, 3) = "Canada" Then
c = Cells(i, 4) + c
End If
Next i
'Range("A16") = a
txtAmerica.Value = a
txtBrazil.Value = b
txtCanada.Value = c
End Sub
Private Sub UserForm_Initialize()
ComboBox1.List = Sheets("Sheet1").Range("G1:G10").Value
End Sub
Assuming the values in column A are dates, and also assuming your locale is using a mm/dd/yyyy date format, this is as simple as just wrapping your summation code in an If statement that checks the date:
For i = 2 To lastrow
If Cells(i, "A").Value = CDate(ComboBox1.Value) Then
If Cells(i, 3) = "America" Then
a = Cells(i, 4) + a
ElseIf Cells(i, 3) = "Brazil" Then
b = Cells(i, 4) + b
ElseIf Cells(i, 3) = "Canada" Then
c = Cells(i, 4) + c
End If
End If
Next i

Nested For Loop in Excel VBA

The following code is working for only when c = 2 ,however I want it to work for other values as well. Below is the Excel table on which I want to run it.
Date PickupCost StorageCost DeliveryCost
1/1/2017 140 35 0
1/8/2017 80 20 0
1/10/2017 0 0 149
1/30/2017 35 8 0
I want to fill data of each date missing but only the value at column 3 (StorageCost) needs to be same in other missing date values as previous day's StorageCost value.
Dim j, p, w, c As Long
Dim date1, date2 As Date
j = Cells(Rows.Count, 1).End(xlUp).Row
w = 2
For c = w To j
date1 = Range("A" & w).Value
date2 = Range("A" & (w + 1)).Value
p = DateDiff("d", date1, date2)
For w = 2 To p
Range("A" & (c + 1)).EntireRow.Insert
ActiveSheet.Cells(c + 1, 1).Value = (ActiveSheet.Cells(c, 1).Value) + 1
ActiveSheet.Cells(c + 1, 2).Value = 0
ActiveSheet.Cells(c + 1, 3).Value = ActiveSheet.Cells(c, 3).Value
ActiveSheet.Cells(c + 1, 4).Value = 0
c = c + 1
Next w
w = w + 1
ActiveSheet.Range("A1").Select
j = Cells(Rows.Count, 1).End(xlUp).Row
Next c
Your main problem is that once you defined your For c = w To j loop then it will only run until it reaches value j had when you defined the for loop.
If you want an endpoint to the loop that adapts to the runtime changing number of rows, you should use a Do Until loop, like this:
Dim p As Long
Dim c, w As Integer
Dim date1, date2 As Date
c = 2
Do Until c = Cells(Rows.Count, 1).End(xlUp).Row
date1 = Range("A" & c).Value
date2 = Range("A" & (c + 1)).Value
p = DateDiff("d", date1, date2)
For w = c To c + p - 2
Range("A" & (w + 1)).EntireRow.Insert
ActiveSheet.Cells(w + 1, 1).Value = (ActiveSheet.Cells(c, 1).Value) + 1
ActiveSheet.Cells(w + 1, 2).Value = 0
ActiveSheet.Cells(w + 1, 3).Value = ActiveSheet.Cells(c, 3).Value
ActiveSheet.Cells(w + 1, 4).Value = 0
c = c + 1
Next w
c = c + 1
Loop

Resources