Sorting + Inserting Values - excel

I have two problems I'm trying to solve.
First, I'm trying to sort by column AP (this column contains a 1 for every row where column AI is not blank).
The code is supposed to sort so that anytime column AP = 1, the rows that have a 1 appear at the bottom.
Unfortunately, this keeps the rows with a 1 in the middle, and doesn't logically order by putting the zeroes at the top and the ones at the bottom.
Sub SortSheet()
Dim lastrow As Long
lastrow = Cells(Rows.Count, 2).End(xlUp).Row
Range("A2:AP" & lastrow).Sort key1:=Range("AP2:AP" & lastrow), _
order1:=xlDescending, Header:=xlNo
End Sub
Second, when we sort by column AP, I want to insert three blank rows between where the sorted rows change from 0 to 1.
So in other words, if the first 5 rows are 0 and the 6th row is a 1, I want to insert three blank rows above row 6.

Maybe you need to paste column AP as values before sorting (if they are linked to a cell). The code correctly sorted AP for me.
Here's the full code
Sub SortSheet()
Dim lastrow As Long
Dim firstzero As Range
Dim x As Long
lastrow = Cells(Rows.Count, 2).End(xlUp).Row
Range("A2:AP" & lastrow).Copy
Range("A2:AP" & lastrow).PasteSpecial Paste:=xlPasteValues
Range("A2:AP" & lastrow).Sort key1:=Range("AP2:AP" & lastrow), _
order1:=xlDescending, Header:=xlNo
Range("AP2:AP" & lastrow).Find(0).Select
For x = 1 To 3
ActiveCell.EntireRow.Select
Selection.Copy
Selection.Insert Shift:=xlUp
Application.CutCopyMode = False
Selection.ClearContents
Next x
End Sub

Related

I do not understand why my VBA code doesn't work for Excel tables with only one row

clever minds.
I've been working on my code for a while now and there is something weird I do not understand.
But first, let me explain to you what is the situation and what I want my VBA code to do.
I have an Excel spreadsheet with several sheets. One sheet = one business unit of my company.
In each of these sheets, there is a table with data related to the business unit.
I've been coding a VBA program whose goal is to take the data from each table and put them in the same table in a sheet named "All".
It "works" but there is one scenario that can break my code. It is when one of my tables has only one row of data.
Everything works when my tables have no data at all or at least 2 or more. But not if one of them has only one row. And I don't understand why.
Here is my full code:
Sub Final_Macro()
'
' Total_Test1 Macro
'Voir clearcontent pour effacer
Dim LastRow As Long
Dim LastRowCount As Long
Sheets("All").Select
Range("A3:DZ50000").ClearContents
Application.Goto Reference:="Ref_EPG" 'Goes to the Ref_EPG table and selects it
If Not IsEmpty(ActiveCell.Value) Then
Selection.Copy 'Copies the Ref_EPG table
Sheets("All").Select 'Goes to the "All" tab
Range("A3").Select 'Selects cell A3
ActiveSheet.Paste 'Paste the Reference Numbs in the rows
Range("B3").Select 'Selects cell B3
Application.CutCopyMode = False 'Clears the clipboard
ActiveCell.FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,EPG_Table,EPG!R1C,FALSE))=0,"""",VLOOKUP(RC1,EPG_Table,EPG!R1C,FALSE))" 'Sets up the VLOOKUP function and if there is nothing in the source cell, returns blank instead of 0.
LastRowCount = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count 'Determines the last row used in column A
LastRow = Sheets("All").Range("A" & Rows.Count).End(xlUp).Row
If LastRowCount > 1 Then
Sheets("All").Range("B3").AutoFill Destination:=Sheets("All").Range("B3:B" & LastRow) 'Autofills the VLOOKUP function from B3 to the last used row of Ref_Numbers
End If
End If
'Now let's do the same with Insulation
Dim LastRow2 As Long
Application.Goto Reference:="Ref_IG" 'Goes to the Ref_IG table and selects it
If Not IsEmpty(ActiveCell.Value) Then
Selection.Copy 'Copies the Ref_IG table
Sheets("All").Select 'Goes to the "All" tab
Range("A" & Rows.Count).End(xlUp).Offset(1).Select 'For Ref_Numbers This function is used to automatically go to the last cell of the table that doesn't have content in it. Should help avoiding overwriting rows
ActiveSheet.Paste 'Paste the Reference Numbs in the rows
'ActiveCell.Offset(0, 1).Select this line is a possible alternative to the next one. The result is the same but just works differently
Range("B" & Rows.Count).End(xlUp).Offset(1).Select 'Selects the last cell of column B that is not used yet
ActiveCell.FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,IG_Table,IG!R1C,FALSE))=0,"""",VLOOKUP(RC1,IG_Table,IG!R1C,FALSE))" 'Sets up the VLOOKUP function and if there is nothing in the source cell, returns blank instead of 0.
Application.CutCopyMode = False 'Clears the clipboard
LastRow2 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count 'Determines the last row used in column A
Range("B" & Rows.Count).End(xlUp).Offset(0).Select
If LastRow2 - LastRow > 1 Then
ActiveCell.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":B" & LastRow2) 'Autofills the VLOOKUP function from the last B cell used to the last used row of Ref_Numbers
End If
End If
'Now let's do the same with Gypsum
Dim LastRow3 As Long
Application.Goto Reference:="Ref_GYPCLG" 'Goes to the Ref_GYP table and selects it
If Not IsEmpty(ActiveCell.Value) Then
Selection.Copy 'Copies the Ref_GYPCLG table
Sheets("All").Select 'Goes to the "All" tab
Range("A" & Rows.Count).End(xlUp).Offset(1).Select 'For Ref_Numbers This function is used to automatically go to the last cell of the table that doesn't have content in it. Should help avoiding overwriting rows
ActiveSheet.Paste 'Paste the Reference Numbs in the rows
Range("B" & Rows.Count).End(xlUp).Offset(1).Select 'Selects the last cell of column B that is not used yet
Application.CutCopyMode = False 'Clears the clipboard
LastRow3 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count 'Determines the last row used in column A
Range("B" & Rows.Count).End(xlUp).Offset(1).Select
ActiveCell.FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,GYPCLG_Table,GYPCLG!R1C,FALSE))=0,"""",VLOOKUP(RC1,GYPCLG_Table,GYPCLG!R1C,FALSE))" 'Sets up the VLOOKUP function and if there is nothing in the source cell, returns blank instead of 0.
If LastRow3 - LastRow2 > 1 Then
ActiveCell.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":B" & LastRow3) 'Autofills the VLOOKUP function from the last B cell used to the last used row of Ref_Numbers
End If
End If
'Now let's do the same with Glass Solutions
Dim LastRow4 As Long
Application.Goto Reference:="Ref_GLASS" 'Goes to the Ref_GLASS table and selects it
If Not IsEmpty(ActiveCell.Value) Then
Selection.Copy 'Copies the Ref_GLASS table
Sheets("All").Select 'Goes to the "All" tab
Range("A" & Rows.Count).End(xlUp).Offset(1).Select 'For Ref_Numbers This function is used to automatically go to the last cell of the table that doesn't have content in it. Should help avoiding overwriting rows
ActiveSheet.Paste 'Paste the Reference Numbs in the rows
Range("B" & Rows.Count).End(xlUp).Offset(1).Select 'Selects the last cell of column B that is not used yet
Application.CutCopyMode = False 'Clears the clipboard
LastRow4 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count 'Determines the last row used in column A
'Range("B" & Rows.Count).End(xlUp).Offset(1).Select
ActiveCell.FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,GLASS_Table,GLASS!R1C,FALSE))=0,"""",VLOOKUP(RC1,GLASS_Table,GLASS!R1C,FALSE))" 'Sets up the VLOOKUP function and if there is nothing in the source cell, returns blank instead of 0.
If LastRow4 - LastRow3 > 1 Then
ActiveCell.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":B" & LastRow4) 'Autofills the VLOOKUP function from the last B cell used to the last used row of Ref_Numbers
End If
End If
'Now let's do the same with Holdings
Dim LastRow5 As Long
Application.Goto Reference:="Ref_HOLD" 'Goes to the Ref_GLASS table and selects it
If Not IsEmpty(ActiveCell.Value) Then
Selection.Copy 'Copies the Ref_INSU table
Sheets("All").Select 'Goes to the "All" tab
Range("A" & Rows.Count).End(xlUp).Offset(1).Select 'For Ref_Numbers This function is used to automatically go to the last cell of the table that doesn't have content in it. Should help avoiding overwriting rows
ActiveSheet.Paste 'Paste the Reference Numbs in the rows
Range("B" & Rows.Count).End(xlUp).Offset(1).Select 'Selects the last cell of column B that is not used yet
Application.CutCopyMode = False 'Clears the clipboard
LastRow5 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count 'Determines the last row used in column A
Range("B" & Rows.Count).End(xlUp).Offset(1).Select
ActiveCell.FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,HOLD_Table,HOLD!R1C,FALSE))=0,"""",VLOOKUP(RC1,HOLD_Table,HOLD!R1C,FALSE))" 'Sets up the VLOOKUP function and if there is nothing in the source cell, returns blank instead of 0.
If LastRow5 - LastRow4 > 1 Then
ActiveCell.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":B" & LastRow5) 'Autofills the VLOOKUP function from the last B cell used to the last used row of Ref_Numbers
End If
End If
Sheets("All").Select
Dim LastRow6 As Long
Dim LastColumn As Long
LastColumn = Sheets("All").Range("B2:DC2" & Columns.Count).End(xlToLeft).Row
LastRow6 = Range("B" & Rows.Count).End(xlUp).Row
Range("B3:B" & LastRow6).Select
Selection.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":DC" & LastRow6), Type:=xlFillDefault 'Autofills the formulas in the column selected to the right untill column DB which is the last header of the table
Range("B3").Select
End Sub
And here's the part of the code that I want to change because it doesn't work when my table has only one row of data :
Dim LastRow5 As Long
Application.Goto Reference:="Ref_HOLD" 'Goes to the Ref_HOLD table and selects it
If Not IsEmpty(ActiveCell.Value) Then
Selection.Copy 'Copies the Ref_INSU table
Sheets("All").Select 'Goes to the "All" tab
Range("A" & Rows.Count).End(xlUp).Offset(1).Select 'For Ref_Numbers This function is used to automatically go to the last cell of the table that doesn't have content in it. Should help avoiding overwriting rows
ActiveSheet.Paste 'Paste the Reference Numbs in the rows
Range("B" & Rows.Count).End(xlUp).Offset(1).Select 'Selects the last cell of column B that is not used yet
Application.CutCopyMode = False 'Clears the clipboard
LastRow5 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count 'Determines the last row used in column A
Range("B" & Rows.Count).End(xlUp).Offset(1).Select
ActiveCell.FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,HOLD_Table,HOLD!R1C,FALSE))=0,"""",VLOOKUP(RC1,HOLD_Table,HOLD!R1C,FALSE))" 'Sets up the VLOOKUP function and if there is nothing in the source cell, returns blank instead of 0.
If LastRow5 - LastRow4 > 1 Then
ActiveCell.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":B" & LastRow5) 'Autofills the VLOOKUP function from the last B cell used to the last used row of Ref_Numbers
End If
End If
This portion of my code is used multiple times throughout my program for each business unit of my company.
Everything runs fine in this code until I reach this part of the code:
If LastRow5 - LastRow4 > 1 Then
ActiveCell.AutoFill Destination:=Sheets("All").Range(ActiveCell.Address & ":B" & LastRow5) 'Autofills the VLOOKUP function from the last B cell used to the last used row of Ref_Numbers
End If
The idea here is that I want to put a VLOOKUP formula in my cell (in column B), and if my source table has several rows, the VBA program is supposed to drag the VLOOKUP formula down for each lines that I have in my source table.
To know how many cells needs be filled with the formula, I use two variables, LastRow5 and LastRow4.
By making the difference between these two variables, I know how many cells need to be filled when dragging the VLOOKUP formula down.
That is why I say, if LastRow5 - LastRow4 > 1. Because If there is only one line in my source table, there is no need to drag the formula down.
Do you have any idea why this code doesn't work when my source table has only one row of data? There is something wrong in my code but I don't know what.
Thank you for your help, if you need any additional information to better understand the situation, do not hesitate.
Your calculation of the last row is incorrect:
LastRow5 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Rows.Count
should be
LastRow5 = Sheets("All").Range("A" & Rows.Count).End(xlUp).Row
There is no need to AutoFill, or to Select, or to use ActiveCell. Write the formula to the entire range in one step:
With Sheets("All")
Dim LastRow As Long
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Dim FirstRow As Long
FirstRow = .Range("B" & .Rows.Count.End(xlUp).Offset(1).Row
.Range("B" & FirstRow & ":B" & LastRow).FormulaR1C1 = _
"=IF(LEN(VLOOKUP(RC1,HOLD_Table,HOLD!R1C,FALSE))=0,"""",VLOOKUP(RC1,HOLD_Table,HOLD!R1C,FALSE))"
End With

copy all rows from dataset for each unique value present in one column to new sheets in vba

Problem
I have a sheet in which first i have to filter the last column.
For each unique value present in last column, I have to copy data from first column to last-1 column
Then I have to add new sheet and need to paste this data in new sheet.
I repeat same process 3 for each unique value present in last column. Like in last column is of language. so first sort this column. then copy and paste data for each language in new sheets.
Sub LoopThroughAllItemsInFilters()
Range("G2", Range("G" & Cells(Rows.Count, 1).End(xlUp).Row)).Select
Selection.Copy
Columns("L").Select
ActiveSheet.Paste
ActiveSheet.Range("$L$1:$L$10000").RemoveDuplicates Columns:=1, Header:=xlYes
Dim ArrayDictionaryofItems As Object, Items As Variant, i As Long, Item As Variant
Set ArrayDictionaryofItems = CreateObject("Scripting.Dictionary")
With ActiveSheet
'show autofilter if not already shown on all rows
If Not .AutoFilterMode Then .UsedRange.AutoFilter
If .Cells.AutoFilter Then .Cells.AutoFilter
'Create list of unique items in column G that get filled into ArrayDictionaryofItems
Dim annoying As Double
If Range("G3").Value <> "" Then
annoying = 2
Items = Range(.Range("L2"), .Cells(Rows.Count, "L").End(xlUp))
'Fills ArrayDictionaryofItems to the UBOUND (max) count of unique items in column L.
For i = 1 To UBound(Items, 1)
ArrayDictionaryofItems(Items(i, 1)) = 1
Next
Else
Item = Range("G2").Value
annoying = 1
End If
'Filter multiple items if annoying is set to equal 2 because G3 is blank
If annoying = 2 Then
For i = 1 To UBound(Items, 1)
Sheets.Add After:=Sheets(i)
Next i
Sheets("DEFAULTERS").Select
Dim x As Double
x = 2
For Each Item In ArrayDictionaryofItems.keys
erow = ActiveSheet.Cells(Rows.Count, 2).End(xlUp).Row
'autofilter on column b with this driver
.UsedRange.AutoFilter field:=7, Criteria1:=Item
Columns("A:G").Select
Selection.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
Sheets(x).Select
Columns("A:G").Select
ActiveSheet.Paste
Sheets("DEFAULTERS").Select
x = x + 1
Next Item
GoTo LINE99:
End If
'Filter a single item in column since G3 is blank and there is only one item in column G to filter
If annoying = 1 Then
Sheets.Add After:=ActiveSheet
Sheets("DEFAULTERS").Select
Item = Range("G2").Value
.UsedRange.AutoFilter field:=7, Criteria1:=Item
End If
Columns("A:G").Select
Selection.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
Sheets(2).Select
Columns("A:G").Select
ActiveSheet.Paste
Sheets("DEFAULTERS").Select
End With
LINE99:
With ActiveSheet
If .AutoFilterMode Then .UsedRange.AutoFilter
End With
End Sub

How to delete duplicate row with condition in VBA

Im completely novice on VBA but i found no solution in google so far. i find 2 seperate code but when combining the solution didnt find out
I have a issue of deleting duplicate row with condition
column b column z
1 22/1/2019
2 22/1/2019
1 23/1/201
2 23/1/2019
outcome
column b column z
1 23/1/2019
2 23/1/2019
My code ( having problem when nested do while with for )
Sub Macro1()
Dim RowsToDelete As Range, innerRow As Long
Set TheRng = Intersect(ActiveSheet.UsedRange, ActiveSheet.Range("B:Z"))
xx = TheRng.Value
innerRow = 1
For i = UBound(xx) To 2 Step -1
Do While ActiveSheet.Range("b" & Row) <> ""
If ActiveSheet.Range("b" & Row) = ActiveSheet.Range("b" & innerRow) Then
For j = i - 1 To 1 Step -1
If ActiveSheet.Range("Z" & Row) < ActiveSheet.Range("Z" & innerRow) Then
Set RowsToDelete = Union(IIf(RowsToDelete Is Nothing, TheRng.Cells(i, 1), RowsToDelete), TheRng.Cells(i, 1))
Exit For
End If
Next j
Loop
RowsToDelete.EntireRow.Select 'Delete
End Sub
It looks like you want to delete duplicates from column B but keep the row with the newest date in column Z.
RemoveDuplicates typically deletes the duplicate with the largest row number (closest to the bottom of the data) so Sort the data with the date descending to leave the latest date at the top and remove duplicates.
Sub Macro1()
With Worksheets("sheet1")
'With .Range(.Cells(1, "B"), .Cells(.Rows.Count, "Z").End(xlUp))
With Intersect(.UsedRange, .Range("B:Z"))
.Sort key1:=.Columns(1), order1:=xlAscending, _
key2:=.Columns(.Columns.Count), order2:=xlDescending, _
Header:=xlNo
.RemoveDuplicates Columns:=1, Header:=xlNo
End With
End With
End Sub

Subtract Single Cell Value from Column Until Empty Cell

I'm looking to 'normalize' a column of data by setting the minimum value to 0 and shifting the entire column's data by the difference of the min value and 0.
The code should be simple, but I can't find the appropriate range selection to stop the code when it reaches a blank cell.
Below is the core that I've unsuccessfully been working off of trying to recognize the first empty cell in column U after U9 up to U700 and correspondingly stop subtracting in column Z. Example screenshots are attached. Thank you!
Private Sub CommandButton1_Click()
[Z9:Z700] = [U9:U700-U8]
End Sub
This is what I get:
This is what I would like to get:
Try this:
Sub foo()
Dim lRow As Long
With ActiveSheet
lRow = .Cells(Rows.Count, "U").End(xlUp).Row
.Range("U9:U" & lRow).Copy .Range("Z9")
With .Range("U8")
.Formula = "=MIN(U9:U" & lRow & ")"
.Copy
End With
.Range("Z9:Z" & lRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlSubtract
Application.CutCopyMode = False
End With
End Sub
EDIT:
If you have formulas in Column U, below your list of numbers, which are returning blank values, then this revision might work better for you:
Sub foo2()
Dim lRows As Long
With ActiveSheet
lRows = WorksheetFunction.Count(.Range("U9:U700"))
.Range("U8").Formula = "=MIN(" & .Range("U9").Resize(lRows, 1).Address(0, 0) & ")"
.Range("U9").Resize(lRows, 1).Copy
.Range("Z9").PasteSpecial Paste:=xlPasteValues
.Range("U8").Copy
.Range("Z9").Resize(lRows, 1).PasteSpecial Paste:=xlPasteValues, Operation:=xlSubtract
End With
Application.CutCopyMode = False
End Sub

VBA Macro to AutoFill Right until Last Column

I have a report that is automatically pulled that requires Sums to be added at the end of certain columns. The report remains static from Column A-R but the amount of columns as of S can be as few as 1 or go up until 52. The amount of rows are never static. I already know how to find the last row and my sums need to start at column J but when I try to autofill to the right to the last column that contains data (on the same row I have summed J), it spits back an error or doesn't work. Anyone know how to do this? This is what I have for code thus far.
Sub TV_Buysheet()
'
' Macro1 Macro
'
Range("J1").Select
FIRST_ROW = ActiveCell.Row
Selection.End(xlDown).Select
LAST_ROW = ActiveCell.Row
Selection.Offset(2, 0).Select
ActiveCell.FormulaR1C1 = "=SUM(R[" & FIRST_ROW - LAST_ROW - 2 & "]C:R[-2]C)"
Dim lastCol As Long
lastCol = Cells(2, Columns.Count).End(xlToLeft).Column
ActiveCell.AutoFill Destination:=Range(ActiveCell, lastCol), Type:=xlFillDefault
End Sub
Just missing the line of code that autofills to the last column...
To find the last column, the following should work
Dim lngLastColumn As Long
lngLastColumn = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Range(Activecell, Cells(Activecell.Row, lngLastColumn)).FillRight

Resources