I am trying to use to use the following formula in an excel document: =IF(C2="","",NOW()). I'm just trynig to capture the time that a cell is populated. The problem I am running into is that everytime one formula updates, they all update.
For example, if I have the two formuals:
=IF(C2="","",NOW())
=IF(C3="","",NOW())
If I update C3, the formula that relates to C2 also upates. So my times are always identical to the last updated cell. I can't get them to update when only there dependent cells update.
One other thing of note, this spreadsheet is being used in MS Teams, so macros are not an option.
Is there a setting I have incorrect potentially? Or a work around?
Thanks in advance!
Have you looked into Office Scripts? They work a lot like macros in VBA, but they are for Excel Online.
https://learn.microsoft.com/en-us/office/dev/scripts/overview/excel
The behavior is expected since =NEW() always returns the current time, and you have no control of when a sheet might recalculate.
The best way to handle this situation is to have a macro that runs when the worksheet updates and it manually writes a value into the desired cell from the current time.
For example if the values to be tracked are in column "C" (the 3rd column) then the code below will write the current time of the adjacent cell (one column over) every time that value changes.
Place the code below under the worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 3 Then
If IsEmpty(Target.Offset(0, 1)) Then
Target.Offset(0, 1).Value = Now()
End If
End If
End Sub
The code above checks to see if a timestamp is already filled before setting it.
Try this:
=IF(CELL("row")=ROW(C2), NOW(), C2)
Drag down your C column as needed.
NOTE: You'll need to enable iterative calculations for formulas (Options -> Formulas).
Related
I'm creating a workbook to replace a company step challenge that is no longer available to us. The goal is to track steps in as real-time as possible (users will select their name from a drop-down in Cell E2 and input their steps into Cell F2). The drop-down is based on Column A using Data Validation and in Column B is their running total of steps. I would like to have a Control Button in place in Column G that takes the number of step inputted by the user and adds to the current steps for that same user in Column B.
So far, I have Data Validation running fine without issue and I have mock users in Column A and their steps in Column B. I assume the logic behind the coding would need to be Selecting the value in Cell E2 and locating that value in Column A. Once the code has a value of true, move over 1 cell to the right, add value in Cell F2 to that current selected cell value, and then delete value from Cell F2.
I attempted to start off with a range.find and I'm under the impression that is incorrect because I keep receiving errors. I then took to already posted questions to find someone with a similar issue but spent an hour just trying to create a patchwork code that didn't work in the end.
Any and all suggestions or links to forums/posts I wasn't able to locate myself would be greatly appreciated. I'm going to continue to search but as a newbie, some items I am finding are well above my skill/comprehension level.
EDIT:
So I've changed my approach based on comments. I now have a list of names spread over columns J2:S2 (this will grow as people sign-up). What I'm now attempting to do is write code that will find the person's name in the column based on cell value E2, then paste the steps they have inputted into cell F2 to the next blank row of that column. I put together another attempt at code but there is something wrong that I cannot figure out (See below). I will then just make a pivot based off of the data that will sit off the the left in Columns A:C.
With the below code I do not get any errors, nothing happens other than the clear contents. Sorry for the time before replying to comments, I wanted to attempt to do this on my own before coming back with an edit. I think there is something going on with me not specifying a cell value more clearly or I am misusing the rng.value as a way to paste rather than just check for a value.
I'm a greenhorn for sure with VBA so I'm learning rules as I go.
Sub Attempt_3()
Dim rng As Range
Set rng = sheets("Sheet1").Range("J2:S2").End(xlDown)
For Each Row In rng
If rng.Value = "E2" Then
rng.Value = rng.Offset(1, 0).Value = "F2"
End If
Next Row
Range("F2").Select
Selection.ClearContents
End Sub
I have a spreadsheet which contains a massive IF then Formula and it's getting a bit out of control, the spreadsheet is getting slower and becoming more difficult to maintain.
Is it possible to move the formulas from the cells to VBA? Would this have any improvement on performance? I was thinking about using a Select Case but need some help as to whether a select case would work. The select case will need to look at multiple cells i.e. If A1 = Yes AND A2 = "Cash" AND A3 = No" then call the Index Match function to retrieve the value. Is this possible?
Is there a big performance gain moving formula's out of the worksheet into VBA?
Thanks for any advice.
Brett
I don't think you find any performance improvement simply from moving the same code from the cell into VBA.
However it will be easier to read, and you may then see that not all of the conditionals are necessary, so you may be able to simplify it - which would speed it up.
"Select Case" will probably not be helpful though as it can only be used for a single comparison, not three like you mention.
I would suggest taking it one step at a time, move the formula into VBA, and convert it to a VBA "if" statement. Then you may be able to see ways to tidy it up.
Yes and No.
The main advantage to using VBA is that you could then also use for or while loops.
So instead of writing the same formula for each cell, you can develop your code to do these calculations in as many cells as you need/want.
Its not an easy question to answer, due to the little amount of information provided in the question.
Having the code in Excel formulas mean that it will be recalculated when any of its parameters changes i.e. you change the value of one Excel cell -> all Excel cells that use this value will be recalculated. This may significantly slow down Excel when you are making constant changes.
One way of handling this is to manually turn off Automatic calculations (Formulas->Calculation Options->Manual). Make your changes and run the calculations manually by hitting Formulas->Calculate Now for recalculating the whole workbook or Formulas->Calculate Sheet for a recalc of only the worksheet.
Another way is to move the formulas to a VBA procedure. This way you can execute the calculation manually while all the other calculations in the workbook are carried out automatically.
EDIT1:
To make an VBA procedure from an Excel formula create a procedure like this:
Sub CalculateFormula
Range("A1").Value = Evaluate("YOUR EXCEL FORMULA WITHOUT '='")
'Simple example below
Range("A1").Value = Evaluate("IF(A1=1,1,2)")
End Sub
EDIT2:
With looping:
Sub CalculateFormula
for i = 1 to 10
Range("A" & i).Value = Evaluate("IF(B" & i & "=""Hello"",2,1)")
Next i
End Sub
How to get the value of a merged cell of an excel having range address like "$B$4:$B$11" in vba
Even if it is really discouraged to use merge cells in Excel (use Center Across Selection for instance if needed), the cell that "contains" the value is the one on the top left (at least, that's a way to express it).
Hence, you can get the value of merged cells in range B4:B11 in several ways:
Range("B4").Value
Range("B4:B11").Cells(1).Value
Range("B4:B11").Cells(1,1).Value
You can also note that all the other cells have no value in them. While debugging, you can see that the value is empty.
Also note that Range("B4:B11").Value won't work (raises an execution error number 13 if you try to Debug.Print it) because it returns an array.
Josh Brown gave (in a comment) what I think is the best answer:
When I don't know the bounds of the merged area, I get the value with
Range("B6").MergeArea.Cells(1,1).Value
This is helpful in VBA when, for example, you are looping through files that might have merged cells of unknown ranges, so you can be much more general with this method. Thanks Josh!
This can be done in 2 steps:
First name the range of the merged cells; highlight the merged cell then go on the Ribbon Bar: Formulas Tab --> Define Name;
Make sure there are no spaces in the name. Example: defined_Name. Go to the desired cell you wish to see the output/result. In that cell, type: =defined_Name.
Press enter because your done.
(Excel 2016)
I am hoping this will help somebody.
I have found that if you press delete on a merged cell,
the target.cells.count = the number of merged cells.
Whereas if you change the value on the same cell, the target.cells.count = 1
This caused me issues as I was skipping multi selections in my worksheet_change code by testing the number of cells selected.
I don't really know much about excel especially VBA. But i need to write something(macro for ex.) that does the following:
if someone inserts a row and fills the first 4 cells of it, it needs to sort the rows (i have a macro for sorting called "sortingmacro") and then it needs to fill cells 7 and 8 by copying the cells above them.
for example if i insert a row to 4th line and fill A4,B4,C4 and D4 it needs to copy G3 to G4 and H3 to H4. (after sorting of course)
any help is appreciated.
edit:
i have formulas in the cells that are to be copied. the formulas for the first row(the top one according to sorting) is a different one and all the others are the same.
You can find out if a cell has been changed with the Worksheet_Change-Event.
Private Sub Worksheet_Change(ByVal Target As Range)
Debug.Print Target.Address
End Sub
Output (something like this):
$A$14
$B$17
$C$13
$C$21
$C$16
So if a matching cell is changed, look for the other 3 in the row and start your macro.
So put a button on the page, then go to the code for it (the click event). In that, use your sortingmacro to sort all the rows. Then you just do something simple like:
Rows(4).Cells(1,7).Formula = Rows(3).Cells(1,7).Formula
Rows(4).Cells(1,8).Formula = Rows(3).Cells(1,8).Formula
Of course instead of hardcoding 4 in there, you'd have a variable for the row (make sure and determine it after sorting).
I filter data into excel from an external financial software. It operates in real time and I want it when say cell B4 changes programatically by the real time financial software that Macro 1 will run. A few issues to be aware of are, the real time data may change in milliseconds.
If this is impossible then as a back up I would like to be able to copy and paste that Cell B4 every time it changes to say B10 then once it changes again put the new value in B10 and have the old value in B10 shift down to B11, then when B4 changes again have that value copied into B10 and shift down the previous two values so that the newest data is always in B10.
Setup an onWorksheet_Change event, this should run everytime the worksheet changes.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$4" Then
'Place appropriate code here
End If
End Sub
I don't know what would occur if another update occurred while this was running though.
If your cell value change every milisecond, you may have performance issues (or loops) with a vba event macro like Craig T showed.
You should probably add some checks on the update frequency and if you need to disable vba event, use :
Application.EnableEvents = False
' Coding to skip these events
Application.EnableEvents = True
Regards,
Max