VBA code to insert column and formula - excel

I have a file where I need to delete certain columns. I then need to insert a column called 'positive values' and add a formula so that only the positive values from another column are picked up in this new column.
So far I have pieced together the following code to delete the columns I do not need, but I am stuck at how to insert a new column next to an existing column called "net" and then have this column only show the positive values from column net in the relevant cells.
Current code
Sub ArrayLoop()
Dim ColumnsToRemove As Variant
Dim vItem As Variant
Dim A As Range
Sheets("sheet 1").Select
ColumnsToRemove = Array("acronym", "valueusd", "value gbp")
For Each vItem In ColumnsToRemove
Set A = Rows(8).Find(What:=vItem, LookIn:=xlValues, lookat:=xlPart)
Debug.Print vItem, Not A Is Nothing
If Not A Is Nothing Then A.EntireColumn.Delete
Next
End Sub
Currently I manually insert the new column and enter the formula max(E9,0) so the new column either shows 0 or a value if the value in the other column is greater than 0. Is it possible to automate this part as well.
Thanks in advance.

For Insertion locate the cell and issue:
If Not A Is Nothing Then A.EntireColumn.Insert
To insert a formula, use cell.formula= with the coresponding string value, e.g.
Cells(1, A.column - 1).Formula = "=max(" & cells(9, A.column - 2).Address & ",0)"
Note A as a range of the found value will shift to the right when inserting a column that's why you need - 1 nad - 2 in cell references.

Related

Edit a cell value for a column based on other column values using vba code

On clicking the "Command button1", I want to edit all the cells of highlighted column, for all rows having value in the "Type" column as "Test Point". The value to be set in cells need to be taken from other two columns from respective row as a substring and combining them with "_". I have created the base code, I am stuck at breaking into substring and setting the value to respective cells
Assuming all values in columns D & E are of equal length, you can try this code :
Sub test()
Range("B6", Range("B1048576").End(xlUp)).Select
For Each mycell In Selection
If mycell.Value = "Test Point" Then
mycell.Offset(0, 1).FormulaR1C1 = "=MID(RC[1],11,8) &""_"" & MID(RC[2],14,2)"
End If
Next mycell
End Sub

Insert Row Every Two Rows and Subtract the Difference

I have numerous excel sheets that contain rows that have paired data. Specifically, I need to subtract the first row from the one that follows (e.g., row 2-row 1; row 4-row3; etc.) and place the result into a new row below each pair. My data in each sheet appear as follows:
I am not new to programming languages, but I am new to visual basic.
My current code is:
Sub test() Dim rng As Range
Columns(1).Insert
With Range("b2", Range("b" & Rows.Count).End(xlUp)).Offset(, -1)
.Formula = "=if(mod(row(),2)=1,1,"""")"
.Value = .Value
.SpecialCells(2, 1).EntireRow.Insert
End With
Columns(1).Delete
With Range("a1", Range("a" & Rows.Count) _
.End(xlUp)(2)).Resize(, 3)
.Columns(1).SpecialCells(4).Value = "Difference"
Union(.Columns(2).SpecialCells(4), .Columns(3) _
.SpecialCells(4)).Formula = _
"=r[-1]c-r[-2]c"
End With
End Sub
However, the result is this:
I am mainly interested in calculating the differences between row pairs in the first column shown, but it is clearly not working.
Any help would be greatly appreciated!
Easier to use formulae, rather than VBA.
Go to a second sheet in the file ("Sheet2")
Enter in A1: =Sheet1!A1-Sheet1!A2
On Sheet2, select Rows1 AND 2.
Drag down.
Then depends on what you need to do.
May be Copy | Paste Special | Values to Sheet3, and sort to remove blank rows.

Sorting places my data with empty cells above it

I have written a bunch of VBA macros to get my data formatted how I need it, and the last step is to sort by this new column I have generated in ascending order. However, when I hit sort by the new column, the code now places all the empty cells above my newly generated column as I think it is reading the empty as a 0 and sorts it above any alphanumeric data. This is happening because of the UDF I have for sorting the data. I need to insert the new column with the UDF for each new cell that I insert, but I don't know how to define the range in the new column.
I am close to solving this but would love some help.
Essentially what I have tried for placing the data in a new column works, but the way I have set the range is placing it in a bad spot and it can easily be sorted in the wrong order now. I include all of my code, but the issue is in the last portion of it where I am setting a range to place the new data.
I think what is happening is when I set my range from C3-C2000 and populate it, the remaining empty cells are now included in my sort and give me "lower" numbers when I sort it ascending. Thus all the empty cells are ranked higher up in the column.
Option Explicit
Sub ContractilityData()
Dim varMyItem As Variant
Dim lngMyOffset As Long, _
lngStartRow As Long, _
lngEndRow As Long
Dim strMyCol As String
Dim rngCell As Range
Columns("B:B").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove 'make new column for the data to go
lngStartRow = 3 'Starting row number for the data. Change to suit
strMyCol = "A" 'Column containing the data. Change to suit.
Application.ScreenUpdating = False
For Each rngCell In Range(strMyCol & lngStartRow & ":" & strMyCol & Cells(Rows.Count, strMyCol).End(xlUp).Row)
lngMyOffset = 0
For Each varMyItem In Split(rngCell.Value, "_") 'put delimiter you want in ""
If lngMyOffset = 2 Then 'Picks which chunk you want printed out (each chunk is set by a _ currently)
rngCell.Offset(0, 1).Value = varMyItem
End If
lngMyOffset = lngMyOffset + 1
Next varMyItem
Next rngCell
Application.ScreenUpdating = True
'Here is where my problem arises
Range("C:C").EntireColumn.Insert
Dim sel As Range
Set sel = Range("C3:C2000")
sel.Formula = "=PadNums(B3,3)"
MsgBox "Data Cleaned"
End Sub
What I would like instead is a way to insert a new column, then have my UDF "PadNums" populate each cell up to the last cell of the previous column, essentially re-naming all my data from the previous column. I can then sort by the new column in ascending order and my data is in the correct order.
I think perhaps what I should do is copy column B into my newly inserted column C, then use some sort of last row function to apply the formula in all cells. That would give me the appropriate range always based on my original column?
I solved this! What I did was use range and xlDown to last row on column B, then pasted it to C, then inserted my UDF into C using the xlDown range!

Wildcard search on Excel

Im creating a macro in excel that has search function. so basically. i will put the list of servers in Sheet3 Column A and it will search the servers ing Sheet1 column A. Once done, it will display the result in Sheet 2 column A. However, im having issue in searching for wildcard. for example. i want to seach server "ABC123" but it will not display the result because it needs to be the whole name of the server "ABC123.def" can anyone help me with the codes?
Option Explicit
Sub HostNameFinder()
Dim srchLen, hName, nxtRw As String
Dim g As Range
'Clear Sheet 2 and Copy Column Headings
Sheets(2).Cells.ClearContents
Sheets(1).Rows(1).Copy Destination:=Sheets(2).Rows(1)
'Determine length of Search Column from Sheet3
srchLen = Sheets(3).Range("A" & Rows.Count).End(xlUp).Row
'Loop through list in Sheet3, Column A. As each value is 'found in Sheet1, Column A, copy it top the next row in Sheet2
With Sheets(1).Columns("A")
For hName = 2 To srchLen
Set g = .Find(Sheets(3).Range("A" & hName), lookat:=xlWhole)
If Not g Is Nothing Then
nxtRw = Sheets(2).Range("A" & Rows.Count).End(xlUp).Row + 1
g.EntireRow.Copy Destination:=Sheets(2).Range("A" & nxtRw)
End If
Next
End With
End Sub
If you fire up the macro recorder and perform a search for "ABC123" with the option to look in formulas and the option "Match entire cell contents" NOT selected, Excel will find the cell with the value ABC123.def
You could then study the code created by the macro recorder and would notice the difference to your code. You use lookat:=xlWhole, i.e. you're looking at the whole cell. Change it to LookAt:=xlPart. This is the equivalent of using a wildcard.
Or build the search term by wrapping it in a set of asterisks.
Set g = .Find("*" & Sheets(3).Range("A" & hName) & "*", lookat:=xlWhole)

adding new rows in excel without breaking a vba macro that uses Range.Value

I've written a macro in VBA that simply fills in a given cell's value from another cell in that sheet. I do this for lots of cells in the sheet, and I'm doing it like so:
Range("B3").Value = Range("B200")
Range("B4").Value = Range("B201")
'etc.
Now, I am often adding values by inserting new rows, so I might insert a new row
between B200 and B201, which will break the macro because it doesn't autoupdate when
I insert the new row.
How can I code the macro so it autoupdates the cell references when I insert new rows or columns?
My suggestion would be to make sure the ROW you want to retrieve values from has a unique value in it that you can .FIND anytime you want, then grab your values from column B of that found cell's row. So right now you want to get a value in B200 and A200 always has the text in it: "Final Total" and that is unique.
Dim MyRNG As Range
Set MyRNG = Range("A:A").Find("Final Total", LookIn:=xlValues, LookAt:=xlWhole)
Range("B3").Value = Range("B" & MyRNG.Row)
Range("B4").Value = Range("B" & MyRNG.Row + 1)
This is not an answer but an alternative.
Naming your range is the way to go as Shiin suggested but then if you have 500 cells then like I mentioned earlier, naming 500 cells and using them in your code can be very painful. The alternative is to use smart code. Let's take an example
Let's say you have a code like this
Sub Sample()
Range("B3").Value = Range("B200")
Range("B4").Value = Range("B201")
Range("B5").Value = Range("B201")
' And
' So On
' till
Range("B500").Value = Range("B697")
End Sub
The best way to write this code is like this
Sub Sample()
Dim i As Long
For i = 200 To 697
Range("B" & i - 197).Value = Range("B" & i)
Next i
End Sub
and say if you insert a line at say row 300 then simply break the above code in two parts
Sub Sample()
Dim i As Long
For i = 200 To 299
Range("B" & i - 197).Value = Range("B" & i)
Next i
For i = 301 To 698
Range("B" & i - 197).Value = Range("B" & i)
Next i
End Sub
So every time you insert a row, simply break the for loop into an extra part. This looks tedious but is much better than naming 500 cells and using them in your code.
If you are planning to use the macro only once (i.e for 1 time use) then read ahead.
If you are worried that when the user inserts the row then the cells are not updated then you can instead of assigning a value, assign a formula.
For example
Range("B3").Formula = "=B200"
This will put a formula =B200 in cell B3. So next time when you insert a row so that the 200th row moves it's position, you will notice that the formula automatically gets updated in cell B3
HTH
Try giving a name to the range. If you refer to the range by name Excel searches for it and retrieves the rows that defines it. Range names update their definition when new rows are added.
Adding to the above, i think this tutorial illustrates my point:
http://www.homeandlearn.co.uk/excel2007/excel2007s7p6.html this is how to define the name of the range.
This tutorial explains how to use it on macros and vba:
http://excel.tips.net/T003106_Using_Named_Ranges_in_a_Macro.html
I hope this helps :D

Resources