Hello everyone,
I have a problem to create VBA excel to duplicate data.
How to combine duplicate rows and sum the values 3 column in excel?
Thank you.
this one uses Remove Duplicates:
Sub dupremove()
Dim ws As Worksheet
Dim lastrow As Long
Set ws = Sheets("Sheet1") ' Change to your sheet
With ws
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
With .Range("B2:C" & lastrow)
.Offset(, 4).FormulaR1C1 = "=SUMIF(C1,RC1,C[-4])"
.Offset(, 4).Value = .Offset(, 4).Value
End With
With .Range("A1:A" & lastrow)
.Offset(, 4).Value.Value = .Value
End with
.Range("E1:G" & lastrow).RemoveDuplicates 1, xlYes
End With
End Sub
edited after OP's clarifications
try this
solution maintaining original data:
Option Explicit
Sub main()
With Worksheets("Sheet01") '<== change "Sheet01" as per your actual sheet name
With .Range("A1:C1").Resize(.Cells(.rows.Count, 1).End(xlUp).Row)
.Copy
With .Offset(, .Columns.Count + 1)
.PasteSpecial xlPasteAll ' copy value and formats
.Columns(2).Offset(1).Resize(.rows.Count - 1, 2).FormulaR1C1 = "=SUMIF(C1,RC1,C[-" & .Columns.Count + 1 & "])"
.Value = .Value
.RemoveDuplicates 1, xlYes
End With
End With
End With
End Sub
solution overwriting original data (kept for reference):
Sub main()
Dim helperRng As Range, dataRng As Range
Dim colToFilter As String
Dim colsToSumUp As Long
With Worksheets("Sheet01") '<== change "Sheet01" as per your actual sheet name
Set dataRng = .Range("A2:C2").Resize(.Cells(.rows.Count, 1).End(xlUp).Row - 1)
colToFilter = "A" ' set here the column header you want to sum up on
colsToSumUp = 3 ' number of adjacent columns to sum up with
Set helperRng = dataRng.Offset(, .UsedRange.Columns.Count + 1).Resize(, 1) 'localize "helper" cells first column out of sheet used range
With helperRng
.FormulaR1C1 = "=RC" & Cells(1, colToFilter).Column 'make a copy of the values you want to sum up on
.Offset(, 1).FormulaR1C1 = "=if(countif(R1C[-1]:RC[-1], RC[-1])=1,1,"""")" 'localize with "1" first occurrence of each unique value
With .Offset(, 2).Resize(, colsToSumUp)
.FormulaR1C1 = "=sumif(C" & helperRng.Column & ", RC" & helperRng.Column & ",C[" & Cells(1, colToFilter).Column - helperRng.Column - 1 & "])" 'sum up in adjacent columns
.Value = .Value 'get rid of formulas
End With
.Offset(, 1).SpecialCells(xlCellTypeFormulas, xlTextValues).EntireRow.Delete 'delete rows with repeted values you want to sum up on
dataRng.Columns(2).Resize(.rows.Count, colsToSumUp).Value = .Offset(, 2).Resize(.rows.Count, colsToSumUp).Value 'copy summed up values from "helper" cells
helperRng.Resize(, 1 + 1 + colsToSumUp).Clear 'clear "helper" cells
End With
End With
End Sub
it's commented so that you can follow the code and adapt to your actual data "structure"
Related
I tried using the code below but it display the entire row in the new sheet. Is there a way that i can move only specific columns to the new sheet by modifying the vba macro code below?
Thanks in advance!
Sub CopyExpired()
Dim bottomB As Integer
bottomB = Sheets("sheet1").Range("B" & Rows.Count).End(xlUp).Row
Dim c As Range
For Each c In Sheets("sheet1").Range("B1:B" & bottomB)
If c.Value = "expired" Then
c.EntireRow.Copy Worksheets("sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next c
End Sub
Try to use an .AutoFilter.
Sub CopyExpired()
With Worksheets("sheet1")
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, "A").CurrentRegion
.AutoFilter field:=2, Criteria1:="expired"
With .Resize(.Rows.Count - 1, 1).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
.SpecialCells(xlCellTypeVisible).Copy _
Destination:=Worksheets("sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
End Sub
Replace
c.EntireRow.Copy
with
Range("C" & c.Row & ",E" & c.Row & ",H" & c.Row).Copy
and you can select what columns to use
if I didnt do the syntax 100% right then sorry. Dont have excel near me.
1st: please dont use A1 codes in your macros. Rather use the R1C1 method as follows:
dim sh as worksheet
set sh =activeworkbook.activesheet
sh.cells(1,2) = "Test worked!!"
'this will put the text into row 1 column 2 of your sheet.
2nd: you could copy each cell via a subroutine.
for example:
dim rw1 as integer, lastRw as integer, cellsToRight as integer
lastRw = sh.UsedRange.SpecialCells(xlCellTypeLastCell).Row
for rw1 = 1 to lrw
for col=1 to 10
sh.cells(rw1,col + cellstoright)=sh.cells(rw1,col)
next col
next rw1
or you could just do the colums yourself manualls, eg... array of integer with the values 1,3,4,6,7,8 ... and then loop over the array with your integers as columns, same thing as the above loops.
I was trying to figure out how to have excel look at a cell in my workbook, if the cell has a value greater than 0 then copy that row into sheet2. It then looks at the next cell in the column.
Does anyone know??
I need it looking at cell I10 to start off and if I10>0 copy data from A10:K10 to sheet2 else look at I11 and repeat, then I12... until all 750+ rows are either copied or not.
Thanks so much for all the help!!!
Option Explicit
Sub Macro1()
Dim cell As Range
Dim lastRow As Long, i As Long
lastRow = Range("I" & Rows.Count).End(xlUp).Row
i = 10 ' change this to the wanted starting row in sheet2
For Each cell In Sheets(1).Range("I10:I" & lastRow)
If cell.Value > 0 Then
cell.EntireRow.Copy Sheets(2).Cells(i, 1)
i = i + 1
End If
Next
End Sub
you can use AutoFilter() method of Range object and avoid looping through cells:
Sub Main()
With Worksheets("OriginWs") '<--| change "OriginWs" to your actual data worksheet name
With .Range("I9", .Cells(.Rows.Count, "I").End(xlUp))
If IsEmpty(.Cells(1, 1)) Then .Cells(1, 1) = "dummyheader"
.AutoFilter Field:=1, Criteria1:=">0"
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then .Offset(1, -8).Resize(.Rows.Count - 1, 11).SpecialCells(xlCellTypeVisible).Copy Worksheets("TargetWs").Cells(1, 1) '<--| change "TargetWs" to your actual destination worksheet name
If .Cells(1, 1).Value = "dummyheader" Then .Cells(1, 1).ClearContents
End With
.AutoFilterMode = False
End With
End Sub
BTW, the statements:
If IsEmpty(.Cells(1, 1)) Then .Cells(1, 1) = "dummyheader"
and
If .Cells(1, 1).Value = "dummyheader" Then .Cells(1, 1).ClearContents
can be avoided if your cell I9 has some text for sure
I have the following form which should be completed BEFORE the data is submitted to the sheet:
I am trying to code it so upon completion of the form and when the save button is clicked, it will find the first empty cell in column A and copy down the formula from above, I have managed to do this successfully but now I want to tab into column B and copy down the formula from above like before.
THEN tab into column C and enter the data in order from the form I have created into adjacent cells.
Here is my code but I really am in the dark here!
Private Sub CommandButton2_Click()
Dim irow As Long
Dim ws As Worksheet
Set ws = Worksheets("Master Data")
NextFree = Range("A10:A" & Rows.Count).Cells.SpecialCells(xlCellTypeBlanks).Row
Range("A" & NextFree).Select
' Copy formula from cell above
Dim oCell As Range
For Each oCell In Selection
If (oCell.Value = "") Then
oCell.Offset(-1, 0).Copy Destination:=oCell
End If
Next oCell
End Sub
' Move to adjacent cell
Sub MoveOver()
ActiveCell.Offset(0, 1).Select
End Sub
'Insert data into cells
Sub LastRow()
.Offset(1, 0) = ComboBox1.Text
.Offset(1, 1) = TextBox1.Value
.Offset(1, 2) = TextBox2.Value
.Offset(1, 3) = TextBox3.Value
.Offset(1, 4) = TextBox4.Value
.Offset(1, 5) = TextBox5.Value
.Offset(1, 6) = TextBox6.Value
End Sub
Could it be something like this you are looking for?
Dim lstRw As Long
lstRw = Cells(Rows.Count, "A").End(xlUp).Row
Range("A" & lstRw & ":B" & lstRw).Copy Range("A" & lstRw + 1)
You can keep it in the same sub, such as
Dim lstRw As Long
Dim Rng As Range
lstRw = Cells(Rows.Count, "A").End(xlUp).Row
Set Rng = Range("A" & lstRw + 1)
Range("A" & lstRw & ":B" & lstRw).Copy Range("A" & lstRw + 1)
With Rng
.Offset(, 2) = ComboBox1.Text
.Offset(, 3) = TextBox1.Value
.Offset(, 4) = TextBox2.Value
.Offset(, 5) = TextBox3.Value
.Offset(, 6) = TextBox4.Value
.Offset(, 7) = TextBox5.Value
.Offset(, 8) = TextBox6.Value
End With
I need to copy values only without Formula from sheet to another. The following code does copy but only with Formula. I tried some solutions presented in this site but they give me errors.
For i = 2 To LastRow
'sheet to copy from
With Worksheets("Hoist")
'check column H value before copying
If .Cells(i, 8).Value >= -90 _
And CStr(.Cells(i, 9).Value) <> "Approved" _
And CStr(.Cells(i, 9).Value) <> "" _
And CStr(.Cells(i, 10).Value) = "" Then
'copy row to "display" sheet
.Rows(i).Copy Destination:=Worksheets("display").Range("A" & j)
j = j + 1
End If
End With
Next i
Try changing this line:
.Rows(i).Copy Destination:=Worksheets("display").Range("A" & j)
to this:
.Rows(i).Copy
Worksheets("display").Range("A" & j).PasteSpecial xlPasteValues
This however drops all formatting. To include formatting, you'll need to add another line like:
Worksheets("display").Range("A" & j).PasteSpecial xlPasteFormats
Another option is to enter a working column and use AutoFilter to avoid loops
insert a column in column A
the working column formuka is =AND(I2>-90,AND(J2<>"",J2<>"Approved"),K2="")
filter and copy the TRUE rows
delete working column A
code
Sub Recut()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets("Hoist")
ws.AutoFilterMode = False
Set rng1 = Range([h2], Cells(Rows.Count, "H").End(xlUp))
ws.Columns(1).Columns.Insert
rng1.Offset(0, -8).FormulaR1C1 = "=AND(RC[8]>-90,AND(RC[9]<>"""",RC[9]<>""Approved""),RC[10]="""")"
With rng1.Offset(-1, -8).Resize(rng1.Rows.Count + 1, 1).EntireRow
.AutoFilter Field:=1, Criteria1:="TRUE"
.Copy Sheets("display").Range("A1")
Sheets("display").Columns("A").Delete
End With
ws.Columns(1).Delete
ws.AutoFilterMode = False
End Sub
This is a separate question stemming from this post: How to use the filename of an excel file to change a column of cells?
I noticed that in the last post's code it was referencing specific cells (J2,K2). However when using the code, I came into an error when the columns changed. So now I am seeking a way to modify the below code to use the names of the header columns to populate the 2nd column instead of referencing specific cells. I think the only line that really needs adjusting is the myRng line, but I will provide all the code I am trying for reference.
In case you don't read the other post, I will describe the issue. I am trying to fill in the 2nd column (name+type) based on the "name" column and the filename. When I was referencing the K or J row in the code, everything was working fine, but when I load a different file and the columns positions have changed, everything gets messed up.
I need to populate the 2nd column (name+type) to be the exactly the same number or rows as the 1st column (name) which is why I am using the Range ("K2:K" & lastCell) formula.
Is there a way to do this?
Current Attempted VBA code:
' Insert Column after name and then rename it name+type
Rows(1).Find("name").Offset(0, 1).EntireColumn.Insert
Rows(1).Find("name").Offset(0, 1).FormulaR1C1 = "name+type"
Dim myRng As Range
Dim lastCell As Long
Dim myOtherRange As Range
Dim column2Range As Range
myOtherRange = Rows(1).Find("name")
column2Range = Rows(1).Find("name+type")
lastCell = Range(myOtherRange).End(xlDown).Row
Set myRng = Range("K2:K" & lastCell)
myOtherRange.FormulaR2C1 = "=LEFT(MID(CELL(""filename""),SEARCH(""["",CELL(""filename""))+1, SEARCH(""]"",CELL(""filename""))-SEARCH(""["",CELL(""filename""))-1),5)&RC[-1]"
myOtherRange.FormulaR2C1.Select
Selection.Copy
myRng.Select
ActiveSheet.Paste
First Draft VBA code:
' Insert Column after name and then rename it name+type
Rows(1).Find("name").Offset(0, 1).EntireColumn.Insert
Rows(1).Find("name").Offset(0, 1).FormulaR1C1 = "name+type"
'Add the contents to the name+type column
Range("K2").Select
ActiveCell.FormulaR1C1 = "=LEFT(MID(CELL(""filename"",RC[-1]),SEARCH(""["",CELL(""filename"",RC[-1]))+1,SEARCH(""]"",CELL(""filename"",RC[-1]))-SEARCH(""["",CELL(""filename"",RC[-1]))-1),5)&RC[-1]"
Range("K2").Select
Selection.Copy
Range("K2:K8294").Select
ActiveSheet.Paste
#Scott or Siddharth Rout probably =) – Jonny 11 hours ago
I would never recommend this :) SO is full of experts who can assist you. Why do you want to limit the help that you can get? ;)
Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, aCol As Long
Dim aCell As Range
Set ws = Sheets("Sheet1") '<~~ Change this to the relevant sheet name
With ws
Set aCell = .Rows(1).Find("Name")
'~~> Check if the column with "name" is found
If Not aCell Is Nothing Then
aCol = aCell.Column
.Columns(aCol + 1).EntireColumn.Insert
.Cells(1, aCol + 1).Value = "Name+Type"
.Activate
.Rows(1).Select
With ActiveWindow
.SplitColumn = 0
.SplitRow = 1
.FreezePanes = True
End With
'~~> Get lastrow of Col which has "name"
lRow = .Range(Split(.Cells(, aCol).Address, "$")(1) & .Rows.Count).End(xlUp).Row
ThisWorkbook.Save
'~~> Add the formula to all the cells in 1 go.
.Range(Split(.Cells(, aCol + 1).Address, "$")(1) & "2:" & _
Split(.Cells(, aCol + 1).Address, "$")(1) & lRow).Formula = _
"=LEFT(MID(CELL(""filename"",RC[-1]),SEARCH(""["",CELL(""filename"",RC[-1]))+1," & _
"SEARCH(""]"",CELL(""filename"",RC[-1]))-SEARCH(""["",CELL(""filename"",RC[-1]))-1),5)&RC[-1]"
.Columns("A:AK").Columns.AutoFit
Else
MsgBox "Name Column Not Found"
End If
End With
End Sub
After modifying the code provided by Siddharth, this is the final code that worked for me. The save feature needed to also remove a format and the Formula to search and add the filename to the cells did not work without this edit. I also had to change the sheet to the activeSheet, because it was constantly changing. Here is the code:
Sub Naming()
Dim LR As Long, i As Long, lngCol As Long
lngCol = Rows(1).Find("NAME", lookat:=xlWhole).Column 'assumes there will always be a column with "NAME" in row 1
Application.ScreenUpdating = False
LR = Cells(Rows.Count, lngCol).End(xlUp).Row
For i = LR To 1 Step -1
If Len(Cells(i, lngCol).Value) < 4 Then Rows(i).Delete
Next i
Application.ScreenUpdating = True
' Insert Column after NAME and then rename it NAME+TYPE
Dim ws As Worksheet
Dim lRow As Long, aCol As Long
Dim aCell As Range
Set ws = ActiveSheet 'Need to change to the Active sheet
With ws
Set aCell = .Rows(1).Find("NAME")
' Check if the column with "NAME" is found, it is assumed earlier
If Not aCell Is Nothing Then
aCol = aCell.Column
.Columns(aCol + 1).EntireColumn.Insert
.Cells(1, aCol + 1).Value = "NAME+TYPE"
.Activate
' Freeze the Top Row
Rows("1:1").Select
With ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
ActiveWindow.FreezePanes = True
' Get lastrow of Col which has "NAME"
lRow = .Range(Split(.Cells(, aCol).Address, "$")(1) & .Rows.Count).End(xlUp).Row
'Save the file and format the filetype
Dim wkb As Workbook
Set wkb = ActiveWorkbook 'change to your workbook reference
wkb.SaveAs Replace(wkb.Name, "#csv.gz", ""), 52 'change "csv.gz" to ".xlsm" if need be
' Add the formula to all the cells in 1 go.
.Range(Split(.Cells(, aCol + 1).Address, "$")(1) & "2:" & _
Split(.Cells(, aCol + 1).Address, "$")(1) & lRow).Formula = _
"=LEFT(MID(CELL(""filename""),SEARCH(""["",CELL(""filename""))+1, SEARCH(""]"",CELL(""filename""))-SEARCH(""["",CELL(""filename""))-1),5)&RC[-1]"
.Columns("A:AK").Columns.AutoFit
Else
MsgBox "NAME Column Not Found"
End If
End With
' Change the Range of the cursor
Range("A1").Select
Application.CutCopyMode = False
End Sub