Excel VBA combine two SUBs - excel

Any chance of getting help combining the two below codes?
I'll try to educate myself on combining these things as I'm sure it's not that complicated, but for now I'd appreciate any assistance.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Application.CutCopyMode = False Then
Application.Calculate
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim UndoList As String
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
On Error GoTo ErrExit
UndoList = Application.CommandBars("Standard").Controls("&Undo").List(1)
If Left(UndoList, 5) = "Paste" Or UndoList = "Auto Fill" Then
MsgBox "Copy / paste is not permitted" & vbCr & _
"- Creator"
With Application
.Undo
.CutCopyMode = False
End With
Target.Select
End If
'The UperCase part______________________________________________
If Not (Application.Intersect(Target, Range("E8:OF57")) _
Is Nothing) Then
With Target
If Not .HasFormula Then
Application.EnableEvents = False
.Value = UCase(.Value)
Application.EnableEvents = True
End If
End With
End If
'_______________________________________________________________
ErrExit:
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
I'm trying to make my workbook as easy to use as possible, and to avoid user mistakes that mess upp formulas and so forth.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
Dim MyPicture As Object
Dim MyTop As Double
Dim MyLeft As Double
Dim TopRightCell As Range
'-----------------------------------------------------------
'- top right cell
With ActiveWindow.VisibleRange
r = 1
c = .Columns.Count
Set TopRightCell = .Cells(r, c)
End With
'------------------------------------------------------------
'- position picture
Set MyPicture = ActiveSheet.Pictures(1)
MyLeft = TopRightCell.Left - MyPicture.Width - 200
With MyPicture
.Left = MyLeft
End With
End Sub

The line starting with Private Sub or Sub begins the macro, and the line End Sub is the end of the macro.
Of the two code blocks you've pasted, the top contains two macros (one Worksheet_SelectionChange and one Worksheet_Change), and the second block only contains a SelectionChange one.
Depending which of those you wish to merge, just cut-paste the code from the inside of one sub (i.e. not including the start and end lines Private Sub and End Sub) into another, to make an amalgamated sub containing both sets of code. You may wish to amalgamate all three, but I'd guess it's just the two SelectionChange subs you want to merge.

Related

Two macros same worksheet

I’m a total newbie at this. I’ve got a worksheet with a list of jobs. One of the columns relate to the location eg, London, Manchester. When London is selected, I want that row copied to the London worksheet, and so on.
Also, I’ve got a column to show when the job is completed. So when I select completed, I want that row cut and pasted into the completed worksheet.
Now, after searching, I’ve found the code for both these actions and individually they work. But I’m trying to get them to work together. I’ve tried multiple things from searches I’ve done on here and google but nothing is working.
These are the codes I’ve got that work individually:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wsUse As Worksheet
Dim wsDc As Worksheet
Dim strdc As String
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
If Target.Cells.Count > 1 Then Exit Sub
If Target.Column <> 9 Then Exit Sub ' change 2 to the correct column number
Set wsUse = ThisWorkbook.Sheets("Workload Overview")
Set wsDc = ThisWorkbook.Sheets("Completed")
With wsUse
strdc = Target.Value
If strdc = "Completed" Then
n = .Rows.Count
Target.EntireRow.Copy
wsDc.Range("A" & n).End(xlUp).Offset(1, 0).PasteSpecial xlValues
wsDc.Range("A" & n).End(xlUp).EntireRow.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
Target.EntireRow.Delete
End If
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wsUse As Worksheet
Dim wsDc As Worksheet
Dim strdc As String
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
If Target.Cells.Count > 1 Then Exit Sub
If Target.Column <> 6 Then Exit Sub ' change 2 to the correct column number
Set wsUse = ThisWorkbook.Sheets("Workload Overview")
Set wsDc = ThisWorkbook.Sheets("London")
With wsUse
strdc = Target.Value
If strdc = "London" Then
n = .Rows.Count
Target.EntireRow.Copy
wsDc.Range("A" & n).End(xlUp).Offset(1, 0).PasteSpecial xlValues
wsDc.Range("A" & n).End(xlUp).EntireRow.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
Target.EntireRow.Copy
End If
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Worksheet_Change is an event that Excel looks out for and the code should be in a worksheet module (rather than ThisWorkbook or a normal module).
You can only have one Worksheet_Change change code in a module - shouldn't compile with it twice as you have.
So you need to combine the two procedures into one.
I've made a couple of assumptions - you set wsDC to London. You were then going to add similar code for Manchester and any other city. If you can guarantee your selected cities will be the same as the sheet name then use that to find your sheet to paste to.
If column 9 isn't Completed (could be Cancelled, In Progress) then can exit the sub as well.
The only difference between a Completed record and a City record are that the completed ones are deleted, so that can be treated the same way as cities except the last IF block that checks whether it needs deleting or not.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ErrorHandler 'Turn on error handling.
'You may not need to turn off calculation or screenupdating.
'Always polite to return it to the setting it was, rather than assuming
'so remember the setting so can be put back later.
Dim CalcMethod As Long
CalcMethod = Application.Calculation
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'This is needed if the row is deleted.
'Deleting a row is a Change event which will cause this code to fire a second time.
Application.EnableEvents = False
If Target.Cells.Count > 1 Then Exit Sub
If Target.Column <> 9 And Target.Column <> 6 Then Exit Sub
If Target.Column = 9 And Target.Value <> "Completed" Then Exit Sub
'Assuming Target value will be the same as the sheet name if column 6,
'or a "Completed" if it's column 9.
'e.g. London, Manchester, New York, Completed.
Dim wsDc As Worksheet
Set wsDc = ThisWorkbook.Worksheets(Target.Value)
Target.EntireRow.Copy
wsDc.Cells(Rows.Count, 1).End(xlUp).Offset(1).PasteSpecial xlValues
wsDc.Cells(Rows.Count, 1).End(xlUp).Offset(1).PasteSpecial xlPasteFormats
If Target.Column = 9 And Target.Value = "Completed" Then
Application.CutCopyMode = False
Target.EntireRow.Delete xlShiftUp
End If
TidyExit:
'Turn everything back on.
Application.EnableEvents = True
Application.Calculation = CalcMethod
Application.ScreenUpdating = True
Exit Sub
'If an error occurs, skip to this section (which is outside the main body),
'deal with the error and jump back into the code so everything can be
'turned back on before exiting.
ErrorHandler:
MsgBox Err.Number & vbCr & Err.Description, vbOKOnly + vbCritical
Resume TidyExit
End Sub

Auto run two vba codes when an Excel workbook opens

I have two VBA codes I would like to run when the Excel workbook is opened.
Sub test2()
Dim c As Range
For Each c In Range("A1:A1").Cells
c.Select
SendKeys "{F2}", True
SendKeys "{ENTER}", True
Next
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim xCell As Range
If Target.Address <> Range("A1").Address Then Exit Sub
Application.ScreenUpdating = False
For Each xCell In Range("B3:P3")
xCell.EntireColumn.Hidden = (xCell.Value < Target.Value)
Next
Application.ScreenUpdating = True
End Sub
It runs perfectly manually.
I have tried Sub Workbook_Open, but it does not work.
I have tried in module, in sheet and in ThisWorkbook too.
Could not make it work automatically as the workbook opens.
This code is supposed to F2+Enter cell A1 and then hide some columns depending on value in A1.
I modified code in this way:
Private Sub Workbook_Open()
test2
End Sub
Sub test2()
Dim c As Range
For Each c In Sheets("MySheet").Range("A1:A1").Cells
c.Select
SendKeys "{F2}", True
SendKeys "{ENTER}", True
Next
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim xCell As Range
If Target.Address <> Range("A1").Address Then Exit Sub
Application.ScreenUpdating = False
For Each xCell In Range("B3:P3")
xCell.EntireColumn.Hidden = (xCell.Value < Target.Value)
Next
Application.ScreenUpdating = True
End Sub
When openning worksheet it starts performing, does the first part (F2+Enter), but stops there. Does not perform this part:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim xCell As Range
If Target.Address <> Range("A1").Address Then Exit Sub
Application.ScreenUpdating = False
For Each xCell In Range("B3:P3")
xCell.EntireColumn.Hidden = (xCell.Value < Target.Value)
Next
Application.ScreenUpdating = True
End Sub
Code writen in Sheet1 (not "ThisWorkbook") manually performs well (not automatically).
The same code writen in "ThisWorkbook" starts performing automatically when file opens, but stops in the middle (as mentions earlier).
I think you're doing an over-engineering here.
Currently you want to:
Call on open Workbook_Open
... the macro test2 which simulates a change in the sheet (by pressing F2 and Enter), so that...
... the code inside Worksheet_Change gets called.
In fact, what you really want is to have the code that is now inside Worksheet_Change inside Workbook_Open.
So:
Remove test2
Remove the code from Worksheet_Change
Add your code directly inside Workbook_Open as follows:
Private Sub Workbook_Open()
Dim xCell As Range
Dim Target As Range: Set Target = Sheets("yourSheet").Range("A1")
Application.ScreenUpdating = False
For Each xCell In Sheets("yourSheet").Range("B3:P3")
xCell.EntireColumn.Hidden = (xCell.Value < Target.Value)
Next
Application.ScreenUpdating = True
End Sub

Renaming Subs for multiple usage, Moving Rows and in VBA

I am brand new to coding.
I am trying to use the code to move rows to different sheets and to move completed rows to a different work.
I am having trouble that the Sub Worksheet_Change is being seen as ambiguous name and doesn't work when I try to change the name to something like Worksheet_ChangeCOMPLETE or WorkSheet_Change3.
Below is the codes that I am trying to use.
What my plan is that I want completed orders (rows) to move to a new workbook in which I have named "COMPLETED" when a command button is pushed which triggers a Macro to insert the word "COMPLETE" in column 13 (M).
This new workbook was formerly my sheet 2 but I made it a new workbook following instruction from another forum. I also need rows to move to sheet 3 when "PARTIAL HOLD" inserted in column 13 via a different command button and then returned to sheet one when the command button on sheet 3 "RESUME" is clicked.
All workbooks and worksheets have all the same columns and spacing, I just can't get the codes to work when I rename them.
The first set of codes I am posting are for moving rows from sheet 1 to sheet 3 when the command button is pressed, followed by the code to move rows to the new workbook these codes are in Sheet 1 under VBA project, not a module.
The third is on sheet 3 to move rows back to sheet 1 once HOLD is complete.
Thank you in advance for your help.
SHEET 1
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDest As Range
Set rngDest = Sheet3.Range("A5:R5")
If Not Intersect(Target, Sheet1.Range("M5:M290")) Is Nothing Then
If UCase(Target) = "PARTIAL HOLD" Then
Application.EnableEvents = False
Target.EntireRow.Select
Selection.Cut
rngDest.Insert Shift:=xlDown
Selection.Delete
Application.EnableEvents = True
End If
End If
End Sub
Private Sub Worksheet_ChangeCOMPLETE(ByVal Target As Range)
Dim destWbk As String
Dim wbk As Workbook
Dim rngDestCOMPLETE As Range
destWbk = ThisWorkbook.Names("Completed.xlsx").RefersTo
destWbk = Replace(destWbk, "=" & Chr(34), "")
destWbk = Replace(destWbk, Chr(34), "")
Set wbk = Application.Workbooks(destWbk)
Set rngDest = wbk.Names("A1:S1").RefersToRange
If Not Intersect(Target, Sheet1.Range("rngTrigger")) Is Nothing Then
If UCase(Target) = "COMPLETED" Then
Application.EnableEvents = False
Target.EntireRow.Select
Selection.Cut
rngDest.Insert Shift:=xlDown
Selection.Delete
Application.EnableEvents = True
End If
End If
End Sub
SHEET 3
Private Sub Worksheet_Change3(ByVal Target As Range)
Dim rngDest3 As Range
Set rngDest3 = Sheet1.Range("A5:S5")
If Not Intersect(Target, Sheet3.Range("M5:M290")) Is Nothing Then
If UCase(Target) = "IN PROGRESS" Then
Application.EnableEvents = False
Target.EntireRow.Select
Selection.Cut
rngDest.Insert Shift:=xlDown
Selection.Delete
Application.EnableEvents = True
End If
End If
End Sub
As I mentioned on the comment you cannot rename these Subs, but you can do something like below:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDest As Range, rngDest2 As Range, rngDest3 As Range
Dim destWbk As String
Dim wbk As Workbook
If UCase(Target.Value) = "PARTIAL HOLD" Then
Set rngDest = Sheet3.Range("A5:R5")
If Not Intersect(Target, Sheet1.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
ElseIf UCase(Target.Value) = "IN PROGRESS" Then
Set rngDest3 = Sheet1.Range("A5:S5")
If Not Intersect(Target, Sheet3.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest3.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
ElseIf UCase(Target.Value) = "COMPLETED" Then
destWbk = ThisWorkbook.Names("Completed.xlsx").RefersTo
destWbk = Replace(destWbk, "=" & Chr(34), "")
destWbk = Replace(destWbk, Chr(34), "")
Set wbk = Application.Workbooks(destWbk)
Set rngDest2 = wbk.Range("A1:S1")
If Not Intersect(Target, Sheet1.Range("rngTrigger")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest2.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
End If
End Sub

Dynamic Search with highlight - Excel VBA

I would like to achieve the following:
In my excel sheet I have a set of data to which I've applied dynamic filtering by creating a "Search box".
The filtering itself works okay, no problems there, however, I would like to further improve it, by highlighting the text (that is entered into the search box) in the filtered rows in red.
I am attaching a screenshot of what I would like to see in the final version.
Any idea how this can be entered into my current code?
As always, any help is greatly appreciated!
Thank you!
Below is the code I use for the dynamic filtering:
Private Sub TextBox1_Change()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
If Len(TextBox1.Value) = 0 Then
Sheet1.AutoFilterMode = False
Else
If Sheet1.AutoFilterMode = True Then
Sheet1.AutoFilterMode = False
End If
Sheet1.Range("B4:C" & Rows.Count).AutoFilter field:=1, Criteria1:="*" & TextBox1.Value & "*"
End If
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Consider something like this - Write in a worksheet the following:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Target <> Range("a1") Then Exit Sub
SelectAndChange (Target)
End Sub
Private Sub SelectAndChange(strValue As String)
Dim rngCell As Range
Dim rngRange As Range
Dim strLookFor As String
Dim arrChar As Variant
Dim lngCounter As Long
If strValue = vbNullString Then Exit Sub
Application.EnableEvents = False
Set rngRange = Range("E1:E10")
rngRange.Font.Color = vbBlack
strLookFor = Range("A1").Value
For Each rngCell In rngRange
For lngCounter = 1 To Len(rngCell) - Len(strLookFor) + 1
If Mid(rngCell, lngCounter, Len(strLookFor)) = strLookFor Then
rngCell.Characters(lngCounter, Len(strLookFor)).Font.Color = vbRed
End If
Next lngCounter
Next rngCell
Application.EnableEvents = True
End Sub
The values in E1:E10 would be dependent from the value in A1 like this:

P.O. check list

I need users to be able to fill in one row to generate a P.O., and when the P.O. is generated the row below would be unhidden. The P.O. depends on column C, E and G to be filled in.
This code only unhides a row if one of the requirements are met. It also makes the workbook lag.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Target.Row < 14 Or Target.Row > 5000 Or Target.Column < 3 Or Target.Column < 5 Or Target.Column <> 7 Then GoTo ExitMe
Rows(Target.Row + 1).Hidden = False
ExitMe:
Application.EnableEvents = True
End Sub
I need one row to be filled in at a time so the P.O. can be generated properly. If there is a better way please let me know.
This macro also conflicts with my macro for protecting changed cells when the worksheet is saved. This is the error that appears: Run-time error '1004': Unable to set hidden property of the Range class.
It is placed in ThisWorkbook
Option Explicit
Private bRangeEdited As Boolean
Private WithEvents ws As Worksheet
Private Sub Workbook_Open()
Set ws = Range("A14:Y3000").Parent
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim sMSG As String
sMSG = "saving the workbook will lock the cells you have entered data into." & vbLf
sMSG = sMSG & "Do you want to go ahead ?"
If Not bRangeEdited Then GoTo Xit
If Not Me.ReadOnly Then
With Range("A14:Y3000")
If MsgBox(sMSG, vbExclamation + vbYesNo) = vbNo Then
Cancel = True
GoTo Xit
End If
.Parent.Unprotect "password"
If .SpecialCells(xlCellTypeBlanks).Address <> .Address Then
.SpecialCells(xlCellTypeConstants).Locked = True
bRangeEdited = False
End If
.Parent.Protect "password"
End With
End If
Xit:
End Sub
Private Sub ws_Change(ByVal Target As Range)
If Not Intersect(Range("A14:Y3000"), Target) Is Nothing Then
bRangeEdited = True
End If
End Sub

Resources