If statement results overwriting each other VBA - vba

I am experiencing a problem with the outputs from my loop. As the sub is running I can see that the results from the final IF statement are being overwritten by the results from the second one. My code is structured as follows:
for i = 1 to 5
for j = 1 to 50
for each events.value in eventArray
if events.value = arrayElem then
if cells(i,j).value = "x" then
type = "col1"
elseif cells(i,j).value = "y" then
date = "col2"
elseif cells(i,j).value = "z" then
num = "col3"
end if
count = count + 1
activeworkbook.worksheets("output").cells(count + 1, 1) = type
activeworkbook.worksheets("output").cells(count + 1, 2) = date
activeworkbook.worksheets("output").cells(count + 1, 3) = num
end if
next arrayElem
if cells(i,j).value = "a" then
name = "row1"
elseif cells(i,j).value = "b" then
size = "row2"
elseif cells(i,j).value = "c" then
height = "row3"
end if
activeworkbook.worksheets("output").cells(count + 2, 1) = name
activeworkbook.worksheets("output").cells(count + 2, 2) = size
activeworkbook.worksheets("output").cells(count + 2, 3) = height
next j
next i
Obviously these are dumby variables and results, but the overall structure is the same as the real code. I can see "name","size", and "height" being printed, but then they get replaced by "type", "date", and "num". How do I prevent this from happening? Each time a new event is found I need it to print its associated characteristics printed into a new row in the "output" sheet.

Consider the following simplified version of your code:
For i = 1 To 100
If x = y Then
rowNum = rowNum + 1
Cells(rowNum + 1, 1) = "A"
End If
Cells(rowNum + 2, 1) = "B"
Next
Each time through the loop you are writing out either one or two things (two if x = y is true, one if it isn't) but you are only incrementing the row number by zero or one (one if x = y is true, zero if it isn't). Even if you know that x will always equal y, you are still trying to write two rows of information out but only increasing the row counter by one.
Assuming you are not trying to replace the "B"s in my example with the "A"s from the next iteration through the loop, you should change the code to something like:
For i = 1 To 100
If x = y Then
rowNum = rowNum + 1
Cells(rowNum, 1) = "A"
End If
rowNum = rowNum + 1
Cells(rowNum, 1) = "B"
Next

Related

Excel VBA how to set number sequence to start at middle of the row?

I previously have a Excel sheet with VBA coding that fills column, row 1 to 10 with the number 1, row 11 to 20 with number 2 and so on. The code I've used is as follows:
Sub fill()
Dim ID
ID = 1
For c = 1 To 34
ActiveWorkbook.Sheets("Sheet1").Cells(c, 1) = ID
ActiveWorkbook.Sheets("Sheet1").Cells(c + 1, 1) = ID
c = c + 1
If (c Mod 10) = 0 Then
ID = ID + 1
End If
Next c
End Sub
Now I want to change it so that the code starts at row 3 onwards. Meaning row 3 to 12 = 1, row 13 to 22 = 2 and so on. So I changed the 'For' statement to:
For c = 3 To 34
But what happens is that the number 1 appears from row 3 to row 10, and then continues with number 2 in row 11 to 20. Not what I was expecting.
Therefore, what would be the best method of changing the code?
If you want exactly the same output but two rows lower, you can use:
Sub fill()
Dim ID
ID = 1
For c = 1 To 34
ActiveWorkbook.Sheets("Sheet1").Cells(c + 2, 1) = ID
ActiveWorkbook.Sheets("Sheet1").Cells(c + 3, 1) = ID
c = c + 1
If (c Mod 10) = 0 Then
ID = ID + 1
End If
Next c
End Sub
If you still only want to go to row 34 but start in row 3, change the 34 to 32 in the above code.
You can also do it without looping and this is easier to adjust the parameters:
Sub fill()
Const NUMBER_OF_ROWS As Long = 34
Const START_ROW As Long = 3
Const ID As Long = 1
Const NUMBER_IN_GROUP As Long = 10
With ActiveWorkbook.Sheets("Sheet1").Cells(START_ROW, 1).Resize(NUMBER_OF_ROWS)
.Value = .Parent.Evaluate("INDEX(INT((ROW(" & .Address & ")-" & START_ROW & ")/" & _
NUMBER_IN_GROUP & ")+" & ID & ",)")
End With
End Sub
When i understand you write, this should work:
You can use the loop how you did at the beginning. and just add plus 2 to c in the ActiveWorkbook.Sheets("Tabelle1").Cells(c + 2, 1) = ID
Sub fill()
Dim ID
ID = 1
For c = 1 To 34
ActiveWorkbook.Sheets("Tabelle1").Cells(c + 2, 1) = ID
ActiveWorkbook.Sheets("Tabelle1").Cells(c + 3, 1) = ID
c= c+1
If (c Mod 10) = 0 Then
ID = ID + 1
End If
Next c
End Sub
something like that should be the simplest way:
Sub fill()
Dim i As Integer
Dim j As Integer
For i = 1 To 4
For j = 1 To 10
ActiveWorkbook.Sheets("Sheet1").Cells(j + (i - 1) * 10 + 2, 1) = i
Next j
Next i
End Sub
EDIT:
No, the simplest way would be type formula into A3:
=ROUNDDOWN(((ROW()-3))/10,0)+1
end drag it donw.

vba array element removal

j = LBound(arrayTime)
Do Until j = UBound(arrayTime)
j = j + 1
b = b + 1
cnc = b + r
MsgBox cnc
If cnc > 7 Then
b = 0
r = 0
cnc = b + r
End If
numMins = Sheet5.Cells(cnc + 3, 2) - arrayTime(j)
If numMins < 0 Then
g = g + 1
ReArrangeArray arrayTime, j
'ReDim Preserve arrayTime(numrows - 1 + g)
'arrayTime(numrows - 1 + g) = arrayTime(j)
'MsgBox (arrayTime(numrows - 1 + g))
Else
Sheet5.Cells(cnc + 3, 2) = numMins
End If
Loop
If the if statement is true I want to be able to put the array value at the end of the array and remove that value from its current spot. As the code is, it just adds it to the end and increases the size of the array from 12 to 13. How can I get the array to remain size 12 and still place the value at the end of the array and then remove it from its original position? I do not want to touch the array values in front. Just want to take that value and move it to the end.
For instance
array(1,2,3,4,5)
If statement
j on third loop.
array(j)=3
end array should be
array(1,2,4,5,3)
You could use a helper Sub like this one:
Sub ReArrangeArray(inputArray as Variant, indexToSwap as long)
Dim I As Long
Dim tempVal As Variant
If indexToSwap >= LBound(inputArray) And indexToSwap < UBound(inputArray) Then
tempVal = inputArray(indexToSwap)
For I = indexToSwap To UBound(inputArray) - 1
inputArray(i) = inputArray(i + 1)
Next I
InputArray(UBound(inputArray)) = tempVal
End If
End Sub
To be called by your main Sub as follows:
ReArrangeArray arrayTime, j

Parsing a Number

Here is my problem:
I am parsing a xml using excel VBA. I open the XML file as regular excel file, Then I go to column which is of my interest.
Cells in that column are 16 character.
So I am parsing each of those characters using Left and Right functions and saving them in a new file.
Mostly those 16 characters are Numeric and sometimes Alpha Character.
example 1111000011110000 or 1111YYYY00001111
when it parses 1111YYYY00001111 -- I get correct output,
like in new file Cell(1,1) =1 Cell(1,1) =1 Cell(1,2) =1 Cell(1,3) =1 Cell(1,4) =1 Cell(1,5) =Y and so on
But When I parse 1111000011110000 -- I dont get the correct output
I get Cell(1,1) =1 Cell(1,2) =. Cell(1,3) =1 Cell(1,4) =1 Cell(1,5) =1 Cell(1,6) =0
I tried to put NumberFormat="0" for column which I was parsing, but still i get the same output.
I also tried to put the debug variables and stored them as strings, Double Integer but I could not get pass it.
Here is my code:
Workbooks.Add
strip_concat = ActiveWorkbook.Name
Workbooks(strip_concat).Sheets(1).Cells(1, 1) = "Subid"
Workbooks(strip_concat).Sheets(1).Cells(1, 2) = "Strip#"
Workbooks(strip_concat).Sheets(1).Cells(1, 3) = "X"
Workbooks(strip_concat).Sheets(1).Cells(1, 4) = "Y"
Workbooks(strip_concat).Sheets(1).Cells(1, 5) = "Reject Code"
Workbooks(strip_concat).Sheets(1).Cells(1, 6) = "X-Y"
Workbooks.OpenXML Filename:=xml_file
stripfile = ActiveWorkbook.Name
For C = 3 To strip_col - 1
r = 1
Do
Y = r
x = C - 2
Workbooks(strip_concat).Sheets(1).Cells(A, 3) = x
Workbooks(strip_concat).Sheets(1).Cells(A, 4) = Y
Workbooks(strip_concat).Sheets(1).Cells(A, 6).NumberFormat = "#"
Workbooks(strip_concat).Sheets(1).Cells(A, 6) = x & "-" & Y
Workbooks(strip_concat).Sheets(1).Cells(A, 1) = Workbooks(stripfile).Sheets(1).Cells(C, Amkor_id_col)
Workbooks(strip_concat).Sheets(1).Cells(A, 2) = ExtractElement(Workbooks(stripfile).Sheets(1).Cells(C, Strip_num_col), 2, ".")
Workbooks(strip_concat).Sheets(1).Cells(A, 5) = Right(Left(Workbooks(stripfile).Sheets(1).Cells(C, Defect_data_col + i), r), 1)
r = r + 1
A = A + 1
Loop Until (r > 16)
If ((x Mod 13) = 0) Then i = i + 1
Next C
from xml file 1131111111111111
I got it working.. This is what I did
Dim x as variant
x = (Workbooks(stripfile).Sheets(1).Cells(C, Defect_data_col + i).Text
Workbooks(strip_concat).Sheets(1).Cells(A, 5) = Right(Left(x,r),1

INDEX MATCH array formula for 1M rows

I have two sets of data that need to be matched based on IDs and timestamp (+/- 3 units converted from time), and below is the formula that I've been using in Excel to do the matching. Recently I've had to run this formula on up to 1 million rows in Excel, and it takes a REALLY long time, crashes too. I'm wondering if there is a faster way to do this, if not in Excel?
=INDEX(A:A,MATCH(1,--(B:B=E3)*--(ABS(C:C-F3)<=3),0),1)
Data Set 1:
Column A: States
Column B: IDs
Column C: Timestamp
Data Set 2:
Column D: Email Addresses
Column E: IDs
Column F: Timestamp
Column G: =INDEX(A:A,MATCH(1,--(B:B=E3)*--(ABS(C:C-F3)<=3),0),1)
Goal: Append "States" Column to Data Set 2 matched on IDs and Timestamp (+/- 3 time units) match.
Just don't know how to run this formula on very large data sets.
Place the following VBA routines in a standard code module.
Run the MIAB1290() routine.
This emulates the precise outcome of your INDEX/MATCH formula, but it is much more efficient. On my computer, a million records are correctly correlated and the results displayed in Column G in just 10 seconds.
Public Sub MIAB1290()
Dim lastB&, k&, e, f, z, v, w, vErr, r As Range
With [a2]
Set r = .Resize(.Item(.Parent.Rows.Count - .Row + 1, 5).End(xlUp).Row - .Row + 1, .Item(, .Parent.Columns.Count - .Column + 1).End(xlToLeft).Column - .Column + 1)
lastB = .Item(.Parent.Rows.Count - .Row + 1, 2).End(xlUp).Row - .Row + 1
End With
With r
.Worksheet.Sort.SortFields.Clear
.Sort Key1:=.Item(1, 2), Order1:=1, Key2:=.Item(1, 2), Order2:=1, Header:=xlYes
v = .Value2
End With
ReDim w(1 To UBound(v), 1 To 1)
vErr = CVErr(xlErrNA)
For k = 2 To UBound(v)
e = v(k, 5)
f = v(k, 6)
w(k, 1) = vErr
z = BSearch(v, 2, e, 1, lastB)
If z Then
Do While v(z, 2) = e
If Abs(v(z, 3) - f) <= 3 Then
w(k, 1) = v(z, 1)
Exit Do
End If
z = z + 1
If z > UBound(v) Then Exit Do
Loop
End If
Next
r(1, 8).Resize(r.Rows.Count) = w
End Sub
Private Function BSearch(vA, col&, vVal, ByVal first&, ByVal last&)
Dim k&, middle&
While last >= first
middle = (last + first) / 2
Select Case True
Case vVal < vA(middle, col)
last = middle - 1
Case vVal > vA(middle, col)
first = middle + 1
Case Else
k = middle - 1
Do While vA(k, col) = vA(middle, col)
k = k - 1
If k > last Then Exit Do
Loop
BSearch = k + 1
Exit Function
End Select
Wend
BSearch = 0
End Function
Excel isn't really made for large ammount of data, and probably no code will do it faster for you then a builtin excel formula. In this case, I would sugest you to give a try to the PowerPivot addin, and see how it handles the situation.

textbox values won't assign to a variable in vba

I was running tests on my software today and found that some of the values it was producing weren't correct.
I decided to step through the code and noticed that the variables I had assigned to textbox values on my userform when hovered over said empty, even though when hovering over the textbox assigned to it, the value inputted by the user showed.
For Example,
n = BiTimeSteps_TextBox.Value
when hovered over
n = empty
even though
BiTimeSteps_TextBox.Value = 2
when hovered over.
So say I have a formula shortly after that says
d = n*2 ,
n when hovered over says empty and d is made 0 when it shouldn't be.
Someone told me if I switch it around to
BiTimeSteps_TextBox.Value = n
it should be recognised but it is still not.
What could possibly be causing this?
See full code below: (it aims to price options using the binomial tree pricing method)
S = BiCurrentStockPrice_TextBox.Value
X = BiStrikePrice_TextBox.Value
r = BiRisk_Free_Rate_TextBox.Value
T = BiexpTime_TextBox.Value
Sigma = BiVolatility_TextBox.Value
n = BiTimeSteps_TextBox.Value
Dim i, j, k As Integer
Dim p, V, u, d, dt As Double
dt = T / n ' This finds the value of dt
u = Exp(Sigma * Sqr(dt)) 'formula for the up factor
d = 1 - u 'formula for the down factor
'V value of option
'array having the values
Dim bin() As Double 'is a binomial arrays, it stores the value of each node, there is a loop
'work out the risk free probability
p = (1 + r - d) / (u - d)
'probability of going up
ReDim bin(n + 1) As Double
'it redims the array, and n+1 is used because it starts from zero
'------------------------------------------------------------------------------------------------------------------------------
''European Call
If BiCall_CheckBox = True Then
For i = 0 To n 'payoffs = value of option at final time
bin(i + 1) = Application.WorksheetFunction.Max(0, (u ^ (n - i)) * (d ^ i) * S - X)
'It takes the max payoff or 0
Cells(i + 20, n + 2) = bin(i + 1) 'to view payoffs on the isolated column on the right
Next i
End If
'european put
If BiPut_CheckBox = True Then
For i = 0 To n 'payoffs = value of option at final time
bin(i + 1) = Application.WorksheetFunction.Max(0, X - (S * (u * (n - i)) * (d * i)))
' European Put- It takes the max payoff or 0
Cells(i + 20, n + 2) = bin(i + 1) 'to view payoffs on the isolated column on the right
Next i
End If
For k = 1 To n 'backward column loop
For j = 1 To (n - k + 1) 'loop down the column loop
bin(j) = (p * bin(j) + (1 - p) * bin(j + 1)) / (1 + r)
Cells(j + 19, n - k + 2) = bin(j)
'' print the values along the column, view of tree
Next j
Next k
Worksheets("Binomial").Cells(17, 2) = bin(1) ' print of the value V
BiOptionPrice_TextBox = bin(1)