Macro to compare two columns and insert one line if missing - vba

here is what I'm trying to achieve, in order to get rid of a lot of manual works. I basically have two lists, each made of two columns (we'll call it colA, colB, codD and colE). The first list (A+B) is normally bigger than the second (D+E), so my goal is to automate the process of spotting missing entries, insert a line when found one (actually, scroll down only the corresponding two cells of colD and colE) and then loop to the end of the left list.
Normally, I manually do this by put an IF comparing the cells in colA and colD, if different -> add a line a scroll down, then loop.
How can this be automate with a VBA Macro? I save you from my junk codes I tried so far, I think it's a super-easy question for you out there... :)
Thanks in advance
A.

here is the idea:
define the cursor at the start of your column D.
Check if the value in your cursor cell is equal to the value in column A on the same row.
If not, add a cell in column D and column E.
Then set your cursor to the cell below.
And redo until the list is finished.
Sub test()
Dim cl As Range
Set cl = Range("D1")
Do While cl.Row < 10000
If cl.Value <> cl.Offset(0, -3).Value Then
cl.Offset(0, 1).Insert Shift:=xlDown
cl.Insert Shift:=xlDown
Set cl = cl.Offset(-1, 0)
End If
Set cl = cl.Offset(1, 0)
Loop
End Sub

Related

Target formula VBA

I'm running VBA to fill in all cells using last row last col. But my VBA fills in from B3 and until last row, and then adds a line below the last row and fills in to last col.
The code looks like this:
Sub RUNFILL()
With Worksheets("Sheet3").Range("B3")
Set Target = .Range(.Cells(1, Columns.Count).End(xlToLeft), Cells(Rows.Count, "A").End(xlUp))
Target.FormulaLocal = "=INDEKS(Sheet1!$N:$N;MATCH(Sheet3!$A:$A&Sheet3!B$1;Sheet1!$R:$R;0))"
End With
End Sub
I'm not sure why it fills in that way, so I'm hoping that someone can see the problem and help me correct it.
Consider that
Worksheets("Sheet3").Range("B3").Range("A1")
is equivalent to
Worksheets("Sheet3").Range("B3")
and that
Worksheets("Sheet3").Range("B3").Range("C5:D10")
is equivalent to
Worksheets("Sheet3").Range("D7:E12")
Your
With Worksheets("Sheet3").Range("B3")
Set Target = .Range(...)
End With
is equivalent to
Set Target = Worksheets("Sheet3").Range("B3").Range(...)
which is why you are not setting it to the area you think you should be.
But I have no idea why Worksheets("Sheet3").Range("B3").Cells(1, ActiveSheet.Columns.Count) (the expanded equivalent of .Cells(1, Columns.Count) in your code) is not crashing out, as that is (assuming Sheet3 is active) equivalent to Cells(2 + 1, 1 + Columns.Count) which will give a 1004 error due to referencing a column beyond the right-hand limit. (And does give that error when I try to run your code.)
And I also have no idea why your code is filling in column B to the last row (but no other columns after B) and is then inserting one extra line (not two) below that which does extend beyond column B.

Excel VBA deleting certain rows with certain conditions

I found a code online which works but I am failing to change it for my purpose. Each entry in my spreadsheet contains different formulas as well as an Iferror function with the aim of making cells with error messages appear as blank. For example lets say a cell E3 is dependent on cell F3 with a certain formula (for clarification lets say F3/2.5). It is obvious if there is no entry in cell F3 then an error message would display in cell E3. For this reason, I use the IFERROR function to display the cell as blank. The difficulty arises when I want to delete blank rows after a click on the macro button. However, since that cell does have an entry (a formula which in turn returns an error message), that cell does not delete. Also I need to run this code over 3 different selection ranges. Please can someone help! The code I found was from a different thread on this forum and is:
`sub foo()
dim r As Range, rows As Long, i As Long
Set r = ActiveSheet.Range("A1:Z50")
rows = r.rows.Count
For i = rows To 1 Step (-1)
If WorksheetFunction.CountA(r.rows(i)) = 0 Then r.rows(i).Delete
Next
End Sub`
Thanks Alot!
EDIT: If statement added to the autofilter as it was deleting a row when there were no blanks
You will want to set up a column in the spreadsheet with the following sumproduct:
=SUMPRODUCT((LEN(A1:F1)>0)*1)
This is calculating how many cells' values have a length more than 0 hence are not blank, you will need to adjust cell references accordingly as I tested on a small sample of fake data.
Following this you can just loop:
For i = rows To 1 Step (-1)
If Cells(i,"G") = 0 Then r.rows(i).Delete 'My formula is in column "G"
Next
Or set up an auto-filter and delete entire rows of the visible cells:
Dim lrow As Integer
If Not WorksheetFunction.CountIf(Range("G:G"), "0") = 0 Then
Range("A1:G1").AutoFilter
Range("A1:G1").AutoFilter Field:=7, Criteria1:="0"
lrow = Cells(rows.Count, 7).End(xlUp).Row + 1
Range("G2:G" & lrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Range("A1:G1").AutoFilter
End If
The only problem with using a leading column to calculate for this is if you have a lot of data coming and going as you will need to replenish the formula, though you could use auto complete in the code i guess.

Loop through columns and copy and paste cells A to B

I am working on a simple code but i have not able to crack it. i want the macro to run and pick up a value (2), and copy and paste the cells A to C , into sheet 2. The code below does copy the Cells A-B and pastes. I failing on the loop . I want it to loop from 1st row to last row. please.
Sub Tier_2()
With Sheets("Sheet1")
.Range(.Cells(1, 1), .Cells(3, 3)).Copy Sheets("Sheet2").Cells(1, 1)
End With
End Sub
This isn't for your specific situation, but the concept is what you are looking for. You should be able to do some research with what I'm showing you and figure it out.
lastRow = Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row 'gets last row of Source sheet
For x = 1 to lastRow
Sheets("Sheet2").Cells(x, 1) = Sheets("Sheet1").Cells(x, 1) 'copy data from Sheet1 to Sheet2 row x
Next x 'loop and add one to x
You can use variables for either the row or column numbers in either the source or target sheets. You can insert another loop inside the first one. I'm not sure of what you are looking for, but your question didn't seem to have a loop in it at all.
If that doesn't get you going in the right direction try "Do While Loop" in a search.
EDIT: Updated the formula to better reflect idea.

VBA Go to last empty row

I have a project on excel macro, I need to highlight the next last row that has an empty value. example cell A1:A100 have data and the next cell is A101 is empty.
when user click a button it should highlight the cell A101...
If you are certain that you only need column A, then you can use an End function in VBA to get that result.
If all the cells A1:A100 are filled, then to select the next empty cell use:
Range("A1").End(xlDown).Offset(1, 0).Select
Here, End(xlDown) is the equivalent of selecting A1 and pressing Ctrl + Down Arrow.
If there are blank cells in A1:A100, then you need to start at the bottom and work your way up. You can do this by combining the use of Rows.Count and End(xlUp), like so:
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Select
Going on even further, this can be generalized to selecting a range of cells, starting at a point of your choice (not just in column A). In the following code, assume you have values in cells C10:C100, with blank cells interspersed in between. You wish to select all the cells C10:C100, not knowing that the column ends at row 100, starting by manually selecting C10.
Range(Selection, Cells(Rows.Count, Selection.Column).End(xlUp)).Select
The above line is perhaps one of the more important lines to know as a VBA programmer, as it allows you to dynamically select ranges based on very few criteria, and not be bothered with blank cells in the middle.
try this:
Sub test()
With Application.WorksheetFunction
Cells(.CountA(Columns("A:A")) + 1, 1).Select
End With
End Sub
Hope this works for you.
This does it:
Do
c = c + 1
Loop While Cells(c, "A").Value <> ""
'prints the last empty row
Debug.Print c

Collect numbers from a column containing empty cells using Excel VBA

I have a little problem, I occasionally bump into this kind of problem, but I haven’t found a fast solution so far.
So, imagine we have an Excel worksheet and let's suppose that we have a couple of numbers in column ’A’ with some empty cells in it. Altogether (just to make it simple) we have the first 10 cells in column 'A' to observe. For example:
3
(empty cell)
(empty cell)
6
(empty cell)
4
(empty cell)
23
(empty cell)
2
Now in the next step I would like to collect these numbers into another column (for example, column ’B’) using VBA. Obviously I just want to collect those cells which contain a number and I want to ignore the empty cells. So I would like to get a column something like this:
3
6
4
23
2
I have already written the following code, but I’m stuck at this point.
Sub collect()
For i = 1 To 10
if cells(i,1)<>"" then...
Next i
End Sub
Is there an easy way to solve this problem?
Probably the quickest and easiest way is to use Excel's Advanced Filter - the only amendment you'll need to make is it add a field name and criteria. You can even list unique items only:
The VBA equivalent is
Sub test()
With Sheet1
.Range("B1:B8").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range( _
"D1:D2"), CopyToRange:=.Range("F1"), Unique:=False
End With
End Sub
You should be able to use the method in the post int the comments, but you could also use SpecialCells like Range("A:A").SpecialCells(xlCellTypeConstants,xlNumbers).Copy to get all of the filled cells.
Edit: needed constants not formulas.
This will work for any number of rows that you select. It will always output in the next column at the start of your selection e.g. if data starts in B10 it will ooutput in C10
Sub RemoveBlanks()
Dim cl As Range, cnt As Long
cnt = 0
For Each cl In Selection
If Not cl = vbNullString Then
Cells(Selection.Cells(1, 1).Row, Selection.Cells(1, 1).Column).Offset(cnt, 1) = cl
cnt = cnt + 1
End If
Next cl
End Sub
If you wish to loop manually and don't mind specifying the maximum row limit;
Dim i As long, values As long
For i = 1 To 10
If cells(i, 1).Value <> "" Then
values = (values + 1)
' // Adjacent column target
cells(values, 2).value = cells(i, 1).value
End If
Next i