I have a excel file that contain daily order record and I need to summarize the order detail base on different staff.
I would like to combine the rows base on same Staff ID and divide to different group.
All order with the same Staff ID(Column B) will divide to a same group, the quantity of item A to item X of the order within a group will sum individual, each group will retain the first order record only and the other order id(Column A) within the group will mark in the remark column(Column G).
I have a macro with many for-loop & if statement to finish the task, but I don't have any idea how to simplify or modified it. Could someone can give me some suggestion?
Please let me know if I can clarify anything for you.
Private Sub test()
lastrow = Cells(Rows.Count, 1).End(xlUp).Row
'sum the quantity of item
For Z = 2 To lastrow
If Range("F" & Z) <> "" Then
ordercount = 2
For c = 2 To lastrow
If Z <> c Then
If Range("F" & Z) = Range("F" & c) Then
For i = 0 To 9
temp = Cells(Z, 3 + i) + Cells(c, 3 + i)
If temp <> 0 Then
Cells(Z, 3 + i) = temp
End If
Next i
Range("G" & Z) = Range("G" & Z).Value & "No." & ordercount
& " " & Range("A" & c).Value & Chr(10)
ordercount = ordercount + 1
End If
End If
Next c
End If
orderno = Range("G" & Z).Value
If orderno <> "" Then
Range("G" & Z) = Left(orderno, Len(orderno) - 1)
End If
Next Z
'delete the other record within the same group
For Z = 2 To lastrow
If Range("F" & Z) <> "" Then
For c = 2 To lastrow
If Z <> c Then
If Range("F" & Z) = Range("F" & c) Then
Rows(c).Delete
c = c - 1
End If
End If
Next c
End If
Next Z
End Sub
Sample:
The following will do what you expect, but the loop starts from the bottom of the data and moves to the second row, as when deleting rows it is advisable to work upwards, so as not to miss the comparison against any row when deleting rows:
Sub foo()
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
'declare and set your worksheet, amend as required
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'get the last row with data on Column A
For i = LastRow To 2 Step -1 'loop from last row to second (missing headers)
CheckID = ws.Cells(i, 2) 'get the Staff ID to check
For x = (i - 1) To 2 Step -1 'second loop for comparison
If ws.Cells(x, 2) = CheckID Then 'if ID's match
ws.Cells(i, 3) = ws.Cells(i, 3) + ws.Cells(x, 3) 'add values for Item A
ws.Cells(i, 4) = ws.Cells(i, 4) + ws.Cells(x, 4) 'add values for Item B
ws.Cells(i, 5) = ws.Cells(i, 5) + ws.Cells(x, 5) 'add values for Item C
ws.Cells(i, 6) = ws.Cells(i, 6) 'get the Group Number
ws.Cells(i, 7) = ws.Cells(i, 7) & Chr(10) & ws.Cells(x, 1) 'Add remark
ws.Rows(x).Delete Shift:=xlUp 'delete row
i = i - 1 'adjust counter
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row 'get new last row
End If
Next x
Next i
End Sub
Related
I have an Excel sheet (doc1) with 4 columns. In "A" I have people names. In "B","C" and "D", I have informations on the CV of each of these people. I would like to extract in another sheet (doc2) these informations in a specific format: For each CV information, I would like to insert a row with the name of the person in "A" and one information about his CV in "B". Basically if I have 3 informations about a person in doc1 (In B,C and D), I want to have 3 rows : In A1, A2 and A3 the name of the person, and in B1, B2 and B3 the person's infos.
I have a macro which does the exact opposite, it is basically doing a Vlookup which throws multiple results. Any idea on how to turn this around? Thanks!
Option Explicit
Sub GO()
Dim J As Long
Dim I As Integer
Dim K As Long
Dim Indice As Long
Dim Tablo
Dim Nb As Integer
Application.ScreenUpdating = False
ReDim Tablo(1 To Range("A" & Rows.Count).End(xlUp).Row - 2, 1 To 2)
Tablo(1, 1) = Range("A2")
Tablo(1, 2) = Range("B2")
Nb = 1
For J = 3 To Range("A" & Rows.Count).End(xlUp).Row
For K = 1 To UBound(Tablo)
If Range("A" & J) = Tablo(K, 1) Then
For I = 1 To UBound(Tablo, 2)
If Tablo(K, I) = "" Then
Tablo(K, I) = Range("B" & J)
Exit For
End If
Next I
If I > UBound(Tablo, 2) Then
ReDim Preserve Tablo(1 To UBound(Tablo), 1 To UBound(Tablo, 2) + 1)
Tablo(K, UBound(Tablo, 2)) = Range("B" & J)
End If
Exit For
ElseIf Tablo(K, 1) = "" Then
Nb = Nb + 1
Tablo(K, 1) = Range("A" & J)
Tablo(K, 2) = Range("B" & J)
Exit For
End If
Next K
Next J
With Sheets("doc2")
.Cells.ClearContents
.Range("A2").Resize(Nb, UBound(Tablo, 2)) = Tablo
.Range("A1") = "Name"
.Range("B1") = "C.V info 1"
.Range("B1").AutoFill .Range("B1").Resize(, UBound(Tablo, 2) - 1), xlFillSeries
End With
End Sub
try somethihng like this:
Function NeverCallAFunctionGO:
dim doc1 as worksheet, doc2 as worksheet
dim lRow as long
'set your doc1 and doc2 sheets
lRow = 1
For i = 1 to doc1.range("A1").end(xldown).row
doc2.range("A" & lRow).value = doc1.range("A" & i).value
doc2.range("B" & lRow).value = doc1.range("B" & i).value
doc2.range("B" & lRow+1).value = doc1.range("C" & i).value
doc2.rangE("B" & lRow+2).value = doc1.rangE("D" & i).value
lRow = lRow + 3
Next i
Following code is suggested by a helpful user, this works well to Calculate "From", "To", "MAX" etc values of a range. But this code gives results in every row of a range. I want to get the results in only first row of each row. Please help with this.
Sub trial()
Dim lastrow As Long
Dim destSht As Worksheet
Dim i As Long, j As Long
Set destSht = Worksheets("Final")
With Worksheets("Source")
lastrow = .Range("B" & .Rows.Count).End(xlUp).Row
For i = 2 To lastrow + 1 'loop whole range (column C)
If .Cells(i, "C") <> "" Then 'If column C is not empty then
For j = i To lastrow + 1 'Loop "group" range to find next empty cell. Start from current loop i to last row and add one row to get to next empty cell.
If .Cells(j, "C") = "" Then 'When next empty cell is found (i.e. end of small group range) then apply formulas
.Cells(i, "E").Value = .Cells(i, "B").Value 'From
.Cells(i, "F").Value = .Cells(j - 1, "B").Value 'To
.Cells(i, "G").Formula = "=MAX(C" & i & ":C" & j - 1 & ")" 'MAX
.Cells(i, "H").Formula = "=MIN(C" & i & ":C" & j - 1 & ")" 'MIN
.Cells(i, "I").Formula = "=AVERAGE(C" & i & ":C" & j - 1 & ")" 'AVG
Exit For
End If
Next j
End If
Next I
End With
End Sub
This Code gives following result
Desired Result
Try changing this line:
If .Cells(i, "C") <> "" Then 'If column C is not empty then
To this line:
If .Cells(i, "C") <> "" AND .Cells(i-1, "C") = "" Then 'If column C is not empty AND the column C above is empty then
I'm trying to make multiple selections from Sheet2. The value is from the same column but different rows (thinking if using ActiveCell.Offset(1,0) will be feasible).
My code takes the value from an ActiveCell select and runs a macro compares it to another sheet (Sheet10) with some information to copy and paste in a target sheet (Sheet5).
The following is the code that I have right now.
a = Sheet10.Cells(Rows.Count, 1).End(xlUp).Row
c = Sheet2.Cells(Rows.Count, 5).End(xlUp).Row
For Each cell In Range(ActiveCell, ActiveCell.Offset(1, 0))
For i = 2 To a 'from Row 1 to the last row of "DMP"
Debug.Print ("i = " & i)
If cell.Value = Sheet10.Cells(i, 1).Value Then 'if selected cell matches (i,1) of "Sheet10 (DMP)"
Debug.Print ("ActiveCell =" & ActiveCell.Value)
For k = 1 To 20 'from Column 1 to Column 20
Debug.Print ("k = " & k)
For r = 1 To c 'from Row 1 to the last row of "Sheet 2(LightOn SKU)"
Debug.Print ("r = " & r)
If Sheet10.Cells(i, k).Value = Sheet2.Cells(r, 4).Value Then 'if value of (i,k) of "Sheet10 (DMP)" = (r,4) of "Sheet2 (LightOn SKU)"
Sheet2.Range("A" & r & ":G" & r).Copy
Sheet5.Activate
b = Sheet5.Cells(Rows.Count, 1).End(xlUp).Row
Sheet5.Cells(b + 1, 1).Select
ActiveSheet.Paste
Range("A" & r & ":L" & r).Borders.Color = vbBlack
End If
Next
Next
End If
Next
Next
Right now, it's running on an endless loop.
Still Unclear
Sub ACCopy2()
Dim a As Long
Dim c As Long
Dim r As Long
Dim i As Long
Dim k As Integer
Dim b As Long
a = Sheet10.Cells(Rows.Count, 1).End(xlUp).Row
c = Sheet2.Cells(Rows.Count, 5).End(xlUp).Row
For r = 1 To c ' from Row 1 to the last row of "Sheet 2(LightOn SKU)"
Debug.Print ("r = " & r)
For i = 2 To a ' from Row 1 to the last row of "DMP"
Debug.Print ("i = " & i)
' if selected cell matches (i,1) of "Sheet10 (DMP)"
If Sheet2.Cells(r, 1).Value = Sheet10.Cells(i, 1).Value Then
Debug.Print ("Sheet2 =" & Sheet2.Cells(r, 1).Value)
For k = 1 To 20 ' from Column 1 to Column 20
Debug.Print ("k = " & k)
' if value of (i,k) of "Sheet10 (DMP)" = (r,4) of
' "Sheet2 (LightOn SKU)"
If Sheet10.Cells(i, k).Value = Sheet2.Cells(r, 4).Value Then
With Sheet5
b = Sheet5.Cells(Rows.Count, 1).End(xlUp).Row
Sheet2.Range("A" & r & ":G" & r).Copy .Cells(b + 1, 1)
.Range("A" & r & ":L" & r).Borders.Color = vbBlack
End With
End If
Next
End If
Next
Next
End Sub
I'm trying to copy a cell and the adjacent cell in a row and insert it as a new row with all the data to the right of this cell also copied over. My data looks like this after mining.
and im trying to get my data to look like this:
the image above is just one record but essentially its moving all the people and their corresponding position in the original row to a new row. In each row there are about 5 employees and their positions.
thanks
EDIT Attempted code for just 2 cols. 1 position. the idea was to create the empty rows and just copy the rest of the data with auto fill, then work from there
Sub TransposeInsertRows()
Dim rng As Range
Dim i As Long, j As Long, k As Long
Dim x As Long, y As Long
Set rng = Application.InputBox _
(Prompt:="Range Selection...", _
Title:="Enter the name col and pos col", Type:=8)
Application.ScreenUpdating = False
x = rng(1, 1).Column + 2
y = rng(1, rng.Columns.Count).Column
For i = rng(rng.Rows.Count, 1).Row To rng(1, 1).Row Step -1
If Cells(i, x) <> "" And Cells(i, x + 1) <> "" Then
k = Cells(i, x - 2).End(xlToRight).Column
If k > y Then k = y
For j = k To x + 1 Step -1
Cells(i + 1, 1).EntireRow.Insert
With Cells(i + 1, x - 2)
.Value = .Offset(-1, 0)
.Offset(0, 1) = .Offset(-1, 1)
.Offset(0, 2) = Cells(i, j)
End With
Cells(i, j).ClearContents
Next j
End If
Next i
Application.ScreenUpdating = True
End Sub
If there are always 5 people in each row then this should do it:
Sub foo()
LastRow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRow 'loop through rows
For x = 1 To 10 Step 2 'loop through columns
LastRow2 = Sheet2.Cells(Sheet2.Rows.Count, "A").End(xlUp).Row + 1 'find the next free row on Sheet2
Sheet2.Cells(LastRow2, 1).Value = Sheet1.Cells(i, x).Value 'add Person Name to Sheet2
Sheet2.Cells(LastRow2, 2).Value = Sheet1.Cells(i, x + 1).Value 'add position to Sheet2
Sheet1.Range("K" & i & ":U" & i).Copy Destination:=Sheet2.Cells(LastRow2, 3) 'copy range from K to U to Sheet2
Next x
Next i
End Sub
My main problem is that I am trying to add a row directly beneath another row based on the time value of that row. Here's an example of what I'm trying to do:
column F ========> new column F
2 1
2
2 1
2
1 1
1 1
2 1
2
To better explain, if the value in the first column F is a 2, that represents a time value that is greater than 0:59:00 and another row is added beneath it. If it is a 1, then it represents a time value that is equal to or less than 0:59:00and no row gets added.
I have multiple coding attempts at fixing this, and this first one is by someone more well-versed in VBA than I and includes some of his comments:
Public Sub ExpandRecords()
Dim i As Long, _
j As Long, _
LR As Long
'set variable types
LR = Range("A" & Rows.Count).End(xlUp).Row
'setting variable LR as number of rows with data
Application.ScreenUpdating = False
Columns("F:F").NumberFormat = "hh:mm:ss"
'sets number format in column b to text
For i = LR To 1 Step -1
'Executes following code from last row with data to row 1 working backwards
'If CLng(Left(Range("F" & i).Value, Len(Range("F" & i).Value) - 6)) > 0 Then
If CLng(Hour(Range("F" & i))) > 0 Then
'If the hour value in column F is greater than 1, then...
With Range("F" & i)
'starting with column F, loop through these statements...
'.Offset(1, 0).Resize(CLng(Left(Range("F" & i).Value, Len(Range("F" & i).Value) - 6)) - 1, 1).EntireRow.Insert Shift:=xlDown
.Offset(1, 0).Resize(CLng(Hour(Range("F" & i))).Value, Len(Range("F" & i).Value) - 1, 1).EntireRow.Insert Shift:=xlDown
'return the value of column F's hour value, change the range to insert the number of rows below based on hour value
'.Resize(CLng(Left(Range("F" & i).Value, Len(Range("F" & i).Value) - 6)), 1).EntireRow.Value = Range("A" & i).EntireRow.Value
.Resize(Hour(Range("F" & i)), 1).EntireRow.Value = Range("A" & i).EntireRow.Value
'Get value of row to be copied
'For j = 0 To CLng(Left(Range("F" & i).Value, Len(Range("F" & i).Value) - 6))
For j = 0 To Hour(Range("F" & i))
Range("H" & i).Offset(j - 1, 0).Value = Application.Text(j, "0")
Next j
End With
Else
Range("H" & i).Value = Application.Text(1, "0")
End If
Next i
Application.ScreenUpdating = True
End Sub
Here is a similar question from a previous user
Any help would be greatly appreciated.
Use this instead:
Public Sub ExpandRecords()
Dim i As Long, s As String
Const COL = "F"
For i = 1 To Cells(Rows.Count, COL).End(xlUp).Row
If Cells(i, COL) = 2 Then s = s & "," & Cells(i, COL).Address
Next
If Len(s) Then
Range(Mid$(s, 2)).EntireRow.Insert
For i = 1 To Cells(Rows.Count, COL).End(xlUp).Row
If Cells(i, COL) = vbNullString Then Cells(i, COL) = 1
Next
End If
End Sub