vba for cut and paste is too slow - vba

I have two protected sheets:
Customer Stock
Collected Stock
Once a customer collects the stock, I trigger column (G:CustomerRow) in Customer Stock Sheet and it automatically cuts and paste above the first row (“2:2”) in the Collected Stock Sheet.
The problem is the VBA code takes too long to do that.
Somebody told my code has to be edited to avoid things like too many .selects etc.
Can somebody help me to modify my code to speed up the cut paste macro?
All I need is a macro for removing one row and pasting its values to another sheet above row ("2:2")
In the Customer Stock Sheet, the code is:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Target.Column = Columns(7).Column Then 'where G is the seventh column
If Target.Value <> "" Then
Call CustomerCollected
End If
End If
End Sub
In the module:
Sub CustomerCollected()
Dim actCell
actCell = Range("G" & ActiveCell.Row)
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
Response = MsgBox("Do you want to transfer this Customer from Customer Stock to Collected Stock?", vbYesNo)
If Response <> 6 Then
Exit Sub
End If
If Response = 6 Then
Worksheets("Collected Stock").Unprotect Password:="a27826" ' change the password to whatever you wish
If actCell <= Date Then
Rows(ActiveCell.Row).Select
Selection.Cut
Sheets("Collected Stock").Select
Rows("2:2").Select
Selection.Insert Shift:=xlDown
Range("A1").Select
Sheets("Customer Stock").Select
Selection.EntireRow.Delete
Range("A1").Select
End If
Worksheets("Collected Stock").Protect Password:="a27826", _
DrawingObjects:=True, _
Contents:=True, _
Scenarios:=True, _
UserInterfaceOnly:=True, _
AllowFormattingCells:=False, _
AllowFormattingColumns:=False, _
AllowFormattingRows:=False, _
AllowInsertingColumns:=False, _
AllowInsertingRows:=False, _
AllowInsertingHyperlinks:=False, _
AllowDeletingColumns:=False, _
AllowDeletingRows:=False, _
AllowSorting:=False, _
AllowFiltering:=False, _
AllowUsingPivotTables:=False
End If
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
ActiveSheet.DisplayPageBreaks = True
End Sub

You hardly ever need to use .Select for anything - you can access an objects properties directly without selecting it first. i.e. :
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 7 And Target.Value <> "" Then
Application.EnableEvents = False '// Prevent infinite loop
CustomerCollected
Application.EnableEvents = True '// Re-enable events
End If
End Sub
and
Sub CustomerCollected()
'// Check user wants to transfer row, if no then exit
If MsgBox("Do you want to transfer this Customer from Customer Stock to Collected Stock?", vbYesNo) = vbNo Then Exit Sub
'// Cut active row and insert into other workbook
ActiveCell.EntireRow.Cut
With Sheets("Collected Stock")
.Unprotect "a27826"
.Rows(2).EntireRow.Insert Shift:=xlDown
.Protect "a27826"
End With
ActiveCell.EntireRow.Delete Shift:=xlUp
Application.CutCopyMode = False
End Sub

Related

Is there a way to convert an Excel VBA to run as an Excel script (Excel online Automate)?

When a cell is selected, I would like to timestamp the row and move it to another sheet?
Private Sub Worksheet_Change
On Error GoTo Handler
If Target.Column = 11 And Target.Value = "COMPLETE" Then
Application.EnableEvents = False
Target.Offset(0, 2) = Format(Now(), "mm-dd-yyyy hh:mm")
Application.EnableEvents = True
End If
Handler:
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Columns(11)) Is Nothing Then
If UCase(Target.Value) = "COMPLETE" Then
Range("A" & Target.Row).Resize(1, 13).Copy Sheets("Closed Request").Cells(Rows.Count, 1).End(xlUp)(2)
Target.EntireRow.Delete
End If
End If
End Sub

Sort dialog box lock data headers vba

All,
I am using some code to bring up the sort dialog box via VBA. My data set will always have a header and I want to lock "My data has headers button in the corner of the sort dialog box"
I have inserted the line
`ActiveSheet.Sort.Header = xlYes`
However this does not seem to be acting in the way I would expect it to. The result I wish to obtain is within the screen shot below;
Full code below;
Sub ShowSortDialogBRR()
Application.ScreenUpdating = False
Application.Calculation = xlManual
ActiveSheet.Unprotect Password:="fsp123"
Application.EnableEvents = False
'select range and show sort dialog box
Dim Lastrow As Long
Lastrow = ActiveSheet.Range("LastRow_BRR").Offset(rowOffset:=-1).Row
Brr.Range("B3:CE" & Lastrow).Select
On Error Resume Next
ActiveSheet.Sort.Header = xlYes
Application.Dialogs(xlDialogSort).Show
If Err.Number = 1004 Then
MsgBox "Place the cursor in the area to be sorted"
End If
Err.Clear
With ActiveSheet
.Protect Password:="fsp123", UserInterfaceOnly:=True, DrawingObjects:=False, Contents:=True, AllowFiltering:=True, AllowFormattingColumns:=True
.EnableOutlining = True
End With
Application.ScreenUpdating = True
Application.Calculation = xlAutomatic
Application.EnableEvents = True
End Sub
any help to resolve this matter would be much appreciated.
That option is grayed out when the range has a filter applied. You don't have to actually filter the data, just have filter dropdowns showing. Here's an example that turns on the fitlers if they're not already.
Sub SortData()
Dim r As Range
Dim HasFilter As Boolean
Set r = Sheet1.Range("A1:B4")
HasFilter = Sheet1.AutoFilterMode
If Not HasFilter Then
r.AutoFilter
End If
Application.Dialogs(xlDialogSort).Show
If Not HasFilter Then
r.AutoFilter
End If
End Sub

VBA - Change cell value when clicked from/to yes/no for multiple merged cells

I have created a form that will give the user the choice to pick from 7 different options which will all be default blank. When they click the cell next to the option it will change from blank to "yes" and when clicked again it will remove the text and so on. Cells R33 and S33 are merged and the code works fine there but i need the code to run across multipe cells that are also merged such as (R35-S35, R37-S37, R39-S39 & R41-S41.
Can you help me out with this please?
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("R33").MergeArea) Is Nothing Then
Select Case True
Case Target.Cells(1) = "yes"
Target.Cells(1) = ""
Case Target.Cells(1) = ""
Target.Cells(1) = "yes"
End Select
Range("A1").Select
End If
Application.EnableEvents = True
End Sub
You can select multiple cells and that should be accounted for. A static union of the merge areas will not have to be redefined on every selection.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
static mrng as range
if mrng is nothing then
set mrng = union(cells(33, "R").mergearea, cells(35, "R").mergearea, _
cells(37, "R").mergearea, cells(39, "R").mergearea, _
cells(41, "R").mergearea)
end if
If Not Intersect(Target, mrng) Is Nothing Then
Application.EnableEvents = False
dim t as range
for each t in Intersect(Target, mrng)
select case lcase(t.value2)
case "yes"
t = vbnullstring
case else
t = "Yes"
end select
next t
Range("A1").Select
End If
Application.EnableEvents = True
End Sub

How to leave an edited-empty cell unlocked when sheet protection is initiated after an event

I would like to lock cells in a worksheet when data is entered. Also, the administrator would have access to unprotect the worksheet when changes have to be made. But with this code I have the following issues:
When data is entered and then the sheet it unprotected for deleting the data, the code then is unable to allow rentry of data into the same cells from where data was deleted, is there a good method to enable this?
I have tried a few options that relate to Target.Cells, ActiveSheet.UsedRange, ActiveSHeet.OnEntry and Application.OnKey but nothing seems to override the delete/baackspace event.
Any help would be appreciated. This is the current code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ToLock As String
Dim R As Range
Application.ScreenUpdating = False
ToLock = MsgBox("This input will now be locked.", vbOKCancel, "Confirm Change")
''If locking is accepted
If ToLock <> vbOK Then
Application.EnableEvents = False
Target.ClearContents
Application.EnableEvents = True
Exit Sub
End If
''Once entry entered, sheet will be locked with this password
ActiveSheet.Unprotect "quality"
' For Each R In ActiveSheet.UsedRange
For Each R In Target.Cells
If R.Value <> "" Then
Target.Locked = True
End If
Next R
ActiveSheet.Protect Password:="quality", DrawingObjects:=True, Contents:=True, Scenarios:=True
Application.ScreenUpdating = True
End Sub
Try this:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rnCell As Range, rnEmpty As Range
On Error Resume Next
Set rnEmpty = emptyCells(Target)
If Not (rnEmpty Is Nothing) Then
If rnEmpty.Address = Target.Address Then Exit Sub
End If
Application.ScreenUpdating = False
Application.EnableEvents = False
On Error GoTo ChangeEnd
If MsgBox("This input will now be locked.", vbOKCancel, "Confirm Change") = vbCancel Then
Target.ClearContents
GoTo ChangeEnd
End If
ActiveSheet.Unprotect "quality"
Target.Locked = True
Set rnEmpty = emptyCells(ActiveSheet.UsedRange)
If Not (rnEmpty Is Nothing) Then rnEmpty.Locked = False
ChangeEnd:
ActiveSheet.Protect Password:="quality", DrawingObjects:=True, Contents:=True, Scenarios:=True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Private Function emptyCells(rnIn As Range) As Range
On Error Resume Next
If rnIn.Cells.Count = 1 Then
If (rnIn.Value = vbNullString) And (rnIn.Formula = vbNullString) Then
Set emptyCells = rnIn
End If
Else
Set emptyCells = rnIn.SpecialCells(Type:=xlCellTypeBlanks)
End If
End Function
Some changes were introduced for readability, some others to fit functionality you seek for, others to avoid looping. Hope that helps... any questions, please comment and will add explanation.
It should work when you paste ranges (empty cells will still be editable)

VBA - Checking Two Different Path Locations

I have an existing VBA Project that I simply need to modify even if does scream to be re-written one day.
The sheet has a hidden sheet called Options that lists a file path in B3 and that path is called \fileserver\Drafting\MBS_JOBS\
The code then assigns a variable this path:
strpathtofile = Sheets("Options").Range("B3").Value
Finally, later on, it puts it all together with this:
strFileToOpen = strpathtofile & ActiveCell.Value & strFilename
What I need to do now is have it check a second path. So I've duplicated some of the code.
I first put the new path in B7 of the OPTIONS page. Then, I created a variable and assigned it:
Public strpathtoProj As String
strpathtoProj = Sheets("Options").Range("B7").Value
So, what I need to do is have this program also check this other path. So wondering if I need some kind of IF, THEN or ELSE statement around this part:
strFileToOpen = strpathtofile & ActiveCell.Value & strFilename
To also make it look at strpathtoProj.
I'm a "work in progress" VBA developer as a SOLO IT guy for a small business and am learning as I go.
Here are the modules that use strpathtofile (and you can see that I've already got some code in there for the strpathtoProj that I now need to use):
Sub RUN_SUMMARY_REPORT()
'assign variable... this is here just in case they haven't ran the "TEST" button
strpathtofile = Sheets("Options").Range("B3").Value
strFilename = Sheets("Options").Range("B4").Value
strThisBook = Sheets("Options").Range("B5").Value
strExtraInformation = Sheets("Options").Range("B6").Value
strpathtoProj = Sheets("Options").Range("B7").Value
'assign variable... this is here just in case they haven't ran the "TEST" button
Application.ScreenUpdating = False
Application.DisplayAlerts = False
ActiveSheet.Unprotect
'Remove any past data
SHOW_WARNING (False)
' Extended The Range To Remove data that continued below line 44. Brian
1/20/2015
' Range("C2:C200").ClearContents ' Jobs
Range("F4:S13").ClearContents ' Bar
Range("G17:G23").ClearContents ' Web Plate
Range("J17:J19").ClearContents ' Cable
Range("M17:M23").ClearContents ' Rod
Range("P17:P25").ClearContents ' Angle
'Remove any past data
'initialize ExtraInformation
Sheets(strExtraInformation).Range("A1:K1000").ClearContents
Sheets(strExtraInformation).Select
Range("A1").Select
'initialize ExtraInformation
SHOW_SHEETS (True)
INITIALIZE_PUBLIC_VARS
IMPORT_ALL_INFORMATION
PRINT_WEB_DATA
PRINT_BAR_DATA
PRINT_BRAC_DATA
PRINT_ROD_DATA
PRINT_ANGLE_DATA
SHOW_SHEETS (False)
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
End Sub
Sub TEST_FOR_BAD_JOB_MUMBERS()
Dim bFound As Boolean
On Error GoTo EXPLAIN
Application.ScreenUpdating = False 'increase performance
Application.DisplayAlerts = False
'Unhide all sheets
Sheets("REPORT").Visible = True
'Unhide all sheets
'Get all of the settings for this macro and assign variables
strpathtofile = Sheets("Options").Range("B3").Value
strFilename = Sheets("Options").Range("B4").Value
strpathtoProj = Sheets("Options").Range("B7").Value
'Get all of the settings for this macro and assign variables
Sheets("REPORT").Select
ActiveSheet.Unprotect
Range("C2").Select
Do Until ActiveCell.Value = ""
bFound = True
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject") 'Wow! What an
efficiency increase!
If Not fso.FileExists(strpathtofile & ActiveCell & strFilename) Then 'Wow!
What an efficiency increase!
Error (53) 'file not found error
End If
ActiveCell.Font.Color = RGB(0, 0, 0)
ActiveCell.Font.Bold = False
ActiveCell.Offset(1, 0).Select
Loop
Range("c2").Select
'Clean up the look of this thing!
Sheets("Options").Visible = False
Sheets("REPORT").Select
If bFound Then
MsgBox "Test Has Passed! All Job Numbers Found on X-Drive"
Else
MsgBox "No Jobs!"
End If
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
Exit Sub
EXPLAIN:
'Clean up the look of this thing!
Sheets("Options").Visible = False
Sheets("REPORT").Select
ActiveCell.Font.Color = RGB(255, 0, 0)
ActiveCell.Font.Bold = True
MsgBox "One Or More Jobs Do Not Exist. Please Check for RED Highlighted
Job."
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
End Sub
Sub IMPORT_ALL_INFORMATION()
'Set variables
Dim file_in As Long
Dim strInput As Variant
'end setting variables
Sheets("REPORT").Select
Range("C2").Select
Do Until ActiveCell.Value = "" '//loop through each job
file_in = FreeFile 'next file number
strFileToOpen = strpathtofile & ActiveCell.Value & strFilename
Open strFileToOpen For Input As #file_in
Put_Data_In_Array (file_in)
Organize_Array_For_Print
Close #file_in ' close the file
file_in = file_in + 1
Sheets("REPORT").Select
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Judging by the title of your question this is what you need, but I am a little confused by your question:
sub MainSub()
FileOne = worksheets("SuperSecretHiddenSheet").range("A1").value
FileTwo = worksheets("SuperSecretHiddenSheet").range("A2").value
if bothfileExists(FileOne, FileTwo) = true then
'do stuff
end if
End Sub
function bothfileExists(ByRef FileOne as string, ByRef fileTwo as string) as boolean
if (dir(fileone) <> "" and dir(fileTwo) <> "") then
bothfileExists = True
else
bothfileExists = False
end if
end function