matrix in visual basic - arrays

so i have a task to create a square matrix then from that return the average of the rows and columns, having some problem though
Dim m, n, i, j As Integer
Dim A(2, 2) As Integer
Console.Write(vbLf & "Enter The Matrix Elements any two : ")
For i = 0 To 2 - 1
For j = 0 To 2 = 1
A(i, j) = Convert.ToInt16(Console.ReadLine())
Next
Next
Console.Clear()
Console.WriteLine(vbLf & "Matrix A : ")
For i = 0 To 2 - 1
For j = 0 To 2 - 1
Console.Write(vbLf & "{0}", A(i, j))
Next
Console.WriteLine(" ")
Next
Console.WriteLine(vbLf & "Transpose Matrix : ")
For i = 0 To 2 - 1
For j = 0 To 2 - 1
Console.Write(vbLf & "{0}", A(j, i))
Next
Console.WriteLine(" ")
Next
End Sub
This is my code, i know its supposed to be a square matrix so how would i do that, when i also try inputing the values it does not let me go past the next one, does anyone have code for a square matrix that gets its values from a user, or someone can help me please

To make it generic, use the GetUpperBound() function to determine how many elements are in your array for each dimension (it should be the same, however, since you have a square matrix):
Sub Main()
Dim size As Integer = 3
Dim numberWidth As Integer = 2
Dim format As String = "D" & numberWidth
Dim A(size - 1, size - 1) As Integer
For i As Integer = 0 To A.GetUpperBound(0)
For j As Integer = 0 To A.GetUpperBound(1)
Console.Write(String.Format("Enter The Matrix Element at A[Row {0}, Col {1}]: ", i, j))
A(i, j) = Convert.ToInt16(Console.ReadLine())
Next
Next
Console.WriteLine("Matrix A :")
For i As Integer = 0 To A.GetUpperBound(0)
Console.Write("| ")
For j As Integer = 0 To A.GetUpperBound(1)
Console.Write("{0} ", A(i, j).ToString(format))
Next
Console.WriteLine("|")
Next
Console.WriteLine("Transpose Matrix :")
For i As Integer = 0 To A.GetUpperBound(0)
Console.Write("| ")
For j As Integer = 0 To A.GetUpperBound(1)
Console.Write("{0} ", A(j, i).ToString(format))
Next
Console.WriteLine("|")
Next
Console.ReadLine()
End Sub
Output:
Enter The Matrix Element at A[Row 0, Col 0]: 1
Enter The Matrix Element at A[Row 0, Col 1]: 2
Enter The Matrix Element at A[Row 0, Col 2]: 3
Enter The Matrix Element at A[Row 1, Col 0]: 4
Enter The Matrix Element at A[Row 1, Col 1]: 5
Enter The Matrix Element at A[Row 1, Col 2]: 6
Enter The Matrix Element at A[Row 2, Col 0]: 7
Enter The Matrix Element at A[Row 2, Col 1]: 8
Enter The Matrix Element at A[Row 2, Col 2]: 9
Matrix A :
| 01 02 03 |
| 04 05 06 |
| 07 08 09 |
Transpose Matrix :
| 01 04 07 |
| 02 05 08 |
| 03 06 09 |
Here's a quick example of how to compute the SUM of each ROW:
Dim Total as Integer
For row As Integer = 0 To A.GetUpperBound(0)
Total = 0 ' reset for each row/column
For col As Integer = 0 To A.GetUpperBound(1)
Total = Total + A(row, col)
Next
Console.WriteLine("Row " & row & " total: " & Total)
' ... do something else with "Total" here; like compute an average ...
Next
The code for computing the total of columns will be very similar, just swap the positions of the For row and For col lines.

Related

Get an 2 dimension array with 0 and 1 combination

My English is not good, so please forgive me if what I describle is not clear for you.
I want to create 2 dimension Array with 0 and 1
when I input n, it should create: Array01(1 to 2^n as long, n as long), and 0 and 1 is combination like this:
n = 1 ==> Arr (2 rows x 1 column)
0 |
1 |
n = 2 ==> Arr (4 rows x 2 columns)
0 0 |
0 1 |
1 0 |
1 1 |
n = 3 ==> Array (8 rows x 3 columns)
0 0 0 |
0 0 1 |
0 1 0 |
1 0 0 |
1 1 0 |
1 0 1 |
0 1 1 |
1 1 1 |
You can use a function like below
Option Explicit
Public Function CreateMatrix(ByVal n As Long) As Variant
Dim Matrix() As Long
ReDim Matrix(1 To 2 ^ n, 1 To n)
Dim i As Long
For i = 0 To 2 ^ n - 1
Dim BinaryString As String
BinaryString = DecToBin(i, n)
Dim c As Long
For c = 1 To n
Matrix(i + 1, c) = CLng(Mid$(BinaryString, c, 1))
Next c
Next i
CreateMatrix = Matrix
End Function
Public Function DecToBin(ByVal DecimalIn As Variant, Optional ByVal NumberOfBits As Variant) As String
Dim Result As String
DecimalIn = CDec(DecimalIn)
Do While DecimalIn <> 0
Result = Trim$(Str$(DecimalIn - 2 * Int(DecimalIn / 2))) & Result
DecimalIn = Int(DecimalIn / 2)
Loop
If Not IsMissing(NumberOfBits) Then
If Len(Result) > NumberOfBits Then
Result = "Error - Number too large for bit size"
Else
Result = Right$(String$(NumberOfBits, "0") & Result, NumberOfBits)
End If
End If
DecToBin = Result
End Function
and call it like
' generate the matrix
Dim MyMatrix() As Long
MyMatrix = CreateMatrix(n:=3)
' and write it to a sheet
Worksheets("Sheet1").Range("A1").Resize(UBound(MyMatrix, 1), UBound(MyMatrix, 2)).Value = MyMatrix
How does this work?
If we look at the matrix below we can see each row as a binary number that can be converted into a decimal number. So binary 000 is decimal 0, then binary 001 is decimal 1 and binary 010 is decimal 2 and so on:
0 0 0 | 'decimal 0
0 0 1 | 'decimal 1
0 1 0 | 'decimal 2
1 0 0 | 'decimal 3
1 1 0 | 'decimal 4
1 0 1 | 'decimal 5
0 1 1 | 'decimal 6
1 1 1 | 'decimal 7
So we know if we want to create that matrix we need to convert the decimal numbers 1 to 7 into binary numbers. Each of this binary numbers then represents one row of the matrix.
Since the only number to define the martix is n (in the example n = 3) we can use that to calculate the dimensions of the matrix:
rows: 2 ^ n (in the example 2^3 = 8)
columns: n
So we define a matrix of that size ReDim Matrix(1 To 2 ^ n, 1 To n).
Then we need to generatate the decimal numbers from 1 to 7 to be able to convert them into binaries. We do that with a loop: For i = 0 To 2 ^ n - 1 (in the example this means For i = 0 To 7).
In that loop we convert each decimal number i into a binary string of the length n. We do that using BinaryString = DecToBin(i, n).
Finally we just need to split that string into the columns of our matrix. Therefore we use another loop that loops through the characters of that BinaryString For c = 1 To n (which means start with character 1 until character n). And fill the matrix:
Matrix(i + 1, c) = CLng(Mid$(BinaryString, c, 1))
Here Mid$(BinaryString, c, 1) picks the character out of the string and CLng converts it into a Long number so it is numeric and writes it into the correct position of the matrix Matrix(i + 1, c).
Fanally we return that matix as result of our function CreateMatrix = Matrix.
This post is 10 months old. But I saw a new post by the OP which led me here, so I thought I'd share another solution.
This can be solved by formula instead of script.
Suppose in cell A1 of some sheet you place the number for n.
In some other cell (say, A3 or C1), you could use the following formula to generate the list in question:
=FILTER(TEXT(SEQUENCE(10^A1,1,0),REPT("0",A1)),NOT(REGEXMATCH(SEQUENCE(10^A1,1,0)&"","[2-9]")))
Essentially, this formula creates a SEQUENCE of all possible numbers between 0 and 10 to the nth, formatted to contain n digits; then it FILTERs out any elements of that sequence that contain any digits from 2 to 9 (i.e., anything other than elements containing only 1s and 0s).

How to assign an array's values to a range?

I'm trying to assign a 1-dimensional array's values to cell range.
For example; my array has 23 items (every item randomized from 1 to 5) and my cell range is range A1 to I7.
I want to assign every value of my array to this cell range randomly.
I randomize the cell values with my array but my array's values are not completely assigned to cells.
Sub define_ore_body()
Dim lb_grade As Integer, ub_grade As Integer
Dim ore_body(1 To 23) As Variant
Dim i As Integer, j As Integer, k As Integer
Dim a As Object
Dim b As Range
Application.ScreenUpdating = False
'my selected range area A1toI7
Set b = Application.Range("A1:I7")
Set a = Application.Cells
'******* low and high ore bound ******
lb_grade = InputBox("Enter lowest ore grade:")
ub_grade = InputBox("Enter highest ore grade:")
'The reason why I do it as follows is that if the random lower bound does not start from 1,
'the largest random number it generates is 2 more than the value I have entered, so
If lb_grade > 1 Then
ub_grade = ub_grade - 2
End If
'******* Random Array ******
'array has 23 items
For i = 1 To 23
ore_body(i) = Int((ub_grade * Rnd) + lb_grade)
Next i
'******* filling random cells with my array******
k = 1
For Each a In b
If a.Value = "" And k < 23 Then
b(Int(7 * Rnd + 1), (8 * Rnd + 1)) = ore_body(k)
ElseIf a.Count > 23 And k > 23 Then
Exit For
Else
k = k + 1
End If
Next a
'******* after filling cell now fill empty cells with Zero******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) = "" Then
Cells(i, j) = 0
Else
End If
Next j
Next i
'******* Coloring only containing array values******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) > 0 Then
Application.Cells(i, j).Interior.ColorIndex = 38
Else
End If
Next j
Next i
End Sub
The array contains 23 items that initialize to Variant/Empty:
Dim ore_body(1 To 23) As Variant
Make that 63 items that initialize to 0:
Dim ore_body(1 To 63) As Long
The rest of the code will now populate the first 23 elements, because that's what the loop does:
For i = 1 To 23
If you want the loop to run through all indexes, consider using LBound and UBound operators to programmatically retrieve the lower and upper boundaries of the array, respectively:
For i = LBound(ore_body) To UBound(ore_body)
Note that you have 23 hard-coded in several places, which is going to make it harder than necessary to modify if/when that 23 needs to be come a 25. Consider replacing every occurrence of it by a Const:
Const ElementCount As Long = 23
Then every instance of 23 can become ElementCount, and then when it needs to become 25 then there's only one place that needs any code to change.
Loop through the array.
Set a to a random cell in the range A1:I7.
If cell is empty put the value from the array in the cell, if it
isn't repeat step 2
Sub define_ore_body()
Dim lb_grade As Integer, ub_grade As Integer
Dim ore_body(1 To 23) As Variant
Dim i As Long, j As Long, k As Long
Dim a As Range
Dim b As Range
Application.ScreenUpdating = False
'my selected range area A1:I7
Set b = Application.Range("A1:I7")
' clear A1:A17
b.Clear
'******* low and high ore bound ******
lb_grade = InputBox("Enter lowest ore grade:")
ub_grade = InputBox("Enter highest ore grade:")
'The reason why I do it as follows is that if the random lower bound does not start from 1,
'the largest random number it generates is 2 more than the value I have entered, so
If lb_grade > 1 Then
ub_grade = ub_grade - 2
End If
'******* Random Array ******
'array has 23 items
For i = 1 To 23
ore_body(i) = Int((ub_grade * Rnd) + lb_grade)
Next i
'******* filling random cells with my array******
For k = 1 To 23
Do
Set a = b.Cells(Int(7 * Rnd) + 1, Int(9 * Rnd) + 1)
Loop Until a.Value = ""
a.Value = ore_body(k)
Next k
'******* after filling cell now fill empty cells with Zero******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) = "" Then
Cells(i, j) = 0
Else
End If
Next j
Next i
'******* Coloring only containing array values******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) > 0 Then
Application.Cells(i, j).Interior.ColorIndex = 38
Else
End If
Next j
Next i
End Sub

VBA Count multiple duplicates in array

I have the same question as here: VBA counting multiple duplicates in array , but I haven't found an answer and with my reputation can't leave comment there.
I have an array with 150 numbers which could contain repetitive numbers from 1 to 50. Not always there are all 50 numbers in the array. Example of output of what I need:
- 10 times: 1, 2;
- 20 times: 3, 4 etc;
- 0 times: 5, 6, 7 etc.
I need to count how many combinations of duplicate numbers it has and what numbers are in those combinations including zero occurrence - which numbers are not in the array.
On mentioned above post there are solutions - but only when you know how many combinations of duplicates there are - and I don't know it - there could be 1 (all 150 numbers are equal) - ... - 20 ... up to 50 combinations if it contains all numbers from 1 to 50 three times each.
Appreciate any help and advice how to store output - finally it should be written to worksheet in the above mentioned format: [times] - [numbers] (here could be a string, example "5 - 6 - 7").
Here is what I've made for 5 combinations, but do 50 cases and then check 50 strings if they are empty or contain something to write to output is not very good option...
For i = 1 To totalNumbers 'my numbers from 1 to 50 or any other number
numberCount = 0
For j = 0 To UBound(friendsArray) 'my array of any size (in question said 150)
If i = friendsArray(j) Then
numberCount = numberCount + 1
End If
Next j
Select Case numberCount
Case 0
zeroString = zeroString & i & " - "
Case 1
oneString = oneString & i & " - "
Case 2
twoString = twoString & i & " - "
Case 3
threeString = threeString & i & " - "
Case 4
fourString = fourString & i & " - "
Case 5
fiveString = fiveString & i & " - "
Case Else
End Select
Next i
I have found possible option using Collection (but have got an headache with getting keys of collection...):
Dim col As New Collection
For i = 1 To totalNumbers
numberCount = 0
For j = 0 To UBound(friendsArray)
If i = friendsArray(j) Then
numberCount = numberCount + 1
End If
Next j
colValue = CStr(numberCount) & "> " & CStr(i) & " - " 'store current combination [key] and number as String
If IsMissing(col, CStr(numberCount)) Then
col.Add colValue, CStr(numberCount) 'if current combination of duplicates [key] is missing - add it to collection
Else 'if current combination [key] is already here - update the value [item]
oldValue = col(CStr(numberCount))
newValue = Replace(oldValue & colValue, CStr(numberCount) & "> ", "") 'delete combinations count
newValue = CStr(numberCount) & "> " & newValue
col.Remove CStr(numberCount) 'delete old value
col.Add newValue, CStr(numberCount) 'write new value with the same key
End If
Next i
For i = 1 To col.Count
Debug.Print col(i)
Next i
and IsMissing function (found here How to check the key is exists in collection or not)
Private Function IsMissing(col As Collection, field As String)
On Error GoTo IsMissingError
Dim val As Variant
val = col(field)
IsMissing = False
Exit Function
IsMissingError:
IsMissing = True
End Function
Output is like this [times]> [numbers]:
(array of 570 numbers)
114> 2 -
5> 6 -
17> 10 -
10> 3 - 8 - 19 - 21 - 30 -
6> 1 - 29 - 33 -
8> 5 - 9 - 13 - 23 - 25 - 28 - 37 - 40 -
4> 12 - 16 - 41 -
13> 43 -
12> 15 - 20 - 22 - 27 - 36 - 38 - 42 - 44 - 45 - 46 -
9> 4 - 7 - 11 - 14 - 34 - 47 - 48 -
7> 17 - 18 - 35 - 49 -
11> 24 - 26 - 31 - 32 - 39 - 50 -
Creating new array and count the number is more simple.
Sub test()
Dim friendsArray(0 To 50)
Dim vTable()
Dim iMax As Long
Dim a As Variant, b As Variant
Dim i As Long, s As Integer, n As Long
dim c As Integer
'Create Sample array to Test
n = UBound(friendsArray)
For i = 0 To n
friendsArray(i) = WorksheetFunction.RandBetween(0, 50)
Next i
'Your code
iMax = WorksheetFunction.Max(friendsArray)
ReDim vTable(0 To iMax) 'create new Array to count
For i = 0 To n
c = friendsArray(i)
vTable(c) = vTable(c) + 1
Next i
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
For i = 0 To iMax
If IsEmpty(vTable(i)) Then
s = 0
Else
s = vTable(i)
End If
If dic.Exists(s) Then
dic.Item(s) = dic.Item(s) & " - " & i
Else
dic.Add s, i
End If
Next i
a = dic.Keys
b = dic.Items
Range("a1").CurrentRegion.Clear
Range("B:B").NumberFormatLocal = "#"
Range("a1").Resize(UBound(a) + 1) = WorksheetFunction.Transpose(a)
Range("b1").Resize(UBound(b) + 1) = WorksheetFunction.Transpose(b)
Range("a1").CurrentRegion.Sort Range("a1"), xlAscending
End Sub

How to sum values in array from different columns + EXCEL VBA

I need to calculate this in excel vba ,using array loop only :
round 0 round 1
9 28
65 84
28 47
84 103
41 60
66 85
115 134
I need to sum values in round 0 in loop so the sum result (408) must be divided by 7 , if not I WANT to sum one value from the round 1 (in this case 84 instead of 65 ) to the rest of values in round 0 so the sum result can divided by 7 . There will be so many round up to 7 . I need VBA code to accomplish this..
Notes :
round 0 and round 1 all in one two-dimensional array
My Question is : is there a way to sum values from different columns in multi-dimensional array ??
there is an image attached .
I appreciate any help or idea .
Thanks in advance
Excel VBA Array Model:
http://im56.gulfup.com/8rDErI.png
Here an example file contains macro "Question1.xlsm"
http://www.gulfup.com/?TKAAYM
Notes : click the link under the big green down arrow to download the file.
UPDATE :
here another macro to the file "Question1.xlsm" :
Sub A1()
Dim arrTemp1() As Integer
Dim sum1 As Integer
arrblkTable1 = Sheets("Sheet1").Range("blkTable1").Value
ReDim Preserve arrTemp1(0 To 1, 1 To 7)
For a = 0 To 1
sum1 = 0
For c = 1 To 7
arrTemp1(a, c) = arrblkTable1(c, 1) + (a * 19)
text6 = text6 & arrTemp1(a, c) & vbCrLf
Worksheets("TEST3").Cells(a + 1, c).Value = arrTemp1(a, c)
sum1 = sum1 + arrTemp1(a, c)
Next c
If XLMod(sum1, 7) = 0 Then
MsgBox "Yes " & sum1
Else
MsgBox "No " & sum1
End If
Next a
MsgBox text6
End Sub
Function XLMod(a, b)
' This replicates the Excel MOD function
XLMod = a - b * Int(a / b)
End Function
UPDATE : here a new update to the previous macro :
Sub A1()
Dim arrTemp1(), arrTemp2(), arrSUMs() As Integer
Dim sum1 As Integer
arrblkTable1 = Sheets("Sheet1").Range("blkTable1").Value
arrblkTable2 = Sheets("Sheet1").Range("blkTable2").Value
'-------------------------------- arrTemp1 ------------------------------
ReDim Preserve arrTemp1(0 To 1, 1 To 7)
For a = 0 To 1
sum1 = 0
For c = 1 To 7
arrTemp1(a, c) = arrblkTable1(c, 1) + (a * 19)
text6 = text6 & arrTemp1(a, c) & vbCrLf
Worksheets("TEST3").Cells(a + 1, c).Value = arrTemp1(a, c)
sum1 = sum1 + arrTemp1(a, c)
Next c
If XLMod(sum1, 7) = 0 Then
MsgBox "Yes " & sum1
Else
MsgBox "No " & sum1
For c = 1 To 7
sum1 = sum1 - arrTemp1(a, c)
arrTemp1(a, c) = arrblkTable1(c, 1) + ((a + 1) * 19)
sum1 = sum1 + arrTemp1(a, c)
If XLMod(sum1, 7) = 0 Then
MsgBox "Yes " & sum1 & " " & arrTemp1(a, c)
End If
Next c
End If
Next a
For x = 0 To UBound(arrTemp1)
For y = 1 To UBound(arrTemp1)
text7 = text7 & arrTemp1(x, y) & vbCrLf
Next y
Next x
MsgBox text7
End Sub
Function XLMod(a, b)
' This replicates the Excel MOD function
XLMod = a - b * Int(a / b)
End Function
I need now to put each sum1 in one array , how I can do that ??
If I understood it correctly you want something similar to this:
Sub p()
v = Range("A2:A8")
v1 = Sheets("Sheet1").Range("B2:B8")
s = Application.WorksheetFunction.Sum(v)
b = False
Count = 0
For i = 1 To 7
temp = v
temp(i, 1) = v1(i, 1)
s = Application.WorksheetFunction.Sum(temp)
b = s Mod 7 = 0
If b = True Then
Count = Count + 1
End If
Next
MsgBox Count
End Sub
It may help tremendously if you can give more detail about what problem you're trying to solve, instead of focusing on how to solve it this way. There is a possibility that there's another way of doing it that hasn't occurred to you that will be much simpler.
This isn't an answer. Yet. But it will take more space than is allowed in a comment to ensure we've got this right.
For your sample data:
round 0 round 1
9 28
65 84
28 47
84 103
41 60
66 85
115 134
You want to:
Sum all the values in Round 0 (9 + 65 + 28 + 84 + 41 + 66 + 115) = 408
Take that sum (408) mod 7 and see if the result is 0
408 / 7 = 58.28, so (408 mod 7) <> 0
If the result isn't 0 (as in this case)
Start substituting numbers from round 1 for numbers in Round 0
Sum (28 + 65 + 28 + 84 + 41 + 66 + 115) = 427
427 / 7 = 61 (427 mod 7) = 0
This is now your valid result set.
Had the first number in Round 1 been 29
Sum (29 + 65 + 28 + 84 + 41 + 66 + 115) = 428
428 / 7 = 61.14 so (428 mod 7) <> 0
Substitute the next number from round 1 for the next number from round 0
Sum (9 + 84 + 28 + 84 + 41 + 66 + 115) = 427
This is now your valid result set.
Is that the logic you're after?
What happens if you get to the end of round 1 and you don't find a total that (mod 7 = 0)?

Multiplying two dimensional arrays

how to multiply two dimensional a(5,3) and b (3,5)
so the arry c( , )= a(5,3) and b (3,5)
the first row of arry a * the columns of arry b then
the second row of arry a * the columns of arry b then
[EDIT] the code of your comment:
Dim arry1(5, 3) As Integer
Dim arry2(3, 5) As Integer
Dim i, j As Integer
For i = 1 To 5
For j = 1 To 3
arry1(i, j) = Int(9 * Rnd + 1)
Next i, j
For i = 1 To 3
For j = 1 To 5
arry2(i, j) = Int(9 * Rnd + 1)
Next i, j
Congrats! it works :)
Some comments:
when you use Dim a, b As Integer then b will be an Integer, but a will be a Variant. It is better to use Dim a As Integer, b As Integer so that both a and b will be Integers
why do you ReDim c(5, 5) As Integer ? You can use Dim c(5, 5) As Integer
Instead of printing to the form I would show the data in a textbox or label control
Dim a, b As Integer
Dim arry1(5, 3) As Integer
Dim arry2(3, 5) As Integer
ReDim c(5, 5) As Integer
Dim i, j, s As Integer
Print ""
Print Space(15); "the first arry"
Print ""
For i = 1 To 5
For j = 1 To 3
arry1(i, j) = Int(9 * Rnd + 1)
Print Space(3); arry1(i, j);
Next j
Print ""
Next i
Print ""
Print Space(15); " the second arry"
Print ""
For i = 1 To 3
For j = 1 To 5
arry2(i, j) = Int(9 * Rnd + 1)
Print Space(3); arry2(i, j);
Next j
Print ""
Next i
Print ""
Print Space(15); " the result"
Print ""
cmd1.Visible = False
For a = 1 To 5
For b = 1 To 5
For j = 1 To 3
s = s + (arry1(b, j) * arry2(j, a))
c(a, b) = s
Next j
s=0
Next b
Next a
For i = 1 To 5
For j = 1 To 5
Print Space(3); c(i, j);
Next j
Print ""
Next i
thank you for your answers i solved the problem by may self and its pleasure me if you tel your openion in my code ... thank you

Resources