I have two sheets. When the second is activated I need to read the first and insert info into the second.
The code below should do this but it is reading the second sheet,"Cabinet install", instead of the first. What is wrong?
Dim k As Integer
Dim j As Integer
Dim Sumknobs As Integer
Dim Cabsht As Worksheet
Dim Installsht As Worksheet
Set Cabsht = Worksheets("Cabinets")
Set Installsht = Worksheets("Cabinet Install")
Application.ScreenUpdating = True
Cabsht.Activate
With Worksheets("Cabinets")
For j = 1 To 4
For k = 1 To 46
Sumknobs = Sumknobs + .Cells(k + 4, 5 * j - 2) * Cells(k + 4, 5 * j - 1)
Next k
Next j
For j = 1 To 2
For k = 1 To 71
Sumknobs = Sumknobs + .Cells(k + 4, 5 * j + 18) * Cells(k + 4, 5 * j + 19)
Next k
Next j
End With
Installsht.Cells(17, 6) = Sumknobs
You are missing some . 's
Replace:
Sumknobs = Sumknobs + .Cells(k + 4, 5 * j - 2) * Cells(k + 4, 5 * j - 1)
with:
Sumknobs = Sumknobs + .Cells(k + 4, 5 * j - 2) * .Cells(k + 4, 5 * j - 1)
same for the second loop-set.
Related
Sub WriteToZeroBasedArray()
Dim E As Integer
Dim rCount As Long: rCount = Worksheets("0618").Cells.SpecialCells(xlLastCell).Row
For E = 9 To 11
Dim V() As Variant ' Note the parentheses!
Dim P() As Variant
Dim N() As Variant
Dim Index As Long
Dim Index_2 As Long
Dim Index_3 As Long
Dim cCount As Long: cCount = Worksheets("0618").Cells.SpecialCells(xlLastCell).Column ' e.g.
Dim c As Long '배열에 값 저장하기
For c = 7 To cCount
If 0 < Worksheets("0618").Cells(E, c).Value And Worksheets("0618").Cells(E, c).Value < 100 Then
ReDim Preserve V(Index)
' A safer way (Option Base related):
'ReDim Preserve V(0 To Index)
V(Index) = Worksheets("0618").Cells(2, c).Value
Index = Index + 1
ReDim Preserve P(Index_2)
P(Index_2) = Worksheets("0618").Cells(4, c).Value
Index_2 = Index_2 + 1
ReDim Preserve N(Index_3)
N(Index_3) = Worksheets("0618").Cells(E, c).Value
Index_3 = Index_3 + 1
End If
Next c
Dim K As Integer
Dim L As Integer
K = UBound(V) '배열의 값 차례로 Sheet2에 넣기
For L = 0 To K
If L < 5 Then
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 1).Value = V(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 2).Value = P(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 3).Value = N(L)
Else
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 5).Value = V(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 6).Value = P(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 7).Value = N(L)
End If
Next
Dim FP As Integer
Dim Sum As Integer
Sum = 0
'수량*단가 구하기
For FP = (6 + 14 * (E - 9)) To (10 + 14 * (E - 9))
Worksheets("sheet2").Cells(FP, 4).Value = Worksheets("sheet2").Cells(FP, 2).Value * Worksheets("sheet2").Cells(FP, 3).Value
Worksheets("sheet2").Cells(FP, 8).Value = Worksheets("sheet2").Cells(FP, 6).Value * Worksheets("sheet2").Cells(FP, 7).Value
'총액 구하기
Sum = Sum + Worksheets("sheet2").Cells(FP, 4).Value + Worksheets("sheet2").Cells(FP, 8).Value
'0 지우기
If Worksheets("sheet2").Cells(FP, 4).Value = 0 Then
Worksheets("sheet2").Cells(FP, 4).ClearContents
End If
If Worksheets("sheet2").Cells(FP, 8).Value = 0 Then
Worksheets("sheet2").Cells(FP, 8).ClearContents
End If
Next
'총액 구하기2
Worksheets("sheet2").Cells(12 + 14 * (E - 9), 8).Value = Sum
'받으실 분
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 2).Value = Worksheets("0618").Cells(E, 3).Value
'주소
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 5).Value = Worksheets("0618").Cells(E, 2).Value
'서식 복사'
Worksheets("sheet3").Range("A1:H13").Copy
Worksheets("sheet2").Range("A" & 15 + 14 * (E - 9)).PasteSpecial
If Index = 0 Then Exit Sub
Next
Debug.Print Join(V, vbLf)
End Sub
I expected this code to be like this
But the result is like this
When E = 9, the code runs exactly the same as I thought, but when E is over 10, it doesn't.
when E = 9, the V array's values and orders are like this [grape, apple], and that's what I wanted.
However, when E = 10, I want the V array's value to be like this [orange]
but the result says it is [ , , orange]
Could someone tell me what's wrong with my code?
For me, the two (different) pictures look like 'Chinese'... So, I cannot refer to them.
No need to use Index, Index2 and Index3. Use only Index and increment it at the second loop end;
'replace this line
Index_3 = Index_3 + 1
'with
Index = Index + 1
' and comment all the previous index incrementations
You must reinitialize the used arrays content and used Index at the first loop end:
'your code...
If Index = 0 Then Exit Sub 'after this existing code line
Erase V: Erase P: Erase N: Index = 0
Next
'Your code
Now, using Redim Preserve to often is bad from memory handling point of view. Please, try firstly ReDim to a value to exceed the necessary number of necessary elements (ReDim V(cCount)) and use only of the end: Redim Preserve V(Index -1). Do the same for the other two used arrays...
Sub WriteToZeroBasedArray()
Dim E As Integer
Dim rCount As Long: rCount =
Worksheets("0618").Cells.SpecialCells(xlLastCell).Row
For E = 9 To rCount
Dim V() As Variant ' Note the parentheses!
Dim P() As Variant
Dim N() As Variant
Dim Index As Long
Dim Index_2 As Long
Dim Index_3 As Long
Dim cCount As Long: cCount = Worksheets("0618").Cells.SpecialCells(xlLastCell).Column ' e.g.
Dim c As Long '배열에 값 저장하기
For c = 7 To cCount
If 0 < Worksheets("0618").Cells(E, c).Value And Worksheets("0618").Cells(E, c).Value < 100 Then
ReDim Preserve V(Index)
' A safer way (Option Base related):
'ReDim Preserve V(0 To Index)
V(Index) = Worksheets("0618").Cells(2, c).Value
Index = Index + 1
ReDim Preserve P(Index_2)
P(Index_2) = Worksheets("0618").Cells(4, c).Value
Index_2 = Index_2 + 1
ReDim Preserve N(Index_3)
N(Index_3) = Worksheets("0618").Cells(E, c).Value
Index_3 = Index_3 + 1
End If
Next c
Dim K As Integer
Dim L As Integer
K = UBound(V) '배열의 값 차례로 Sheet2에 넣기
For L = 0 To K
If L < 5 Then
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 1).Value = V(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 2).Value = P(L)
Worksheets("sheet2").Cells(L + 6 + 14 * (E - 9), 3).Value = N(L)
Else
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 5).Value = V(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 6).Value = P(L)
Worksheets("sheet2").Cells(L + 1 + 14 * (E - 9), 7).Value = N(L)
End If
Next
Dim FP As Integer
Dim Sum As Integer
Sum = 0
'수량*단가 구하기
For FP = (6 + 14 * (E - 9)) To (10 + 14 * (E - 9))
Worksheets("sheet2").Cells(FP, 4).Value = Worksheets("sheet2").Cells(FP, 2).Value * Worksheets("sheet2").Cells(FP, 3).Value
Worksheets("sheet2").Cells(FP, 8).Value = Worksheets("sheet2").Cells(FP, 6).Value * Worksheets("sheet2").Cells(FP, 7).Value
'총액 구하기
Sum = Sum + Worksheets("sheet2").Cells(FP, 4).Value + Worksheets("sheet2").Cells(FP, 8).Value
'0 지우기
If Worksheets("sheet2").Cells(FP, 4).Value = 0 Then
Worksheets("sheet2").Cells(FP, 4).ClearContents
End If
If Worksheets("sheet2").Cells(FP, 8).Value = 0 Then
Worksheets("sheet2").Cells(FP, 8).ClearContents
End If
Next
'총액 구하기2
Worksheets("sheet2").Cells(12 + 14 * (E - 9), 8).Value = Sum
'받으실 분
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 2).Value = Worksheets("0618").Cells(E, 3).Value
'주소
Worksheets("sheet2").Cells(3 + 14 * (E - 9), 5).Value = Worksheets("0618").Cells(E, 2).Value
'서식 복사'
Worksheets("sheet3").Range("A1:H13").Copy
Worksheets("sheet2").Range("A" & 15 + 14 * (E - 9)).PasteSpecial
Erase V, P, N
If Index = 0 Then Exit Sub
Next
Debug.Print Join(V, vbLf)
End Sub
I used "Erase V, P, N" at the last part of this code to make V,P,N into empty arrays, because the code has to repeat from E = 9 to E = Column number and as it repeats, these arrays has to be continuously empty at the last part of the code, to use them again at the next repeat.
But when I run this code, these arrays doesn't become empty. The values are accumulated more and more as the code repeats. I think maybe the code "Erase V, P, N" is the wrong code.
So Could anybody please tell me how to make the the arrays empty?
I'm trying to get my VBA code to output a graph in excel based on an inputted range that was selected using a user defined function from multiple cells. I've passed the data to the sub as a range but it ends up assuming that the range is two data sets rather than one data set with x and y values. The data set is selected from excel into a function that is being written separately which then calls the sub.
Sub CreateChart(ByRef r As Range)
Dim cht As Object
Set cht = ActiveSheet.Shapes.AddChart2
cht.Chart.SetSourceData Source:=r
cht.Chart.ChartType = xlXYScatterLines
End Sub
I called the sub through
Call CreateChart(r)
with r being a two column range of data that was selected from excel.
Public Function cubic(ByVal r As Range, x As Double, Optional check As Integer = 1) As Double
The overall function code is here as well
Public Function cubic(ByVal r As Range, x As Double, Optional check As Integer = 1) As Double
Dim data() As Double
Dim check1 As Integer
Dim Smatrix() As Double
Dim Tmatrix() As Double
Dim Xmatrix() As Double
Dim Amatrix() As Double
Dim Hmatrix() As Double
Dim m As Integer
Dim i As Integer
m = r.Rows.Count
ReDim data(1 To m, 2)
ReDim Smatrix(1 To m, 1 To m)
ReDim Tmatrix(1 To m, 4)
ReDim Xmatrix(1 To m)
ReDim Amatrix(1 To m - 1, 1 To 4)
ReDim Hmatrix(1 To m)
check1 = Test(check)
For i = 1 To m
data(i, 1) = r(i, 1).Value
data(i, 2) = r(i, 2).Value
Next i
Smatrix(1, 1) = 1
Smatrix(m, m) = 1
For i = 1 To m - 1
Hmatrix(i) = data(i + 1, 1) - data(i, 1)
Next i
If check1 = 2 Then
Smatrix(1, 2) = -1
Smatrix(m, m - 1) = -1
End If
For i = 2 To m - 1
Smatrix(i, i - 1) = Hmatrix(i - 1)
Smatrix(i, i + 1) = Hmatrix(i)
Smatrix(i, i) = 2 * (Hmatrix(i - 1) + Hmatrix(i))
Next i
For i = 2 To m - 1
Tmatrix(i, 4) = 6 * ((data(i + 1, 2) - data(i, 2)) / Hmatrix(i) - (data(i, 2) - data(i - 1, 2)) / Hmatrix(i - 1))
Next i
For i = 1 To m
If i <> 1 Then
Tmatrix(i, 1) = Smatrix(i, i - 1)
End If
Tmatrix(i, 2) = Smatrix(i, i)
If i <> m Then
Tmatrix(i, 3) = Smatrix(i, i + 1)
End If
Next i
For i = 2 To m
Tmatrix(i, 1) = Tmatrix(i, 1) / Tmatrix(i - 1, 2)
Tmatrix(i, 2) = Tmatrix(i, 2) - Tmatrix(i, 1) * Tmatrix(i - 1, 3)
Tmatrix(i, 4) = Tmatrix(i, 4) - Tmatrix(i, 1) * Tmatrix(i - 1, 4)
Next i
Xmatrix(m) = Tmatrix(m, 4) / Tmatrix(m, 2)
For i = m - 1 To 1 Step -1
Xmatrix(i) = (Tmatrix(i, 4) - Tmatrix(i, 3) * Xmatrix(i + 1)) / Tmatrix(i, 2)
Next i
For i = 1 To m - 1
Amatrix(i, 1) = (Xmatrix(i + 1) - Xmatrix(i)) / 6 * Hmatrix(i)
Amatrix(i, 2) = Xmatrix(i) / 2
Amatrix(i, 3) = (data(i + 1, 2) - data(i, 2)) / Hmatrix(i) - Hmatrix(i) * Xmatrix(i) / 2 - Hmatrix(i) * (Xmatrix(i + 1) - Xmatrix(i)) / 6
Amatrix(i, 4) = data(i, 2)
Next i
If x < data(1, 1) Or x > data(m, 1) Then
Call Check2(x)
If x < data(1, 1) Then
cubic = Amatrix(1, 1) * (x - data(1, 1)) ^ 3 + Amatrix(1, 2) * (x - data(1, 1)) ^ 2 + Amatrix(1, 3) * (x - data(1, 1)) + Amatrix(1, 4)
ElseIf x > data(m, 1) Then
cubic = Amatrix(m - 1, 1) * (x - data(m - 1, 1)) ^ 3 + Amatrix(m - 1, 2) * (x - data(m - 1, 1)) ^ 2 + Amatrix(m - 1, 3) * (x - data(m - 1, 1)) + Amatrix(m - 1, 4)
End If
ElseIf x = data(m, 1) Then
cubic = data(m, 2)
Else
For i = 1 To m - 1
If data(i, 1) < x And x < data(i + 1, 1) Then
cubic = Amatrix(i, 1) * (x - data(i, 1)) ^ 3 + Amatrix(i, 2) * (x - data(i, 1)) ^ 2 + Amatrix(i, 3) * (x - data(i, 1)) + Amatrix(i, 4)
ElseIf x = data(i, 1) Then
cubic = data(i, 2)
End If
Next i
End If
Call CreateChart(r)
End Function
As well as the subroutine and function called within the function that haven't been posted
Public Function Test(check As Integer) As Integer
Dim Response As Integer
If check = 1 Then
Response = MsgBox("Boundary Condition 1 selected, is this correct (select No for boundary condition 2)?", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 1
Else
Test = 2
End If
ElseIf check = 2 Then
Response = MsgBox("Boundary Condition 2 selected, is this correct (select No for boundary condition 1)?", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 2
Else
Test = 1
End If
Else
Response = MsgBox("Incorrect Boundary Condition, select Yes for condition 1 and No for condition 2", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 1
Else
Test = 2
End If
End If
End Function
Public Sub Check2(x)
MsgBox ("Value given is outside data range, answer may not be correct, extrapolating from calculated polynomial")
End Sub
Try
Sub CreateChart(ByRef r As Range)
Dim cht As Object
Set cht = ActiveSheet.Shapes.AddChart2(XlChartType:=xlXYScatterSmooth)
cht.Chart.SetSourceData Source:=r
End Sub
I'm trying to use this VBA code to price American or European options... But I run into
"Compile error: Can't find project or library"
with dt =T/n highlighted.
I can't determine what is wrong. Hoping someone smarter than I can point out what I'm overlooking.
Function CRRTree(Spot, K, T, rf, vol, n, OpType As String, ExType As String)
dt = T / n
u = Exp(vol * (dt ^ 0.5))
d = 1 / u
p = (Exp(rf * dt) - d) / (u - d)
' Tree for stock price
Dim S() As Double
ReDim S(n + 1, n + 1) As Double
For i = 1 To n + 1
For j = i To n + 1
S(i, j) = Spot * u ^ (j - i) * d ^ (i - 1)
Next j
Next i
' Calculate Terminal Price for Calls and Puts
Dim Op() As Double
ReDim Op(n + 1, n + 1) As Double
For i = 1 To n + 1
Select Case OpType
Case "C": Op(i, n + 1) = Application.Max(S(i, n + 1) - K, 0)
Case "P": Op(i, n + 1) = Application.Max(K - S(i, n + 1), 0)
End Select
Next i
' Calculate Remaining entries for Calls and Puts
For j = n To 1 Step -1
For i = 1 To j
Select Case ExType
Case "A":
If OpType = "C" Then
Op(i, j) = Application.Max(S(i, j) - K, Exp(-rf * dt) * (p * Op(i, j + 1) + (1 - p) * Op(i + 1, j + 1)))
ElseIf OpType = "P" Then
Op(i, j) = Application.Max(K - S(i, j), Exp(-rf * dt) * (p * Op(i, j + 1) + (1 - p) * Op(i + 1, j + 1)))
End If
Case "E":
Op(i, j) = Exp(-rf * dt) * (p * Op(i, j + 1) + (1 - p) * Op(i + 1, j + 1))
End Select
Next i
Next j
CRRTree = Op(1, 1)
End Function
I am working on a schedule determining who is going to cook and who is doing dishes for a trip with some friends.
I have the names for the participants listed in column "A" and using CountIf to see how many times the specific person appears on the schedule to make it fair for everyone. The code picks 2 random persons for cooking and 2 for dishes making sure they are not the same. Then putting those names into the schedule I have defined in the worksheet.
My current code looks like this and is working so far as intended.
Private Sub cookplan()
last_row = Range("A1").End(xlDown).Row
Dim awesome()
Dim index1 As Integer
Dim index2 As Integer
Dim cook1 As String
Dim cook2 As String
Dim dish1 As String
Dim dish2 As String
ReDim awesome(last_row - 1, 0)
For i = 0 To last_row - 1
awesome(i, 0) = Range("A" & i + 1)
Next
For i = 1 To 5
index1 = Int((last_row - 1 - 0 + 1) * Rnd + 0)
cook1 = awesome(index1, 0)
Cells(i * 2, 6).Value = cook1
Do
index2 = Int((last_row - 1 - 0 + 1) * Rnd + 0)
cook2 = awesome(index2, 0)
Cells(i * 2, 7).Value = cook2
Loop While cook2 = cook1
Do
index1 = Int((last_row - 1 - 0 + 1) * Rnd + 0)
dish1 = awesome(index1, 0)
Loop While dish1 = cook1 Or dish1 = cook2
Do
index2 = Int((last_row - 1 - 0 + 1) * Rnd + 0)
dish2 = awesome(index2, 0)
Loop While dish2 = cook1 Or dish2 = cook2 Or dish2 = dish1
Cells(i * 2, 8).Value = dish1
Cells(i * 2, 9).Value = dish2
Next
End Sub
Is there a way to make a name appear a maximum and minimum number of times? As it is now, 2 or 3 times seems to be a fair number when I run the code and look at the CountIf results.
UPDATE
I have now gotten the code to work as intended. Each person needs at least one cooking and dishes duty, so the coding looks like this now. I know it is not that pretty, but it gets the job done :)
Private Sub cookplan()
last_row = Range("A1").End(xlDown).Row
Dim awesome()
Dim index As Integer
Dim cook1 As String
Dim cook2 As String
Dim dish1 As String
Dim dish2 As String
Dim counter1 As Integer
Dim counter2 As Integer
ReDim awesome(last_row - 2, 0)
For i = 0 To last_row - 2
awesome(i, 0) = Range("A" & i + 2)
Next
Do
For i = 1 To 5
Do
index = Int((last_row - 2 - 0 + 1) * Rnd + 0)
cook1 = awesome(index, 0)
Cells(i * 2, 6).Value = cook1
Loop While Cells(index + 2, 2) > 2 Or Cells(index + 2, 3) > 2
Do
index = Int((last_row - 2 - 0 + 1) * Rnd + 0)
cook2 = awesome(index, 0)
Cells(i * 2, 7).Value = cook2
Loop While Cells(index + 2, 2) > 2 Or Cells(index + 2, 3) > 2 Or cook2 = cook1
Do
index = Int((last_row - 2 - 0 + 1) * Rnd + 0)
dish1 = awesome(index, 0)
Cells(i * 2, 8).Value = dish1
Loop While Cells(index + 2, 2) > 2 Or Cells(index + 2, 3) > 2 Or dish1 = cook1 Or dish1 = cook2
Do
index = Int((last_row - 2 - 0 + 1) * Rnd + 0)
dish2 = awesome(index, 0)
Cells(i * 2, 9).Value = dish2
Loop While Cells(index + 2, 2) > 2 Or Cells(index + 2, 3) > 2 Or dish2 = cook1 Or dish2 = cook2 Or dish2 = dish1
Next
counter1 = 0
counter2 = 0
For i = 2 To last_row
If Cells(i, 2).Value = 0 Then
counter1 = counter1 + 1
End If
If Cells(i, 3).Value = 0 Then
counter2 = counter2 + 1
End If
Next
Loop While counter1 > 0 Or counter2 > 0
End Sub
You could put your random generation in a separte function, that checks the worksheet, if the selected name has already been used twice. If false, it returns the name. If true, the function calls itself (hence generates a new name), until a name is found, which fits your criteria.
Update Please note, that this is some kind of pseudo-code, which is not intended to work
In your Sub cookplan, you add the name of the Function everytime you need a new name
cook1 = GetName()
After the End Sub you insert a new Funktion called GetName (or whatever you want)
Function GetName() As String
'Determine your name here
If CountForDeterminedName > 2 Then
'Call Function Again to find another Name
GetName = GetName()
Else
GetName = DeterminedName
End If
End Function