I'm a complete novice at macro programming in excel. I have an excel file with over 1000 lines of data and would like to delete the entire row when the data in column 44 is repeated in consecutive rows. I've attached the script that I've been trying to tweak to no avail.
Currently the script deletes most of the duplicate rows but not all and I can't figure out why.
Sub deleteDupes()
Dim i As Long
With Sheets("Sheet1")
For i = .Cells(Rows.Count, 1).End(xlUp).row To 2 Step -1
If .Cells(i, 44).Value = .Cells(i - 1, 44).Value Then _
.Rows(i).Delete
Next i
End With
End Sub
You should delete the rows all at once rather than at each line. You can use the UNION method to accomplish this. This WILL successfully do what you are describing. If you have issues it has to do with your data.
More importantly, this will make your procedure one MUCH faster.
Sub deleteDupes()
Dim i As Long
With Sheets("Sheet1")
Dim killRng As Range
Set killRng = Rows(Rows.Count)
For i = .Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
If .Cells(i, 44).Value = .Cells(i - 1, 44).Value Then _
Set killRng = Union(Rows(i), killRng)
Next i
End With
killRng.EntireRow.Delete
End Sub
Related
Sample Data :
0votes
https://stackoverflow.com/questions/32382401/autohide-multiple-rows-in-excel/32383360#32383360
vbaexcel
answered Sep 3, 2015 at 18:53
0votes
Accepted
https://stackoverflow.com/questions/32273121/corretc-excel-vba-macro-to-return-the-values-as-text-and-as-date/32273219#32273219 'clickable format
vbaexcel
answered Aug 28, 2015 at 14:18
I want to insert a row between votes and url line if the answer is not accepted and url immediately follws votes line with a purpose to make grouping of 5 rows for ultimately transposing data in a single row.
Code use by me is as follows :
Sub insertrow()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet2")
Last = Cells(Rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "A").Value) Like "*vote*" And (Cells(i + 1, "A").Value) <> "Accepted" Then
Cells(i + 1, "A").EntireRow.Insert
End If
Next i
End Sub
I am getting Run time error 13 Type mismatch on the following line although this program ran succesfully yesterday night for simmiliar data.
` If (Cells(i, "A").Value) Like "*vote*" And (Cells(i + 1, "A").Value) <> "Accepted" `
Any help shall be appreciated very much.
Did a quick test with the data and the code you provided and had no issues. However, there is a problem with the code: Although you assign a specific sheet to a variable, you continue to work with the ActiveSheet. It is likely that this sheet is not the sheet with your sample data and may contain data that lead to the type mismatch error.
When programming VBA in Excel, you should always qualify exactly on which worksheet you want to work. One way is to use a With-statement. Take care that before every instance of Cells, Range, Rows and Columns you add a dot - that tells VBA you are referring to the object of the With-statement.
Sub insertrow()
With ThisWorkbook.Sheets("Sheet2")
Dim Last As Long, i As Long
Last = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step -1
If (.Cells(i, "A").Value) Like "*vote*" _
And (.Cells(i + 1, "A").Value) <> "Accepted" Then
.Cells(i + 1, "A").EntireRow.Insert
End If
Next i
End With
End Sub
Or, if you like that better:
Sub insertrow()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet2")
Dim Last As Long, i As Long
Last = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step -1
If (ws.Cells(i, "A").Value) Like "*vote*" _
And (ws.Cells(i + 1, "A").Value) <> "Accepted" Then
ws.Cells(i + 1, "A").EntireRow.Insert
End If
Next i
End Sub
Errors like type mismatch usually can be revealed rather easy by checking the related data (in this case content of 2 cells) with the debugger.
Situation:
I have an excel macro which imports a column of data into an existing sheet in the next free column, it also clears formatting of the previous column which will be set at the completion of the macro (the bit I'm trying to work out here).
I need the code to compare each cell in the new column to the previous column to see if there is a match, if no match then highlight the cell.
Problem:
I keep getting type mismatch errors, or the code does not run. My latest attempt (which incluces copying the unique data to a different sheet which would be a bonus if working) is below.
Dim rngCell As Range
For Each rngCell In Range(Cells(2, Worksheets("Data").Columns(LastColumn)), Cells(10000, Worksheets("Data").Columns(LastColumn)))
'I know hardcoding values is bad, but i did this for testing purposes
If WorksheetFunction.CountIf(Range(Cells(2, Worksheets("Data").Columns(LastColumn)), Cells(10000, Worksheets("Data").Columns(LastColumn))), rngCell) = 0 Then
Range("D" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
Ideal outcome:
The code runs through and highlights unique values in column 1 (using column index references as each day a new column is imported).
The code copies the unique values to another sheet for ease of use.
Thanks in advance for any pointers or code.
Since you are only posting a part of your code, I'd have to assume that the part wher you insert and clear formatting is already working well.
Sometimes you define a worksheet, sometimes you don't so I'm not sure what sheet we are working with here.
But just to clarify, if you had data in column "A", and then ran the macro to paste data in column "B", would you want something like this:
prevCol = 1
lastCol = 2
Set Rng = Range(Cells(2, prevCol), Cells(100, prevCol))
Set Rng2 = Range(Cells(2, lastCol), Cells(100, lastCol))
For Each rngCell In Rng
If WorksheetFunction.CountIf(Rng2, rngCell) = 0 Then
rngCell.Interior.Color = RGB(250, 230, 20)
End If
Next
Where unique items in the column that existed before the new one got inserted are highligted?
So in the end, maybe something more like this:
Sub SubName()
Dim sht As Worksheet
Dim lastCol As Long, lastRow As Long
Set sht = Worksheets("Data") 'or whatever
' Instert column
' clear formatting
lastCol = sht.Cells(2, sht.Columns.Count).End(xlToLeft).Column
lastRow = sht.Cells(sht.Rows.Count, lastCol - 1).End(xlUp).Row
For Each rngCell In Range(Cells(2, lastCol - 1), Cells(lastRow, lastCol - 1))
If WorksheetFunction.CountIf(Range(Cells(2, lastCol), Cells(lastRow, lastCol)), rngCell) = 0 Then
rngCell.Interior.Color = RGB(250, 230, 20)
End If
Next
End Sub
I have been given a work task where im to find and replace 8 digits numbers with a corresponding new values coming from a 2 column table....basically a vlookup then replace the old value with a new one...
The challenge im facing is.... the 2 column table is 882k rows, and the cells im trying to replace is about 120 million (41,000 rows x 3000 columns)...
I tried running a vba code i found somewhere...
Option Explicit
Sub Replace_Overwrite()
Dim LRow As Long, i As Long
Dim varSearch As Variant
With Sheets("Sheet2")
LRow = .Cells(.Rows.Count, 1).End(xlUp).Row
varSearch = .Range("A2:B" & LRow)
End With
With Sheets("Sheet1").UsedRange
For i = LBound(varSearch) To UBound(varSearch)
.Replace what:=varSearch(i, 1), replacement:=varSearch(i, 2), lookat:=xlWhole
Next
End With
End Sub
I tried using this and it ran it for 8 hours and my work laptop crashed....
I'm not sure anymore if this is still possible with MS Excel alone...
I wonder if anyone can help me with a code that can process it.. i can leave my system open over the weekend if its stable and does work.. it only has 8GB ram btw, running excel 2013...
To speed up things, do as much as possible in memory and minimize the interaction between VBA and Excel (as this makes things really slow).
The following attempt reads the lookup-list into a dictionary and then processes the data column by column.
I did a test, creating 880.000 lookup rows and 40.000 x 100 cells of data. Building the dictionary took less than a minute, processing the columns took 3-4 seconds per column. I added a logic that after every 10 columns, the whole workbook is saved, that increased the processing time but ensures that after a crash you can more or less continue where you left (the yellow color tells you where, just replace the 1 in for col=1 with the column where you want to restart).
I have added some DoEvents, that in theory slows down the process a little bit. Advantage is that you can see the output of the debug.print and the whole Excel process is not displayed as unresponsive in the task manager.
To build the dictionary, I read the complete data into an array at once (if you are not familiar with Dictionaries: You need to add a reference to the Microsoft Scripting Runtime).
Function createDict() As Dictionary
Dim d As New Dictionary
Dim rowCount As Long
Dim list()
Debug.Print Now, "Read data from Lookup sheet"
With ThisWorkbook.Sheets(1)
rowCount = .Cells(.Rows.Count, 1).End(xlUp).row
list = .Range("A1:B" & rowCount).Value
End With
Debug.Print Now, "Build dictionary."
Dim row As Long
For row = 1 To UBound(list)
If Not d.Exists(list(row, 1)) Then d.Add list(row, 1), list(row, 2)
If row Mod 1000 = 0 Then DoEvents
Next row
Set createDict = d
End Function
As said, replacing the data is done column by column. Again, I read the whole column at once into an array, do the replace on this array and then write it back to the sheet.
Sub replaceAll()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim d As Dictionary
Set d = createDict
Dim row As Long, col As Long
Dim rowCount As Long, colCount As Long
With ThisWorkbook.Sheets(2)
rowCount = .Cells(.Rows.Count, 1).End(xlUp).row
colCount = .Cells(1, .Columns.Count).End(xlToLeft).Column
For col = 1 To colCount
Debug.Print Now & "processing col " & col
DoEvents
Dim data
data = .Range(.Cells(1, col), .Cells(rowCount, col))
For row = 1 To rowCount
If d.Exists(data(row, 1)) Then data(row, 1) = d(data(row, 1))
Next row
.Range(.Cells(1, col), .Cells(rowCount, col)) = data
.Cells(1, col).Interior.Color = vbYellow
If col Mod 10 = 0 Then ThisWorkbook.Save
Next
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
One remark: You should consider to use a database for such amount of data.
Its been a while since I have done any sort of coding, so I am very rusty.
I am trying to write some VBA code, so that when a button is clicked in the excel sheet it will check another sheet in the same workbook and copy of specific cell values. This is based on a criteria in one of the columns (column 15, I counted); I should probably add that the data is in a table. if that row meets the specified criteria from column 15, then specific columns are copied over to the worksheet with the button.
I do have some code, but I know there is a lot missing from it.
Would appreciate some input, am I on the right track? can anyone help on there I can get more info and tips on the coding I need to use. Not sure if there is an easy way to do this using tables?
Private Sub CommandButton1_Click()
''This will count how many rows are populated in the table''
a = Worksheets("Billable").Cells(Rows.Count, 1).End(xlUp).Row
''Loop will run from row 6 to the last row (Row 6 is the first row in table)''
For i = 6 To a
''If statement which will check the status column for Detailed Estimate Submitted > column 15''
If Worksheets("Billable").Cells(i, 15).Value = "Detailed Estimate Submitted" Then
Worksheets("Billable").Rows(i).Copy
Worksheets("PM_Forecast").Activate
b = Worksheets("PM_Forecast").Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("PM_Forecast").Cells(a + 1, 1).Select
ActiveSheet.Paste
End If
Next
Application.CutCopyMode = False
End Sub
An example of the table: -
I only need to copy over 3 of the columns if they meet a specific criteria in the status column
You did not answer my question regarding the format pasting...
So, please, test the next code which pastes on a classical way. But without selecting and declaring all used variables:
Private Sub CommandButton1_Click()
Dim shB As Worksheet, shPM As Worksheet, lastRowB As Long, lastRowPM As Long
Dim i As Long, lastCol As Long
Set shB = Worksheets("Billable")
Set shPM = Worksheets("PM_Forecast")
lastRowB = Worksheets("Billable").Cells(Rows.Count, 1).End(xlUp).row
'Loop will run from row 6 to the last row (Row 6 is the first row in table)''
For i = 6 To lastRowB
If shB.Cells(i, 15).Value = "Detailed Estimate Submitted" Then
lastCol = shB.Cells(i, Columns.Count).End(xlToLeft).Column
lastRowPM = shPM.Cells(Rows.Count, 1).End(xlUp).row
shB.Range(shB.Range("A" & i), shB.Cells(i, lastCol)).Copy _
shPM.Cells(lastRowPM + 1, 1)
End If
Next
Application.CutCopyMode = False
End Sub
For array using variant you must only declare a new variable Dim arr As Variant and replace this part:
shB.Range(shB.Range("A" & i), shB.Cells(i, lastCol)).Copy _
shPM.Cells(lastRowPM + 1, 1)
with this one:
arr = shB.Range(shB.Range("A" & i), shB.Cells(i, lastCol)).Value
shPM.Cells(lastRowPM + 1, 1).Resize(, UBound(arr, 2)).Value = arr
Then, delete the code line Application.CutCopyMode = False. It is not necessary, anymore, since the Clipboard memory is not used...
And use Option Explicit on top of your module. It will save you many times, when the code will become complex.
I cant comment so I will ask the question through this answer:
Your variable b is currently not being used, I think it was meant to be in this line: Worksheets("PM_Forecast").Cells(b + 1, 1).Select but you have written a instead of b.
Does this solve your current issue?
I have an excel sheet with 2 columns as below:
IMPORT_ID EXPORT_ID
SI1313721 SI1440839
SI1313721 SI1440997
SI1313722 SI1440672
SI1313722 SI1440776
SI1313722 SI1441313
IMPORT_IDs are getting repeated (SI1313721 - 2 times and SI1313722 - 3 times). I want to transpose this sheet into
SI1313721 SI1440839 SI1440997
SI1313722 SI1440672 SI1440776 SI1441313
How do I do that in Excel probably with vba?
I'm not sure if the order that they are stacked on the right matters but you could try this.
Sub TransposingColumns_to_Avoid_redundancies()
Dim rw As Long, p As Long
With ActiveSheet '<- set this worksheet reference properly!
For rw = .Cells(Rows.Count, 1).End(xlUp).Row To 3 Step -1
If CBool(Application.CountIf(.Cells(1, 1).Resize(rw - 1), .Cells(rw, 1).Value2)) Then
p = Application.Match(.Cells(rw, 1).Value2, .Cells(1, 1).Resize(rw - 1), 0)
.Cells(p, Columns.Count).End(xlToLeft).Offset(0, 1) = .Cells(rw, 2).Value2
.Rows(rw).EntireRow.Delete
End If
Next rw
End With
End Sub
The rows are deleted as the values from column B are stacked to the right. It is usually better to start at the bottom and work up when deleting rows.