Excel VBA Macro to concatinate two columns using column header id name - vba

I am really new in writing Excel macros through VBA. I want to concatenate two columns in my Excel worksheet. I have data in columns A, B & C and I want to concatenate B & C column to D column. This is the code I wrote:
Sub FINAL()
'
' FINAL Macro
'
'
Columns("D:D").Select
Selection.Insert Shift:=xlToRight
Range("D2").Select
ActiveCell.FormulaR1C1 = "SO::LI"
Range("D3").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=RC[-2]&""::""&RC[-1]"
Range("D3").Select
Dim lastRow As Long
lastRow = Range("C" & Rows.Count).End(xlUp).Row
Range("D3").AutoFill Destination:=Range("D3:D" & lastRow)
End Sub
This works fine. But This works only when my data is in columns A, B & C.
When the data is in different columns, such as E, F & G, this does not work.
So what I want is to find the column using column header name and concatenate data.
Style S/O L/I
392389 265146 40
558570 300285 10
558570 300285 20
After concatenation:
Style S/O L/I SO::LI
392389 265146 40 265146::40
558570 300285 10 300285::10
558570 300285 20 300285::20

You can find a column header by using the worksheet MATCH function inside VBA, here I'll put it in to a variable called c1
c1 = Application.WorksheetFunction.Match("S/O", Range("1:1"), 0)
It's best to wrap this identification in a potential error handler, because if there IS no match then you'll get a run-time error
If Application.WorksheetFunction.CountIf(Range("1:1"), "S/O") > 0 Then
c1 = Application.WorksheetFunction.Match("S/O", Range("1:1"), 0)
Else
MsgBox ("Couldn't find ""S/O"" header!")
Exit Sub
End If
Here it uses the worksheet function COUNTIF to make sure there is at least one instance of "S/O" - if there isn't then the subroutine ends.
After that, you've identified your S/O column so can carry on with the rest of the code as usual - if you assume the columns are always consecutive then you can use c1 + 1 to mean "L/I" column and c1 + 2 to mean the CONCAT column
Below is a fully working version of the code:
Private Sub CommandButton1_Click()
Dim c1 As Long
Dim lastRow As Long
' If instance of "S/O" exists then find the column number else show error message and end
If Application.WorksheetFunction.CountIf(Range("1:1"), "S/O") > 0 Then
c1 = Application.WorksheetFunction.Match("S/O", Range("1:1"), 0)
Else
MsgBox ("Couldn't find ""S/O"" header!")
Exit Sub
End If
' Get last row for formula based on the "S/O" column header in c1
lastRow = Cells(Rows.Count, c1).End(xlUp).Row
' add 2 to c1 to make the c1 variable contain column number for SO::LI
c1 = c1 + 2
' use FormulaR1C1 as usual to flood the whole column from row 2 to lastRow
Range(Cells(2, c1).Address, Cells(lastRow, c1).Address).FormulaR1C1 = "=RC[-2]&""::""&RC[-1]"
End Sub

You may give this a try...
The code will find the headers in row2 and concatenate the columns.
Sub Final()
Dim FirstCell As Range, SecondCell As Range
Dim lr As Long, r As Long, c As Long
Application.ScreenUpdating = False
'Assuming that the Row2 is the Header Row, if not change it.
Set FirstCell = Rows(2).Find("S/O")
If FirstCell Is Nothing Then
MsgBox "A column with the header S/O was not found.", vbExclamation
Exit Sub
End If
Set SecondCell = Rows(2).Find("L/I")
If SecondCell Is Nothing Then
MsgBox "A column with the header L/I was not found.", vbExclamation
Exit Sub
End If
r = FirstCell.Row + 1
c = SecondCell.Column + 1
Set FirstCell = FirstCell.Offset(1)
Set SecondCell = SecondCell.Offset(1)
lr = Cells(Rows.Count, SecondCell.Column).End(xlUp).Row
Columns(c).Insert
Range(Cells(r, c), Cells(lr, c)).Formula = "=" & FirstCell.Address(0, 0) & "&""::""&" & SecondCell.Address(0, 0) & ""
Application.ScreenUpdating = True
End Sub

Use FormulaR1C1 instead is useful
Sub mergeColumn()
Dim col As Integer
Dim tr As Long
Application.ScreenUpdating = False
On Error Resume Next
col = Rows(1).Find(What:="S/O").Column
On Error GoTo 0
If col <> 0 Then ' if not found, it goes to 0
tr = Cells(Rows.Count, col).End(xlUp).Row
Range(Cells(1, col + 2), Cells(tr, col + 2)).Value = "=RC[-2] & ""::"" & RC[-1]"
End If
Application.ScreenUpdating = True
End Sub

Related

Using Vlookup In VBA With Filter Conditions

What I am trying to accomplish here is
1) Is to iterate the values in column O and for the ones that are not null - filter the worksheet titled DATA to only show values where Column B = X and use VLOOKUP() to return the lookup values to the corresponding row in Column P
2) If column O is null then filter the sheet titled DATA to only show values where Column B <> X and use VLOOKUP() to return the lookup values to the corresponding row in Column P.
I attempted the syntax below but I am getting an error of
Method 'Rarnge' of object '_Worksheet' failed
What do I need to do differently in my code below to get the syntax to return the values I desire?
Dim destSheet As Worksheet: Set destSheet = Sheets("Main")
For i = Range("A" & Rows.Count).End(3).Row To 2 Step -1
If Not IsEmpty(Cells(i, "O").Value) Then
Sheets("Data").Select
Selection.AutoFilter
ActiveSheet.Range("$A:$C").AutoFilter Field:=2, Criteria1:="<>"
Sheets("Main").Select
Application.CutCopyMode = False
form2 = "=IFERROR(VLOOKUP(RC[-15],Lookup!C[-15]:C[-13],3,FALSE),"""")"
destSheet.Range("P:P" & lr).Formula = form2
Else
Sheets("Data").Select
Selection.AutoFilter
Sheets("Main").Select
Application.CutCopyMode = False
form3 = "=IFERROR(VLOOKUP(RC[-15],Lookup!C[-15]:C[-13],3,FALSE),"""")"
destSheet.Range("P:P" & lr).Formula = form3
End If
Next i
It was a bit hard to understand for me what you are trying to do, please correct me if I get you wrong.
First of all selecting sheets is not a preferred method while running macros, unless you intentionally do it, so avoid it.
Secondly, you don't need to filter anything, you can control it by checking conditions within your code. You don't do things physically, you do them theoretically within your code, and display the output.
Have a look at this code and ask wherever you need help to understand.
Sub VLookups()
Dim destSheet As Worksheet: Set destSheet = Sheets("Main")
Dim i As Long
Dim myVal As Variant
Set lookupRange = Sheets("Data").Range("$A:$C") 'This is your lookup range
For i = 2 To Range("O" & Rows.Count).End(xlUp).Row 'Iterate from 2nd row till last row
myVal = Application.VLookup(destSheet.Cells(i, "A").Value, lookupRange, 2, False)
If IsError(myVal) Then GoTo Skip 'If searched value not found then skip to next row
If Not IsEmpty(Cells(i, "O").Value) Then 'If Cell in Column O not empty
If myVal = "YOUR X VALUE FOR COLUMN B" Then 'If Your Column B X value exists
destSheet.Cells(i, "P").Value = Application.VLookup(destSheet.Cells(i, "A").Value, _
lookupRange, 3, False) 'Column P Cell is populated by Data Sheet Column C Cell
End If
Else 'If Cell in Column O empty
If myVal <> "YOUR X VALUE FOR COLUMN B" Then 'If Your Column B X value not exists
destSheet.Cells(i, "P").Value = Application.VLookup(destSheet.Cells(i, "A").Value, _
lookupRange, 3, False) 'Column P Cell is populated by Data Sheet Column C Cell
End If
End If
Skip:
Next i
End Sub

VBA: adding up irregular ranges

I need some help to create a macro which adds all the values on the column E between the rows with the "avg" word. the result should be displayed on the cells where the "Sum here" label is displayed. Both texts "avg" and "sum here" is just for illustrate the example, "avg" could be replaced by any other word and "sum here" should actually be the aggregation of the values above it.
The real challenge is that the number of ranges on column E is variable, so i would like to find a macro which is able to deal with "n" number of ranges on column E.
Finally, the values on column D are only the example of the expected value on the "sum here" cells.
This is what I have tried to far:
Sub Macro1()
'
' Macro1 Macro
'
Dim sumhere As Range
Dim startingpoint As Range
Dim endingpoint As Range
'
Range("C17").Select
Selection.End(xlDown).Select
If ActiveCell = "avg" Then
ActiveCell.Offset(rowoffset:=0, columnoffset:=2).Select
Set sumhere = ActiveCell
Set startingpoint = ActiveCell.Offset(rowoffset:=-1, columnoffset:=0)
Selection.End(xlUp).Select
If (ActiveCell.Value) = "Sum here" Then
Set endingpoint = ActiveCell.Offset(rowoffset:=1, columnoffset:=0)
sumhere.Formula = "=sum(range(startingpoint:endingpoint)"
Else
Selection.End(xlUp).Select
If (ActiveCell.Value) = "Sum here" Then
Set endingpoint = ActiveCell.Offset(rowoffset:=1, columnoffset:=0)
sumhere.Formula = "=Sum(Range(startingpoint.adress:endingpoint.adress))"
Else: End If
End If
End If
End Sub
Additionally, as you can see, I do not know, how to define a range using variables. My original idea was to combine this code with some kind of "do while" or/and "for i= 1 to x" and "next i". But I can't see how to combine it.
Using formula only, and providing that column A only has avg (or any text) on each subtotal row.
I've given two versions of the formula - the volatile version (updates everytime you change anything on the spreadsheet), and the non-volatile version (only updates if it needs to).
The formula should be entered on row 6 - change the $E6 to which ever row you need.
(volatile)
=SUM(OFFSET($E6,IFERROR(LOOKUP(2,1/($A$1:INDEX($A:$A,ROW()-1)<>""),ROW($A$1:INDEX($A:$A,ROW()-1))),0)-ROW()+1,,ROW()-1-IFERROR(LOOKUP(2,1/($A$1:INDEX($A:$A,ROW()-1)<>""),ROW($A$1:INDEX($A:$A,ROW()-1))),0)))
(non volatile):
=SUM(INDEX($E:$E,IFERROR(LOOKUP(2,1/($A$1:INDEX($A:$A,ROW()-1)<>""),ROW($A$1:INDEX($A:$A,ROW()-1))),0)+1):INDEX($E:$E,ROW()-1))
or if you don't mind using a helper column:
In cell B6:
=IFERROR(LOOKUP(2,1/($A$1:INDEX($A:$A,ROW()-1)<>""),ROW($A$1:INDEX($A:$A,ROW()-1))),0)
In E6: (volatile)
=SUM(OFFSET($E6,$B6-ROW()+1,,ROW()-1-$B6))
or (non volatile):
=SUM(INDEX($E:$E,$B6):INDEX($E:$E,ROW()-1))
Edit:
Thought I'd add a UDF to calculate it to if you're after VBA.
Use the function =AddSubTotal() in the rows you want the sub total to be shown in, or use =AddSubTotal("pop",6) to sum everything in column F (col 6) using "pop" rather than "avg".
Public Function AddSubTotal(Optional Delim As String = "avg", Optional ColNumber = 5) As Double
Dim rCaller As Range
Dim rPrevious As Range
Dim rSumRange As Range
Set rCaller = Application.Caller
With rCaller.Parent
Set rPrevious = .Range(.Cells(1, 1), .Cells(rCaller.Row - 1, 1)).Find(Delim, , , , , xlPrevious)
If Not rPrevious Is Nothing Then
Set rSumRange = rPrevious.Offset(1, ColNumber - 1).Resize(rCaller.Row - rPrevious.Row - 1)
Else
Set rSumRange = .Range(.Cells(1, ColNumber), .Cells(rCaller.Row - 1, ColNumber))
End If
End With
AddSubTotal = WorksheetFunction.Sum(rSumRange)
End Function
The following VBA routine assumes that
your data is in Columns C:E
Nothing else relevant (nothing numeric) in that range
Your "key word" where you want to show the sum is avg
avg (the key word) is hard-coded in the macro
You could easily modify this routine to also perform an average of those values, and put those results, for example, in Column D
Any of the above are easily modified
Option Explicit
Sub TotalSubRanges()
Dim vSrc As Variant, rSrc As Range
Dim dAdd As Double
Dim I As Long
Const sKey As String = "avg"
Set rSrc = Range(Cells(1, "C"), Cells(Rows.Count, "C").End(xlUp)).Resize(columnsize:=3)
vSrc = rSrc
'Do the "work" in a VBA array, as this will
' execute much faster than working directly
' on the worksheet
For I = 1 To UBound(vSrc, 1)
If vSrc(I, 1) = sKey Then
vSrc(I, 3) = dAdd
dAdd = 0
Else
If IsNumeric(vSrc(I, 3)) Then dAdd = dAdd + vSrc(I, 3)
End If
Next I
'write the results back to the worksheet
' and conditionally format the "sum" cells
With rSrc
.EntireColumn.Clear
.Value = vSrc
.Columns(3).AutoFit
.EntireColumn.ColumnWidth = .Columns(3).ColumnWidth
.FormatConditions.Delete
.FormatConditions.Add _
Type:=xlExpression, _
Formula1:="=" & .Item(1, 1).Address(False, True) & "=""" & sKey & """"
With .FormatConditions(1)
.Interior.ColorIndex = 6
End With
End With
End Sub
Surely you just need something like:
Sub sums()
Dim i As Integer, j As Integer, k As Integer
j = Range("C1048576").End(xlUp).Row
k = 1
For i = 1 To j
If Range("C" & i).Value <> "" Then
Range("E" & i).Value = "=Sum(E" & k & ":E" & i - 1 & ")"
k = i + 1
End If
Next i
End Sub
Change:
Dim startingpoint As Range
Dim endingpoint As Range
To:
Dim startingpoint As Variant
Dim endingpoint As Variant
As the startingpoint and endingpoint is used in a formula, you cant define them as a Range.

Compare 4 columns in one excel sheet using vba

I need your help please, I have 4 columns in an excel sheet and I need to compare them 2 by 2 i will explain to you :
In column A i have users(user1,user2,user3 ...)
In column B i have functionalities ( fonc1, fonc2, fonc3.....)
In column C i have users(user1,user2,user3 ...)
In column D i have functionalities ( fonc1, fonc2, fonc3.....)
The columns C and D are a new version of columns A and B in the columns C and D the users may change order or change functionalities .
When i execute my code i put the result in other new columns:
column F where i have the users
column G where i put the Deleted_functionalities
column H where i put the New_functionalities
The first problem is that the code doesn't get the users it get only the new and deleted functionalities. The second problem is that when the column A is more than column C where the users are stocked the code doesn't work. Can you please help me to find a solution? Thank you in advance .
Here is my code and the file I am working on :
Private Sub CommandButton2_Click()
Dim rngCell As Range
For Each rngCell In Range("B2:B2000")
If WorksheetFunction.CountIf(Range("D2:D2000"), rngCell) = 0 Then
Range("G" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
For Each rngCell In Range("D2:D2000")
If WorksheetFunction.CountIf(Range("B2:B2000"), rngCell) = 0 Then
Range("H" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
End Sub
and this is the excel file
http://www.cjoint.com/c/FCxnwjp22rv
try this
Private Sub CommandButton2_Click()
Dim ws As Worksheet
Dim cell As Range, funcCell As Range
Dim oldUserRng As Range, newUserRng As Range, reportRng As Range
Dim iReport As Long
Dim oldFunc As String, newFunc As String
Set ws = ThisWorkbook.Worksheets("users") '<== adapt it to your needs
With ws
Set oldUserRng = .Columns(1).Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
Set newUserRng = .Columns(3).Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
Set reportRng = .Range("F1:I1") '<== added one report column to account for unchanged functions
End With
reportRng.Value = Array("user", "deleted", "new", "same")
iReport = 1
For Each cell In oldUserRng
With cell
oldFunc = .Offset(, 1).Value
Set funcCell = FindAndOffset(newUserRng, .Value, 1)
If funcCell Is Nothing Then
reportRng.Offset(iReport) = Array(.Value, "", "", oldFunc)
Else
newFunc = funcCell.Value
If newFunc = oldFunc Then
reportRng.Offset(iReport) = Array(.Value, "", "", newFunc)
Else
reportRng.Offset(iReport) = Array(.Value, oldFunc, newFunc, "")
End If
End If
iReport = iReport + 1
End With
Next cell
For Each cell In newUserRng
With cell
Set funcCell = FindAndOffset(oldUserRng, .Value, 1)
If funcCell Is Nothing Then
reportRng.Offset(iReport) = Array(.Value, "", .Offset(, 1).Value, "")
iReport = iReport + 1
End If
End With
Next cell
End Sub
Not so sure it does what you need.
you'd better provide screenshots of "before" and "after" scenarios.
BTW, is it safe to assume that both old and new user columns cannot hold duplicates (i.e.: two or more "userX" in column A and/or column C?)
But it does speed up thing considerably since it iterates only through non empty cells.
I hope I get what you want to achieve. Does the following solve your problem?
Private Sub CommandButton2_Click()
Dim rngCell As Range
For Each rngCell In Range("A2:A20000")
If WorksheetFunction.CountIf(Range("C2:C20000"), rngCell) > 0 Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 1) = rngCell.Offset(0, 1).Value
Range("F" & Rows.Count).End(xlUp).Offset(0, 2) = Application.WorksheetFunction.VLookup(rngCell.Value, Range("C2:D20000"), 2, 0)
ElseIf (rngCell <> "") Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 1) = rngCell.Offset(0, 1).Value
End If
Next
For Each rngCell In Range("C2:C20000")
If (WorksheetFunction.CountIf(Range("A2:A20000"), rngCell) = 0 And rngCell <> "") Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 2) = rngCell.Offset(0, 1).Value
End If
Next
End Sub
A user is only included in column F when he appears both in columns A and C.In case you want to include every user that is either in column A or C the code has to be altered.

Search for two values and copy everything in between in a loop

I have a worksheet which has many terms in Column A.I want to search for two terms for example
term A and term B and copy all rows between the two terms and paste it into a new sheet.These two terms may repeat in the column. The problem which I am basically facing the following problem : whenever I run my code it also copies rows between term B and term A which is unnecessary. Following is the code i am using for two terms term A and term B.
For example my column A is
Institute
Event
Job
Computer
Laptop
Figures
Event
figures
format
computer
and many more terms
I want to copy all the rows between term A: Event and term B: Laptop and paste it into a new sheet. What my code is doing is it is copying the rows between all combinations of Event and computer. Even the rows between computer and event are copied(in this case Figure and laptop).
Sub OpenHTMLpage_SearchIt()
Dim Cell As Range, Keyword$, N%, SearchAgain As VbMsgBoxResult
Dim ass As Variant
Dim Cellev As Range, prakash$, P%, SearchAgaina As VbMsgBoxResult
Dim asa As Variant
StartSearch:
N = 1
Keyword = "Event"
If Keyword = Empty Then GoTo StartSearch
For Each Cell In Range("A1:A500")
If Cell Like "*" & Keyword & "*" Then
ass = Cell.Address
P = 1
prakash = "Computer"
If prakash = Empty Then GoTo StartSearch
For Each Cellev In Range("A1:A500")
If Cellev Like "*" & prakash & "*" Then
asa = Cellev.Address
Range(asa, ass).Select
Selection.Copy
Sheets.Add After:=Sheets(Sheets.Count)
Range("B13").Select
ActiveSheet.Paste
Worksheets("sheet1").Select
P = P + 1
End If
Next Cellev
N = N + 1
End If
Next Cell
End Sub
Edit: code formatting.
The following is the code which is working for me.This copies everything in between Event and laptop and pastes it into a new sheet. Then again it searches for a second time and this time the search will start from the next row to the first search.I hope I am clear with this.
Sub Star123()
Dim rownum As Long
Dim colnum As Long
Dim startrow As Long
Dim endrow As Long
Dim lastrow As Long
rownum = 1
colnum = 1
lastrow = Worksheets("Startsheet").Range("A65536").End(xlUp).Row
With ActiveWorkbook.Worksheets("StartSheet").Range("a1:a" & lastrow)
For rownum = 1 To lastrow
Do
If .Cells(rownum, 1).Value = "Event" Then
startrow = rownum
End If
rownum = rownum + 1
If (rownum > lastrow) Then Exit For
Loop Until .Cells(rownum, 1).Value = "Laptop"
endrow = rownum
rownum = rownum + 1
Worksheets("StartSheet").Range(startrow & ":" & endrow).Copy
Sheets("Result").Select
Range("A1").Select
ActiveSheet.Paste
Next rownum
End With
End Sub
Try this:
Sub DoEeeeeet(sheetName, termA, termB)
Dim foundA As Range, _
foundB As Range
Dim newSht As Worksheet
With Sheets(sheetName).Columns(1)
Set foundA = .Find(termA)
If Not foundA Is Nothing Then
Set foundB = .Find(termB, after:=foundA, searchdirection:=xlPrevious)
End If
End With
If foundA Is Nothing Or foundB Is Nothing Then
MsgBox "Couldn't find " & IIf(foundA Is Nothing, termA, termB)
Else
Range(foundA, foundB).Copy
Set newSht = Sheets.Add
newSht.Range("B13").PasteSpecial
End If
End Sub
You can call it as follows:
DoEeeeeet "Sheet1","Event","Laptop"
It'll find the first instance of "Event" and the last instance of "Laptop" on the sheet named "Sheet1" and copy all of that data to B13 and subsequent cells in a new sheet.
Is that what you want? Or do you want each of the subranges beginning with "Event" and ending with "Laptop"?

Excel: How to split a column into two columns based off a third, odd/even parameter column?

I will be referencing the below picture:
I seek to split up the FirstValue Column into the two columns right of it; however, I want to split the columns based off the Parameter column. When the Parameter value is odd, I want to copy the values only to the OtherValue1 column. When the Parameter value is even, I want to copy the values only to the OtherValue2 column. After reading forums and trying excel's "Text to Columns" feature, I am unable to find a solution.
Is there a way implement this using VBA?
*Note: The worksheet is actually about 10,000 rows long, so speed would also be helpful.
EDIT:
Here is the code I have so far. I am getting Object errors in this line of code: .Cells(2, MF1Col).Formula = "=IF(MOD(paraformula,2)=1,WTRfor,"")"
Dim rw As Worksheet
Dim secondCell, MF1Cell, MF2Cell, paraCell, MF1formula, MF2formula, paraformula, WTRfor As Range
Dim secondCol As Long, MF1Col As Long, MF2Col As Long, paraCol As Long
Set rw = ActiveSheet
With rw
Set secondCell = .Rows(1).Find("FirstValue”)
' Check if the column with “FirstValue” is found
'Insert Two Columns after FirstValue
If Not secondCell Is Nothing Then
secondCol = secondCell.Column
.Columns(secondCol + 1).EntireColumn.Insert
.Columns(secondCol + 2).EntireColumn.Insert
.Cells(1, secondCol + 1).Value = "OtherValue1"
.Cells(1, secondCol + 2).Value = "OtherValue2"
.Activate
Set MF1Cell = .Rows(1).Find("OtherValue1")
MF1Col = MF1Cell.Column
Set MF2Cell = .Rows(1).Find("OtherValue2")
MF2Col = MF2Cell.Column
Set paraCell = .Rows(1).Find("Parameter")
paraCol = paraCell.Column
Set paraformula = Range(.Cells(2, paraCol).Address(RowAbsolute:=False, ColumnAbsolute:=False))
Set MF1formula = Range(.Cells(2, MF1Col).Address(RowAbsolute:=False, ColumnAbsolute:=False))
Set WTRfor = Range(.Cells(2, secondCol).Address(RowAbsolute:=False, ColumnAbsolute:=False))
.Cells(2, MF1Col).Formula = "=IF(MOD(" & paraformula & ",2)=1," & WTRfor & ","""")"
Range(.Cells(2, MF1Col).Address).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ActiveSheet.Paste
Set MF2formula = Range(.Cells(2, MF2Col).Address(RowAbsolute:=False, ColumnAbsolute:=False))
.Cells(2, MF2Col).Formula = "=IF(MOD(" & paraformula & ",2)=0," & WTRfor & ","""")"
Range(.Cells(2, MF2Col).Address).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ActiveSheet.Paste
End If
End With
in C2, =IF(MOD(E2,2)=1,B2,"")
in D2, =IF(MOD(E2,2)=0,B2,"")
copy these down to the end of your data
assuming the same format (Data,Col1,Col2,Parameter), but using relative addressing
Column 1: =IF(MOD(OFFSET(C2,0,2),2)=1,OFFSET(C2,0,-1),"") replace C2 with the current cell
Column 2: =IF(MOD(OFFSET(D2,0,1),2)=0,OFFSET(D2,0,-2),"") replace D2 with the current cell
again, copy and paste - once you have the first one correct, excel will adjust the formula for the current cell
For Cell D2:
=IF(MOD(E2,2),B2,"")
Explanation:
If Range E2 is not divisible by two, the display value from B2, otherwise display nothing.
you can reverse this by inserting a 'NOT' around the MOD for Cell C2:
=IF(NOT(MOD(E2,2)),B2,"")
VBA:
Sub odd_even()
a = 1 ' start row
b = 10 ' end row
c = 1 ' column with values inputs
For d = a To b ' FOR loop from start row to end row
If ActiveSheet.Cells(d, c) Mod 2 Then 'mod becomes high when value is odd
ActiveSheet.Cells(d, c + 2) = ActiveSheet.Cells(d, c) 'odd value gets copied to the odd-column ( two to the right of the values)
ActiveSheet.Cells(d, c + 3) = "" 'same row on even-column gets cleared
Else:
ActiveSheet.Cells(d, c + 3) = ActiveSheet.Cells(d, c) 'even value gets copied to the even-column ( three to the right of the values)
ActiveSheet.Cells(d, c + 2) = "" 'same row on odd-column gets cleared
End If
Next d ' go to next row
End Sub