I would like to prevent a cell from being edited as I need to preserve the formula in it. The problem is, I want to copy paste a large range of values from another workbook over into my sheet, and the target range for pasting includes some cells which must not change. Thus, a simple lock option wouldn't work, as this would prevent me from doing this operation in one go.
I tried using a code wherein the cell changes back to its intended formula upon change of the cell, however, this yields an infinite loop. See simplified example below:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F28")) Is Nothing Then
Range("F28").Formula = "=if(E28=0,0,G28/E28)"
End If
End Sub
Many thanks for your help, much appreciated.
Edit:
An automated solution that would transfer from this other workbook wouldn't work as I receive these files in various formats and workbook names.
If your problem is infinite loop than here goes quite common solution for the problem. You just need to switch off events for a while and than switch them on back. Your code could looks like:
Private Sub Worksheet_Change(ByVal Target As Range)
'turns off events
Application.EnableEvents = False
If Not Intersect(Target, Range("F28")) Is Nothing Then
Range("F28").Formula = "=if(E28=0,0,G28/E28)"
End If
'turns on events back
Application.EnableEvents = True
End Sub
You have to make a Sub that enters the "resident" formulas. Just make a call to this sub after pasting the new values.
Related
There is a problem which I really need to resolve and need your help with.
There are a lot of different VBA Excel websites I have looked at to find an answer to my issue, but unfortunately I haven't been able to find the answer I am looking for.
I have around 200 modules in my "personal.xlsb" with a lot of code in it.
I also have a lot of forms and class modules used for several things.
This is my issue:
For some reason range("B4") from the Activesheet is being cleared automatically after running code.
In general it does not matter which code is being used, but after using code range B4 is being cleared.
For instance I could run code to copy the Activeworkbook.Fullname to the clipboard.
When I put in text or whatever in B4 after the cell was cleared before it is also automatically being cleared after that. I cannot put in any text in the cell without it being automatically cleared.
I tried to find out which code is being run to clear B4 e.g. with Worksheet_SelectionChange(ByVal Target As Range) or with the Watch window, but it hasn't helped me so far unfortunately.
I haven't found specific code referring to B4 in all of my code, or referring to column 2 row 4.
I am more or less desperately looking for the code which is responsible for clearing range B4 automatically.
For example when I put this in the Direct window: Range("B4").value = "B4 changed" it is automatically removed. The Worksheet_SelectionChange(ByVal Target As Range) is too late to see why the cell was cleared and the watch window on B4 doesn't spot anything even though I thought it should. I have tried a lot of things already (understatement).
When I change this in the Direct window: Application.Calculation = xlManual then it does not clear B4 when I put in text, but after I put it back to xlAutomatic, B4 will be cleared anyways.
I also checked if using Application.EnableEvents = False is helping, but it does not change anything on automatically clearing B4. I also checked if some Public declarations would refer to B4 but they don't. Also there is no conditional formatting involved.
Please help me find out which code is being run automatically to clear B4, I would really appreciate this!!
Kind regards,
Richard
I would approach this step-wise. First create a new standard module and include:
Public WhoAmI As String
Sub ev_on()
Application.EnableEvents = True
End Sub
Sub ev_off()
Application.EnableEvents = False
End Sub
and in the worksheet code area:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Be_4 As Range
Set Be_4 = Range("B4")
If Intersect(Target, Be_4) Is Nothing Then Exit Sub
MsgBox WhoAmI
End Sub
Get to the point in your process where you know that B4 will auto-clear if you try to manually enter a value in it.
Run ev_off
Verify that the worksheet is un-protected and B4 is un-locked
Verify that B4 is not subject to Data Validation
Attempt to put a value in B4
Note if the auto-clear occurs.
If the auto-clear still occurs, you have a problem that is beyond my ability. If the auto-clear has been prevented you begin a very tedious process of updating your subs one-by-one to include at the top:
Sub anyroutine()
WhoAmI = "anyroutine"
' more stuff
End Sub
So all suspect subs will record their names in the global string. Then run ev_on and try to detect the miscreant.
EDITED WITH PROGRESS
Dear Stackoverflow community,
I am working on a big excel file that does some calculations for me and my colleagues. Because the calculation data is a lot and is entered in Ranges (like "A1:H8"), not single cells (like "A1","C1",...), I want the users to be able to copy data from the same or another excel instance to my file.
The problem (edited):
The problem is, that just pasting cells formats the target cells (even if they are protected against formatting) and this has to be avoided. I searched through a lot of online discussions and finally made my own code, that allows me to copy and paste between two excel files in the same excel instance. Sadly, it does not work, if I copied the cells from another instance.
The code:
This is the code I use in "ThisWorkbook":
Sub PasteValuesOnly()
'if cells are pasted in named worksheets, only values are pasted
'is linked to Ctrl+V in options of macro menu
On Error GoTo err_handler
Dim Target As Range
Set Target = Selection
If Target.Parent.Name <> "Table1" Then
Selection.PasteSpecial
Else
Selection.PasteSpecial Paste:=xlPasteValues
End If
err_handler:
Exit Sub
End Sub
The system:
Windows 7
Excel 2010
What I tried besides my code (new progress):
As mentioned in the comments, I know Siddharth Rout's solution for only letting the users paste values, but I can't get it to work (not even in a fresh file when copying and pasting inside one Excel instance). I tried it for the whole workbook and for one single sheet.
What would help (edited):
It would be very helpful, if you could tell me how to optimize my code, so it works for two instances as well. If you know what is to do when I have an error with UndoList = Application.CommandBars(“Standard”).Controls(“&Undo”).List(1) in Siddharth Rout's solution with Excel 2010, this would be helpful, too.
Otherwise I would like every solution, that let's my users paste like they ever do, but prevent them from formatting the cells while pasting.
Thank you in advance
RaspiManu
After long hours of searching the internet, I found the solution of Donna Landy (Bella_Donna) in the microsoft forum. Her code is simple and works for CTRL+C / CTRL+V, Copy and Paste over Right Click Menu, Drag'n'Drop and even with two excel instances.
Because it starts on every single cell change and goes back to the cell or range that was changed, I slightly optimized it for my needs. Now, users that enter a list manually won't have to press "Enter" two times every time, they want to get to the next line below.
Assuming, the standard user will normally copy and paste, if there is a range of data, he or she does not want to retype, I changed the code, so the module sub only gets activated, if more than one cell has been changed (see below).
The solution:
In every worksheet, that has to be protected against formatting (modified):
Private Sub Worksheet_Change(ByVal Target As Range)
'activates format protection when changing a range
If Target.Cells.Count > 1 Then 'If more than one cell has been changed...
Call Worksheet_Change_Protected(Target) '...activating protection
End If
End Sub
In a module (unmodified):
Sub Worksheet_Change_Protected(ByVal Target As Range)
'Prevents user blithely obliterating in-cell formatting by undoing their paste and pasting the value
'Donna Landy 26.11.2018
'May be freely copied - hat tip appreciated :)
Dim SavedVal As Variant
On Error GoTo ErrHan
'Save the pasted value for later
SavedVal = Target.Value
'Switch off events to prevent infinite loop
Application.EnableEvents = False
'Undo the user's paste
Application.Undo
'Set target value
Target.Value = SavedVal
ErrExit:
'Remember to re-enable events
Application.EnableEvents = True
Exit Sub
ErrHan:
Resume ErrExit
End Sub
Thank you very much, Donna Landy!
I receive every week a file that has always the same structure and format and what I want to do is to get a message when double clicking in some the cells of one of the columns.
I have the code and it works but I have to paste everytime in the worksheet once I open it. I want make this code "generic" so I can use it automatically everytime I open one of these workbooks without having to copy every time or do anything rather than the double clicking to get the message.
Private Sub Worksheet_BeforeDoubleClick(ByVal target As Range, cancel As Boolean)
If Not Application.Intersect(target, myrange) Is Nothing Then
cancel = True
MsgBox "some message"
End If
End Sub
Some comments.. the sheet i need to work with it's always called the same and the column I need to work with is always the same too. The only change is the number of rows it contains.
After some research I don't know if I should do this in a class module or as an addi-in. I'm a begginer in VBA so this is out of my scope...yet.
Thanks!
I'm trying to create a pair of cells on two different sheets of my workbook, such that anything you enter into one cell gets copied across to the other. If this was one way, it would obviously be trivial. I want to make it so that the link is two-way, though. That's going to involve VBA scripting, and I'm something of a novice at that. Does anyone have some pointers on how to learn what I need to know? I have Googled, but that just produced some code samples without explanation, and I don't want to put in code that I don't understand.
Let's assume you have Sheet1 and Sheet2 and their names are exactly that.
At Sheet1, go to Developer and click on View Code. You should be looking at a blank coding sheet for Sheet1
On the left drop down of the coding area, select Worksheet instead of the default (General)
On the right drop down. select Change. You would automatically be given the following:
Private Sub Worksheet_Change(ByVal Target As Range)
End Sub
Changes to any cell in Sheet1 will trigger the code above.
The cell that has been changed is referred to as the Target range.
You can easily identify the address and content of the Target range using Target.Address and Target.Value. You can then use this address and value to update Sheet2.
Private Sub Worksheet_Change(ByVal Target As Range)
ThisWorkbook.Sheets("Sheet2").Range(Target.Address).Value = Target.Value
End Sub
To copy data from Sheet2 to Sheet1, just repeat the steps above but at Sheet2.
Private Sub Worksheet_Change(ByVal Target As Range)
ThisWorkbook.Sheets("Sheet1").Range(Target.Address).Value = Target.Value
End Sub
However, if change to Sheet1 will trigger a change to Sheet2, which in turn will trigger a change to Sheet1, the changes will happen for an indefinite time which does not make sense. Therefore, we need to add some code to apply the change only when the values on both Sheet1 and Sheet2 are different. If the values are the same, there is no need to apply change. Therefore, the code for Sheet2 should appear as below:
Private Sub Worksheet_Change(ByVal Target As Range)
If ThisWorkbook.Sheets("Sheet1").Range(Target.Address).Value <> Target.Value Then
ThisWorkbook.Sheets("Sheet1").Range(Target.Address).Value = Target.Value
End If
End Sub
You would use a pair of event macros to accomplish this. Here is an example that you can adapt:
mirror changes
I have a worksheet where in the first three columns (A,B,C) I store data. These values are used in a macro.
I would like to know how it is possible to make this macro run automatically after data is pasted onto these columns. I am almost sure that I will use the Worksheet-Change module, but as for the code I am clueless.
Thanks in advance.
A simple implementation:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1:C" & ThisWorkbook.Worksheets(1).UsedRange.Rows.Count)) Is Nothing Then
'Call your Macro to do stuff
End If
End Sub
Intersect checks if Target is in the range you want to monitor. So if something changes in columns past C, Intersect will return Nothing and your macro won't be called. Just keep in mind that the Worksheet_Change event fires on any change, even double clicking into the cells. If all you are doing in this Worksheet is copy&pasting data and then running your Macro, this should be fine, but if you are manipulating your data further, you might have to look at more sophisticated solutions. Examples include mirroring your Worksheet and comparing it pre/post Worksheet Changed Event. You can read more on this here: Detect whether cell value was actually changed by editing