Rectangular Array with macro - vba

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.

Related

VBA excel - reading an nxn range in excel as an array

Hey I have the following test in my excel spreadsheet. I'm trying to be able to read the range as an array.
Period CAt1 Cat2 Cat3 Cat4
0 A B C D
1 E F g h
2 l k d i
3 m B dsfasd D
4 n a C D
5 o B fs D
6 p B C D
7 q B df D
8 r B fas D
9 s B fad D
10 Test Deal B dsfasd D
11 u B C D
I've made a range name for this call Check. I'm trying the following code, it works for a 2-d array. I want it to work on an abstract number based on the range name. I've tried adjusting it to work. The idea is that I want to call the row so that my udt can be able to read at a Period the Category value.
So in my main():
Sub Tst()
Dim Temp As Variant
Temp = Check("Initialise")
Debug.Print Check("0")
End Sub
Function Check(getItem As String)
Static CapitalFactors(362, 2)
Static Counter As Integer
Dim cell As Variant
Dim I As Integer
Dim j As Integer
Dim exitflag As Boolean
Dim Response As Integer
Dim Wsheet As String
Dim TopRow As Integer
Dim LeftCol As Integer
exitflag = False
If getItem = "Initialise" Then
I = 1
j = 1
For Each cell In Range("Check")
CapitalFactors(I, j) = cell
j = j + 1
If j > 2 Then
j = 1
I = I + 1
End If
Next
'Range("InputMonitor").ClearContents
Counter = 0
Else
I = 0
Do Until I = UBound(CapitalFactors, 1) Or exitflag = True
I = I + 1
If UCase(CapitalFactors(I, 1)) = UCase(getItem) Then
Check = CapitalFactors(I, 2)
exitflag = True
'If CapitalFactors(I,[Customized CashFlow Flag] = "No" Then Debug.Print 1 'GoSub SheetHighlight
End If
Loop
If exitflag = False Then Response = MsgBox("Parameter -" & getItem & "- not found", vbCritical)
End If
End Function

vba looping FOR between two sheets

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

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

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

Excel vba Create combinations in same row each one

I need help with a macro that exports all combinations of a range in same row each one ( I mean horizontal exports).
Every combination I want to be in one cell each time.
I want to change any time the number of strings in the range and also the number of strings combinations (In the example below 4 strings in the range and 3 for combinations)
1. A B C D -------------ABC --ABD--ACD--BCD
2. E F G H--------------EFG---EFH--EGH--FGH
3. I G K L----------------IGK----IGL---IKL---GKL
Below its a module that I found in web that is very close to what I need.
I am very new to Vba macros and I cannot achieve what I am looking for with the below code
Private NextRow As Long
Sub Test()
Dim V() As Variant, SetSize As Integer, i As Integer
SetSize = Cells(2, Columns.count).End(xlToLeft).Column
ReDim V(1 To SetSize)
For i = 1 To SetSize
V(i) = Cells(2, i).Value
Next i
NextRow = 4
CreateCombinations V, 3, 3
End Sub
Sub CreateCombinations( _
OriginalSet() As Variant, _
MinSubset As Integer, MaxSubset As Integer)
Dim SubSet() As Variant, SubSetIndex As Long
Dim SubSetCount As Integer, Bit As Integer
Dim k As Integer, hBit As Integer
Dim MaxIndex As Long
hBit = UBound(OriginalSet) - 1
ReDim SubSet(1 To UBound(OriginalSet))
MaxIndex = 2 ^ UBound(OriginalSet) - 1
For SubSetIndex = 1 To MaxIndex
SubSetCount = BitCount(SubSetIndex)
If SubSetCount >= MinSubset And SubSetCount <= MaxSubset Then
k = 1
For Bit = 0 To hBit
If 2 ^ Bit And SubSetIndex Then
SubSet(k) = OriginalSet(Bit + 1)
k = k + 1
End If
Next Bit
DoSomethingWith SubSet, SubSetCount
End If
Next SubSetIndex
End Sub
Sub DoSomethingWith(SubSet() As Variant, ItemCount As Integer)
Dim i As Integer
For i = 1 To ItemCount
Cells(NextRow, i) = SubSet(i)
Next i
NextRow = NextRow + 1
End Sub
Function BitCount(ByVal Pattern As Long) As Integer
BitCount = 0
While Pattern
If Pattern And 1 Then BitCount = BitCount + 1
Pattern = Int(Pattern / 2)
Wend
End Function
Here is a way to do it:
In your excel sheet, add an array formula like this:
A B C D E
1
2 A B C D {=k_combinations(CONCATENATE(A2;B2;C2;D2);3)}
3 E F G H {=k_combinations(CONCATENATE(A3;B3;C3;D3);3)}
Note that you should extend the array formula to columns F, G, H and so on so that you get all results. (The { and } are not to be inserted manually, they are the mark of the array formula) :
Select cells E2, F2, G2, H2, and so on to Z2
Type the formula
To validate input, press Ctrl+Shift+Enter
Put the following code into a code module.
Public Function k_combinations(ByVal chLetters As String, ByVal k As Long) As Variant
Dim chCombinations() As String
Dim uCount As Long
Dim vReturn() As Variant
Dim i As Long
uCount = Get_k_combinations(chLetters, chCombinations, k)
ReDim vReturn(0 To uCount - 1) As Variant
For i = 0 To uCount - 1
vReturn(i) = chCombinations(i)
Next i
k_combinations = vReturn
End Function
Private Function Get_k_combinations(chLetters As String, chCombinations() As String, ByVal k As Long) As Long
Dim i As Long
Dim M As Long
M = Len(chLetters)
If k > 1 Then
Get_k_combinations = 0
For i = 1 To M - (k - 1)
Dim chLetter As String
Dim uNewCombinations As Long
Dim chSubCombinations() As String
Dim j As Long
chLetter = Mid$(chLetters, i, 1)
uNewCombinations = Get_k_combinations(Right$(chLetters, M - i), chSubCombinations, k - 1)
ReDim Preserve chCombinations(0 To Get_k_combinations + uNewCombinations) As String
For j = 0 To uNewCombinations - 1
chCombinations(Get_k_combinations + j) = chLetter & chSubCombinations(j)
Next j
Get_k_combinations = Get_k_combinations + uNewCombinations
Next i
Else
ReDim chCombinations(0 To M - 1) As String
For i = 1 To M
chCombinations(i - 1) = Mid$(chLetters, i, 1)
Next i
Get_k_combinations = M
End If
End Function
Get_k_combinations is called recursively. The performance of this method is quite poor (because it uses string arrays and makes a lot of reallocations). If you consider bigger data sets, you will have to optimize it.