1

At first, I tried to write down multiple If & VLOOKUP formulas and insert them via VBA. This caused my computer to crash. I have to check for serval conditions/criteria. Here is the example table:

enter image description here

The grayed values are the ones I want to delete. Wrong dates in the example (should be weekly, not daily).

Every friday, I want to insert a new column between C & D with the todays date (you can find the macro further down. It works). Then the macro should check for the inserted values. If the macro inserts a new value that wasn't there before, it should take it and delete everything else in the row of the columns A to C in the example (this is variable because I'll insert a new column every week - it should check the columns A:[X] LastCol Offset -2). If the macro puts out the same value a week later, it should only keep the oldest one. This will let us now, when the value got entered. Last step: in column D insert the value we have kept - this means the only value in the range A:[X] LastCol Offset -2. If the output is nothing (#N/A) in all cells, then insert "Other" in column D (LastCol Offset -1)

At the moment the columns have an INDEX(MATCH(()) formula. This formula will get copied into the new column and the column that got copied will special pasted with values only (the last step isn't in the code, but that's not the problem).

Sub insertColumn()

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

'Copies the third last column and inserts it between the column [last date] and Overall'
With Sheets("getDATA")
    Lastcol = .Cells(1, .Columns.Count).End(xlToLeft).Column
    .Columns(Lastcol - 2).Copy
    .Columns(Lastcol - 1).Insert Shift:=xlToRight
End With

With Sheets("getDATA")
    .Range("G7").End(xlToRight).Offset(0, -2).Value = Date
End With

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic

End Sub

TL;DR: If Output is same like the weekS before, only keep the oldest value. If the value is different from the weekS before, only keep the new value. If nothing got entered, write "Other" in column D in this example (LastCol Offset -1). If it has a value, insert it in column D

Public Sub TestMe()

Dim myRow           As Range
Dim myCell          As Range
Dim inputRange      As Range
Dim previousCell    As Range
Dim flagValue       As Boolean
Dim lastCell        As Range
Dim LastRow         As Long
Dim LastCol         As Long

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

With Sheets("getDATA")
LastRow = .Cells(.Rows.Count, "G").End(xlUp).Row
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With

Set inputRange = Worksheets(1).Range(Cells(8, 13).Address(), Cells(LastRow, LastCol - 2).Address())
For Each myRow In inputRange.Rows
    Set previousCell = Nothing
    flagValue = False
    For Each myCell In myRow.Cells
        If Len(myCell) Then flagValue = True
        If Not previousCell Is Nothing Then
            If previousCell <> myCell Then
                previousCell.clear
                Set previousCell = myCell
            Else
                myCell.clear
            End If
        Else
            Set previousCell = myCell
        End If
        Set lastCell = myCell
    Next myCell

    If Not flagValue Then
        lastCell.Offset(0, 1) = "Other"
    Else
        lastCell.Offset(0, 1) = previousCell
    End If
Next myRow

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Bluesector
  • 329
  • 2
  • 11
  • 21
  • Using the current input, what 4 dates exactly would you expect in the new column between C and D? – Peter Pesch Dec 14 '17 at 09:53
  • I know that the dates are not weekly in this example (sorry for that). The new value would be 15.12.2017 (friday). Every Friday we will do this report. But this isn't the problem, because I will insert the today() date via macro in the new column. – Bluesector Dec 14 '17 at 09:55
  • So would you want to have 15.12.2017 in every row? Or would you expect different dates? Or did you mean that the new date only goes into the header of the new column? – Peter Pesch Dec 14 '17 at 09:58
  • The date isn't the problem. The macro already inserts the date in the title of the new column. The problems are the values 92H... like in the example. In the new column is a index(match()) function. The macro should only keep the new value if it changed and delete all old ones, or keep the oldest one when nothing changed. – Bluesector Dec 14 '17 at 10:00
  • At the moment you copy column C to the new column, will the formulas be exactly the same (before you do the special paste which you left out of your code), or will does the formula depend on the column? (Please note: If the formula stays the same, you will end up with columns which in fact all have an incorrect date) – Peter Pesch Dec 14 '17 at 10:12

1 Answers1

1

You need two nested loops - one through rows and one through cells. The rest is a bit of fixing the cells, remembering values and puting flags. Instead of clearing the cell, I have colored it in red.

To clear it, change the myCell.Font.Color = vbRed to myCell.clear.

Public Sub TestMe()

    Dim myRow           As Range
    Dim myCell          As Range
    Dim inputRange      As Range
    Dim previousCell    As Range
    Dim flagValue       As Boolean
    Dim lastCell        As Range

    Set inputRange = Worksheets(1).Range("A1:C4")
    inputRange.Font.Color = vbBlack
    For Each myRow In inputRange.Rows
        Set previousCell = Nothing
        flagValue = False
        For Each myCell In myRow.Cells
            If Len(myCell) Then flagValue = True
            If Not previousCell Is Nothing Then
                If previousCell <> myCell Then
                    previousCell.Clear
                    Set previousCell = myCell
                Else
                    myCell.Font.Color = vbRed 'or myCell.clear to clear the value
                End If
            Else
                Set previousCell = myCell
            End If
            Set lastCell = myCell
        Next myCell    
        If Not flagValue Then
            lastCell.Offset(0, 1) = "Other"
        Else
            lastCell.Offset(0, 1) = previousCell
        End If
    Next myRow
End Sub

Input:

enter image description here

After the code:

enter image description here

Concerning identifying the inputRange. It really depends how your range looks like and from which row and column does it start. In the general case, if it starts from A1 to the last used one, the range can be setted like this:

With Worksheets(1)
    Set inputRange = .Range(.Cells(1, 1), .Cells(LastUsedRow, LastUsedColumn))
End With

LastUsedColumn and LastUsedRow are from here. If you want to eliminate two left columns, you can simply do it like this:

With Worksheets(1)
    Set inputRange = .Range(.Cells(1, 1), .Cells(LastUsedRow, LastUsedColumn-2))
End With
Vityata
  • 42,633
  • 8
  • 55
  • 100
  • Could you please make ONE example? Like: If a new & different value gets inserted in the new column, delete everything that was before the new value. Writing down a formula for that is easy, but translating this to VBA is hard for me. – Bluesector Dec 14 '17 at 10:04
  • @Bluesector - the code is almost working with values in `A1:C4` :) – Vityata Dec 14 '17 at 10:15
  • @Vityata The specifications are still unclear. We cannot tell whether your solution will work, as we do not know the formulas Bluesector is using ... – Peter Pesch Dec 14 '17 at 10:17
  • @PeterPesch - if you put the input of the OP as it is and you run my code it will delete the grayed out values. It is about 95% of the job done. Only vlaues in column D are not generated. – Vityata Dec 14 '17 at 10:18
  • @Vityata But the cells in column C will (probably) keep their 15-december value, while the column header will be 14 dec (or 8 dec). And if the formula in new column D is exactly the same as the formula in column C, then the check will *always* think that their was no change, so all values of column C would be deleted ... – Peter Pesch Dec 14 '17 at 10:22
  • @PeterPesch - see the screenshots. – Vityata Dec 14 '17 at 10:24
  • @PeterPesch - or just like the screenshot from the OP. :) – Vityata Dec 14 '17 at 10:25
  • @Vityata No. Using your code column B would have been empty too, as its values would have been deleted during the previous run ... – Peter Pesch Dec 14 '17 at 10:28
  • Works as intended. I will test a few scenarios and come back to you! @Peter for a better understanding. If something is blank and had a value before - it's correct that everything before gets deleted. I didn't mention this case but it's correct. – Bluesector Dec 14 '17 at 10:29
  • @Bluesector OK. I will do some tests, and try to see whether there is any scenario in which you actually keep something in the previous row ... – Peter Pesch Dec 14 '17 at 10:33
  • Now I stuck a little by defining the range. I can get the macro to work till the last row `.Range("M8:O" & LastRow)` but how can I combine it with the last column offset -2? `Lastcol = .Cells(1, .Columns.Count).End(xlToLeft).Column.Offset(0, -2)` – Bluesector Dec 14 '17 at 10:46
  • @Vityata @Bluesector Had some trouble getting a proper test enviroment in place The first run of `Testme` will clear all cells in the newest column, effectively removing all formulas from that column. The next time `insertColumn` runs, it will insert an empty column ... – Peter Pesch Dec 14 '17 at 11:23
  • @Bluesector You can use the technique you used in `insertColumn` to get that part of `Testme` working. – Peter Pesch Dec 14 '17 at 11:24
  • @Peter Pesch but I made the insertColumn with Offset. In this case I want to do it for the entire range. Every week I'll add another column so the range has to be A2:LastRow&LastCol. – Bluesector Dec 14 '17 at 11:29
  • @Peter Pesch you are right. I'll add something to the insertColumn so that it will insert the formula. – Bluesector Dec 14 '17 at 11:32
  • Okay now I got stuck at the same problem. I don't know how to define a range with LastCol and LastRow – Bluesector Dec 14 '17 at 11:43
  • @Vityata I inserted my code in the post above. can you please take a look? Somehow it doesn't work correct anymore. I think it's because of the range. – Bluesector Dec 14 '17 at 12:52
  • @Bluesector An easy way to define that range might be `.Range("A2", .Cells(LastRow, LastCol))` (if you are within a `With Sheets("getDATA")` ) – Peter Pesch Dec 14 '17 at 12:56
  • @Bluesector - the definition of a range is a tricky but quite researched matter - see https://stackoverflow.com/questions/11169445/error-in-finding-last-used-cell-in-vba and http://www.cpearson.com/excel/LastCell.aspx – Vityata Dec 14 '17 at 13:02
  • Thank you! If you take a look at my above code you can see that I found a solution. But now I have the feeling that you code doesn't work anymore. I think the code checks the wrong cells. The new cells get cleared – Bluesector Dec 14 '17 at 13:14
  • @Bluesector Of course the new cells get cleared. That is a direct consequence of the way you wrote the specifications ... Now if the Formulas would be in the `Final` column or in the `Overall` column, and if your specifications would say that the new column should be filled with the `.Value` of the live column, ... – Peter Pesch Dec 14 '17 at 13:42
  • I think I got it now. Changed the inputRange – Bluesector Dec 14 '17 at 13:45
  • @Vityata I noticed a problem with the macro. It only checks the last cell. For example: If I have the same value 3 weeks in a row it will only keep the freshly inserted value instead of the oldest one. Could please adjust the code so that it will check for the entire range (LastCol-2). I updated my post with my code again. – Bluesector Dec 15 '17 at 07:05