Applying formula to range of cells, then pasting values - excel

I need to apply a formula/function (the DOLLAR function) to a range of cells, then cut and paste just the values.
I have a heading row and use Find to get to the column that I need. Then with all of the cells below, I want to apply the DOLLAR formula. However, the result at the end of my macro needs to be that those cells now contain just the value after applying the formula, and not the formula itself (this is because I'm going to use the sheet to run a mail merge so it can't have formulas).
I've tried running Do While and other cut/paste methods. I just don't have the skill to get it done :(
Sub ProjectSummaryAdjustment()
Workbooks("Project Summary").Activate
Range("A1",Range("A1").End(xlToRight)).Find("TD Budget Effort").Select
This is as far as I've gotten with the code. Now for all the cells below, I want to apply the DOLLAR formula, then have just the values pasted there. I don't mind if it has to cut and paste to the first empty column and then cut and paste back to the original column.

First make sure that you should avoid Select and Activate. Then you can simple use evaluate to do the conversion. You do need to set the field as text first:
With Workbooks("Project Summary").Worksheets("Sheet1") 'Change to your sheet name
Dim rng As Range
Set rng = .Range("A1", .Range("A1").End(xlToRight)).Find("TD Budget Effort")
'Test to make sure the header was found
If Not rng Is Nothing Then
With .Range(.Cells(2, rng.Column), .Cells(.Rows.Count, rng.Column).End(xlUp))
.NumberFormat = "#"
.Value = .Parent.Evaluate("index(DOLLAR(" & .Address & "),)")
End With
End If
End With

Related

Return cells content from range

Yesterday I learned here how to copy a row to a second sheet.
Sub maJolieProcedure(Texte As String)
With Worksheets("employes").Range("A:A")
Set c = .Find(what:=Texte)
If Not c Is Nothing Then
firstAddress = c.Row
Worksheets("employes").Rows(firstAddress).Copy _
Destination:=Worksheets("rapport").Range("A1")
MsgBox "Ok"
Else
MsgBox "Nok"
End If
End With
End Sub
To respect the formatting of the second sheet, I want to copy and paste the contents of each cell one by one.
I can identify the line number. However, I can't figure out how the Range object can return each cell one by one. For example, C3 content if Rows = 3.
Thanks a lot.
If you don't want to paste the formatting from one range to another paste values only.
Worksheets("employes").Rows(firstAddress).Copy
Worksheets("rapport").Range("A1").PasteSpecial xlValues
That's the same for all ranges, whether 1 cell or a million. The Copy process copies the subject to memory as one block. Any parsing must be done before the Copy instruction. An alternative is to read a range into an array.
Dim Arr As Variant
Arr = Worksheets("employes").Rows(firstAddress).Value
This will create a 3D array of 1 row and about 16000 columns. You might decide to limit your enthusiasm to only what you need.
With Worksheets("employees")
Arr = .Range(.Cells(firstAddress, 1), .Cells(firstAddress, .Columns.Count).End)xlToLeft)).Value
End With
Pay attention to the leading periods within the With statement. Each such period stands for the object mentioned in the With statement.
If your goal is to respect the formating of the second sheet, you don't need to loose time copying cell by cell.
It is more effective to do a paste special, like you do with the mouse:
Range("A1").Copy
Range("B1").PasteSpecial Paste:=xlPasteValues
works very well also with bigger ranges if you need:
Range("A1:A12").Copy
Range("B1:B12").PasteSpecial Paste:=xlPasteValues
or even
Range("A1:A12").Copy
Range("D3").PasteSpecial Paste:=xlPasteValues
If your goal is to really access all cell of a range individually , you just iterate on the range. For example:
For Each cell In Range("A1:A12")
cell.Value = cell.Value + 2
Next cell

Excel VBA to look for the last non-blank cell in a column and convert it to a value

I have a column thats rows are currently filled with this formula:
=IF(VLOOKUP(H3,B:D,3,0)="NOT_FOUND","",VLOOKUP(H3,B:D,3,0))
That fills rows one by one with the value that it finds. I am hoping that there is a macro that will search the column (I) for the single last non-blank cell and convert the formula answer into a value so I can eventually sum all of the values. I assume it is not a very difficult macro, but I have no experience working with VBA so any help would be appreciated!
Here is a pic of part of the table I am trying to make. Where the 13.8 is I would like for that to be converted to just a value since it is the last non-blank cell in the column. Please let me know if this makes sense or if more info is needed. Thank you!
nofriendsnojo, if overwriting the formula in a cell (in this case VLOOKUP) is all you need, then please see my code below:
Sub paste_values()
Dim lastRow As Long
Dim cel As Range
'get last non-blank cell in column I
lastRow = Cells(Rows.Count, "I").End(xlUp).Row
'loop that overwrites cell contents with simple values
For Each cel In Range("I1:I" & lastRow)
cel.Copy
cel.PasteSpecial xlPasteValues
Next cel
Application.CutCopyMode = False
End Sub
This is the basic code, it copies values of the cell and then pastes them to the same cell as values. This ultimately gets rid of any formula and converts the result of the formula into a simple value. It is quite common practice.
Of course, you can then add some references like ThisWorkbook. or ActiveSheet. or whatever scope you need.
I hope this solves your issue or atleast directs you in the right way.

VBA to reference the same cell even after the addition or deletion of rows & Columns

I'm using VBA code to write to cells in excel. For eg.
Range("C3") = code
Or
Cells(3,3) = code
If a row is inserted in the sheet, the code does then not update accordingly and would still write to Range("C3") etc. So the code then writes to the incorrect cell.
Is there a better way I can structure my code so it will update accordingly? Perhaps using a table instead of cells?
One solution is to used Named Ranges. You can define a Named Range in Formula Tab by clicking on Name Manager.
Then you will write.
Range("Name of the Range") = code
My believe is that named ranges update automatically when a row or column is inserted, so your code will print the value in the correct cell.
Thanks, good idea. I ended up defining the column filled with values as a range, then use a for loop to search for the defined string. That way it doesnt matter what row it is in aslong as the name and string doesnt change (Using a Named Range will probably be better for that exact reason).
Worksheets("Sheet1").Select
Set WS = ActiveSheet
With WS
LastRow = .Cells(.Rows.Count, 2).End(xlUp).Row 'Determine the last row number with data in it for column B
For Each acell In .Range("B1:B" & LastRow) 'Defines the search range from B1 to last row
If acell.Value = "String Searched For" Then
'Do stuff based on found cell location
End If
If acell.Value = "String Searched For#2" Then
'Do stuff based on found cell location#2
End If
Next
End With

Multi-step VLookup, Substitute, and then Evaluate Process

I have a three-step process that should end up giving me Boolean values of True/False and also an occasional #N/A or #VALUE (which I actually want to keep as errors). I am using a workbook with multiple named worksheets and am pulling cell values from one tab through a VLookup, replacing a string in those values, and then making those values into a formula to be evaluated. Here's what I have so far; I've included comments in the code explaining where I'm stuck.
Public Sub DetermineRowsToExamine()
'Define what our Rows are for the calculations
Dim NumRecords As Long
NumRecords = Workbooks("POVA Daily Reporter.xlsm").Worksheets("Paste Daily Data").Range("B" & Rows.Count).End(xlUp).Row
Dim CellsForFormula As Range
Set CellsForFormula = Workbooks("POVA Daily Reporter.xlsm").Worksheets("Paste Daily Data").Range("g2", "G" & NumRecords)
'Now I Insert the VLookup
Dim WSLogic As Worksheet
Dim WSData As Worksheet
Set WSData = Workbooks("POVA Daily Reporter.xlsm").Worksheets("Paste Daily Data")
Set WSLogic = Workbooks("POVA Daily Reporter.xlsm").Worksheets("Logic Statements")
CellsForFormula.Value = Application.WorksheetFunction.VLookup(WSData.Range("B2"), WSLogic.Range("A:D"), 4, False)
'This works in principle, but the problem is the "B2" in the VLookup - I need the "B2" to change to "B3" related
'to each row, just as it would if I pasted the rows down the columns as an cell formula
'Now I want to take that value and perform a replacement:
CellsForFormula.Value = Application.WorksheetFunction.Substitute(Range("g2"), "ZZZ", "C2")
'Again, this works great, but I need it to replace "G2" or "G3" or whatever cell it's in.
'Finally, I then want to evaluate that cell as if it were a formula. When the above calculations are working,
'I end up with: AND(LEN(C2)=10,OR(LEFT(C2,2)="57",LEFT(C2,2)="13"))
'I want to evaluate this as a formula, basically making it =AND(LEN(C2)=10,OR(LEFT(C2,2)="57",LEFT(C2,2)="13"))
End Sub
I think what I'm just not understanding is how to get the Cell references in the VLookup and Substitute functions to relate to whatever row I'm in.
Agreeing with what #AlanWaage is saying, you should put the actual VLOOKUP formula in the cell. Then, to get the formula to update relative to its location, you can utilize copy and paste. Finally, once you have the formulas there, you can copy and paste values, and do your replacement based on the values now in CellsForFormula range. See the updated code below:
' Put the formula in the first cell of your range
CellsForFormula(1, 1).Formula = _
"=VLOOKUP(Paste Daily Data!B2,Logic Statements!$A$1:$D$10000,4,0)"
' Copy the formula to the rest of your range
CellsForFormula(1, 1).Copy _
Destination:=Range(CellsForFormula(2, 1), CellsForFormula(NumRecords - 1, 1))
' Copy and paste values to just get the values in your range
CellsForFormula.Copy
CellsForFormula.PasteSpecial Paste:=xlPasteValues
' Execute your replacement
for each cell in CellsForFormula
cell.Replace("ZZZ", cell.offset(0,-4).Address)
'Use the line below instead of the line above if you only
'want to replace if the entire value is "ZZZ"
'cell.Replace("ZZZ", cell.offset(0,-4).Address,xlWhole)
cell.Formula = "=" & cell.value
Next cell
---EDIT---
Note that I did Logic Statements!$A$1:$D$10000 instead of Logic Statements!A:D; this will be much faster than having Excel examine all rows in the columns A:D. Make this number larger or smaller as you see fit, but you should try to avoid using complete column/row references in formulas unless necessary

Using the left-function [VBA]

I'm trying to create a simple macro that copys the two first numbers in each cell in a column and printing them in a different column. This is in a excel-document with more than 1 worksheet. I've tried for a while to write the code, but with no prior experience, I have a hard time figuring out what to do. I know the "left()"-function is able to do this, but I don't know how I define which column to draw data from and to which column it will be printed. Any help will be greatly appreciated.
With no prior experience to writing VBA code, I am going to reccommend you stick to the formula method of doing. Honestly, even if you were familiar with VBA, you might still opt to use the formula.
A formula is put into the actual cell you want the value to be copied.
=LEFT(sourceCell, #of characters you want)
This is how it would look:
=LEFT(Sheet1!A1, 2)
Think of it as saying "this cell shall equal the first n characters in cell OO, starting from the left".
Once you are done with your formula, if you don't need it to be binded to the source anymore (if the sourceCell changes, so does the cell with the LEFT formula), you can highlight the cells, Ctrl + C to copy, then right-click and select Paste Special. Then select VALUE and hit OK and now the cells are hard-coded with the value they were showing, as if you typed it yourself.
Once you master using formulas, the next step is VBA. Don't go confusing yourself by jumping into VBA and writing code for ranges, etc. if you aren't comfortable with using =LEFT yet. One step at a time, and you'll be a pro before you know it. :)
Here is a quick sample sub to get you started:
Public Sub LeftSub()
Dim SourceRange As Range, DestinationRange As Range, i As Integer
'Define our source range as A1:A10 of Sheet1
Set SourceRange = Sheet1.Range("A1:A10")
'Define our target range where we will print.
'Note that this is expected to be of same shape as source
Set DestinationRange = Sheet1.Range("B1:B10")
'Iterate through each source cell and print left 2 bits in target cell
For i = 1 To SourceRange.Count
DestinationRange(i, 1).Value = Left(SourceRange(i, 1).Value, 2)
Next i
End Sub
How about
Sub foo()
Dim cell As Range
Dim sourceRange As Range
'//define the source column - looks for contiguous downward data from A1;
Set sourceRange = Range(Sheets("Sheet1").Range("A1"), Selection.End(xlDown))
'//iterate each cell
For Each cell In sourceRange
If IsEmpty(cell.Value) Then Exit For
'//example to place the value in corresponding row of column B in sheet 2
Sheets("Sheet2").Range("B" & cell.Row).Value = Left$(cell.Value,2)
Next
End Sub
Or an equivalent formula (in the destination cell)
=LEFT(Sheet1!A1,2)

Resources