vba range of hours and dates - excel

hi I have a table that I schedule workers at the workers are scheduled at a range of hours for example 11:00-18:00 and a range of dates for example 21/01/2021-26/01/2021
and I need to spot duplicates for example if the same worker is scheduled at 21/04/2021-22/04/2021 at 11:00:18:00 and 13:00-15:00 it would detect a duplicate schedule
the table looks like this
my code right now spots only exact same schedule duplicate or once that start at the same hour
Private Sub CommandButton1_Click()
Dim lrow As Long
Dim x As Integer
Dim y As Integer
Dim i As Integer
lrow = ActiveSheet.ListObjects("LeaveTracker").DataBodyRange.Rows.Count + 5
shibuzim.ListObjects("LeaveTracker").ListColumns(2).DataBodyRange.Clear
For x = 5 To lrow
For y = x + 1 To lrow
If (Cells(x, 12).Value = Cells(y, 12).Value And _
Cells(x, 13).Value = Cells(y, 13).Value And _
Cells(x, 14).Value = Cells(y, 14).Value And _
Cells(x, 17).Value = Cells(y, 17).Value And _
Cells(x, 18).Value = Cells(y, 18).Value And _
Cells(x, 20).Value = Cells(y, 20).Value) _
Or _
(Cells(x, 12).Value = Cells(y, 12).Value And _
Cells(x, 13).Value = Cells(y, 13).Value And _
Cells(x, 14).Value = Cells(y, 14).Value And _
Left(Cells(x, 17).Value, 3) = Left(Cells(y, 17).Value, 3) And _
Cells(x, 18).Value = Cells(y, 18).Value And _
Cells(x, 20).Value = Cells(y, 20).Value) _
Then
Cells(x, 11).Value = "duplicate"
Cells(y, 11).Value = "duplicate"
MsgBox "line" & " " & x - 4 & " " & "with line" & " " & y - 4
End If
Next y
Next x
End Sub

This create a list of all shifts on a sheet named Check , sorts them by employee, start date, days and then checks them for shifts that start before the previous one ended.
Option Explicit
Sub CheckDupl()
Const COL_DUPL = 2 ' table column 2
Const COl_EMPLOYEE = 3
Const COL_START = 4
Const COL_END = 5
Const COL_HOURS = 8
Dim wb As Workbook, ws As Worksheet, wsCheck As Worksheet
Dim tbl As ListObject, lrow As Long
Dim r As Long, p As Long, iDupl As Long, count As Long
' clear table
Set wb = ThisWorkbook
Set ws = wb.Sheets(1) ' or wb.ActiveSheet
Set tbl = ws.ListObjects("LeaveTracker")
With tbl
lrow = .DataBodyRange.Rows.count
.ListColumns(COL_DUPL).DataBodyRange.Clear
End With
Dim sEmploy As String, s As String
Dim dtStart As Date, dtEnd As Date, dt As Date
Dim bDupl As Boolean, arHours, dur As Single
' prepare output sheet
Set wsCheck = wb.Sheets("Check")
wsCheck.Cells.Clear
wsCheck.Range("A1:F1") = Array("Employee", "Shift Start", "Shift End ", _
"Days", "Table Row", "Duplicate")
' scan table
iDupl = 2
For r = 1 To lrow
sEmploy = Trim(tbl.DataBodyRange(r, COl_EMPLOYEE))
dtStart = tbl.DataBodyRange(r, COL_START)
dtEnd = tbl.DataBodyRange(r, COL_END)
' get shift start/end times
s = Replace(tbl.DataBodyRange(r, COL_HOURS), " ", "") 'remove spaces
If Not s Like "##:##-##:##" Then
MsgBox "Check times '" & s & "'", vbCritical, "Table Row " & r
Exit Sub
Else
arHours = Split(s, "-")
End If
' add each shift to duplicate sheet
dt = dtStart
Do While dt <= dtEnd
With wsCheck.Cells(iDupl, 1)
.Value = sEmploy
.Offset(, 1) = CDate(Format(dt, "yyyy-mm-dd ") & arHours(0))
.Offset(, 2) = CDate(Format(dt, "yyyy-mm-dd ") & arHours(1))
.Offset(, 3) = dtEnd - dtStart
.Offset(, 4) = r ' table row
' sanity check
If .Offset(, 2) - .Offset(, 1) < 0 Then
MsgBox "ERROR - End date before Start date for " & _
sEmploy, vbCritical, "Table Row " & r
Exit Sub
End If
End With
dt = dt + 1
iDupl = iDupl + 1
Loop
Next
iDupl = iDupl - 1
' sort calendar by employee, start date, days
' check longer date ranges against shorter ones
With wsCheck.Sort
With .SortFields
.Clear
.Add key:=Range("A2:A" & iDupl), SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortNormal
.Add key:=Range("B2:B" & iDupl), SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortNormal
.Add key:=Range("D1:D" & iDupl), SortOn:=xlSortOnValues, _
Order:=xlDescending, DataOption:=xlSortNormal
End With
.SetRange Range("A1:F" & iDupl)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' now check for overlaps
With wsCheck
p = 2
For r = 3 To iDupl
' check start is before previous end for same employee
If .Cells(r, 1) = .Cells(p, 1) _
And .Cells(r, 2) < .Cells(p, 3) Then
.Cells(r, 6) = "Overlap with row " & p
' update table
tbl.DataBodyRange(.Cells(r, 5), COL_DUPL) = "Duplicate"
count = count + 1
Else
p = r
End If
Next
.Columns("A:F").AutoFit
.Activate
.Range("A1").Select
End With
MsgBox count & " duplicates found - see sheet " & wsCheck.Name, vbInformation
End Sub

Related

Find and output empty cells

The table contains column G = City, H = Department and J = Date. In the columns J Date some values are missing. I want to output these rows on a new worksheet with (column A) the rownumber, (column B) the city and (column) the departement.
The code I have looks like this but in the output all rows with a value in J = Date and the output is in the columns "G, H, J". I tried to change the columns in the code but I failed.
Sub missing()
Dim ws, wsOut As Worksheet
Set ws = ActiveWorkbook.Sheets("Table1")
Set wsOut = ActiveWorkbook.Sheets("output")
lastRow = ws.Range("G" & Rows.Count).End(xlUp).Row
lastRowOut = wsOut.Range("G" & Rows.Count).End(xlUp).Row + 1
For i = 1 To lastRow
If (ws.Cells(i, 10).Value = "") _
And _
((ws.Cells(i, 7).Value = "Peking") Or _
(ws.Cells(i, 7).Value = "Tokio") Or _
(ws.Cells(i, 7).Value = "London") Or _
(ws.Cells(i, 7).Value = "Rom") Or _
(ws.Cells(i, 7).Value = "Lissabon") Or _
(ws.Cells(i, 7).Value = "Panama") Or _
(ws.Cells(i, 7).Value = "Budapest") Or _
(ws.Cells(i, 7).Value = "Prag") Or _
(ws.Cells(i, 7).Value = "Dublin") Or _
(ws.Cells(i, 7).Value = "Luxemburg")) _
And _
((ws.Cells(i, 8).Value = "A") Or _
(ws.Cells(i, 8).Value = "B") Or _
(ws.Cells(i, 8).Value = "C") Or _
(ws.Cells(i, 8).Value = "D") Or _
(ws.Cells(i, 8).Value = "E") Or _
(ws.Cells(i, 8).Value = "F") Or _
(ws.Cells(i, 8).Value = "G") Or _
(ws.Cells(i, 8).Value = "H") Or _
(ws.Cells(i, 8).Value = "I") Or _
(ws.Cells(i, 8).Value = "J")) _
Then
wsOut.Range("B" & lastRowOut & ":C" & lastRowOut).Value = ws.Range("G" & i & ":H" & i).Value
wsOut.Range("A" & lastRowOut).Value = i
lastRowOut = lastRowOut + 1
End If
Next i
End Sub
while i was writing this others have answered and honestly I like there solution but can also be done like this:
Sub missing()
Dim ws, wsOut As Worksheet
Set ws = ActiveWorkbook.Sheets("table")
Set wsOut = ActiveWorkbook.Sheets("output")
lastRow = ws.Range("A" & Rows.Count).End(xlUp).Row
lastRowOut = wsOut.Range("A" & Rows.Count).End(xlUp).Row + 1
For i = 2 To lastRow
If ws.Cells(i, 3).Value = "" Then
wsOut.Range("A" & lastRowOut & ":B" & lastRowOut).Value = ws.Range("A" & i & ":B" & i).Value
wsOut.Range("C" & lastRowOut).Value = i
lastRowOut = lastRowOut + 1
End If
Next i
End Sub
assuming table is in worksheet "table" and output is wanted in a worksheet called "output" [note output has to have a value somewhere in column A before the code is run or an error will be thrown]
Also the code you show does not appear to be trying to answer the question you've asked, it may just be that you took a wrong turn but it is quite different, let us know if we've all missed the point!
Click on cell "A1", press Ctrl+G and choose "Special", "current region" (that should select the whole array). Again press Ctrl+G and choose "Special", this type choose "Blanks".
In the address bar, type "No Date".
Press Ctrl+ENTER (don't forget the control-button).
You can record this into a macro.
Have fun :-)
Oh, by the way, this is wrong:
If Cells(i, 1).Value = "Peking" Or "Tokio" Or "London" Or ...
It should be something like:
If Cells(i, 1).Value = "Peking" Or_
Cells(i, 1).Value = "Tokio" Or_
...
(The underscore after "Or" is just to explain VBA that this should be treated as one single line.)
Not sure i'm 100% with you, but
Dim r as range
dim c as range
dim a() as variant
dim i as long
set r=range("c2:c22").specialcells(xlcelltypeblanks)
redim a(1 to r.cells.count,1)
i=1
for each c in r.cells
a(i,0) = cells(c.row,1)
a(i,1)=cells(c.row,2)
i=i+1
next c
' Output, to j1 on the same sheet.
cells(1,10).resize(ubound(a),2).value=a

How do I sum the results of each loop done in VBA, Excel?

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.

Ownership Partners Grouping using excel VBA

I have data which shows the acquisition of property from one partner to another and transfer of properties. Based on the inactive date and then seeing the document date I have to detect the transfer of property. Here is the snap of data:
For example in the second picture when the contract inactive date passes, ownership transfers to other having document date of the next day. Like in first group the 13th one William G & ALMA have ownership now look inactive date it is 10/3/1971, now I will find the next day date in document dates which I found 10/4/1971 for ALMA TEST TR, therefore, ownership transferred to him and new partners are WILLIAM G & ALMA TEST TR as both make to 100% of ownership. Here the output I have done manually but I need a VBA code to make it easier as I am new to VBA here is the required output.
Here is my code:
Sub DateFill()
Dim rng As Range, destRow As Long
Dim shtSrc As Worksheet, shtDest As Worksheet
Dim c As Range '-- this is used to store the single cell in the For Each loop
Set shtSrc = Sheets("Input") ' Sets "Sheet1" sheet as source sheet
Set shtDest = Sheets("Output") 'Sets "Sheet2." sheet as destination sheet
destRow = 2 'Start copying to this row on destination sheet
Dim x, y, i As Long
y = Array("ERROR", "(ERROR)") ' To delete rows having the name error to clean data
With ActiveSheet.UsedRange.Columns(1)
x = .Value
For i = 1 To UBound(x, 1)
If Not IsError(Application.Match(LCase(x(i, 1)), y, 0)) Then x(i, 1) = ""
Next
.Value = x
.SpecialCells(4).EntireRow.Delete
End With
' >> Look for matching dates in columns F to G <<
For Each c In rng.Cells
If (c.Offset(0, 2).Value + 1 = c.Offset(1, 3).Value) Then
shtSrc.Range("A" & c.Row).Copy shtDest.Range("A" & destRow)
shtSrc.Range("B" & c.Row).Copy shtDest.Range("B" & destRow)
shtSrc.Range("C" & c.Row).Copy shtDest.Range("C" & destRow)
shtSrc.Range("D" & c.Row).Copy shtDest.Range("D" & destRow)
shtSrc.Range("E" & c.Row).Copy shtDest.Range("E" & destRow)
shtSrc.Range("F" & c.Row).Copy shtDest.Range("F" & destRow)
shtSrc.Range("G" & c.Row).Copy shtDest.Range("G" & destRow)
destRow = destRow + 1
' > Ends search for dates <
End If
Next
End Sub
It's over my knowledge level. Any help would be appreciated, as I can't seem to figure this code out. If you could explain how this works in simple terms, that would be equally awesome!
I used the following data as sheet "Data". Note that the columns need to be in exactly this order and position. The code addresses the columns by A, B, C …
Note that I used another date format, but the code will work with any other date format too, as long as the cells contain real dates and not strings.
The following code has to be in a module. You need to specify your sheet names.
Option Explicit
Global wsData As Worksheet
Global wsDest As Worksheet
Global LastRow As Long
Global LastCol As Long
Global GroupCounter As Long
Public Sub ExtractGroups()
Set wsData = ThisWorkbook.Worksheets("Data") 'specify source sheet
Set wsDest = ThisWorkbook.Worksheets("Groups") 'specify destination sheet
LastRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row
LastCol = wsData.Cells(1, wsData.Columns.Count).End(xlToLeft).Column
GroupCounter = 0
'## Sort data
With wsData.Sort
.SortFields.Clear
'sort by Acquistion Date, Document Date and Inactive Date
.SortFields.Add Key:=Range("E2:E" & LastRow), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.SortFields.Add Key:=Range("F2:F" & LastRow), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.SortFields.Add Key:=Range("G2:G" & LastRow), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.SetRange wsData.UsedRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'## Find first group
Dim iRow As Long
iRow = LastRow
Dim IntSum As Double
Do While IntSum + wsData.Cells(iRow, "C").Value <= 100
IntSum = IntSum + wsData.Cells(iRow, "C").Value
Application.CutCopyMode = False
wsDest.Rows(2).Insert xlDown
wsData.Rows(iRow).Resize(ColumnSize:=LastCol).Copy
wsDest.Rows(2).Cells(1, "A").Value = GroupCounter
wsDest.Rows(2).Cells(1, "B").PasteSpecial xlPasteAll
iRow = iRow - 1
Loop
'## Analyze the data
Dim GroupRows As Long
GroupRows = LastRow - iRow
Dim destRow As Long, FirstGroupRow As Long, FirstDate As Date, AddedRows As Long
Do While GroupRows >= 0
GroupCounter = GroupCounter + 1
FirstGroupRow = 2
AddedRows = 0
destRow = 2 + GroupRows - 1
FirstDate = 0
GroupRows = 0
Do While destRow + GroupRows >= FirstGroupRow + GroupRows
If FirstDate = 0 Then
If Not IsDate(wsDest.Cells(destRow + GroupRows, "H").Value) Then Exit Do
FirstDate = wsDest.Cells(destRow + GroupRows, "H").Value
GroupRows = GroupRows + AddNextOwners(wsDest.Cells(destRow + GroupRows, "H").Value + 1)
ElseIf FirstDate <> wsDest.Cells(destRow + GroupRows, "H").Value Then
GroupRows = GroupRows + 1
Application.CutCopyMode = False
wsDest.Rows(2).Insert xlDown
wsDest.Rows(destRow + GroupRows).Resize(ColumnSize:=LastCol - 1).Offset(ColumnOffset:=1).Copy
wsDest.Rows(2).Cells(1, "A").Value = GroupCounter
wsDest.Rows(2).Cells(1, "B").PasteSpecial xlPasteAll
End If
destRow = destRow - 1
Loop
If GroupRows = 0 Then Exit Do
'## Sort within the group
With wsDest.Sort
.SortFields.Clear
.SortFields.Add Key:=wsDest.Range("H2").Resize(RowSize:=GroupRows), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.SetRange wsDest.Rows("2").Resize(RowSize:=GroupRows)
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'## color every second group
With wsDest.Rows("2").Resize(RowSize:=GroupRows).Interior
If GroupCounter Mod 2 = 0 Then
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent4
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
Else
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End If
End With
'## check if group int exceeds 100 %
If Application.WorksheetFunction.Sum(wsDest.Range("D2").Resize(RowSize:=GroupRows)) > 100 Then
MsgBox "'Int' in group " & GroupCounter & " exceeded 100 %. Please fix the source data.", vbCritical
'ReNumberGroups
Exit Sub
End If
DoEvents
Loop
'ReNumberGroups
'## everything was going correctly!
MsgBox "Mission accomplished!", vbInformation
End Sub
'## Substitute the old owner with the new ones (for the next group)
Private Function AddNextOwners(DocDate As Date) As Long
Dim iRow As Long
For iRow = LastRow To 2 Step -1
If wsData.Cells(iRow, "F").Value = DocDate Then
AddNextOwners = AddNextOwners + 1
Application.CutCopyMode = False
wsDest.Rows(2).Insert xlDown
wsData.Rows(iRow).Resize(ColumnSize:=LastCol).Copy
wsDest.Rows(2).Cells(1, "A").Value = GroupCounter
wsDest.Rows(2).Cells(1, "B").PasteSpecial xlPasteAll
End If
Next iRow
End Function
And it will end up with the worksheet "Groups" like this below.
Note that the algorithm fails in the end because of some data inconsistency.
If you want the group numbers the other way round use …
Private Sub ReNumberGroups()
Dim iRow As Long
Const StartGroupNumber As Long = 1 'define first group number
For iRow = 2 To wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row
wsDest.Cells(iRow, "A").Value = GroupCounter - wsDest.Cells(iRow, "A").Value + StartGroupNumber
Next iRow
End Sub

Copy value of entire row and past it into a different worksheet

I have the following code:
Option Explicit
Dim LastRow As Long
Dim i As Long
Dim myCell2 As Range
Dim oWkSht As Worksheet
Private Sub Worksheet_Activate()
Application.ScreenUpdating = False
'-------------------------------------------
'//Head Row A1\\
'-------------------------------------------
Range("A1").Value = "Department"
Range("B1").Value = "AOS Location"
Range("C1").Value = "Article Number"
Range("D1").Value = "HFB"
Range("E1").Value = "Article Name"
Range("F1").Value = "General Comments"
Range("G1").Value = "Home Location"
Range("H1").Value = "A. Stock"
Range("I1").Value = "SGF"
Range("J1").Value = "Incoming Good"
Range("K1").Value = "M.P.QTY"
Range("L1").Value = "Pallet Qty"
Range("M1").Value = "Start Date"
Range("N1").Value = "AOS SSS"
Range("O1").Value = "End Date"
Range("P1").Value = "End Qty"
Range("Q1").Value = "Promotion week"
Range("R1").Value = "Start-Up Qty"
Range("S1").Value = "Old AWS"
Range("T1").Value = "Goal"
Range("U1").Value = "QTY Sold LW"
Range("V1").Value = "Price"
Range("W1").Value = "GM0"
Range("X1").Value = "Sales Before"
Range("Y1").Value = "Sales this Month"
Range("Z1").Value = "Total Sold this month"
'-----------------------------------------------------------------
'//Date\\
'-----------------------------------------------------------------
Dim FirstDate As Date
Dim LastDate As Date
Dim NextDate As Date
Dim r As Long
Range("AA1").Value = DateSerial(Year(Date), Month(Date), 1)
FirstDate = DateSerial(Year(Date), Month(Date), 1)
LastDate = DateSerial(Year(Date), Month(Date) + 1, 0)
r = 28
Do
FirstDate = FirstDate + 1
Cells(1, r) = FirstDate
r = r + 1
Loop Until FirstDate = LastDate
LastRow = Range("A100000").End(xlUp).Row
Range("Y2").Formula = "=SUM(Registration!AA2:Registration!BE2)"
Range("Y2").Select
Range("Y2:Y" & LastRow).Select
Selection.FillDown
Range("Z2").Formula = "=Registration!Y2*Registration!V2"
Range("Z2").Select
Range("Z2:Z" & LastRow).Select
Selection.FillDown
Selection.NumberFormat = _
"_([$€-x-euro2] * #,##0.00_);_([$€-x-euro2] * (#,##0.00);_([$€-x-euro2] * ""-""??_);_(#_)"
'--------------------------------------------------
'//Format Head, Row A1\\
'--------------------------------------------------
Range("A1", Range("XFD1").End(xlToLeft)).Select
With Selection.Font
.Name = "Calibri"
.FontStyle = "Bold"
.Size = 13
End With
'--------------------------------------------------
'//Select Used rows and column and shift one row down\\
'--------------------------------------------------
Range("A1", Range(Range("A1:A" & LastRow), Range("A1", Range("XFD1").End(xlToLeft)))).Offset(1).Select
With Selection.Font
.Name = "Calibri"
.FontStyle = "Regular"
.Size = 11
End With
'--------------------------------------------------
'//Autofit and Align all cells in rows and columns\\
'--------------------------------------------------
With Cells
.EntireColumn.AutoFit
.EntireRow.AutoFit
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlLeft
End With
'--------------------------------------------------
'//This Code will freeze the first row in the worksheet\\
'--------------------------------------------------
With ActiveWindow
.SplitColumn = 6
.SplitRow = 1
.FreezePanes = True
End With
'--------------------------------------------------
'//This code will delete all of the old products and replace them to the sheet old_products.\\
'--------------------------------------------------
Dim l As Long
Dim dst As Range
Dim sht As Worksheet: Set sht = Worksheets("Old_Products")
With Sheets("Registration")
For l = 2 To LastRow
If .Cells(l, 6).Value = "old product" Then
Set dst = sht.Range("F" & sht.Rows.Count).End(xlUp).Offset(1, -5)
.Cells(l, 6).EntireRow.Copy
dst.PasteSpecial xlPasteValues
.Cells(l, 6).EntireRow.Delete
End If
Next l
End With
'--------------------------------------------------
'//Sorting Column A in Department order\\
'--------------------------------------------------
Dim oRangeSort As Range
Dim oRangeKey As Range
' one range that includes all colums to sort
Set oRangeSort = Range("A1", Range(Range("A1:A" & LastRow), Range("A1", Range("XFD1").End(xlToLeft))))
' start of column with keys to sort
Set oRangeKey = Range("A2")
'//custom sort order\\
Dim sCustomList(1 To 28) As String
sCustomList(1) = "OTW showroom"
sCustomList(2) = "Launch Area"
sCustomList(3) = "Living"
sCustomList(4) = "Media"
sCustomList(5) = "Dining"
sCustomList(6) = "Kitchen"
sCustomList(7) = "Work"
sCustomList(8) = "Sleeping"
sCustomList(9) = "Storage"
sCustomList(10) = "Children"
sCustomList(11) = "Familly"
sCustomList(12) = "Staircase"
sCustomList(13) = "Lift"
sCustomList(14) = "OTW"
sCustomList(15) = "Koken en Eten"
sCustomList(16) = "Textiel"
sCustomList(17) = "Bed"
sCustomList(18) = "Bad"
sCustomList(19) = "Home Organisation"
sCustomList(20) = "Lighting"
sCustomList(21) = "Rugs"
sCustomList(22) = "Wall"
sCustomList(23) = "Home Decoration"
sCustomList(24) = "Self Storage"
sCustomList(25) = "CheckOut"
sCustomList(26) = "Cash Line"
sCustomList(27) = "AS IS"
sCustomList(28) = "SWFOOD"
Application.AddCustomList ListArray:=sCustomList
Sort.SortFields.Clear
oRangeSort.Sort Key1:=Range("A1:A" & LastRow), Order1:=xlAscending, Key2:=Range("B1:B" & LastRow), Order2:=xlAscending, Header:=xlYes, OrderCustom:=Application.CustomListCount + 1, MatchCase:=False, Orientation:=xlTopToBottom, DataOption1:=xlSortNormal
' clean up
ActiveSheet.Sort.SortFields.Clear
Application.DeleteCustomList Application.CustomListCount
'-------------------------------------------------------
'//This code will compare the sart date for the new product and
'if it's more than one day then it will removes the product from the Registration sheet to the Planned New Products.\\
'-------------------------------------------------------
Dim j As Integer
For j = 2 To LastRow
If Sheets("Registration").Cells(j, "M").Value > Date + 1 Then
Sheets("Registration").Cells(j, "M").EntireRow.Copy Destination:=Sheets("Planned_New_Products").Range("A" & Rows.Count).End(xlUp).Offset(1)
Sheets("Registration").Cells(j, "M").EntireRow.Delete
End If
Next j
''// Stop flickering...
'--------------------------------------------------
Range("A2").Select
Application.ScreenUpdating = True
End Sub
This code copies the entire row based on the inserted text in column F and pastes the row in a different sheet. Now the problem is that I have the following code in column Y
=SUM(Registration!AA2:Registration!BE2) 'the number is from 2 to lastrow
And the following code in column Z
=Registration!Y2*Registration!V2 'the number is from 2 to lastrow
Now my question is how can I only copy the value of this entire row and paste it into a different worksheet?
To copy the entire row of values:
Dim dst As Range
Dim sht As Worksheet: Set sht = Worksheets("Old_Products")
With Sheets("Registration")
For l = lastRow to 2 Step -1
If .Cells(l, 6).Value = "old product" Then
Set dst = sht.Range("F" & sht.Rows.Count).End(xlUp).Offset(1, -5)
.Cells(l, 6).EntireRow.Copy
dst.PasteSpecial xlPasteValues
.Cells(l, 6).EntireRow.Delete
End If
Next l
End With

Generated Project Portfolio Timeline

I have a list of Projects:
Project A
Project B
Project C
and milestones for each project with a date for the milestone:
Project A Milestone 1 01/01/2015
Project A Milestone 2 01/02/2015
Project A Milestone 3 01/03/2015
Project B Milestone 1 01/04/2015
I am looking to generate a type of timeline for all of the projects in one sheet, with milestones displayed in their respective month.
Column A would have the list of projects and row 1 have months, then to display the milestone where the month and project match.
So far I have been able to extract the list of projects using a macro:
Sub UniqueList()
Dim rListPaste As Range
Dim iReply As Integer
On Error Resume Next
Set rListPaste = Application.InputBox _
(Prompt:="Please select the destination cell", Type:=8)
If rListPaste Is Nothing Then
iReply = MsgBox("No range nominated," _
& " terminate", vbYesNo + vbQuestion)
If iReply = vbYes Then Exit Sub
End If
Range("A1", Range("A65536").End(xlUp)).AdvancedFilter _
Action:=xlFilterCopy, CopyToRange:=rListPaste.Cells(1, 1), Unique:=True
End Sub
After this I am pretty stuck. Any advice would be greatly appreciated.
I've done a similar setup to develop a milestone chart based on the current week. I've modified it to match your requirements:
Sub CreateMilestoneChart()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim LastRow As Long
Dim i As Long, j As Long
Dim FirstMonth As Long
Dim FirstYear As Long
Dim LastMonth As Long
Dim LastYear As Long
Dim curRange As Range
Set ws1 = Worksheets("Project List")
Set ws2 = Worksheets("Milestone Chart")
Application.ScreenUpdating = False
LastRow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
'-----You will want to modify or remove these lines once-----
'-----you get the sheet formatted the way you want-----------
ws2.Cells.Clear
ws2.Range("A1").Value = "Milestone Chart"
ws2.Range("A2").Value = "Generated on " & Date
ws2.Range("A3").Value = "Month:"
ws2.Range("A3").HorizontalAlignment = xlRight
'------------------------------------------------------------
ws1.Range("A1:C" & LastRow).Copy
ws2.Range("A4").PasteSpecial Paste:=xlPasteAllUsingSourceTheme, Operation:=xlNone _
, SkipBlanks:=False, Transpose:=False
LastRow = LastRow + 3
For i = 4 To LastRow
ws2.Cells(i, 1).Value = ws2.Cells(i, 1).Value & " " & ws2.Cells(i, 2).Value
Next i
ws2.Range("A4:A" & LastRow).HorizontalAlignment = xlRight
ws2.Range("B4:B" & LastRow).Delete Shift:=xlToLeft
With ws2.Sort
.SortFields.Clear
.SortFields.Add Key:=Range("B4:B" & LastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange Range("A4:B" & LastRow)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
FirstMonth = DatePart("m", ws2.Range("B4").Value)
FirstYear = DatePart("yyyy", ws2.Range("B4").Value)
LastMonth = DatePart("m", ws2.Range("B" & LastRow).Value)
LastYear = DatePart("yyyy", ws2.Range("B" & LastRow).Value)
ws2.Range("B3").Value = CDate(FirstMonth & "/" & FirstYear)
Set curRange = ws2.Range("B3")
i = 1
Do Until DatePart("m", curRange.Value) = LastMonth And DatePart("yyyy", curRange.Value) = LastYear
Set curRange = ws2.Cells(3, i + 2)
curRange.Value = DateAdd("m", 1, ws2.Cells(3, i + 1).Value)
i = i + 1
Loop
ws2.Cells(3, i + 2).Value = DateAdd("m", 1, ws2.Cells(3, i + 1).Value)
For i = 4 To LastRow
j = 2
Do Until ws2.Cells(i, j).Value >= ws2.Cells(3, j).Value And ws2.Cells(i, j).Value < ws2.Cells(3, j + 1).Value
ws2.Cells(i, 2).Insert Shift:=xlToRight
ws2.Cells(i, 2).Value = "'-----------------"
j = j + 1
Loop
Next i
Application.ScreenUpdating = True
End Sub
It's not very clean by any means, but it will work. You will need to modify it to fit your needs.

Resources