I am trying to make a macro that will create a matrix based upon an equation in an VBA.
For example:
If I have the following 3x3 matrix:
3 5 7
6 3 4
1 2 3
I want to create a 3x3 matrix that takes the value 1st value and divides it by the sum of the row, and so on.
0.2 0.3 0.5
0.5 0.2 0.3
0.2 0.3 0.5
I tried the following code:
Sheets("sheet1").Select
Range("C2").Select
Selection.End(xlDown).Select
ActiveCell.Offset(2, 0).Range("A1").Select 'So the new matrix starts underneath the old matrix
Dim i As Integer
Dim n As Integer
i = 4
n = 1
Do While Cells(i, 3).Value <> ""
ActiveCell.FormulaRnC1 = "=RiC3/SUM(RiC3:RiC52)*100"
i = i + 1
ActiveCell.Offset(1, 0).Range("A1").Select
The number or rows will vary.
I have limited experience with this platform, please let me know how to improve framing this question.
I will recommend you put your first matrix on Sheet1 starting in cell A1. This will output the other Matrix to the new workbook, Sheet1, starting in cell A1.
Sub example()
Dim x As Variant, y As Variant
Dim row_sum As Double
Dim i As Integer, j As Integer
Dim wbk As Workbook
With ThisWorkbook.Sheets(1)
x = .Range("a1:" & .Cells(.Range("a" & .Rows.Count).End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft).Column).Address).Value2
End With
y = x
With Application.WorksheetFunction
For i = LBound(x, 1) To UBound(x, 1)
row_sum = .Sum(.Index(x, i))
For j = LBound(x, 2) To UBound(x, 2)
y(i, j) = x(i, j) / row_sum
Next j
Next i
End With
Set wbk = Workbooks.Add
wbk.Sheets(1).Range("a1").Resize(UBound(y, 1), UBound(y, 2)) = y
End Sub
Related
I have a problem with the function CountIF when used with decimals.
Below the code I have:
Sub Compair()
Dim I As Double
Row = 3
For I = 139.5 To 141.5 Step 0.25
Cells(Row, 3) = I
Cells(Row, 4) = Application.WorksheetFunction.CountIf(Range("A:A"), "<" & Cells(Row, 3))
Row = Row + 1
Next I
End Sub
And below the output:
It seems that the code functions good when it is compairing integer value and not with decimals.
PS: I do not want to loop on column A cells, as there could be more than 100k values and it will be so slowly
You can pull everything into variant arrays, which will be quicker on larger datasets than COUNTIFS:
Sub Compair()
With ActiveSheet
Dim rngArr As Variant
rngArr = Intersect(.UsedRange, .Range("A2", .Cells(.Rows.Count, 1))).Value2
Dim outArr() As Variant
ReDim outArr(1 To Int((141.5 - 139.5) / 0.25) + 1, 1 To 2)
Dim I As Double
Row = 1
For I = 139.5 To 141.5 Step 0.25
outArr(Row, 1) = I
outArr(Row, 2) = 0
Dim j As Long
For j = 1 To UBound(rngArr, 1)
If rngArr(j, 1) < I Then outArr(Row, 2) = outArr(Row, 2) + 1
Next j
Row = Row + 1
Next I
.Range("C3").Resize(UBound(outArr, 1), 2).Value = outArr
End With
End Sub
Your code is correct
just confirm your region, if you need the comas as decimal separatos configure your Windows format, and your excel format
Windows Format
https://www.windowscentral.com/how-change-date-and-time-formats-windows-10
Excel Format
https://edu.gcfglobal.org/en/excel2013/formatting-cells/1/
Sub Compair()
Range("A16").Select
Dim I As Double
Row = 16
For I = 139.5 To 141.5 Step 0.25
Cells(Row, 3) = I
Cells(Row, 4) = Application.WorksheetFunction.CountIf(Range("A:A"), "<" & Cells(Row, 3))
Row = Row + 1
Next I
End Sub
I am a VBA beginner.
I want to copy cells from Sheet 1 into Sheet 2 in a certain sequential (in my case, after every 13 rows) with the condition of this: if any of the D2 to D32 in Sheet 1 is 0, copy A2 to A32 respectively. Then paste it in a sequential of +13 starting from B23 in Sheet 2.
For example:
if D2 is 0, copy A2 and paste it into B23 in Sheet 2.
if D3 is 0, copy A3 and paste it into B36 in Sheet 2.
If D4 is not 0, skip to next.
If D5 is 0, copy A5 and pate it into B49 in Sheet 2.
I feel that it is workable in VBA but I can't seem to figure it out.
I have searched the web but no answer came close to my requirement.
Sub Test()
Sheets("Sheet1").Select
For i = 2 To 32
If Sheets("Sheet1").Cells(i, 4) = 0 Then
Cells(i, 1).Copy
Else
End If
Sheets("Sheet2").Select
For j = 23 To 361 Step 13
Sheets("Sheet2").Cells(j, 2).PasteSpecial Paste:=xlPasteValues
Next j
Next i
End Sub
My current VBA keeps looping in Sheet2 until the end when the condition in Sheet1 is met. That's not what I want.
For flexibility in ranges, some speed using array and avoiding .Select and .PasteSpecial, you could try the following:
Sub Test()
Dim lr As Long, x As Long, z As Long, arr As Variant
With Sheets("Sheet1") 'Change accordingly
lr = .Cells(.Rows.Count, "A").End(xlUp).Row
arr = .Range("A2:D" & lr).Value
End With
For x = LBound(arr) To UBound(arr)
If arr(x, 4) = 0 Then
Sheets("Sheet2").Cells(23 + z * 13, 2) = arr(x, 1)
z = z + 1
End If
Next x
End Sub
If you always just interested in A2:A32 then this will do:
Sub Test()
Dim x As Long, z As Long, arr As Variant
arr = Sheets("Sheet1").Range("A2:D32").Value
For x = LBound(arr) To UBound(arr)
If arr(x, 4) = 0 Then
Sheets("Sheet2").Cells(23 + z * 13, 2) = arr(x, 1)
z = z + 1
End If
Next x
End Sub
You'll benefit from reading this too.
Please try this
Sub Test()
Dim i As Integer, n As Integer
Sheets("Sheet1").Select
n = 0
For i = 2 To 32
Sheets("Sheet1").Activate
If Sheets("Sheet1").Cells(i, 4) = 0 Then
Cells(i, 1).Copy
Sheets("Sheet2").Activate
Sheets("Sheet2").Cells(23 + (n * 13), 2).PasteSpecial Paste:=xlPasteValues
n = n + 1
Else
End If
'Sheets("Sheet2").Select
' For j = 23 To 361 Step 13
' Sheets("Sheet2").Cells(j, 2).PasteSpecial Paste:=xlPasteValues
' Next j
Next i
End Sub
Try this one:
Sub Test()
Dim i,j as integer
j= 1
Sheets("Sheet1").Activate
For i = 2 To 32
If Sheets("Sheet1").Cells(i, 4) = 0 Then
Sheets("Sheet2").Cells(10 + 13 * j, 2).Value2 = Cells(i, 1).Value2
j = j + 1
End If
Next
End Sub
Hope it helps
I have the values on the range "A1:O1".
Each Column has a unique value in this range.
I need help to develop a loop that will fill down 04 times on each column the same Top Value (Column Value). Below a Pseudo Code
Sub FillDownRowsRandomly()
Dim i As Integer, j As Integer
'RamdomRow=Total of 04 unique ramdom numbers
'choosen from 01 to 06 {1,2,3,4,5,6}
'meaning that in a loop of 6 interations, when fill down
'2 will be Null or empty
'
For i = 1 To 15 'Columns "A" To "O"
For j = 2 To 7 '
'
Cells(RandomRow, i).Value = Cells(1, i).Value
Next j
Next i
End Sub
Below an Image where will be possible identify the result of the code.
Disregard the "Null" word written in the cells. I wrote that just to clarify that during the random loop, the code "ignored that cell".
Maybe something like:
Sub FillDownRowsRandomly()
Dim x As Long, y As Long, z As Long
With Sheet1 'Change accordingly
For y = 1 To 15
z = 0
Do While z < 4
x = Int((7 - 2 + 1) * Rnd + 2)
If .Cells(x, y) <> .Cells(1, y) Then
.Cells(x, y) = .Cells(1, y)
z = z + 1
End If
Loop
Next y
End With
End Sub
Loop the columns and randomly place the values till there are four in the six rows.
Sub FillDownRowsRandomly()
ActiveSheet.Range("A2:O7").ClearContents
Dim i As Long
For i = 1 To 15 'iterate the columns
Do Until Application.CountIf(ActiveSheet.Cells(2, i).Resize(6), ActiveSheet.Cells(1, i).Value) >= 4
Dim j As Long
j = Application.RandBetween(2, 7)
ActiveSheet.Cells(j, i).Value = ActiveSheet.Cells(1, i).Value
Loop
Next i
End Sub
I am new to Excel VBA and I want to calculate the distance between two atoms and make a loop to calculate it for all wanted cases
with coordinate B(i), C(i), D(i) in the Excel sheet correspond to x,y,z cartesian coordinate..
these atoms are located : One in a row (i) and the other in a row (i+5)
I write this algorithm but I cant transfer it to excel VBA
For i=4 to 1000
For j=9 to 1000
d=SQRT(POWER(B(i)-B(j),2)+ POWER(C(i)-C(j),2)+ POWER(D(i)-D(j),2))
print **d** in (P(i)) #want to print the distance **d** in a case
j=j+4 # **j** is a multiple of 4
i=i+4 # **i** is a multiple of 4
next i
Thanks, this is my first question
I think that the following should work for you:
Sub FindDistances()
Dim i As Long, j As Long
Dim r As Long, c As Long 'row and column indices for output
Dim data As Variant
Application.ScreenUpdating = False 'useful when doing a lot of writing
data = Range("B4:D1000").Value 'data is a 1-based array
c = 5 'column E
For i = 1 To UBound(data) - 5 Step 4
r = 1 'first row printed in -- adjust if need be
For j = i + 5 To UBound(data) Step 4
Cells(r, c).Value = Sqr((data(i, 1) - data(j, 1)) ^ 2 + (data(i, 2) - data(j, 2)) ^ 2 + (data(i, 3) - data(j, 3)) ^ 2)
r = r + 1
Next j
c = c + 1
Next i
Application.ScreenUpdating = True
End Sub
Something like this? In VBA, you refer to cells like Cells(row, column). Data is supposed to be located in a worksheet named Sheet1. I'm calculating each dimension separately (d1, d2, d3) just for reading simplicity. You can merge those four lines in one if you like. EDIT: reading your comments above, I add a nested loop (j).
Sub Distances()
Dim i As Integer
Dim j As Integer
Dim d1 As Double, d2 As Double, d3 As Double, d As Double
For i = 4 To 1000 Step 4 'Can't understand your data, but Step 4 tries to account for your j=j+4 and i=i+4
For j = 9 To 1000 Step 4
d1 = (Worksheets("Sheet1").Cells(i, 2) - Worksheets("Sheet1").Cells(j, 2)) ^ 2
d2 = (Worksheets("Sheet1").Cells(i, 3) - Worksheets("Sheet1").Cells(j, 3)) ^ 2
d3 = (Worksheets("Sheet1").Cells(i, 4) - Worksheets("Sheet1").Cells(j, 4)) ^ 2
d = Sqr(d1 + d2 + d3)
Worksheets("Sheet1").Cells(i, 16).Value = d
Next j
Next i
End Sub
Option Explicit
Sub AtomDistance()
'
' AtomDistance Macro1
'
'
Dim i As Integer
Dim j As Integer
Dim Distance As Double
Dim Column As String
Column = InputBox("Which column you want to print results(put a letter)?")
Dim MyCell11 As String
Dim MyCell12 As String
Dim MyCell13 As String
Dim MyCell21 As String
Dim MyCell22 As String
Dim MyCell23 As String
Dim MyCell3 As String
j = 9
For i = 4 To 12
MyCell3 = Column & i
MyCell11 = "B" & i
MyCell12 = "C" & i
MyCell13 = "D" & i
MyCell21 = "B" & j
MyCell22 = "C" & j
MyCell23 = "D" & j
Distance = (((Range(MyCell11).Value - Range(MyCell21).Value) ^ 2) + ((Range(MyCell12).Value - Range(MyCell22).Value) ^ 2) + ((Range(MyCell13).Value - Range(MyCell23).Value) ^ 2)) ^ 0.5
If i Mod 4 = 0 Or j Mod 4 = 0 Then
Range(MyCell3).Value = Distance
End If
j = j + 1
Next i
i'm currently trying to compare each and every cell in a column with each other in order to find duplicates. I wrote below code, i know it as possible via default Excel functions, but i would like to write a macro with the above mentioned function. Excel currently doesn't respond when i run my code, my guess is that i run a double for loop with 14K cells to compare is each resulting in 14.000*14.000 loops, which is kinda unhandy. Any help will be appreciated :).
Sub findidentical()
Dim i As Integer
Dim j As Integer
Dim x As Integer
Dim ColumnG As Integer
x = 0
ColumnG = Application.WorksheetFunction.CountA(Range("G:G"))
'ColumnG is 14K cells long'
For i = 2 To ColumnG
For j = 1 + 1 To ColumnG
If Cells(i, 7).Value = Cells(j, 7).Value Then
x = x + 1 & Cells(i, 7).Font.Bold = True & Cells(j, 7).Font.Bold = True
End If
Next j
Next i
Range("L25").Text = "Amount of duplicates"
Range("L26").Value = x
End Sub
Try this:
Sub findidentical()
Dim i As Integer
Dim j As Integer
Dim x As Integer
Dim ColumnG As Integer
x = 0
ColumnG = Application.WorksheetFunction.CountA(Range("G:G"))
'ColumnG is 14K cells long'
For i = 2 To ColumnG
For j = i + 1 To ColumnG
If Cells(i, 7).Value = Cells(j, 7).Value Then
x = x + 1
Cells(i, 7).Font.Bold = True
Cells(j, 7).Font.Bold = True
End If
Next j
Next i
Range("L25").Text = "Amount of duplicates"
Range("L26").Value = x
End Sub
First you need to make each command in the if statement its own line or separate them with : instead of &. & is a string concatenation not a command separator.
Second there is no reason to start Loop j at 2 it has already been compared to everything above. So start it at i+1