Run a macro while you are actively in a cell? - excel

I have the below code. I want to have my cursor active in a cell, run the macro, and have the vba put the string of periods onto the clipboard then paste them into the cell where my cursor is active. Can this be done?
Dim obj As New DataObject
Dim txt As String
'Put some text inside a string variable
txt = ".............................."
'Make object's text equal above string variable
obj.SetText txt
'Place DataObject's text into the Clipboard
obj.PutInClipboard

Looking at your last question you may be able to use a Worksheet_Change event to simply add your periods at the end of the string after every edit.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.CountLarge = 1 Then
If Len(Target) > 0 Then
Application.EnableEvents = False
Target = Target & "......"
Application.EnableEvents = True
End If
End If
End Sub
You can customize this to a degree if this route is feasible. For instance, right now the macro ignores any changes that result in the cell being blank (i.e. you can still clear a cell with normal functionality). As per #BigBen's suggestion, the macro also ignores changes that apply to multiple cells at once (i.e. pasting a range to your sheet) You can also amend this to only fire if the cell changed is in a certain row/column. etc.

Related

Worksheet_change event to add character in front of every populated cell VBA

Is there a way to add a ' character before each cell that has a value on a worksheet when a worksheet_change() event triggers? For instance, if a cell is modified, I would like the code to run through every cell on the worksheet and add a ' in front of each populated cells value.
3/31/2021 converted to '3/31/2021
$56.092 converted to '$56.092
59.5% converted to '59.5%
Edit
Below is an example used to achieve this method; however, this performs slow over large datasets that may be pasted in.
Dim cell As Range
For Each cell In Target
If cell <> "" Then
cell.Value = "'" & cell.Value
End If
Next cell
End Sub
This will only apply formatting to the last cell edited... but as long as the existing data is good this housekeeping should be enough. you can loop the same code to correct your existing data if need be.
I haven't tested it on every data type, but it works on the handful I did test.
On Sheet Module:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Cells.Count = 1 Then
If Target <> "" Then
Target.Value = "'" & Format(Target, Target.NumberFormat)
End If
End If
End Sub

Automatic Sheet Calculation (Checkbox linked to cell)

I'm working on a table where I've inserted some Checkboxes (Form Control) which are linked to cells that return True or False when either Checkbox is ticked.
I wrote a code that should change the cell's color according to the returned value.
The code works fine but only when I double click the cell and validate by pressing Enter, or when I run the Sub by hitting F5 or a clicking a button.
(I used a similar code that updates everything automatically in another project but it doesn't seem to work here)
How can I make the Sub run automatically (or the sheet update) once a checkbox is ticked?
Here is the code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("A2:Q21"), Range(Target.Address)) Is Nothing Then
Dim cell As Range
For Each cell In ActiveWorkbook.Sheets("Sheet1").Range("A2:Q21")
If cell.Value = "True" Then
cell.Interior.Color = vbGreen
ElseIf cell.Value = "False" Then
cell.Interior.Color = vbRed
End If
Next
End Sub
I know I could use conditional formatting but this sheet will expand rapidly and I don't see myself copy-pasting hundreds of checkboxes
As the sheet will expand I think it'll be better to include a "lastRow" statement since I will be adding new rows at the bottom using a UserForm
Thanks!
You should extract the part doing the coloring to a new function and call that from both the original and from the checkbox's event handler.
' In Sheet1 Module
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("A2:Q21"), Range(Target.Address)) Is Nothing Then
ColorCells
End If
End Sub
' In Module1 Module
Sub CheckBox1_Click()
ColorCells
End Sub
Public Sub ColorCells()
Dim cell As Range
For Each cell In ActiveWorkbook.Sheets("Sheet1").Range("A2:Q21")
If cell.Value = "True" Then
cell.Interior.Color = vbGreen
ElseIf cell.Value = "False" Then
cell.Interior.Color = vbRed
End If
Next
End Sub
Update
If there are too many checkboxes than you may use the Worksheet's Calculation event handler assuming that the checkboxes have Linked Cells and some other Cell refers to their value.
' In Sheet1 Module
Private Sub Worksheet_Calculate()
ColorCells
End Sub
Note, if the checkbox does not have a Linked Cell, it won't work. If the checkbox has a Linked Cell but it is not referred to by any other cell, it won't work. This is because in these cases no recalculation will be initiated.
You can test this: Assign A1 to a Checkbox (on a new sheet), and try if the macro runs (should not), then write in A2 =2*--A1, and check again, now it should work.
If you want to minimize the footprint of this requirement, find an unused cell on the sheet and enter the following formula: =INDEX(1:1048576,1,1). This refers to all cells but it does not require a lengthy calculation. Of course, if you want to place it into A1, you should change the ,1,1 part to something else to avoid circular references.
Instead of firing your colouring sub at Worksheet_Change, put it under Worksheet_Calculate. Then insert the formula =A1:Q21(or whatever you need to cover your range) somewhere in your sheet. It will resolve to #value but that isn't important. This formula will force your sheet to automatically recalculate when anything within its range is changed, including the cells linked to your checkboxes. And then upon recalculate it will fire the sub that colours your cells correctly.

Fill a cell with VBA if contents get deleted by User

I am designing a time report for my colleagues. There are cells which contain a (hidden) formula but are unprotected because I need the user to still be able to manually override the formula.
Now, if a user enters his/her own content and then deletes it again, the cell is empty, which is what I don't want, as it will only lead to confusion.
I want to write a VBA macro which recognizes if the cell contents in a previously declared range are deleted / empty and if they are deleted / empty, then a formula from another (password-protected and hidden) cell should be copied to the empty cell.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myRange As Range
Set myRange = Intersect(Range("F9:I108"), Target)
If Not myRange Is Nothing Then
'I'm guessing something with WorksheetFunction and possibly CountA,
'but I don't know how to make it work
End If
End Sub
The formulas which should be entered if the content of a cell (or of multiple cells) is deleted is always in line 117 (same worksheet). For example, if the user deletes G50, then G117's formula should be copied into G50 in the same way you usually copy formulas in Excel (so if there's a non-$-reference in G117 that points to A117, it should then point to A50 after the formula is copied to G50).
If possible, I want to work without loops--they always take so long to execute.
Thanks in advance!
Here is a super simple example that involves only 3 cells, A1, A2 and A3. You must modify this to accommodate your formula-cells.
We first create a secret worksheet (called secret). We place the formulas from A1 through A3 from the main worksheet into the secret sheet, but we store them as Strings rather than Formulas:
Then we put the following worksheet event macro in the main sheet:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Set rng = Range("A1:A3")
If Intersect(Target, rng) Is Nothing Then Exit Sub
If Target.Count <> 1 Then Exit Sub
If Target.Value <> "" Then Exit Sub
Application.EnableEvents = False
Target.Formula = Sheets("secret").Range(Target.Address).Value
Application.EnableEvents = True
End Sub
The sub monitors changes to the three cells and if any of them are cleared, that formula will be restored from the secret worksheet.
Because it is worksheet code, it is very easy to install and automatic to use:
right-click the tab name near the bottom of the Excel window
select View Code - this brings up a VBE window
paste the stuff in and close the VBE window
If you have any concerns, first try it on a trial worksheet.
If you save the workbook, the macro will be saved with it.
If you are using a version of Excel later then 2003, you must save
the file as .xlsm rather than .xlsx
To remove the macro:
bring up the VBE windows as above
clear the code out
close the VBE window
To learn more about macros in general, see:
http://www.mvps.org/dmcritchie/excel/getstarted.htm
and
http://msdn.microsoft.com/en-us/library/ee814735(v=office.14).aspx
To learn more about Event Macros (worksheet code), see:
http://www.mvps.org/dmcritchie/excel/event.htm
Macros must be enabled for this to work!
Here's another possible answer. In order to copy the formula and have it maintain the "relative addressing" of the formula, you need to copy using the R1C1 notation. So a quick sub for this could look like
Option Explicit
Sub RestoreFormula(ByRef emptyCell As Range)
Dim formulaWS As Worksheet
Dim formulaCell As Range
Set formulaWS = ThisWorkbook.Sheets("Sheet1")
Set formulaCell = formulaWS.Range("A17")
emptyCell.FormulaR1C1 = formulaCell.FormulaR1C1
End Sub
The important line here is the emptyCell.FormulaR1C1 = formulaCell.FormulaR1C1 part.
Then, over in the Worksheet_Change event it could look like this
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim checkRange As Range
Set checkRange = ActiveSheet.Range("A1:A9")
If Not Intersect(checkRange, Target) Is Nothing Then
Dim changedCell As Range
For Each changedCell In Target
If IsEmpty(changedCell) Then
RestoreFormula changedCell
End If
Next changedCell
End If
End Sub
If anyone else ever has the same problem and maybe wants to use my solution, which is a combination of PeterT's and Gary's Student's suggestions (thank you both so much):
First I created a new worksheet, in which I copied all of the formulas I wish to retain. I made sure to copy them to the exact same cell as in the original sheet.
Then I appended this code to the original worksheet:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Bereich1 As Range
Set Bereich1 = Range("F9:I108") 'Do NOT enter multiple, non-contiguous ranges here! It crashes Excel!
If Not Intersect(Bereich1, Target) Is Nothing Then
Dim changedCell1 As Range
For Each changedCell1 In Target
If changedCell1 = "" Then
changedCell1.Formula = Sheets("Tagebuch_secret").Range(changedCell1.Address).Formula
End If
Next changedCell1
End If
Dim Bereich2 As Range
Set Bereich2 = Range("E112") 'instead duplicate the code snippet
If Not Intersect(Bereich2, Target) Is Nothing Then
Dim changedCell2 As Range
For Each changedCell2 In Target
If changedCell2 = "" Then
changedCell2.Formula = Sheets("Tagebuch_secret").Range(changedCell2.Address).Formula
End If
Next changedCell2
End If
End Sub
This works fine for every scenario in which cell contents get deleted, both if the user deletes contents of a single or multiple cells!
My next step is to make the _secret sheet very hidden, password-protect the workbook structure and then password-protect my vba project. Then only people who know the password (me) can destroy my file :)

Insertion of character in cell through clicking

How to insert a character in Excel cell by simply clicking on it? Clicking again on the cell would remove the character from the cell.
Example:
I have a cell range, A1:A10. If I click on a cell on this range a "X" is inserted on that specific cell, clicking again on it would remove the "X".
Can this be made through a button assigned to a macro? (the button would be assign to a specific cell)
I have a cell range, A1:A10. If I click on a cell on this range a "X" is inserted on that specific cell, clicking again on it would remove the "X".
You have to be very careful when you are using Worksheet_BeforeDoubleClick. If you do not take care of that in the code then the code will fire whenever there is a double click. Also use Cancel = True appropriately else you may get undesired results.
Is this what you are trying?
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, _
Cancel As Boolean)
'~~> Check if the double click happened in Range A1:A10
'~~> Also notice the placement of `Cancel = True`
If Not Intersect(Target, Range("A1:A10")) Is Nothing Then
'~~> Check if the cell is empty
If Len(Trim(Target)) = 0 Then
Target.Value = "X"
Cancel = True
'~~> Check if the cell already has X. This is to ensure that
'~~> the cell is not cleared if the user has typed something
'~~> else in the cell.
ElseIf UCase(Trim(Target)) = "X" Then
Target.ClearContents
Cancel = True
End If
End If
End Sub
I would suggest to use double click to enter/remove value. If you're ok with using double click..then here's the code for that:
Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
If IsEmpty(Target.Cells) Then
Target.Cells.Value = "x"
Else: Target.Cells.Clear
End If
Cancel = True
End Sub
The code needs to be placed in ThisWorkbook object
This does not seem like a good approach. Why not use dropdowns?
Go to Data->Validation select a list. You can either select your list of options from an Excel range or simply specify the list like this "Item1;Item2" etc.
Using any VBA will prevent the usage Undo function in Excel meaning - any time a macro executes in Excel all you undo history is cleared. This is very inconvenient when making changes.

Copy-paste doesn't trigger worksheet_change

Here is what I need to do: When I have written something into a cell in the sheet, my Worksheet_Change code should check if the cell contains certain characters and then replace those characters. That part of the code is working fine.
However there is a slightly odd behavior. Here's the code so far:
Private Sub Worksheet_Change(ByVal Target As Range)
Target.Value = Replace(Target.Value, "ß", "ß")
MsgBox "This is the value: " & Target.Value
End Sub
What's happening is that when I have the characters that need to be changed in my clipboard (using Ctrl+C). When I double-click onto the cell, paste the characters into the cell using Ctrl+V, and then press Enter, the code works just fine, the characters are changed. (Note: Without the double-click, you can't see the cursor.)
However, if I just go to the cell with my arrow keys and paste over whatever else is in the cell, nothing happens. I suspect the Worksheet_Change isn't even triggered, or else it would at least display my MsgBox.
(I don't know if it's relevant to this, but i am using Excel 2010 in a Mac)
You can use Worksheet_Calculate on a trigger sheet.
Create a new sheet which only contains a link to the range you want
to watch (i.e. =Sheet1!A1:B3)
Add a macro called Worksheet_Calculate to your trigger sheet
Now whenever any date in the linked range changes a recalculation of your trigger sheet gets triggered which in turn sets off your macro
This also works when the user enters a formula in the corresponding cell and one of the predecessors changes.
With manual calculation the recalculation of the trigger sheet and the macro only happen when the user presses F9.
Always use EnableEvents property when working with Worksheet_Change event. For more details link
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo err_rout
Application.EnableEvents = False
If Target.Count > 1 Then Exit Sub
Target.Value = Replace(Target.Value, "ß", "ß")
MsgBox "This is the value: " & Target.Value
err_rout:
Application.EnableEvents = True
End Sub
If Target.Column = 3 Then
Dim startRow As Integer
Dim endRow As Integer
startRow = Target.Row
endRow = Target.Row + Target.Count - 1
For i = startRow To endRow
' blah blah blah
maybe it helps

Resources