I'm trying to sum the results of a loop. So far the code takes values from WsIn by row, runs them through a model and gives results in WsOut. The code takes the values in row 1 and gives results based on these and goes back and does it for row 2 and so on. The results are overwritten by the new results as the code loops. But I want it to add the results given by row 1 to the results given by row 2 added to row 3, etc. The results are ranges C5:C33 and D5:D33 in WsOut. I think the code for this would be something like the loop I put at the bottom but I'm not sure how to make this. Any ideas on what I should do?
Sub TEST1()
Dim WsIn As Worksheet ' Input
Dim WsT As Worksheet ' Taken
Dim WsOut As Worksheet ' Output
Dim WsMod As Worksheet ' Model
Dim Arr As Variant
Dim Rl As Long
Dim R As Long
Dim Rout As Long ' WsOut row
Dim Cmod As Long ' WsMod column
Dim XXX As Integer
Dim YYY As Integer
Dim WWW As Integer
Set WsT = Sheets("Inputs Taken")
Set WsIn = Sheets("Input Values")
Set WsOut = Sheets("Output")
Set WsMod = Sheets("Model")
Application.ScreenUpdating = False
Rl = WsIn.Cells(WsIn.Rows.Count, "B").End(xlUp).Row
For R = 2 To Rl
'Pasting Input Values into Inputs Taken
With WsIn
Arr = .Range(.Cells(R, 1), .Cells(R, 4)).Value
WsT.Cells(5, "D").Resize(UBound(Arr, 2), UBound(Arr)) _
.Value = Application.Transpose(Arr)
Arr = .Range(.Cells(R, 5), .Cells(R, 6)).Value
WsT.Cells(11, "C").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
Arr = .Range(.Cells(R, 7), .Cells(R, 8)).Value
WsT.Cells(16, "C").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
Arr = .Range(.Cells(R, 9), .Cells(R, 14)).Value
WsT.Cells(9, "G").Resize(UBound(Arr, 2), UBound(Arr)) _
.Value = Application.Transpose(Arr)
Arr = .Range(.Cells(R, 15), .Cells(R, 16)).Value
WsT.Cells(20, "C").Resize(UBound(Arr, 2), UBound(Arr)) _
.Value = Application.Transpose(Arr)
Arr = .Range(.Cells(R, 17), .Cells(R, 18)).Value
WsT.Cells(20, "D").Resize(UBound(Arr, 2), UBound(Arr)) _
.Value = Application.Transpose(Arr)
End With
'Setting Opening PUP to 100% and refreshing
WsT.Cells(5, "G").Value = 1
Application.CalculateFull
'Calculating No RPs
With WsOut
Cmod = 62 ' BJ:BP
For Rout = 7 To 13
.Cells(Rout, "C").Value = SumProduct(Cmod, WsMod)
Cmod = Cmod + 1
Next Rout
.Cells(14, 3).Value = Application.Sum(.Range("C11:C13"))
Cmod = 71 ' BS:CB
For Rout = 17 To 26
.Cells(Rout, "C").Value = SumProduct(Cmod, WsMod, True)
Cmod = Cmod + 1
Next Rout
.Cells(5, 3).Value = WsMod.Cells(6, "BL").Value _
- WsMod.Cells(6, "BS").Value _
- WsMod.Cells(6, "BT").Value
.Cells(15, 3).Value = Application.Sum(.Range("C5,C7:C10, C14"))
.Cells(27, 3).Value = Application.Sum(.Range("C17:C26"))
.Cells(29, 3).Value = Application.Sum(WsMod.Range("AN6:AN365"))
.Cells(30, 3).Value = Application.Sum(WsMod.Range("AP6:AP365"))
.Cells(31, 3).Value = WsOut.Cells(2, 3).Value
.Cells(33, 3).Value = WsOut.Cells(15, 3) - Application.Sum(.Range("C29:C31, C27"))
End With
'Changing PUP rate
WsT.Cells(5, "G").Value = 0
Application.CalculateFull
'Calculate with RP
With WsOut
Cmod = 62 ' BJ:BP
For Rout = 7 To 13
.Cells(Rout, "D").Value = SumProduct(Cmod, WsMod)
Cmod = Cmod + 1
Next Rout
.Cells(14, 4).Value = Application.Sum(.Range("D11:D13"))
Cmod = 71 ' BS:CB
For Rout = 17 To 26
.Cells(Rout, "D").Value = SumProduct(Cmod, WsMod, True)
Cmod = Cmod + 1
Next Rout
.Cells(5, 4).Value = WsMod.Cells(6, "BL").Value _
- WsMod.Cells(6, "BS").Value _
- WsMod.Cells(6, "BT").Value
.Cells(15, 4).Value = Application.Sum(.Range("D5,D7:D10, D14"))
.Cells(27, 4).Value = Application.Sum(.Range("D17:D26"))
.Cells(29, 4).Value = Application.Sum(WsMod.Range("AN6:AN365"))
.Cells(30, 4).Value = Application.Sum(WsMod.Range("AP6:AP365"))
.Cells(31, 4).Value = WsOut.Cells(2, 3).Value
.Cells(33, 4).Value = WsOut.Cells(15, 4) - Application.Sum(.Range("D29:D31, D27"))
End With
'Exit For
Next R
Application.ScreenUpdating = True
For XXX = 5 To 33
For YYY = 6 To 7
For WWW = 3 To 4
WsOut.Cells(XXX, YYY).Value = WsOut.Cells(XXX, WWW).Value
Next WWW
Next YYY
Next XXX
End Sub
Private Function SumProduct(ByVal Cmod As Long, _
WsMod As Worksheet, _
Optional ByVal Negative As Boolean) As Double
Dim AuxRng As Range
With WsMod
Set AuxRng = .Range(.Cells(6, Cmod), .Cells(365, Cmod))
SumProduct = Application.SumProduct( _
.Range("AD6:AD365"), _
.Range("AG6:AG365"), _
AuxRng)
End With
End Function
Have an integer add to itself at the end of each loop. totNum = totNum + this rows count. At the end total sum will = totNum.
Related
I need to generate a sheet of values out of a database between dates that the user selects. The date is in column 2 of the database, but I need the whole row for every date in this range. I got some advice to use a For Each instead to more easily use the SpecialCells(xlCellTypeVisible). While I am no longer getting any errors I also get no data in my product worksheet. Could someone tell me why I am not returning data?
Sub Generate()
Dim g As Integer
Dim h As Integer
Dim datemin As String
Dim datemax As String
datemin = CDbl(CDate(Sheets("start").Cells(15, 8)))
datemax = CDbl(CDate(Sheets("start").Cells(15, 9)))
Worksheets("Database").Range("A1").AutoFilter Field:=10, Criteria1:=">=" & datemin, _
Operator:=xlAnd, Criteria2:="<=" & datemax
g = 0
For Each Row In Worksheets("database").Range("A1")
g = g + 1
If Cells(g, 1).SpecialCells(xlCellTypeVisible) = True And Cells(g, 1) <> "" Then
Sheets("product").Activate
Dim NextRow As Long
NextRow = Application.WorksheetFunction.CountA(Range("A:A")) + 10
'fill KPI
Cells(NextRow, 1) = Format(Sheets("database").Cells(g, 1), "mm/dd/yyyy") 'Date1
Cells(NextRow, 2) = Format(Sheets("database").Cells(g, 2), "mm/dd/yyyy") 'Date2
Cells(NextRow, 3) = Sheets("database").Cells(g, 3) 'value1
Cells(NextRow, 4) = Sheets("database").Cells(g, 4) 'value2
Cells(NextRow, 6) = Sheets("database").Cells(g, 5) 'value3
Cells(NextRow, 9) = Sheets("database").Cells(g, 8) 'comment
Cells(NextRow, 13) = Sheets("database").Cells(g, 6) 'person
Else
Exit For
End If
Next
End Sub
You are only 'looping' through one cell - A1.
If you want to use a loop for this try looping through all the rows on the database and checking if they are visible or not.
If they are visible then copy the relevant data to the other sheet.
Sub Generate()
Dim rngDst As Range
Dim rngSrc As Range
Dim datemin As String
Dim datemax As String
Dim g As Integer
Dim h As Integer
datemin = CDbl(CDate(Sheets("start").Cells(15, 8)))
datemax = CDbl(CDate(Sheets("start").Cells(15, 9)))
Worksheets("Database").Range("A1").AutoFilter Field:=10, Criteria1:=">=" & datemin, _
Operator:=xlAnd, Criteria2:="<=" & datemax
Set rngSrc = Worksheets("Database").Range("A2")
Set rngDst = Worksheets("Product").Range("A11")
Do
If Not rngSrc.EntireRow.Hidden And rngSrc.Value <> "" Then
'fill KPI
rngDst.Value = Format(rngSrc.Value, "mm/dd/yyyy") 'Date1
rngDst.Offset(, 1).Value = Format(rngSrc.Offset(, 1).Value, "mm/dd/yyyy") 'Date2
rngDst.Offset(, 2).Value = rngSrc.Offset(, 2).Value 'value1
rngDst.Offset(, 3).Value = rngSrc.Offset(, 3).Value 'value2
rngDst.Offset(, 5).Value = rngSrc.Offset(, 4).Value 'value3
rngDst.Offset(, 8).Value = rngSrc.Offset(, 7).Value 'comment
rngDst.Offset(, 12).Value = rngSrc.Offset(, 5).Value 'person
Set rngDst = rngDst.Offset(1, 0)
End If
Set rngSrc = rngSrc.Offset(1, 0)
Loop Until rngSrc = ""
End Sub
first post and also new to VBA so I apologize for anything that is unclear. I have created a code to generate a daily printout of employees, equipment, and subcontractors. The loop is looking for "S" (subcontractors) each day. There is only one day where "S" is present and there are 4 on that day. The issue is that the loop begins correctly and populates the correct information when it finds "S" and lists the 4 separate subcontractors, but every day before and after that it continues to list the first subcontractor even though no "S" is found on those dates. How can I get it to clear that entry if no other "S" are found? I hope that makes sense and I have included the code. Thank you!
Screesnhot
Sub WriteReport_Click()
Dim EachName(1 To 5000) As Variant
Dim NameHours(1 To 5000) As Variant
Dim NamePhase(1 To 5000) As Variant
Dim EquipHours(1 To 5000) As Variant
Dim EquipPhase(1 To 5000) As Variant
Dim EachDate(1 To 5000) As Date
Dim EachEquip(1 To 5000) As Variant
Dim EachSub(1 To 5000) As Variant
Dim SubAmount(1 To 5000) As Variant
Dim i As Long 'loop through records
Dim k As Integer 'count employees
Dim h As Integer 'count equipment
Dim t As Integer 'count subcontractor
Dim m As Integer 'count dates
Dim j As Integer
Dim x As Integer
Dim lr, s, p, StartBorder, EndBorder As Integer 'keeps row counts Start & Finish
Dim TestString As String
Sheets("Data").Activate
k = 1 'counts EachName
h = 1 'counts EachEquip
t = 1 'counts EachSub
m = 1 'counts dates
lr = 1
p = 0
For i = 1 To Rows.Count
If Cells(i, 3) = "L" Then
EachName(1) = Cells(i, 11)
Exit For
End If
Next i
For i = 1 To Rows.Count
If Cells(i, 3) = "E" Then
EachEquip(1) = Cells(i, 12)
Exit For
End If
Next i
For i = 1 To Rows.Count
If Cells(i, 3) = "S" Then
EachSub(1) = Cells(i, 9)
Exit For
End If
Next i
NameHours(1) = 0
EquipHours(1) = 0
EachDate(1) = Cells(1, 1)
SubAmount(1) = 0
Dim LastRow As Integer
For i = 1 To 5000
If EachDate(m) <> Cells(i, 1) Then
m = m + 1 'setting array for next new date
EachDate(m) = Cells(i, 1)
lr = Sheets("Report").Cells(Rows.Count, 1).End(xlUp).Row + 1
StartBorder = lr
Sheets("Report").Cells(lr, 1) = Format(EachDate(m - 1), "mm/dd/yy") 'prints date
Sheets("Report").Cells(lr, 1).Interior.ColorIndex = 4 'highlights date
For j = 1 To k 'prints employees, hours and phase
Sheets("Report").Cells((lr + j), 1) = EachName(j)
Sheets("Report").Cells((lr + j), 2) = NameHours(j)
Sheets("Report").Cells((lr + j), 4) = NamePhase(j)
Sheets("Report").Cells((lr + j), 5).Formula = _
"=IF(A" & CStr(lr + j) & "<>"""",VLOOKUP(A" & CStr(lr + j) & ",Employee,2,FALSE),"""")"
Next j
k = 1
lr = Sheets("Report").Cells(Rows.Count, 1).End(xlUp).Row + 1
For s = i To 5000 'getting first employee for next date
If Cells(s, 1) = EachDate(m) And Cells(s, 3) = "L" Then
EachName(1) = Cells(s, 11)
Exit For
End If
Next s
Erase NameHours 'clearing manhours for next date
For j = 1 To h
Sheets("Report").Cells((lr + j), 1) = Trim(EachEquip(j))
Sheets("Report").Cells((lr + j), 3) = EquipHours(j)
Sheets("Report").Cells((lr + j), 4) = EquipPhase(j)
Sheets("Report").Cells((lr + j), 5).Formula = _
"=LEFT(IF(A" & CStr(lr + j) & "<>"""",VLOOKUP(A" & CStr(lr + j) & ",EquipList,2,FALSE),""""),20)"
Next j
h = 1
For s = i To 5000 'getting first equipment for next date
If Cells(s, 1) = EachDate(m) And Cells(s, 3) = "E" Then
EachEquip(1) = Cells(s, 12)
Exit For
End If
Next s
Erase EquipHours ' clearing equipment hours for next date
lr = Sheets("Report").Cells(Rows.Count, 1).End(xlUp).Row + 1
For x = 1 To t
Sheets("Report").Cells((lr + x), 1) = EachSub(x)
Sheets("Report").Cells((lr + x), 3) = SubAmount(x)
Next x
For x = i To 5000 'getting subcontractor for next date
If Cells(x, 1) = EachSub(m) And Cells(x, 3) = "S" Then
EachSub(1) = " "
Exit For
End If
Next x
EndBorder = lr + x
t = 1
With Worksheets("Report") 'draws borders
.Range(.Cells(StartBorder, 1), .Cells(EndBorder, 8)).BorderAround ColorIndex:=1, Weight:=xlThick
End With
End If
Select Case Cells(i, 3).Value
Case "L"
If Cells(i, 11) = EachName(k) Then
If Cells(i, 7) = 0 Then
p = p + 1 'adding up per diem
End If
NamePhase(k) = Cells(i, 2)
NameHours(k) = NameHours(k) + Cells(i, 7)
Else
k = k + 1
EachName(k) = Cells(i, 11)
NamePhase(k) = Cells(i, 2)
If Cells(i, 7) = 0 Then
p = p + 1
End If
NameHours(k) = NameHours(k) + Cells(i, 7)
End If
Case "E"
If Cells(i, 12) = EachEquip(h) Then
EquipPhase(h) = Cells(i, 2)
EquipHours(h) = EquipHours(h) + Cells(i, 7)
Else
h = h + 1
EachEquip(h) = Cells(i, 12)
EquipPhase(h) = Cells(i, 2)
EquipHours(h) = EquipHours(h) + Cells(i, 7)
End If
Case "S"
If Cells(i, 9) = EachSub(t) Then
EachSub(t) = Cells(i, 9)
SubAmount(t) = SubAmount(t) + Cells(i, 8)
Else
t = t + 1
EachSub(t) = Cells(i, 9)
SubAmount(t) = SubAmount(t) + Cells(i, 8)
End If
End Select
Next i
MsgBox "Report Completed !!!"
End Sub
You will find your code easier to debug/maintain if you separate the collection of the data and the report generation into 2 discrete steps, preferably in subroutines. For example
Option Explicit
Dim EachName(0 To 5000, 1 To 3) As Variant '1=name 2=hours 3=phase
Dim EachEquip(0 To 5000, 1 To 3) As Variant '1=name 2=hrs 3=phase
Dim EachSub(0 To 5000, 1 To 2) As Variant ' 1=name 2=amount
Dim k As Long 'count employees
Dim h As Long 'count equipment
Dim t As Long 'count subcontractor
Sub WriteReport_Click()
' specify book and sheets to process
Dim wb As Workbook, wsData As Worksheet, wsRep As Worksheet
Set wb = ThisWorkbook ' or ActiveWorkBook
' determine extent of data
Dim LastRow As Long, iRow As Long
Set wsData = wb.Sheets("Data")
LastRow = wsData.Cells(Rows.Count, 1).End(xlUp).Row
' clear report sheet
Set wsRep = wb.Sheets("Report")
wsRep.Cells.Clear
' scan data for first date
Dim RepDate As Date
RepDate = wsData.Cells(1, 1)
Call GetData(RepDate, wsData)
' scan data for more dates
For iRow = 1 To LastRow
If wsData.Cells(iRow, 1) <> RepDate Then
' report existing date
Call ReportData(RepDate, wsRep)
' get data for new date
RepDate = wsData.Cells(iRow, 1)
Call GetData(RepDate, wsData)
End If
Next
' report last date
Call ReportData(RepDate, wsRep)
'end
wsRep.Columns("A:E").AutoFit
MsgBox "Report Completed", vbInformation, LastRow & " rows scanned"
End Sub
Sub ReportData(d As Date, ws As Worksheet)
Debug.Print "ReportData", d
Dim lr As Long, StartBorder As Long, EndBorder As Long, j As Long
lr = ws.Cells(Rows.Count, 1).End(xlUp).Row + 1
StartBorder = lr
ws.Cells(lr, 1) = Format(d, "mm/dd/yy") 'prints date
ws.Cells(lr, 1).Interior.ColorIndex = 4 'highlights date
'prints employees, hours and phase
For j = 1 To k
ws.Cells((lr + j), 1) = EachName(j, 1) 'empoyee name
ws.Cells((lr + j), 2) = EachName(j, 2) 'hrs
ws.Cells((lr + j), 4) = EachName(j, 3) 'phase
ws.Cells((lr + j), 5).Formula = _
"=IF(A" & CStr(lr + j) & "<>"""",VLOOKUP(A" & CStr(lr + j) & ",Employee,2,FALSE),"""")"
Next j
' report equipment
lr = ws.Cells(Rows.Count, 1).End(xlUp).Row + 1
For j = 1 To h
ws.Cells((lr + j), 1) = EachEquip(j, 1) 'equip name
ws.Cells((lr + j), 3) = EachEquip(j, 2) 'hours
ws.Cells((lr + j), 4) = EachEquip(j, 3) 'phase
ws.Cells((lr + j), 5).Formula = _
"=LEFT(IF(A" & CStr(lr + j) & "<>"""",VLOOKUP(A" & CStr(lr + j) & ",EquipList,2,FALSE),""""),20)"
Next j
' report sub contractors
lr = ws.Cells(Rows.Count, 1).End(xlUp).Row + 1
For j = 1 To t
ws.Cells((lr + j), 1) = EachSub(j, 1) 'sub name
ws.Cells((lr + j), 3) = EachSub(j, 2) 'amount
Next j
' draws borders
EndBorder = ws.Cells(Rows.Count, 1).End(xlUp).Row
ws.Range(ws.Cells(StartBorder, 1), ws.Cells(EndBorder, 8)) _
.BorderAround ColorIndex:=1, Weight:=xlThick
End Sub
Sub GetData(d As Date, ws As Worksheet)
Debug.Print "GetData", d
Dim LastRow As Long, i As Long
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
' clear global arrays
Erase EachName
Erase EachEquip
Erase EachSub
k = 0: h = 0: t = 0
For i = 1 To LastRow
If ws.Cells(i, 1) = d Then
Select Case ws.Cells(i, 3)
Case "L" ' Employee
If ws.Cells(i, 11) <> EachName(k, 1) Then
k = k + 1
End If
EachName(k, 1) = ws.Cells(i, 11)
EachName(k, 2) = ws.Cells(i, 7) + EachName(k, 2) ' hours
EachName(k, 3) = ws.Cells(i, 2) ' phase
Case "E" ' Equipment
If ws.Cells(i, 12) <> EachEquip(h, 1) Then
h = h + 1
End If
EachEquip(h, 1) = Trim(ws.Cells(i, 12)) ' equip name
EachEquip(h, 2) = ws.Cells(i, 7) + EachEquip(h, 2) ' hours
EachEquip(h, 3) = ws.Cells(i, 2) ' phase
Case "S" ' Subcontractor
If ws.Cells(i, 9) <> EachSub(t, 1) Then
t = t + 1
End If
EachSub(t, 1) = ws.Cells(i, 9) ' sub name
EachSub(t, 2) = ws.Cells(i, 8) + EachSub(t, 2) ' amount
Case Else
MsgBox "Unknown code at row " & i, vbExclamation
End Select
End If
Next
End Sub
So how do i put this i am a vba rookie and i have been trying to make an excel file and the purpose is that it should be an inventory of all items one sheet is for putting items in and other is for giving them away. But that is not the problem, the thing is i wanted to have a page called "databaseinventory" where all products that are taken out are writen down but my value is doing strange. (look at the image)
So this is the input screen and if i type this
this is the output on a different sheet but i don't want it to be 0
I noticed if i change the input and add 3 rows it works but that prevents me of typing more then one product
this is the output that i want to have and i really don't know what is wrong with the code
Sub Btn_Clickweggegeven()
Dim x As Long
Dim Givenaway As Worksheet
Dim Inventory As Worksheet
Dim productn As String
Dim erow As Long
Dim rng As Range
Dim rownumber As Long
Dim row As Long
Dim wsData As Worksheet
Dim wsIn As Worksheet
Dim nextRow As Long
Dim BtnText As String
Dim BtnNum As Long
Dim strName As String
x = 2
Do While Cells(x, 1) <> ""
' go through each item on list
productn = Cells(x, 1)
' if item is not new then add quanity to total Inventory
With Worksheets("Inventory").Range("A:A")
Set rng = .Find(What:=productn, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
'if item is new add item to the bottom of Inventory list
If rng Is Nothing Then
erow = Worksheets("Inventory").Cells(1, 1).CurrentRegion.Rows.Count + 1
Worksheets("Inventory").Cells(erow, 1) = Worksheets("Givenaway").Cells(x, 1)
Worksheets("Inventory").Cells(erow, 2) = Worksheets("Givenaway").Cells(x, 2)
Worksheets("Inventory").Cells(erow, 3) = Worksheets("Givenaway").Cells(x, 3)
Worksheets("Inventory").Cells(erow, 4) = Worksheets("Givenaway").Cells(x, 4)
GoTo ende
Else
rownumber = rng.row
End If
End With
Worksheets("Inventory").Cells(rownumber, 2).Value = Worksheets("Inventory").Cells(rownumber, 2).Value _
- Worksheets("Givenaway").Cells(x, 2).Value
Worksheets("Inventory").Cells(rownumber, 4).Value = Worksheets("Inventory").Cells(rownumber, 4).Value _
+ Worksheets("Givenaway").Cells(x, 2).Value
ende:
x = x + 1
Loop
'after complete delete items from Givenaway list
Worksheets("Givenaway").Select
row = 2
Do While Cells(row, 1) <> ""
Range(Cells(row, 1), Cells(row, 3)).Select
Selection.Delete
Loop
Set wsIn = Worksheets("Givenaway")
Set wsData = Worksheets("Databaseinventory")
With wsData
nextRow = .Cells(.Rows.Count, "A") _
.End(xlUp).Offset(1, 0).row
End With
With wsData
With .Cells(nextRow, 1)
.Value = Now
.NumberFormat = "mm/dd/yyyy hh:mm:ss"
End With
.Cells(nextRow, 2).Value = productn
.Cells(nextRow, 3).Value = Worksheets("Databaseinventory").Cells(rownumber, 3).Value _
+ Worksheets("Givenaway").Cells(x, 2).Value
End With
End Sub
This code is deleting the value
Worksheets("Givenaway").Select
row = 2
Do While Cells(row, 1) <> ""
Range(Cells(row, 1), Cells(row, 3)).Select
Selection.Delete
Loop
before this line copies it to Databaseinventory
Cells(nextRow, 3).Value = Worksheets("Databaseinventory").Cells(rownumber, 3).Value _
+ Worksheets("Givenaway").Cells(x, 2).Value
It appears to work if you have 3 rows is because on exit from the Do While Cells(x, 1) <> "" loop the value of x will be 3. After deleting the first record then Worksheets("Givenaway").Cells(x, 2).Value will be the value for the third record.
The database update routine also need to be within the loop
Option Explicit
Sub Btn_Clickweggegeven()
Dim wb As Workbook, rng As Range
Dim wsInv As Worksheet, wsGiven As Worksheet, wsData As Worksheet
Dim iRow As Long, iDataRow As Long, iInvRow As Long
Dim sProduct As String, nValue As Single
Set wb = ThisWorkbook
Set wsGiven = wb.Sheets("GivenAway")
Set wsInv = wb.Sheets("Inventory")
Set wsData = wb.Sheets("Databaseinventory")
iDataRow = wsData.Cells(Rows.Count, 1).End(xlUp).row
iRow = 2
With wsGiven
Do While .Cells(iRow, 1) <> ""
sProduct = .Cells(iRow, 1)
nValue = .Cells(iRow, 2)
' if item is not new then add quanity to total Inventory
With wsInv.Range("A:A")
Set rng = .Find(What:=sProduct, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
End With
If rng Is Nothing Then
iInvRow = wsInv.Cells(Rows.Count, 1).End(xlUp).row + 1
wsInv.Cells(iInvRow, 1).Resize(1, 4).Value = .Cells(iRow, 1).Resize(1, 4).Value
Else
iInvRow = rng.row
wsInv.Cells(iInvRow, 2).Value = wsInv.Cells(iInvRow, 2).Value - nValue
wsInv.Cells(iInvRow, 4).Value = wsInv.Cells(iInvRow, 4).Value + nValue
End If
' write to database
iDataRow = iDataRow + 1
With wsData.Cells(iDataRow, 1)
.Value = Now
.NumberFormat = "mm/dd/yyyy hh:mm:ss"
.Offset(0, 1) = sProduct ' col B
.Offset(0, 2) = wsInv.Cells(iInvRow, 3).Value + nValue ' col C ??
End With
iRow = iRow + 1
Loop
End With
'delete from GivenAway
wsGiven.Range("A2").Resize(iRow, 3).Delete
MsgBox iRow - 2 & " records processed", vbInformation
End Sub
Also how do I stop the loop from taking in empty cells? I've tried Do While and Do Until but it still takes in the empty cells. I want the code to take the values in the Input Values tab one row at a time and give results for each one until an empty cell. Then sum the results given by each row of inputs. This is the code I have so far. The calculation itself works, but the loop doesn't.
'''
Sub TEST()
Dim i As Long
For i = 1 To 1000000
i = i + 1
'Pasting Input Values into Inputs Taken
Sheets("Input Values").Range("A" & i).Copy
Sheets("Inputs Taken").Range("D5").PasteSpecial xlPasteValues
Sheets("Input Values").Range("B" & i).Copy
Sheets("Inputs Taken").Range("D6").PasteSpecial xlPasteValues
Sheets("Input Values").Range("C" & i).Copy
Sheets("Inputs Taken").Range("D7").PasteSpecial xlPasteValues
Sheets("Input Values").Range("D" & i).Copy
Sheets("Inputs Taken").Range("D8").PasteSpecial xlPasteValues
Sheets("Input Values").Range("E" & i).Copy
Sheets("Inputs Taken").Range("C11").PasteSpecial xlPasteValues
Sheets("Input Values").Range("F" & i).Copy
Sheets("Inputs Taken").Range("D11").PasteSpecial xlPasteValues
Sheets("Input Values").Range("G" & i).Copy
Sheets("Inputs Taken").Range("C16").PasteSpecial xlPasteValues
Sheets("Input Values").Range("H" & i).Copy
Sheets("Inputs Taken").Range("D16").PasteSpecial xlPasteValues
Sheets("Input Values").Range("I" & i).Copy
Sheets("Inputs Taken").Range("G9").PasteSpecial xlPasteValues
Sheets("Input Values").Range("J" & i).Copy
Sheets("Inputs Taken").Range("G10").PasteSpecial xlPasteValues
Sheets("Input Values").Range("K" & i).Copy
Sheets("Inputs Taken").Range("G11").PasteSpecial xlPasteValues
Sheets("Input Values").Range("L" & i).Copy
Sheets("Inputs Taken").Range("G12").PasteSpecial xlPasteValues
Sheets("Input Values").Range("M" & i).Copy
Sheets("Inputs Taken").Range("G13").PasteSpecial xlPasteValues
Sheets("Input Values").Range("N" & i).Copy
Sheets("Inputs Taken").Range("G14").PasteSpecial xlPasteValues
'Setting Opening PUP to 100% and refreshing
Sheets("Inputs Taken").Range("G5").Value = 1
Application.CalculateFull
'Calculating No RPs
Sheets("Output").Range("C7").Formula = _
"=SUMPRODUCT(Model!BJ6:BJ365,Model!AD6:AD365,Model!AG6:AG365)"
Sheets("Output").Range("C8").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BK6:BK365)"
Sheets("Output").Range("C10").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BM6:BM365)"
Sheets("Output").Range("C11").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BN6:BN365)"
Sheets("Output").Range("C12").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BO6:BO365)"
Sheets("Output").Range("C13").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BP6:BP365)"
Sheets("Output").Range("C14").Formula = "=SUM(Output!C11:C13)"
Sheets("Output").Range("C17").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BS6:BS365)"
Sheets("Output").Range("C18").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BT6:BT365)"
Sheets("Output").Range("C19").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BU6:BU365)"
Sheets("Output").Range("C20").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BV6:BV365)"
Sheets("Output").Range("C21").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BW6:BW365)"
Sheets("Output").Range("C22").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BX6:BX365)"
Sheets("Output").Range("C23").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BY6:BY365)"
Sheets("Output").Range("C24").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BZ6:BZ365)"
Sheets("Output").Range("C25").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!CA6:CA365)"
Sheets("Output").Range("C26").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!CB6:CB365)"
Sheets("Output").Range("C5").Formula = "=Model!BL6-Model!BS6-Model!BT6"
Sheets("Output").Range("C15").Formula = "=SUM(Output!C7:C10,Output!C14)"
Sheets("Output").Range("C27").Formula = "=SUM(Output!C17:C26)"
Sheets("Output").Range("C29").Formula = "=-SUM(Model!AN6:AN365)"
Sheets("Output").Range("C30").Formula = "=-SUM(Model!AP6:AP365)"
Sheets("Output").Range("C31").Formula = "=-Output!C2"
Sheets("Output").Range("C33").Formula = "=SUM(Output!C29:C31,Output!C27,Output!C15)"
'Removing Formulas from output
Sheets("Output").Range("C5:C33").Copy
Sheets("Output").Range("C5:C33").PasteSpecial xlPasteValues
'Changing PUP rate
Sheets("Inputs Taken").Range("G5").Value = 0
Application.CalculateFull
'Calculate with RP
Sheets("Output").Range("D7").Formula = _
"=SUMPRODUCT(Model!BJ6:BJ365,Model!AD6:AD365,Model!AG6:AG365)"
Sheets("Output").Range("D8").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BK6:BK365)"
Sheets("Output").Range("D10").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BM6:BM365)"
Sheets("Output").Range("D11").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BN6:BN365)"
Sheets("Output").Range("D12").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BO6:BO365)"
Sheets("Output").Range("D13").Formula = _
"=SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BP6:BP365)"
Sheets("Output").Range("D14").Formula = "=SUM(Output!D11:D13)"
Sheets("Output").Range("D17").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BS6:BS365)"
Sheets("Output").Range("D18").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BT6:BT365)"
Sheets("Output").Range("D19").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BU6:BU365)"
Sheets("Output").Range("D20").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BV6:BV365)"
Sheets("Output").Range("D21").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BW6:BW365)"
Sheets("Output").Range("D22").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BX6:BX365)"
Sheets("Output").Range("D23").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BY6:BY365)"
Sheets("Output").Range("D24").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!BZ6:BZ365)"
Sheets("Output").Range("D25").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!CA6:CA365)"
Sheets("Output").Range("D26").Formula = _
"=-SUMPRODUCT(Model!AD6:AD365,Model!AG6:AG365,Model!CB6:CB365)"
Sheets("Output").Range("D5").Formula = "=Model!BL6-Model!BS6-Model!BT6"
Sheets("Output").Range("D15").Formula = "=SUM(Output!D7:D10,Output!D14)"
Sheets("Output").Range("D27").Formula = "=SUM(Output!D17:D26)"
Sheets("Output").Range("D29").Formula = "=-SUM(Model!AN6:AN365)"
Sheets("Output").Range("D30").Formula = "=-SUM(Model!AP6:AP365)"
Sheets("Output").Range("D31").Formula = "=-Output!C2"
Sheets("Output").Range("D33").Formula = "=SUM(Output!D29:D31,Output!D27,Output!D15)"
'Removing Formulas from output
Sheets("Output").Range("D5:D33").Copy
Sheets("Output").Range("D5:D33").PasteSpecial xlPasteValues
If Sheets("Input Values").Cells(i, 2).Value = "" Then Exit For
Next i
End Sub
'''
As is the case with all heroic efforts undertaken against all odds, your attempt at coding is truly inspiring. I have reduced your code but not quite enough. As you perhaps see, the middle section is repeated twice, once for column C and then for column D, and that should have been achieved by calling the same procedure twice, with just one different argument. Perhaps you will make this your task over the Easter holidays :-) Here's your revised code.
Sub TEST()
Dim WsIn As Worksheet ' Input
Dim WsT As Worksheet ' Taken
Dim WsOut As Worksheet ' Output
Dim WsMod As Worksheet ' Model
Dim Arr As Variant
Dim Rl As Long
Dim R As Long
Dim Rout As Long ' WsOut row
Dim Cmod As Long ' WsMod column
Set WsT = Sheets("Inputs Taken")
Set WsIn = Sheets("Input Values")
Set WsOut = Sheets("Output")
Set WsMod = Sheets("Model")
Application.ScreenUpdating = False
Rl = WsIn.Cells(WsIn.Rows.Count, "B").End(xlUp).Row
For R = 1 To Rl
'Pasting Input Values into Inputs Taken
With WsIn
Arr = .Range(.Cells(R, 1), .Cells(R, 4)).Value
WsT.Cells(5, "D").Resize(UBound(Arr, 2), UBound(Arr)) _
.Value = Application.Transpose(Arr)
Arr = .Range(.Cells(R, 5), .Cells(R, 6)).Value
WsT.Cells(11, "C").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
Arr = .Range(.Cells(R, 7), .Cells(R, 8)).Value
WsT.Cells(16, "C").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
Arr = .Range(.Cells(R, 9), .Cells(R, 14)).Value
WsT.Cells(9, "G").Resize(UBound(Arr, 2), UBound(Arr)) _
.Value = Application.Transpose(Arr)
End With
'Setting Opening PUP to 100% and refreshing
WsT.Cells(5, "G").Value = 1
'Calculating No RPs
With WsOut
Cmod = 62 ' BJ:BP
For Rout = 7 To 13
If Rout <> 9 Then ' skip result in C9
.Cells(Rout, "C").Value = SumProduct(Cmod, WsMod)
Cmod = Cmod + 1
End If
Next Rout
.Cells(14, 3).Value = Application.Sum(.Range("C11:C13"))
Cmod = 71 ' BS:CB
For Rout = 17 To 26
.Cells(Rout, "C").Value = SumProduct(Cmod, WsMod, True)
Cmod = Cmod + 1
Next Rout
.Cells(5, 3).Value = WsMod.Cells(6, "BL").Value _
- WsMod.Cells(6, "BS").Value _
- WsMod.Cells(6, "BT").Value
.Cells(15, 3).Value = Application.Sum(.Range("C7:C10, C14"))
.Cells(27, 3).Value = Application.Sum(.Range("C17:C26"))
.Cells(29, 3).Value = Application.Sum(WsMod.Range("AN6:AN365")) * -1
.Cells(30, 3).Value = Application.Sum(WsMod.Range("AP6:AP365")) * -1
.Cells(31, 3).Value = WsOut.Cells(2, 3).Value * -1
.Cells(33, 3).Value = Application.Sum(.Range("C29:C31, C15, C27"))
End With
'Changing PUP rate
WsT.Cells(5, "G").Value = 0 ' Excel should recalculate automatically
' Application.CalculateFull
'Calculate with RP
With WsOut
Cmod = 62 ' BJ:BP
For Rout = 7 To 13
If Rout <> 9 Then ' skip result in D9
.Cells(Rout, "D").Value = SumProduct(Cmod, WsOut)
Cmod = Cmod + 1
End If
Next Rout
.Cells(14, 4).Value = Application.Sum(.Range("D11:D13"))
Cmod = 71 ' BS:CB
For Rout = 17 To 26
.Cells(Rout, "D").Value = SumProduct(Cmod, WsOut, True)
Cmod = Cmod + 1
Next Rout
.Cells(5, 4).Value = WsMod.Cells(6, "BL").Value _
- WsMod.Cells(6, "BS").Value _
- WsMod.Cells(6, "BT").Value
.Cells(15, 4).Value = Application.Sum(.Range("D7:D10, D14"))
.Cells(27, 4).Value = Application.Sum(.Range("D17:D26"))
.Cells(29, 4).Value = Application.Sum(WsMod.Range("AN6:AN365")) * -1
.Cells(30, 4).Value = Application.Sum(WsMod.Range("AP6:AP365")) * -1
.Cells(31, 4).Value = WsOut.Cells(2, 3).Value * -1
.Cells(33, 4).Value = Application.Sum(.Range("D29:D31, D15, D27"))
End With
Exit For
Next R
Application.ScreenUpdating = True
End Sub
Private Function SumProduct(ByVal Cmod As Long, _
WsMod As Worksheet, _
Optional ByVal Negative As Boolean) As Double
Dim AuxRng As Range
With WsMod
Set AuxRng = .Range(.Cells(6, Cmod), .Cells(365, Cmod))
SumProduct = Application.SumProduct( _
.Range("AD6:AD365"), _
.Range("AG6:AG365"), _
AuxRng) * IIf(Negative, -1, 1)
End With
End Function
I draw your attention to the end of the main procedure where it says Exit For. This curtails the run to a single loop. I thought, perhaps you never saw the result of your labors. In some instances you are converting columns to rows, and to save my life I wouldn't be able to tell where to put the next line of your data, not to mention the 999,998 you were hoping for. I have reduced that number to the actual number of rows in your worksheet but that isn't the problem. The immediate problem is where to put the next data set - or how that data set could be different from the one the code now generates.
I'm trying to split a string based on ampersand (&), remove all the ampersands and separate each part to columns.
The number of strings differ every time.
Sample text:
My output:
What I need:
For i = 2 To 7
fullname = Cells(i, 1).Value
commaposition = InStr(fullname, "&")
Cells(i, 2).Value = Left(fullname, commaposition - 2)
For x = 2 To 7
fullname = Cells(i, 1).Value
commaposition = InStr(fullname, "&")
Cells(i, 3).Value = Mid(fullname, commaposition + 2)
Cells(x, 3).Value = Mid(fullname, commaposition + 2)
For y = 2 To 7
fullname = Cells(i, 1).Value
commaposition = InStr(fullname, "&")
Cells(i, 4).Value = Mid(fullname, commaposition + 2)
Cells(x, 4).Value = Mid(fullname, commaposition + 2)
Next y
Next x
Next i
Another option (other then #Storax's method) would be to use Regular Expressions which could account for more then just an ampersand.
Option Explicit
Public Sub FindNames()
Dim rng As Range
Dim j As Long
Dim c, Match
' Update for your range
With ActiveSheet
Set rng = .Range(.Cells(1, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1))
End With
With CreateObject("vbscript.regexp")
.Global = True
.Pattern = "\w+"
For Each c In rng
j = 0
If .test(c.Value2) Then
For Each Match In .Execute(c.Value2)
j = j + 1
c.Offset(0, j).Value2 = Match
Next Match
End If
Next c
End With
End Sub
You could try something like that
Sub SplitAmper()
Const AP = "&"
Dim v As Variant
Dim rg As Range
Set rg = Range("A2:A7") ' Adjust to your needs
Dim sngCell As Range
For Each sngCell In rg
v = Split(sngCell.Value, AP)
Cells(sngCell.Row, 1).Resize(, UBound(v) + 1) = v
Next
End Sub
Update: Another solution mentioned in the comments from SJR would be Text to Columns
Sub AnotherAmper()
Const AP = "&"
Dim rg As Range
Set rg = Range("A1:A7") ' Adjust to your needs
rg.TextToColumns Destination:=Range("B1"), DataType:=xlDelimited, _
Other:=True, OtherChar:=AP
End Sub