I'm trying to get an equal sign "=" as first character in a cell to let the cell do a calculation. For example, the A column is representing, when present, the formula like '=12*12' so you can see what's behind the result in the B column. With this behavior I'm trying to let Excel act like a calculator inspired by programs like Speedcruch and Speq.
Unfortunately Excel is doing strange things when I try some code, it looks like the active cell is jumping to a sort of random cell.
Here is what I've got:
What is going wrong here?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
' The variable KeyCells contains the cells that will
' cause an alert when they are changed.
Set KeyCells = Range("B1:B1000")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
If Left(Range(Target.Address), 1) = "=" Then
' Do nothing
Else
Range(Target.Address) = "=" & Range(Target.Address)
Range(Target.Address).Select
End If
End If
End Sub
Changed code:
Private Sub Worksheet_Change(ByVal Target As Range)
' Do nothing if more than one cell is changed or content deleted
'If Target.Cells.Count > 1 Or IsEmpty(Target) Then Exit Sub
If Not Intersect(Target, Range("B1:B1000")) Is Nothing Then
' Change the range required
' Ensure target is a number before doing anything
'If IsNumeric(Target) Then
' Stop any runtime errors
On Error Resume Next
' Turn off events so a change doesn’t start an endless loop
Application.EnableEvents = False
Dim Value
Value = Chr(61) & Range(Target.Address).Value
'MsgBox "Value: " & Value 'Range(Target.Address).Value
If Left(Range(Target.Address).Value, 1) <> Chr(61) Then
MsgBox "Value: " & Value
Range(Target.Address).Formula = Value
End If
' Turn events on
Application.EnableEvents = True
' Allow run time errors again
On Error GoTo 0
'End If
End If
End Sub
This code places an equals sign ('=') in front of every entry in column B.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("B1:B1000")) Is Nothing _
And Left(Target.Value, 1) <> Chr(61) Then
Target.NumberFormat = "#"
Target = Chr(61) & Target.Value
End If
Application.EnableEvents = True
End Sub
To get Excel to not treat the equals sign as a formula indicator, you need to set the NumberFormat property to 'Text', which is done in this line:
Target.NumberFormat = "#"
Related
This macro will execute another macro when the wanted cell is active.
This macro works till column X. Adding more after that produces the "procedure too large" error. I think it has reached its capacity limit. How do I make the code shorter/work?
Note: this code continues till column AA and the only thing that changes are the range columns ("B11"->"C11") and code (B_11 -> C_11).
Picture 1: Columns B:AA is areas and rows 11:14 are tasks.
The code calls different macros set for those cells. Example cell B11 calls for B_11 macro and so on.
Select area&task
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count = 1 Then
' B-Column Click Macro------------------------------------------------------------
If Not Intersect(Target, Range("B11")) Is Nothing Then Call B_11
If Not Intersect(Target, Range("B12")) Is Nothing Then Call B_12
If Not Intersect(Target, Range("B13")) Is Nothing Then Call B_13
If Not Intersect(Target, Range("B14")) Is Nothing Then Call B_14
If Not Intersect(Target, Range("B16")) Is Nothing Then Call B_16
If Not Intersect(Target, Range("B17")) Is Nothing Then Call B_17
If Not Intersect(Target, Range("B19")) Is Nothing Then Call B_19
If Not Intersect(Target, Range("B20")) Is Nothing Then Call B_20
If Not Intersect(Target, Range("B21")) Is Nothing Then Call B_21
If Not Intersect(Target, Range("B22")) Is Nothing Then Call B_22
If Not Intersect(Target, Range("B24")) Is Nothing Then Call B_24
If Not Intersect(Target, Range("B25")) Is Nothing Then Call B_25
If Not Intersect(Target, Range("B26")) Is Nothing Then Call B_26
If Not Intersect(Target, Range("B27")) Is Nothing Then Call B_27
' C-Column Click Macro------------------------------------------------------------
If Not Intersect(Target, Range("C11")) Is Nothing Then Call C_11
If Not Intersect(Target, Range("C12")) Is Nothing Then Call C_12
If Not Intersect(Target, Range("C13")) Is Nothing Then Call C_13
If Not Intersect(Target, Range("C14")) Is Nothing Then Call C_14
If Not Intersect(Target, Range("C16")) Is Nothing Then Call C_16
If Not Intersect(Target, Range("C17")) Is Nothing Then Call C_17
If Not Intersect(Target, Range("C19")) Is Nothing Then Call C_19
If Not Intersect(Target, Range("C20")) Is Nothing Then Call C_20
If Not Intersect(Target, Range("C21")) Is Nothing Then Call C_21
If Not Intersect(Target, Range("C22")) Is Nothing Then Call C_22
If Not Intersect(Target, Range("C24")) Is Nothing Then Call C_24
If Not Intersect(Target, Range("C25")) Is Nothing Then Call C_25
If Not Intersect(Target, Range("C26")) Is Nothing Then Call C_26
If Not Intersect(Target, Range("C27")) Is Nothing Then Call C_27
continues till range("AA11")... call AA_11
Picture 2: After clicking for example cell B11 the below macro that is named B_11 will be active. The purpose of this macro is to filter mass data to the wanted area and task. So column B = Area 082M and Row 11 = Frame. In the datasheet, areas are set in rows and tasks are in table headlines so to filter tasks I need to hide unnecessary columns.
After call_11 macro
Sub B_11()
'
' Area-082M
Sheets("Tasks").Select
' hiding unnecessary columns
Columns("F:BI").Hidden = False
Columns("J:BI").Hidden = True
' filter data to only area 082M
ActiveSheet.ListObjects("Table2435").Range.AutoFilter Field:=4, Criteria1:= _
"082M"
End Sub
Please, try the next way. I only supposed that your rest of the sausage code keeps the same pattern...
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rng As Range
If Target.Count > 1 Then Exit Sub 'if selection contains more than a cell, the code exists
Set rng = Me.Range("B11:AA14,B16:AA17,B19:AA22,B24:AA27") 'the discontinuous range where the selection to trigger the event
If Not Intersect(Target, rng) Is Nothing Then
Dim MacroName As String
MacroName = Split(Target.Address, "$")(1) & "_" & Target.Row 'build the macro to be called name
Application.Run MacroName 'call existing macros
End If
End Sub
The above code is triggered only if a cell in the necessary range is selected, then it builds the name of the existing sub to be called and calls it (Application.Run MacroName)
Edited:
The next version will call a single Sub (instead of all existing), configured to act according to selected Target cell address. I configured it only up to "F" column (LiteralP variable). It will send an elocvent message if you try selecting cells situated after F:F column...
The adapted event will look like:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rng As Range
If Target.Count > 1 Then Exit Sub 'if selection contains more than a cell, the code exists
Set rng = Me.Range("B11:AA14,B16:AA17,B19:AA22,B24:AA27") 'the discontinuous range where the selection to trigger the event
If Not Intersect(Target, rng) Is Nothing Then
doTheJob Target
End If
End Sub
And the called Sub like this:
Sub doTheJob(Target As Range)
Dim LiteralP As String, ws As Worksheet, tbl As ListObject
Dim rngUnhide As Range, strRng As String, crit As String
LiteralP = Split(Target.Address, "$")(1) 'extract the literal part of the Target address
Set ws = Sheets("Hyttityöt"): Set tbl = ws.ListObjects("Table2435")
ws.Columns("F:BI").Hidden = False 'common for all cases: unhide the respective columns range
Select Case LiteralP 'select specific filter criteria:
Case "B"
crit = "082M": If Target.Row = 21 Then strRng = "F:AK,AP:BI"
Case "C"
crit = "081M": If Target.Row = 21 Then strRng = "F:AC,AP:BI"
Case "D"
crit = "093M": If Target.Row = 21 Then strRng = "F:AK,AP:BI"
Case "E"
crit = "092M": If Target.Row = 21 Then strRng = "F:AC, AP:BI"
Case "F"
crit = "091M": If Target.Row = 21 Then strRng = "F:AK, AP:BI"
' complete the necessary Target literal part, up to AA
Case Else
MsgBox "Letter " & LiteralP & " has not been configured above...", vbInformation, "Not configured...": Exit Sub
End Select
Select Case Target.Row 'select the appropriate ranges to be hidden:
Case 11: strRng = "J:BI"
Case 12: strRng = "F:I,N:BI"
Case 13: strRng = "F:M,R:BI"
Case 14: strRng = "F:Q,F:BI"
Case 16: strRng = "F:U,Z:BI"
Case 17: strRng = "F:Y,AD:BI"
Case 19: strRng = "F:AC,AH:BI"
Case 20: strRng = "F:AG,AL:BI"
'Case 21 looks specific for each letter address...
Case 22: strRng = "A:O,AL:BI"
Case 24: strRng = "F:AS,AX:BI"
Case 25: strRng = "F:AW,BB:BI"
Case 26: strRng = "F:BA,BF:BI"
Case 27: strRng = "F:BI,F:BE"
End Select
ws.Range(strRng).EntireColumn.Hidden = True 'hide the above established columns range
tbl.AutoFilter.ShowAllData 'show all filter data
tbl.Range.AutoFilter Field:=4, Criteria1:=crit 'apply the filter for the fourth field
If Target.Row = 13 Then tbl.Range.AutoFilter Field:=3, Criteria1:="SEMI" 'apply the second filter on the third column, different criteria
If Target.Row = 14 Then tbl.Range.AutoFilter Field:=3, Criteria1:="HYLSY" 'apply the second filter on the third column, different criteria
ws.Activate
End Sub
The code will be more compact, easier to be adapted if needed and using common variables declared and set only once. I think it shouldn't be difficult to continue the Sub configuration, looking to what I've done. If something not clear, I will try clarifying it if you ask for clarifications...
I need to ensure that the user types in an integer with length (blank) in any cell of a certain column. If the user inputs a number that is not length (blank), the Excel freezes the user at that cell and prompts to re-enter until integer length (blank) has been inputted or cancel is hit.
I currently have most of the things I request working. However, my issue is that Excel doesn't recognize length errors until I move away from the cell and come back to it.
For example (using 3 as desired length):
If i am currently on Cell B12 and type in 15646, which is not length 3, I can still click enter and it will move to Cell B13, which I want to prevent. But if I move up to B12 again from B13, the length error is seen and Excel prompts me to input integer with correct length until its fixed.
For now, the length error is only being recognized when I come back to cell. I need it to recognize as soon as I hit enter and prevent from moving on to next cell.
Sub InputNum()
row = ActiveCell.row
col = ActiveCell.Column
If col = 2 And ActiveCell.Value <> "" Then
Dim lotTextLen As Integer
lotTextLen = Len(ActiveCell.Value)
'checks to ensure the number put in is 3 characters long
'requests an input number to be put in
If lotTextLen <> 3 Then
lotData = InputBox("Invalid Entry Length. Scan in Lot #")
If Len(lotData) <> 3 Then
'error message
Result = MsgBox("Invalid Lot # Inputed. Must be 3 Characters. Try Again?", vbOKCancel)
'if cancel is clicked, input number is made blank and sub is exited
If Result <> vbOK Then
ActiveCell.Value = ""
'if ok is clicked to try again, recurses to beginning of code again
Else
InputNum
End If
Else
ActiveCell.Value = lotData
End If
End If
End If
End Sub
InputNum is being called in the Sheet1
Public Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("B:C")) Is Nothing Then
InputNum
End If
End Sub
In the sheet object place the following
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Columns(2)) Is Nothing Then
Application.EnableEvents = False
InputNum Target
Application.EnableEvents = True
End If
End Sub
Then use this in a standard module
Public Sub InputNum(Target As Range)
Dim IoTData As String
Dim Result As String
Dim isCancel As Boolean
Do While Len(Target.Value2) <> 3
IoTData = InputBox("Invalid Entry Length. Scan in Lot #")
If Len(IoTData) = 3 Then
Target.Value2 = IoTData
Else
If IoTData <> vbNullString Then
' error message
Result = MsgBox("Invalid Lot # Inputed. Must be 3 Characters. Try Again?", vbOKCancel)
If Result <> vbOK Then isCancel = True
Else
isCancel = True
End If
End If
If isCancel Then
Target.Value2 = vbNullString
Exit Do
End If
Loop
End Sub
By placing your code in a loop it will keep pestering the user for the right length until either they enter the right format or they press cancel in which instance the cell will be cleared of it's input.
You can also add And IsNumeric(IoTData) to your If statement to test that a number has been entered.
Replace
If Len(IoTData) = 3 Then
With
If Len(IoTData) = 3 And IsNumeric(IoTData) Then
Option Explicit
Dim add As String
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B:C")) Is Nothing And Target.Count = 1 Then
If Len(Target.Value) <> 3 Then
MsgBox "Invalid entry in cell with address " & add
Application.EnableEvents = False
Target.Activate
'Enter more code
Application.EnableEvents = True
End If
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Range("B:C")) Is Nothing And Target.Count = 1 Then
add = Target.Address
End If
End Sub
Keep getting error mentioned in the title on the "insert" line of code. Both the cut and insert lines of code appear to be the same size. I've been staring at this thing for hours. I can't figure out where I'm messing up.
Sub Worksheet_Change(ByVal Target As Range)
'convert communites by status
If Not Intersect(Target, Range("H1:H1000")) Is Nothing Then
If Cells(Target.Row, 8) = "Takedown" Then
Range(Target.EntireRow, Target.Offset(13, 0).EntireRow).Cut
Sheets("AIKEN.AUGUSTA-TAKEDOWN").Range(Range("A12").EntireRow,
Range("A25").EntireRow).Insert
Range("B12:B25").Interior.ColorIndex = 3
Range("C13").Select
End If
End If
End Sub
expected result: row range is cut from one part of the sheet and inserted in a different area of the sheet.
Actual result: error on insert line of code.
Try this:
Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
If Target.CountLarge > 1 Then Exit Sub
Set rng = Application.Intersect(Target, Me.Range("H26:H1000"))
If Not rng Is Nothing Then
If Cells(rng.Row, 8) = "Takedown" Then
Application.EnableEvents = False '<< don't re-trigger on Cut
Range(rng.EntireRow, rng.Offset(13, 0).EntireRow).Cut
Me.Range("A12:A25").EntireRow.Insert
Application.EnableEvents = True '<< re-enable events
Me.Range("B12:B25").Interior.ColorIndex = 3
Me.Range("C13").Select
End If
End If
End Sub
I am currently trying to add a script into excel. excuse my terminology, I am not that hot with programming!
I do all of my accounting on excel 2003, and I would like to be able to add the value of say cells f6 to f27 to the cells e6 to e27, respectively. The thing is, I want the value of the "f" column to reset every time.
So far I have found this code, which works if I copy and paste it into VBA. but it only allows me to use it on one row:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Target.Address = Range("f7").Address Then
Range("e7") = Range("e7") + Range("f7")
Range("f7").ClearContents
End If
Application.EnableEvents = True
End Sub
would somebody be kind enough to explain how I can edit this to do the same through all of my desired cells? I have tried adding Range("f7",[f8],[f9] etc.. but i am really beyond my knowledge.
First, you need to define the range which is supposed to be "caught"; that is, define the range you want to track for changes. I found an example here. Then, simply add the values to the other cell:
Private Sub Worksheet_Change(ByVal Target as Range)
Dim r as Range ' The range you'll track for changes
Set r = Range("F2:F27")
' If the changed cell is not in the tracked range, then exit the procedure
' (in other words, if the intersection between target and r is empty)
If Intersect(Target, r) Is Nothing Then
Exit Sub
Else
' Now, if the changed cell is in the range, then update the required value:
Cells(Target.Row, 5).Value = Cells(Target.Row, 5).Value + Target.Value
' ----------------^
' Column 5 =
' column "E"
' Clear the changed cell
Target.ClearContents
End if
End Sub
Hope this helps
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ErrHandler
Application.ScreenUpdating = False
Application.EnableEvents = False
If Intersect(Target, Range("B1:B5,F6:F27")) Then 'U can define any other range
Target.Offset(0, -1) = Target.Offset(0, -1).Value + Target.Value ' Target.Offset(0,-1) refer to cell one column before the changed cell column.
'OR: Cells(Target.row, 5) = Cells(Target.row, 5).Value + Target.Value ' Where the 5 refer to column E
Target.ClearContents
End If
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
I am trying to implement a code, where if you click a certain cell; you go to the first empty cell in a certain column.
Now I have this code:
If Selection.Count = 1 Then
If Not Intersect(Target, Range("B2")) Is Nothing Then
Columns("E").Find(vbNullString, Cells(Rows.Count, "E")).Select
End If
End If
But there is a problem with this code: I want it to start checking the first empty cell; starting at row 3. How do I do this?
Edit1:
I have made some adjustments to the code to fit my needs (for practice and aesthetics);
Dim lastCell As Range
Set lastCell = Range("E:E").Find(vbNullString, [E3], , , , xlNext)
lastCell.Interior.Color = RGB(100, 200, 100)
lastCell.Offset(0, -3) = "Last Cell -->"
lastCell.Offset(0, -3).Interior.Color = RGB(0, 110, 250)
lastCell.Offset(0, -3).Font.Color = vbWhite
If Not Intersect(Target, [B2]) Is Nothing Then
lastCell.Select
Side Note
The reason for Offset three columns to the right is because of the lay-out of the sheet :)
I clear the formatting of the cell and the text somewhere else if lastCell is changed. So if anyone is interested, let me know.
You can re-write your code like this, just by supplying SearchDirection argument.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("B2")) Is Nothing Then
Columns("E").Find(vbNullString, Cells(Rows.Count, "E") _
, , , , xlPrevious).Select
End If
End If
End Sub
Or you can try this one:
Edit1: For brettdj :)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error Goto errhandler
Application.EnableEvents = False
If Target.Cells.Count = 1 Then
If Not Intersect(Target, [B2]) Is Nothing Then _
Range("E:E").Find(vbNullString, [E3], , , , xlNext).Select
End If
continue:
Application.EnableEvents = True
Exit Sub
errhandler:
MsgBox Err.Description
Resume continue
End Sub
Both code works the same way except if there are blank cells in between E3:E(x).
Your revise code finds the first empty cell in Column E with reference to the last non empty cell.
The next code literally finds the first empty cell from E3. Don't know which is really what you need.
Side Notes:
Columns("E") is the same as Range("E:E").
Why use Range("E:E") then? Well, Intellisense kicks in with Range and not with Columns.
So I prefer using Range so you can see all the available arguments of .Find method.
This is what I would do:
Dim maxrows&, iRow&, iCol&, zcell As Range
maxrows = Excel.Rows.Count
If Selection.Count = 1 Then
iRow = Target.Row
iCol = Target.Column
Set zcell = Range(Cells(3, iCol), Cells(maxrows, iCol)).Find(vbNullString)
zcell.Select
End If