vba looping FOR between two sheets - vba

So I've this challenge. But first a little information for you: p goes from 1 to 24.
When p is 1 and Cells(X,4)>0 then I want to store all the values when this is true (it might be true several times, while it loops down the 2000 rows) into a value in Worksheets("myvalues").Cells(6,11).Value = a.
After this, I want p to be 2 and then do the same, and store the sum of these into Worksheets("myvalues").Cells(7,11).Value = a.
And so on until p is 24 (incl. 24)
Option Explicit
Sub main()
Dim x As Integer
Dim rowshift As Integer
Dim a As Double
Dim b As Integer, p as Integer
For x = 2 To 2000
If Worksheets("DATA").Cells(x, 2) = p And Worksheets("DATA").Cells(x, 4) > 0 Then
a = a+ Worksheets("DATA").Cells(x, 5)
p=p+1
End If
For rowshift = 6 to 29
Worksheets("myvalues").Cells(rowshift, 11).Value = a

Might this do what you intend?
Sub Main()
Dim TargetRow As Long
Dim Spike As Double
Dim p As Integer
Dim R As Long
TargetRow = 6
For p = 1 To 24
For R = 2 To 2000
With Worksheets("DATA").Rows(R)
If (.Cells(2).Value = p) And (.Cells(4).Value > 0) Then
Spike = Spike + .Cells(5).Value
End If
End With
Next R
Worksheets("MyValues").Cells(TargetRow, 11).Value = Spike
Spike = 0
TargetRow = TargetRow + 1
Next p
End Sub

To obtain the equivalent of Excel's formula
=SUMIFS(Data!$E$2:$E$2000,Data!$B$2:$B$2000,ROW()-5,Data!$D$‌​2:$D$2000,">0")
using VBA, I suggest you change your code to have a loop within a loop
Option Explicit
Sub main()
Dim x As Long
Dim rowshift As Long
Dim a As Double
For rowshift = 6 to 29
a = 0
For x = 2 To 2000
If Worksheets("DATA").Cells(x, 2) = rowshift - 5 And _
Worksheets("DATA").Cells(x, 4) > 0 Then
a = a + Worksheets("DATA").Cells(x, 5)
End If
Next
Worksheets("myvalues").Cells(rowshift, 11).Value = a
Next
End Sub

I think you need to set p value.
Please try this full code.
Option Explicit
Sub main()
Dim x As Integer
Dim rowshift As Integer
Dim a As Double
Dim b As Integer, p as Integer
p = 1
For x = 2 To 2000
a = 0
If p < 25 Then
If Worksheets("DATA").Cells(x, 2) = p And Worksheets("DATA").Cells(x, 4) > 0 Then
a = a+ Worksheets("DATA").Cells(x, 5)
p=p+1
End If
End If
If a > 0 Then
For rowshift = 6 to 29
Worksheets("myvalues").Cells(rowshift, 11).Value = a
Next rowshift
End If
Next x

Related

EXCEL VBA FOR inside IF

Never used VBA before and basically just trying write this sub:
Sub Populate_Empties()
Dim i As Integer
Dim j As Integer
Dim n As Integer
Dim m As Integer
Dim k As Integer
' test for 50 rows...then change i from 2 to 278970
m = 2
For k = 3 To 8
For i = 2 To 50
If (IsEmpty(Cells(i, k).Value)) Then
m = i 'any statement
Else
j = i - 1
For n = m To j
Cells(n, k).Value = Cells(i, k).Value
m = i + 1
End If
End Sub
I keep getting error End If without Block
Any suggestions?
You're missing the closing statements on your for loops
Sub Populate_Empties()
Dim i As Integer
Dim j As Integer
Dim n As Integer
Dim m As Integer
Dim k As Integer
' test for 50 rows...then change i from 2 to 278970
m = 2
For k = 3 To 8
For i = 2 To 50
If (IsEmpty(Cells(i, k).Value)) Then
m = i 'any statement
Else
j = i - 1
For n = m To j
Cells(n, k).Value = Cells(i, k).Value
Next n
m = i + 1
End If
Next i
Next k
End Sub

Nested Do While inner loop runs only on first iteration of outer loop

I am trying to do a multiple condition search. If two parameters are equal to another two parameters in another worksheet, then do something.
The inner Do While runs once.
Sub main()
Dim mat As String
Dim sp As String
Dim colArt As Integer
colArt = 8
Dim colMat As Integer
colMat = 2
Sheets("Art.1 (2)").Activate
Dim i As Integer
i = 5
Dim j As Integer
j = 2 'Row
Do While i < 12
If (Cells(i, colArt) <> "") Then
Dim tempMat As String
tempMat = Cells(i, colArt)
Dim tempSp As Integer
tempSp = Cells(i, colArt - 1)
Do While j < 16
If (Worksheets("Mat").Cells(j, colMat) <> "") Then
Dim tempMatMat As String
tempMatMat = Worksheets("Mat").Cells(j, colMat)
If (StrComp(tempMat, tempMatMat, vbTextCompare) = 0) Then
MsgBox (tempMatMat)
End If
End If
j = j + 1
Loop
End If
i = i + 1
Loop
End Sub
Federico, you need to reset j each time you loop in the outer loop:
Do While i < 12
j = 2
If (Cells(i, colArt) <> "") Then
Dim tempMat As String
tempMat = Cells(i, colArt)

column name of max no in a row

Column header for different sheet
iI have many rows having data in sheet 2 and iI want the column name of the max of a row (i.e. from column from column name of B2 to AH2 inside if loop).
Sub shanaya()
Dim j As Integer
Dim i As Integer
Dim z As Integer
Dim x As Integer
z = 35
For i = 11 To 28
For j = 2 To 19
If Sheet8.Cells(j, 1) = Sheet1.Cells(i, 1) Then
Sheet1.Cells(i, 10) = Sheet8.Cells(j, z)
Max [(Sheet8.Cells(J,2)): (Sheet8.Cells(j,z))]
Sheet1.Cells(i,13) = column header of max function
End If
Next j
Next i
End Sub
Using MATCH worksheet function will give you the column matching the MAX :
There is a +1 because your range start at col 2! ;)
Sub shanaya()
Dim j As Integer
Dim i As Integer
Dim z As Integer
Dim x As Integer
Dim ColOfMax As Integer
Dim RgToSearch As Range
z = 35
For i = 11 To 28
For j = 2 To 19
If Sheet8.Cells(j, 1) = Sheet1.Cells(i, 1) Then
Sheet1.Cells(i, 10) = Sheet8.Cells(j, z)
Set RgToSearch = Sheet8.Range(Sheet8.Cells(j, 2), Sheet8.Cells(j, z))
ColOfMax = Application.WorksheetFunction.Match(Application.WorksheetFunction.Max(RgToSearch), RgToSearch, 0) + 1
Sheet1.Cells(i, 13) = Sheet8.Cells(1, ColOfMax)
End If
Next j
Next i
End Sub

Rectangular Array with macro

I've tried to create an array with 2 row and 5 columns in VBA codes. Is it possible? i wrote like this
Sub robin()
Cells.Select 'this codes clears previous entries
Range("T17").Activate
Selection.ClearContents
Range("E4").Select
Dim myArray(1, 4) As Double
Dim a As Double, b As Double
Dim i As Integer
Dim j As Integer
Dim c As Double
c = 1
For a = 0 To UBound(myArray())
For b = 0 To UBound(myArray())
myArray(a, b) = c
ThisWorkbook.Sheets("Sheet1").Cells(a + 1, b + 1).Value = myArray(a, b)
c = c + 1
Next b
Next a
End Sub
But it comes with two rows and two columns. What to do?
By default UBound will return the highest index of the first dimension of an array. You'll need to set the optional parameter to 2 to get the last index of the 2nd dimension.
For b = 0 To UBound(myArray(), 2)
Sub batman()
[Sheet1!A1:E2] = [{1,2,3,4,5;6,7,8,9,10}]
End Sub
or
Sub robin()
Dim myArray(1 To 2, 1 To 5) As Double, c As Long
For c = 1 To 5
myArray(1, c) = c
myArray(2, c) = c + 5
Next
[Sheet1!A1:E2] = myArray
End Sub
Thanks all of you for your time. I've figured out my way to get what I was looking for. I rewrote the code like this:
Sub robin()
Cells.Select 'this codes clears previous entries
Range("T17").Activate
Selection.ClearContents
Range("E4").Select
Dim myArray(1, 5) As Double
Dim a As Double, b As Double
Dim i As Integer
Dim j As Integer
Dim c As Double
c = 1
For a = LBound(myArray, 1) To UBound(myArray, 1)
For b = LBound(myArray, 2) To UBound(myArray, 2)
myArray(a, b) = c
ThisWorkbook.Sheets("Sheet1").Cells(a + 1, b + 1).Value = myArray(a, b)
c = c + 1
Next b
Next a
End Sub
And that worked perfect for me. Thanks again.

Calculating a Sum

What I am trying to do is develop a model that takes a cell that is greater than 1 then to take the sum of the area to the first row using a cone shape, so for example cell D4, sum the area C3:C5 + B2:B6 + A1:A7.
At the moment I have this but it obviously is not working.
Dim I As Double
Dim J As Double
Dim Size As Integer
Dim x As Integer
Dim y As Integer
Dim z As Integer
'Dim Range As Integer
Dim PV1 As Integer
'MCArray = Worksheets("Data")
I = WorksheetFunction.CountA(Worksheets("Data").Rows(1))
J = WorksheetFunction.CountA(Worksheets("Data").Columns(1))
'Loop to Move down the rows
For x = 1 To J
'Loop to move acoss the columns
For y = 1 To I
'IfElse to determine if cell value is greater or equal to zero
If Cells(J, I).Value >= 0 Then
'Loop to sum the cells above
For z = 1 To J
PV1 = (ActiveCell.Value) + Worksheet.Sum(Range([J - z], [I-z:I+z]))
'IfElse to determine if final sum is greater than zero
If PV1 > 0 Then
Worksheets("MC").Range("B4").Value = PV1
Range([J - z], [I-z:I+z]).Interior.ColourIndex = 1
End If
Next z
End If
Next y
Next x
Here is a function you can use either as a UDF or from another routine. Just pass it the single cell you want to start from (D4 in your example) and this function will calculate the sum of the cone as you described.
Public Function SUMCONE(r As Range) As Double
Application.Volatile
SUMCONE = Application.Sum(r, r(-0, -0).Resize(, 3), r(-1, -1).Resize(, 5), r(-2, -2).Resize(, 7))
End Function
Here is an example of how to use the above function from your VBA routine:
Public Sub Demo()
Dim j&
For j = 5 To 10
If Cells(5, j) > 0 Then
Debug.Print SUMCONE(Cells(5, j))
End If
Next
End Sub
UPDATE
Based on your feedback I have updated the function and the demo routine to form an upward cone summation from the initial cell.
UPDATE #2
The above is for a fixed-size cone, extending upwards, that can be initiated from any cell in the worksheet.
But if you would prefer for the cone to always extend all the way up to row 1 regardless of which cell it originates in, then the following is what you are after:
Public Sub Demo()
Dim i&, j&
For j = 1 To Application.CountA(Worksheets("Data").Rows(1))
For i = 1 To Application.CountA(Worksheets("Data").Columns(1))
If Cells(i, j) > 0 Then
Debug.Print Cells(i, j).Address, SumAndColorCone(Cells(i, j))
End If
Next
Next
End Sub
Public Function SumAndColorCone(r As Range) As Double
Dim i&, k&, c As Range
Set c = r
For i = r.Row - 1 To 1 Step -1
Set c = Union(c, r(-k, -k).Resize(, (k + 1) * 2 + 1))
k = k + 1
Next
c.Interior.Color = vbRed
SumAndColorCone = Application.Sum(c)
End Function
UPDATE #3
As I suspected there was a problem if the cone was initiated too close to the left edge of the worksheet. I've added code to handle that now. Also your method for accessing the large matrix (which I had used in the Demo routine) did not work properly. I fixed that as well:
Public Sub Demo()
Dim i&, j&
For j = 1 To Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
If Val(Cells(i, j)) > 0 Then
Debug.Print Cells(i, j).Address, SumAndColorCone(Cells(i, j))
End If
Next
Next
End Sub
Public Function SumAndColorCone(r As Range) As Double
Dim i&, k&, c As Range
Set c = r
For i = r.Row - 1 To 1 Step -1
If r.Column - k < 2 Then Exit For
Set c = Union(c, r(-k, -k).Resize(, (k + 1) * 2 + 1))
k = k + 1
Next
c.Interior.Color = vbRed
SumAndColorCone = Application.Sum(c)
End Function