if I programmatically or manually enter a value, let's say 10000, into an excel cell, I need it automatically divided it by 1000 for me, can this happen?
No.1, I am not asking about display format, I need seriously change the entered value.
No.2, the formula shall not apply to the whole worksheet.
You can do this by using the Worksheet change event. However to make sure that you only do this once and not everytime this event is fired, you need to track the value somewhere. You can do this on an invisible sheet, somewhere else on the sheet, etc.
Logic wise, you basically check when a cell is changed if it's in the range of cels you want this to happen. If it is, you make sure that it's not the same value it had before you touched the cell (no changes were made) by comapring it to the record. If it has changed, you simply divide by 1000 and update the record.
Hope this helps.
Private Sub Worksheet_Change(ByVal Target As Range)
'Turn off events to stop this from looping
Application.EnableEvents = False
'Let's say you want this to happen for A1:A10
'Store the value of the cells on a hidden sheet or somewhere. Here let's assume B1:B10 is the hidden record
If Target.Column = 1 Then
If Target.Row > 0 And Target.Row < 11 Then
If Target.Value <> Target.Offset(, 1) Then
Target.Value = Target.Value / 1000
Target.Offset(, 1).Value = Target.Value
End If
End If
End If
'Turn events back on
Application.EnableEvents = True
End Sub
Sorry for some reason the formating thing is not indenting the code properly...
I'd shy away from this if I were you as you'll get problems with reediting the cell with perpetual dividing by 1000. Of course you could multiply the number by 1000 when editing starts but I don't see that being particularly robust.
The approach I would take would be to have a region of the spreadsheet (that the user doesn't normally see) that contains formulas of the form =A1/1000 and have the rest of the calculation flow depend on those cells.
Doing this means you keep everything on-spreadsheet with no VBA.
Related
In order to avoid the user typing = before they enter an arithmetic operation in a cell (i.e. 5+2, 8*8, etc) I have this code:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not Intersect(Target, Range("C4:C303")) Is Nothing Then
If Target = "" Then Exit Sub
Application.EnableEvents = False
TempTarget = Target
Target = "=" & TempTarget
If IsError(Target) Then Target = TempTarget
Application.EnableEvents = True
End If
On Error GoTo 0
End Sub
It works perfectly for additions (5+5) and multiplications (9*55), but doesn't work well for divisions and subtractions with small numbers (5-2, 8/9) because Excel treats them as dates. It works well for subtractions and divisions with bigger numbers (that couldn't be dates). I want to have in the cell the arithmetic formula but displaying the result. How can I fix the code so that it always work the way I want?
This isn't as straight-forward to solve as it might appear. If you enter values like 5-2 or 8/9 there's no way to intercept the change taking place to the cell before Excel changes it into a Date format.
However there is a solution, although it may not suit your purpose.
Set the Format of each of the cells you want to apply this to (presumably C4:C303) to "Text" or "#".
Change your code to include the addition of Target.NumberFormat = "General" before setting the value of the cell.
The code to achieve that would look like this:
...
Application.EnableEvents = False
TempTarget = Target
' Add this line to change the format back to General
Target.NumberFormat = "General"
Target = "=" & TempTarget
...
This will then correctly handle cases like 5-2 or 8/9 that would otherwise become dates automatically.
Side Effect
This creates an undesired side effect that if one of the existing calculated cells is edited again later it will now be in "General" format instead of text.
This could be resolved by using the SelectionChange event and by setting the format of the cell to "Text" or "#" again if it's inside the range you are working in, but you'd want to undo that if the user doesn't edit the value of the cell.
It's a bit messy. Excel clearly doesn't lend itself to this type of approach.
I am working on a spreadsheet to copy a users data from the previous day, then delete any numerical values but keep cells with "NA". What I want is for users to not be able to change/delete the cells that still have "NA" in them. I found some code that used OFFSET to move down one cell if a certain cell was selected (based on the row and column) but I haven't been able to figure out how to use the OFFSET to move down one cell if the current cell contains "NA". (https://www.extendoffice.com/documents/excel/3820-excel-lock-cell-without-protecting-sheet.html) This worksheet is already locked with a Quality-set password, so I can't do anything to unlock the spreadsheet, then select the "NA" cells to be locked, then relock the spreadsheet, thus looking for a creative way to keep the cells from being selected or changed. Also, the code would need to run all the time, not just when a macro was selected to run. Any ideas?
If it's possible for the user to open the book without macros enabled, then I'm not sure what you're asking is possible.
If you can assume macros are enabled though, you could use events to either prevent the user selecting the cell (similar to the OFFSET you mention) or you could track changes manually onto a hidden tab in order to note changes and deal with them as you see fit. There are many ways you can achieve the latter, just search "VBA tracking changes to a sheet" etc.
This is how you'd use the OFFSET method:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells(1, 1).Text = "NA" Then
Beep
Cells(Target.Row, Target.Column).Offset(0, 1).Select
End If
End Sub
Keep in mind though, this is a very simplistic method. It won't prevent users selecting multiple cells (a range) and deleting the contents. Nor will it prevent values being pasted to range that includes the 'NA'.
UPDATE:
The following is an improved version that will at least prevent users from selecting multiple cells (for pasting into or deleting) if one of the cells contains "NA".
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim testarea As Range
Set testarea = Intersect(UsedRange, Target.Cells)
If Not (testarea Is Nothing) Then
Application.EnableEvents = False
For Each cell_to_check In Intersect(UsedRange, Target.Cells)
If cell_to_check.Text = "NA" Then
Beep
Cells(cell_to_check.Row, cell_to_check.Column).Offset(0, 1).Select
Do Until Selection.Text <> "NA"
Selection.Offset(0, 1).Select
Loop
Exit For
End If
Next
Application.EnableEvents = True
End If
End Sub
This is still slightly flawed however, as it is still possible to drag-fill cells from other areas over a cell containing "NA".
I currently have the following in excel for other users.
The Number column does not change. Users will input values in Multiplier 1 and Multiplier 2 columns and they will get a value in Outcome column.
Is there an automatically way where the user can also input a value in Outcome column and the Multiplier 1 column will change?
Currently Number and Outcome column are protected, will I need to unprotect the Outcome column?
I recommend you use some VBA code using the Sub Worksheet_Change(ByVal Target as range) in the worksheet.
If the user enters a value in D2 it will put the formula "=D2/(A2*C2)" in B2
If the user enters a value in B2 it will put the formula "=A2*B2*C2" in D2
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Target.Cells.Count > 1 Then Exit Sub
On Error GoTo LastLine
If Not Intersect(Target, Range("D2")) Is Nothing Then
Range("B2").Formula = "=D2/(A2*C2)"
ElseIf Not Intersect(Target, Range("B2")) Is Nothing Then
Range("D2").Formula = "=A2*B2*C2"
End If
LastLine:
Application.EnableEvents = True
End Sub
This can be done. Begin by noticing that your formula is so simple that you
Can easily solve for multiplier1 as a function of:
outcome divided by (number times multiplier2)
Next get tricky by adding a 1 pixel wide column that will contain your formula
for outcome to the right of (now an input not a formula) the original
outcome column.
Similarly add a 1 pixel wide col to the right of multiplier1 that contains
your new formula for multiplier1. Adjust data validation on original input
cells for multiplier1 and outcome to allow only one of the two to be
entered at a time (use isblank function appropriately in an excel custom data
validation rule for each cell).
Finally right align the two 1 pixel wide cells so that their calculated values
appear within the corresponding enterable cells when they are blank.
Yes it's tricky but it works.
Sorry this is just an outline but I have used this in an application and it
works great. No vba, so undo redo don't break. Try it you'll like it.
I have two columns with (1) DATE/TIME COMPLETED and (2) STATUS.
(1) has a formula of =IF(B1="COMPLETED", NOW(), "")
NOTE: I have changed the B1, B2, etc.. corresponding to the row number.
It means if the (2) STATUS is "COMPLETED", it should show the current date/time in column (1), else it should show blank.
But when I COMPLETED a cell, all other cell with COMPLETED status validate/refresh as well, which marks all with same date and time value.
How can I update only the status for the cell that is updated, without changing the other cells in STATUS as well?
You really shouldn't rely on NOW() in this case, whatsoever. Excel re-validates for a number of different reasons. You could either create a macro that gets the current time and sets it as text, or do the same thing manually.
Alternatively, to convert existing formulas to literal values, follow this guide. This should be done for each row immediately following the completion of the task, so that Excel doesn't have the opportunity to incorrectly re-evaluate it.
now() gives you the current time as at the time of processing the formula. With it being a dynamic value, it will update everytime to the current date/time.
The only way I've found to be able to automate this is to use VBA (macros):
Private Sub Worksheet_Change(ByVal Target As Range)
' Assuming column 2 is actually columns "B". In case it's not, change target.column to the right column number
If Target.Column = 2 And UCase(Target.Text) = "COMPLETED" Then
'Assuming the datetime field goes to the column to the left of the above column.
Cells(Target.Row, Target.Column - 1) = Now
Else
If Target.Column = 2 Then Cells(Target.Row, Target.Column - 1).Clear
End If
End Sub
Hope this solves your issue.
I have a cell on Sheet1 that contains a drop-down list, let's say N3. The items in the drop down change, depending on the value in J3. At start, both cells are blank. Enter data in J3, and the drop down populates in N3. If I clear the contents of J3, the drop down in N3 is now empty, but the last selected value (if one was selected), still appears as a 'ghost' entry. It's a ghost entry to ME because it is old data, but I do understand the software is doing as designed. If J3 is cleared of contents, how do I get N3 to be cleared of that last selection? I am not VBA trained, but dangerous enough to handle it if that's what's needed to accomplish this. thanks!
You may consider to use the worksheet_change event.Put the below code in sheet1 code module.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo err_rout
Application.EnableEvents = False
If Not Intersect(Range("J3"), Target) Is Nothing And Target.Value = vbNullString Then
Range("N3").Value = vbNullString
End If
err_rout:
Application.EnableEvents = True
End Sub