I am currently working on an Excel VBA Macro script where in it will do a simple TRUE or False test to the active cell. My problem is, i cannot make this working until the end of the list. It only run once and ends the program. I need this VB script to perform the IF & ELSE test up to the bottom of the list.
Description of the problem:
Let's say i have a list of dates in A1 to A9999 and beside it (F1:F9999) there's also a list that has a text on it. the F1:F9999 list contains two values only. (a)SAME DATE and (b) NOT THE SAME.
Perform a True or False test in the List F1:F9999.
If the active cell value is equal to the text "SAME DATE" (TRUE), it will ignore and move to the next item in the list then perform again number 1.
If the active cell value is equal to the text "SAME DATE" (FALSE), it will insert a row above it and then move to the next item in the list then perform again number 1
The TRUE or FALSE test will run until the end of the list.
The TRUE or FALSE test will stop running if it reached the bottom of the list.
by the way, the number of items in the list is not consistent. I just put there F1:F9999 for example purposes.
here's my code!
Sub IFandElseTest()
If ActiveCell.Value = "Same Date" Then
Range(Selection, Cells(ActiveCell.Row, 1)).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
ActiveCell.Offset(1, 0).Select
Else:
ActiveCell.Offset(1, 0).Select
Range(Selection, Cells(ActiveCell.Row, 1)).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
End If
End Sub
Appreaciate if you could help me on this.
Give this a try.
Explanation:
You should avoid using .Select/ActiveCell etc. You might want to see this LINK
When working with the last row, it's better not to hard code values but dynamically find the last row. You might want to see this LINK
Work with Objects, what if the current sheet is not the sheet with which you want to work with?
The below FOR loop will traverse the row from below and move up.
Code:
Sub Sample()
Dim ws As Worksheet
Dim LRow As Long, i As Long
Dim insertRange As Range
'~~> Chnage this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet1")
'~~> Work with the relevant sheet
With ws
'~~> Get the last row of the desired column
LRow = .Range("E" & .Rows.Count).End(xlUp).Row
'~~> Loop from last row up
For i = LRow To 1 Step -1
'~~> Check for the condition
'~~> UCASE changes to Upper case
'~~> TRIM removes unwanted space from before and after
If UCase(Trim(.Range("E" & i).Value)) = "SAME DATE" Then
'~~> Insert the rows
.Rows(i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
End If
Next i
End With
End Sub
Screenshot:
Followup From Comments
It really worked! BUT, one final modification. in your code: Set ws = ThisWorkbook.Sheets("Sheet1") Is it possible is you can set the WS as the Active worksheet. The reason of this is because the name of the worksheet unique and not consistent also.
Like I mentioned, in the first link above as well in the comment, do not use Activesheet. Use CodeNames of the sheet which do not change. See the screenshot below.
Blah Blah is the name of the sheet which you see in the worksheet tab but Sheet1 is the CodeName which will not change. i.e. you can change the name of the sheet from Blah Blah to say Kareen but in the VBA editor, you will notice that the Codename doesn't change :)
Change the code
Set ws = ThisWorkbook.Sheets("Sheet1")
to
'~~> Replace Sheet1 with the relevant Code Name
Set ws = [Sheet1]
Edit:
If you leave out the r.copy line it does more or less exactly what Siddharth Rout's solution does
Sub insrow()
Dim v, r As Range
Set r = [d1:e1]
v = r.Columns(1).Value
Do
' r.copy
If v = "Same Date" Then r.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Set r = r.Offset(1)
v = r.Columns(1).Value
Loop Until v = ""
End Sub
This does not yet include the end condition if row exceeds line 9999 but that should be easy to add ...
Related
I would like the user to be able to click the green button on the right of each named range to insert a new data entry row below the named range header. The code I have hard codes the insert row number for the first named range. I need a way to have the code to be smart enough to know that the first row below the header of the second, third, & forth named range will changed.
Another big part is that the inserted row needs to have the same formatting (dropdowns, formulas, color, etc.) as the rows below.
First named range button code:
Sub BidSheetAddRow_Materials()
' BidSheetAddRow_Materials Macro
Rows("19:19").Select
Selection.Copy
Rows("19:19").Select
Selection.Insert Shift:=xlDown
Range("A19").Select
Application.CutCopyMode = False
Selection.ClearContents
Range("C19").Select
Selection.ClearContents
Range("K19").Select
Selection.ClearContents
End Sub
Based on the screenshot all table headers are in colA, the first input row is 3 cells below the header, and the first input cell on each table row is a merged cell.
So this works for me:
Sub AddMaterial()
AddRow "MATERIALS"
End Sub
Sub AddRate()
AddRow "RATE"
End Sub
Sub AddRow(TableHeader As String)
Dim f As Range, ws As Worksheet, c As Range
Set ws = ThisWorkbook.Worksheets("Input") 'or whatever
Set f = ws.Columns("A").Find(what:=TableHeader, lookat:=xlWhole) 'find the header
If Not f Is Nothing Then
Set c = f.Offset(3) 'step down to first input row below header
Do While c.Offset(1).MergeArea.Cells.Count > 1 'keep looping while `c` is merged
Set c = c.Offset(1)
Loop
c.Offset(1).EntireRow.Insert shift:=xlDown 'insert
c.EntireRow.Copy c.Offset(1) 'copy
c.Offset(1).EntireRow.ClearContents 'clear new row
Else
MsgBox "Table header '" & TableHeader & "' not found!"
End If
End Sub
Before/after:
I'm very new to VBA and learning through code I find on the internet, and also using macros to see code.
I have an imported xls with three columns of data. I have code that does the following:
Inserts a new column A
Deletes column B
Delete rows with no data
Inserts two columns
So far - okay. What I am then trying to do is insert a number starting at 1 in column A1 and sequentially filling in until all rows with records have a number. I used a macro to see the code, but the range will vary (i.e. there are not always 52 rows in my import).
Is there a way to make this dynamic by only applying a number where there is data in the row (Column B will always have data)?
Thanks in advance - all help greatly appreciated!
Sub DeleteBlankRows()
Dim x As Long
Dim lastRow As Long
Dim A As Long
' INSERT A NEW COLUMN A FOR NUMERICAL SEQUENCE
Columns("A:A").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
'DELETE ALL BLANK ROWS
With ActiveSheet
For x = .Cells.SpecialCells(xlCellTypeLastCell).Row To 1 Step -1
If WorksheetFunction.CountA(.Rows(x)) = 0 Then
ActiveSheet.Rows(x).Delete
End If
Next
End With
'add two new columns for population
ActiveCell.Offset(0, 2).Columns("A:A").EntireColumn.Select
Selection.Delete Shift:=xlToLeft
ActiveCell.Columns("A:B").EntireColumn.Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.NumberFormat = "#"
'code to enter a sequential number starting at 1 for every row that has a record
ActiveSheet.Range("A1").Select
ActiveCell.Select
ActiveCell.FormulaR1C1 = "1"
ActiveCell.Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:A52"), Type:= _
xlFillSeries
ActiveCell.Range("A1:A52").Select
ActiveWindow.SmallScroll Down:=15
End Sub
There are a lot of stuff to improve your my code, but this should get you started
Some things to begin:
Use option explicit at the top of your modules so you don't have unexpected behavior with undefined variables
Always indent your code (see www.rubberduckvba.com a free tool that helps you with that)
Try to separate your logic defining variables and the reusing them
Name your variables to something meaningful and easy to unterstand (avoid x or r)
Write the code steps in plain English first, then develop it in VBA
Check the code's comments, and adapt it to fit your needs
Code
Public Sub PrepareFormat()
' Set a target sheet
Dim targetSheet As Worksheet
Set targetSheet = ActiveSheet ' This could be always the same sheet. If so, replace activesheet with thisworkbook.Sheets("NameOfTheSheet")
' Insert a new column for numerical sequence
targetSheet.Columns("A:A").Insert shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
' Delete all blank rows
Dim counter As Long
With targetSheet
For counter = .Cells.SpecialCells(xlCellTypeLastCell).Row To 1 Step -1
If WorksheetFunction.CountA(.Rows(counter)) = 0 Then
.Rows(counter).Delete
End If
Next counter
End With
' Add two new columns for population (this next lines would make column B empty, so filling sequentally would not work below
'targetSheet.Columns("D:D").Delete shift:=xlToLeft
'targetSheet.Columns("A:B").Insert shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
'targetSheet.Columns("A:B").CurrentRegion.NumberFormat = "#" -> commented this line because cells are going to be empty. What do you want to format as text? maybe this could go after you add the numbers. Also formatting the whole column is a waste of resources
' Insert a number starting at 1 in column A1 (added number 2 to fill down in sequence)
targetSheet.Range("A1").Value = 1
targetSheet.Range("A2").Value = 2
' Sequentially fill in until all rows with records have a number (this doesn't take into account if there are gaps in column b)
Dim referenceRange As Range
Set referenceRange = targetSheet.Range("B1:B" & targetSheet.Range("B" & targetSheet.Rows.Count).End(xlUp).Row)
targetSheet.Range("A1:A2").AutoFill Destination:=referenceRange.Offset(0, -1)
End Sub
Let me know if it works
PS. Check Sidar's answer on how to properly delete empty rows: https://stackoverflow.com/a/9379968/1521579
Could you try this?
'code to enter a sequential number starting at 1 for every row that has a record
'remove your code from here on and substitute with the following
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
ActiveSheet.Range("A1").Select
With ActiveCell
.FormulaR1C1 = "1"
.AutoFill Destination:=ActiveCell.Range("A1:A" & LastRow), Type:=xlFillSeries
End With
I need your help. I'm trying to run a macro on every row of a table. I want to have the first and the last interaction date with all clients of the list. What I already did on a macro is to copy the first date from a sheet2 and paste it on sheet1 to get the first date, then with CTRL-Down do it again with the next date to get the last date. However, since it's not a loop, it only does it on the cells I did it. (Down is the code I have). I would like the code to do the same thing on every cell, until the end of the table.
I have attached screenshot of the two sheets. I hope I made myself clear and I hope someone can help you out.
sheet1 sheet2
Sheets("Total").Select
Range("D6923").Select
Selection.End(xlDown).Select
Selection.Copy
Sheets("Timeline").Select
ActiveSheet.Paste
Range("C189").Select
Sheets("Total").Select
Selection.End(xlDown).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Timeline").Select
ActiveSheet.Paste
Range("B190").Select
Sheets("Total").Select
Selection.End(xlDown).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Timeline").Select
ActiveSheet.Paste
Range("C190").Select
Sheets("Total").Select
Selection.End(xlDown).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Timeline").Select
ActiveSheet.Paste
I can see you are very new to this and that is fine, we all were once! Using recorded macros is a good way to see how excel views what you are doing at the time but it is extremely inefficient compared to what it could be. As Ron has mentioned, select really is not a friend of efficient code. For example, your first four lines could be rewritten into one line as:
Sheets("Total").Range("D6923").End(xlDown).copy
However even this isn't the best way. I'm going to assume that you are working from the top of your sheet to the bottom and answer your question based on what I think you are trying to do. I'm also assuming that your sheet called Timeline is sheet 1 and your sheet called Total is sheet 2. Within total I am assuming that any number of entries could be there rather than just the two shown in the three examples given.
Sub ExampleCode()
'Variables, you can create and store things in VBA to make life easier for you
Dim Wb as Workbook 'This is the workbook you are using
Dim wsTimeline as Worksheet 'This is your worksheet called Timeline
Dim wsTotal as Worksheet 'This is your worksheet called as Total
Const rMin as byte = 5 'This is where the loop will start, I'm assuming row 5. As _
this won't change throughout the code and we know it at the _
start it can be a constant
Dim rMax as long 'This will be the last row in your loop
Dim r as long 'This will be how your loop knows which row to use
Dim timelineRow as long 'This will be the row that the data is pasted in Timeline
Dim timelineLastRow as Long 'This is the last row of data in your timeline sheet
Set Wb = Thisworkbook 'Your whole workbook is now stored in the variable Wb
Set wsTimeline = Wb.Sheets("Timeline") 'As the workbook was stored in Wb we can use it as _
shorthand here. Now the sheet Timeline is in wsTimeline
Set wsTotal = Wb.Sheets("Total") 'Same as above, this sheet is now stored
rMax = wsTotal.Cells(Rows.Count, 1).End(xlUp).Row 'This is the equivalent of starting at the _
bottom row in column A and pressing _
Ctrl+Up. This takes you to the last _
row of data in column A. …(Rows.Count, 2)… _
would be column B etc.
timelineLastRow = wsTimeline.Cells(Rows.Count, 1).End(xlUp).Row
'This is the bit where you start to loop, the line below basically says "Do the code in this _
loop for every value between rMin and rMax, each time make 'r' that value (r for row!)
With wsTotal 'Means that anything below starting with '.' will _
be the same as 'wsTotal.'
For r = rMin To rMax
'Ensure working on a line with data
If .Cells(r, 1) = "" Then
r = .Cells(r, 1).end(xlDown).row
If r > rMax Then
End With 'Closes the With statement above as no longer needed.
Exit For 'Exits the loop as we have ended up beyond rMax
End if
End if
'This will look for the person in wsTimeline and if they aren't there then add them
If IsError(Application.Match(.Cells(r, 1), wsTimeline.Range("A3:A" & timelineLastRow), 0)) Then
wsTimeline.Cells(timelineLastRow + 1, 1) = wsTotal.Cells(r, 1)
timelineRow = timeLineLastRow + 1
timelineLastRow = timelineRow
Else
timelineRow = Application.Match(.Cells(r, 1), wsTimeline.Range("A3:A" & timelineLastRow), 0)
End If
'I'm assuming that all records in 'Total' are chronologically ascending with no gaps between _
each row for a single person.
wsTimeline.Cells(timelineRow, 3) = .Cells(r + 2, 4)
If .cells(r + 3, 4) <> "" then
wsTimeline.Cells(timelineRow, 4) = .Cells(r + 2, 4).End(xlDown)
Else
wsTimeline.Cells(timelineRow, 4) = .Cells(r + 2, 4).End(xlDown)
End If
'Now that the data has been brought across from Total to Timeline we can move on to _
the next row.
Next r 'This will add one to the value stored in r and start the code again where _
the loop started
End With
'The loop has now ended having gone through every row in your worksheet called Total.
End Sub
this is my first post and I am super excited about it. I apologize in advance if my writing wouldn't make sense since I'm not super familiar with coding/programming terms.
Here is the Micro_Enabled_Excel_File which I'm using.
I have an excel file with multiple columns and rows. The number of rows will increase as time passes. I'm trying to filter two columns and copy the latest/most recent datapoint(row) and paste it in a new sheet to create a status report.
Excel Dataset: image
What the results would look like: image
What I have done so far:
Created a Micro to go through columns "SCOPE" and "TRADE NAME" to grab the unique entries and copy it into another sheet called "Code".
Sub First_COPY_STYLE_TO_REPORT()
'creating the Report sheet
Sheets("Report").Select
Cells.Select
Selection.Delete Shift:=xlUp
Sheets("Status Updates").Select
Cells.Select
Selection.Copy
Sheets("Report").Select
ActiveSheet.Paste
Rows("2:1048576").Select
Application.CutCopyMode = False
Selection.ClearContents
End Sub
Created a Micro to create a template for sheet "Report" which will eventually be filled with the results of next Micro.
Sub Second_COPY_UNIQUE_TO_CODE()
'add title to filter columns in the Code sheet
Sheets("Code").Select
Rows("1:1").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A1").Select
ActiveCell.FormulaR1C1 = "Filter1"
Range("B1").Select
ActiveCell.FormulaR1C1 = "Filter2"
'creating the filter criteria also known as scope and trade name
'Finds Duplicates on SCOPE column and copies it to a new sheet called CODE
Sheets("Status Updates").Select
Dim s1 As Worksheet, s2 As Worksheet
Set s1 = Sheets("Status Updates")
Set s2 = Sheets("Code")
s1.Range(Range("B2"), Range("B2").End(xlDown)).Copy s2.Range("A2")
s2.Range("A:A").RemoveDuplicates Columns:=1, Header:=xlNo
'Finds Duplicates on NAME column and copies it to a new sheet called CODE
Dim s3 As Worksheet, s4 As Worksheet
Set s3 = Sheets("Status Updates")
Set s4 = Sheets("Code")
s1.Range(Range("C2"), Range("C2").End(xlDown)).Copy s2.Range("B2")
s4.Range("B:B").RemoveDuplicates Columns:=1, Header:=xlNo
'Clears formating and autofits column widths
Sheets("Code").Cells.ClearFormats
ThisWorkbook.Worksheets("Code").Cells.EntireColumn.AutoFit
End Sub
Created a Micro (Not Functioning) which includes two loops to filter two columns, sort the first column and copy and paste the second row of the sheet into the sheet "Report".
Sub Third_Generate_Latest_Status_Report()
Dim a1 As Long, a2 As Long, b1 As Long, b2 As Long
a1 = Cells.Find("Filter1").Offset(1, 0).Row
a2 = Cells.Find("Filter1").End(xlDown).Row
b1 = Cells.Find("Filter2").Offset(1, 0).Row
b2 = Cells.Find("Filter2").End(xlDown).Row
Dim g As Long, i As Long
For g = a1 To a2 'Look up for Filter1 column. Then loop through all criterias.
ActiveSheet.Range("$C$1:$J$300").AutoFilter Field:=2, Criteria1:=g
For i = b1 To b2 'Look up for Filter2 column. Then loop through all criterias.
ActiveSheet.Range("$C$1:$J$300").AutoFilter Field:=3, Criteria1:=i
'sort the NO column from largest to smallest (to get the latest/most recent update).
'I have copied this part of the code from the Micro I recorded.
ActiveWorkbook.Worksheets("Status Updates").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Status Updates").AutoFilter.Sort.SortFields.Add2 _
Key:=Range("C1:C300"), SortOn:=xlSortOnValues, Order:=xlDescending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Status Updates").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
'I think I need to add code here to copy the row to sheet Report, and run the loop again
End With
Next i 'take next value in column Filter2
Next g 'take next value in column Filter1
End Sub
What I believe I need:
Sheet "Status Updates" - Filter "SCOPE" column and run through all criteria.Then,
Sheet "Status Updates" - Filter "TRADE NAME" column and run through all criteria.
Sort the "NO" column to get the most recent datapoint.
Copy the first row of data (meaning, the first row after the titles)
Paste it in another sheet called "Report".
Could you please take a look at my code and let me know what my mistakes are?
This is my first time coding/programming/using VBA.
Having an extra "code" sheet usually just makes things unnecessarily complicated. And because your "Status Updates" sheet is already sorted with Oldest updates to Newest updates, we know that for any given unique combo, you'll always want the bottom update. We can guarantee pulling that if we loop over your data backwards (from bottom row to first row, that's what the Step -1 does).
Then use a dictionary to check for unique combinations and pull the first encountered row (remember we're going backwards, so the first encountered row will be the latest update) for each unique combo and copy those rows over to your report sheet.
In the end, here's a fairly beginner friendly version of code for this task. I've commented it heavily for clarity so that you can follow along and understand what it does.
Sub tgr()
'Declare and set workbook and worksheet object variables
Dim wb As Workbook: Set wb = ActiveWorkbook
Dim wsUpdt As Worksheet: Set wsUpdt = wb.Worksheets("Status updates")
Dim wsRprt As Worksheet: Set wsRprt = wb.Worksheets("Report")
'Declare and set a range variable that contains your data
Dim rUpdateData As Range: Set rUpdateData = wsUpdt.Range("A2:G" & wsUpdt.Cells(wsUpdt.Rows.Count, "A").End(xlUp).Row)
'Verify data actually exists
If rUpdateData.Row < 2 Then Exit Sub 'If the beginning row is the header row, then no data actually exists
'Use a dictionary object to keep track of unique Scope and Trade Name combos
Dim hUnqScopeTrades As Object: Set hUnqScopeTrades = CreateObject("Scripting.Dictionary")
'Declare your resulting Copy Range variable. This will be used to gather only the range of rows that will be copied over to the Report worksheet
Dim rCopy As Range
'Declare a looping variable
Dim i As Long
'Loop through each row in your Status Updates data. Because your updates are already sorted Oldest to Newest, begin at the end and loop backwards to guarantee newest updates are found first
For i = rUpdateData.Rows.Count To 1 Step -1
'Verify this Scope/Trade combo hasn't been seen before
If Not hUnqScopeTrades.Exists(rUpdateData.Cells(i, 2).Value & "|" & rUpdateData.Cells(i, 3).Value) Then
'This is a newly encountered unique combo
'Add the combo to the dictionary
hUnqScopeTrades(rUpdateData.Cells(i, 2).Value & "|" & rUpdateData.Cells(i, 3).Value) = i
'If this is the first unique combo found, rCopy will be empty, check if that's the case
If rCopy Is Nothing Then
'rCopy is empty, add the first found unique combo to it
Set rCopy = rUpdateData.Cells(i, 1)
Else
'rCopy is not empty, add all additional unique combos with the Union method
Set rCopy = Union(rCopy, rUpdateData.Cells(i, 1))
End If
End If
Next i
'Clear previous results (if any)
wsRprt.Range("A1").CurrentRegion.Offset(1).Clear
'Verify rCopy isn't empty and then copy all rows over
If Not rCopy Is Nothing Then rCopy.EntireRow.Copy wsRprt.Range("A2")
End Sub
I've been looking all afternoon for the answer to this.
the code works as I want (after lots of time researching, I'm rather green to this) except I'd like to fill down to the last row used in previous column rather than the whole sheet.
I can't give exact referece to the previous column because it isn't always in the same place hence why I am looking it up and doing everything based on that look up result.
All answers I have found use the Range command but I can't find how to use my colNum variable for that.
Sub cndob()
'
' cndob change dob
'
' find column number and select
'
Dim colNum As Integer
colNum = WorksheetFunction.Match("BDate", Range("1:1"), 0)
Columns(colNum + 1).Select
' insert column right
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
' formula fill down
Cells(2, colNum + 1).Select
ActiveCell.FormulaR1C1 = "=RIGHT(RC[-1],2)&CHAR(47)&MID(RC[-1],5,2)&CHAR(47)&LEFT(RC[-1],4)"
Range(ActiveCell, ActiveCell.End(xlDown)).FillDown
Please help
The Range.Offset property is the perfect solution for this. Change your last line of code to:
Range(ActiveCell, ActiveCell.Offset(0, -1).End(xlDown)).FillDown
The first argument to .Offset is the row offset. That we don't want to change. The column offset, though, is set to one to the left of the active column.
I am not sure what exactly do you want to do, but from what I understood, something like this will do the job:
Option Explicit
Sub TestMe()
Dim colNum As Long
Dim sht As Worksheet
Dim rng As Range
Set sht = ActiveSheet
colNum = WorksheetFunction.Match("BDate", Range("1:1"), 0)
Set rng = sht.Cells(1, colNum)
rng.Offset(0, 1).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
rng.Offset(0, 1).FormulaR1C1 = "=1+1"
Range(rng, rng.End(xlDown)).Offset(0, 1).FillDown
End Sub
What it does? It looks for a cell "Bdate" on the first row and if it finds it, it inserts column to the right (if not, it gives an error :)). After this, it inserts a formula 1+1 for each cell, which is to the right. Anyhow, something like this: