I have four or five macro's each copying and pasting different subsets of data (all defined as ranges) from one tab to another tab. Occasionally someone may need to change some of the pasted data or rather portions of this.
Each of these macro's contains defined points I can goto. BUT if I needed to get to these points from another macro without running the bit before the goto point in the target macro - how can I do this.
I can call or application.run the second macro, but I need only run a part of it, not the whole thing.
I am a bit stuck.
Here is the part of the code which defines the goto point in one of the target macro's.
Grade:
Grades = Application.InputBox("Which Grade chemistry do you wish to load & Check against" & vbLf & vbLf & "1. S355 J2H" & vbLf & vbLf & "2. S355NH" & vbLf & vbLf & "3. S355NLH" & vbLf & vbLf, "Select which option to load")
Select Case Grades
Case 1
Ans = MsgBox("You have selected S355J2H is this correct?", vbYesNo) ' allows a loop if you have made a mistake and will take you back to the selection option
If Ans = vbNo Then GoTo Grade Else:
rng8.Copy: rng7.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ws.Activate
Columns("BC:BD").Select
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
Case 2
Ans = MsgBox("You have selected S355NH is this correct?", vbYesNo) ' allows a loop if you have made a mistake and will take you back to the selection option
If Ans = vbNo Then GoTo Grade Else:
rng8a.Copy: rng7.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ws.Activate
Columns("BC:BD").Select
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
Case 3
Ans = MsgBox("You have selected S355NLH is this correct?", vbYesNo) ' allows a loop if you have made a mistake and will take you back to the selection option
If Ans = vbNo Then GoTo Grade Else:
rng8b.Copy: rng7.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ws.Activate
Columns("BC:BD").Select
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
Case Else ' this is where no input or an alternative input is done, it will exit the subroutine
dummy = MsgBox("wrong input please try again", vbCritical)
Exit Sub
End Select
There is a similar code before this step, which I do NOT want to run and I would ideally like to not repeat this code and others from the target macro's in a separate macro, and call this new macro. When I need to update the information it means updating in multiple places instead one just the one or two maximum.
As BigBen suggested, you need to refactor your code. Copy the below code in a Module
Option Explicit
Public rRng8 As Range, rRng8a As Range, rRng8b As Range
Sub CopyRange(rCopyToRng As Range)
Dim iGrade As Long, iAns As Long, iTryAgain As Long
' Set Default Values
iAns = vbNo
iTryAgain = vbYes
' Loop to copy the correct range
Do While iAns <> vbYes And iTryAgain <> vbNo
' Get grade
iGrade = Application.InputBox("Which Grade chemistry do you wish to load & Check against" & vbLf & vbLf & "1. S355 J2H" & vbLf & vbLf & "2. S355NH" & vbLf & vbLf & "3. S355NLH" & vbLf & vbLf, "Select which option to load", , , , , , 1)
' Case to select the correct range to copy
Select Case iGrade
Case 1
iAns = MsgBox("You have selected S355J2H is this correct?", vbYesNo)
If iAns = vbYes Then CopyRangeHelper rCopyToRng, rRng8
Case 2
iAns = MsgBox("You have selected S355NH is this correct?", vbYesNo)
If iAns = vbYes Then CopyRangeHelper rCopyToRng, rRng8a
Case 3
iAns = MsgBox("You have selected S355NLH is this correct?", vbYesNo)
If iAns = vbYes Then CopyRangeHelper rCopyToRng, rRng8b
Case Else
' If the user entere incorrect number, ask if the want to try again
iTryAgain = MsgBox("Wrong input. Do you want to try again?", vbQuestion + vbYesNo)
End Select
Loop
End Sub
Sub CopyRangeHelper(rCopyToRange As Range, rRngToCopy As Range)
' Copy range
rRngToCopy.Copy: rCopyToRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
' Set range format
With rCopyToRange
.Interior.ThemeColor = xlThemeColorDark1
.Interior.TintAndShade = 0
End With
End Sub
NOTE: You don't need to use Select or Activate. You just reference what you need to work with
How to use this:
Below is a sample UDF that calls CopuRange UDF to perform the action
Sub TestThis()
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet3") ' Change sheet reference
Set rRng8 = oWS.Range("A1:A16") ' Set ranges as required
Set rRng8a = oWS.Range("B1:B16")
Set rRng8b = oWS.Range("C1:C16")
CopyRange ThisWorkbook.Worksheets("Sheet4").Range("A1:A16") ' Change sheet reference and range
End Sub
Related
I have the below code that creates a pop-up when new data is pasted into the specified range (A15 : E33). What I would like is when the user attempts to paste data into the range the pop up shows up and if the user selects no the data isn't pasted, preventing accidental overwrite.
Currently when the user selects no all it does is prevent cell B2 from being timestamped.
Thank you in advance for your help
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$15:$E$33" Then
Dim answer As Integer
answer = MsgBox("You are about to overwrite existing data, would you like to continue?", vbQuestion + vbYesNo)
If answer = vbYes Then
Range("B2") = "=NOW()"
Range("B2").Copy
Range("B2").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("a15:e33").Select
Else
MsgBox "Cancelled"
End If
End If
End Sub
Your code cannot know about your intention to paste in a specific range...
The above code is an event, being automatically triggered when the pasting has already been done. What you can do is using Application.UnDo:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.address = "$A$15:$E$33" Then
Dim answer As VbMsgBoxResult
answer = MsgBox("You are about to overwrite existing data, would you like to continue?", vbQuestion + vbYesNo)
If answer = vbYes Then
Application.EnableEvents = False 'to avoid the event being triggered again...
Range("B2") = "=NOW()"
Range("B2").Copy
Range("B2").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("a15:e33").Select
Application.EnableEvents = True
Else
Application.EnableEvents = False 'to avoid the event being triggered again...
Application.Undo
Application.EnableEvents = True
MsgBox "Cancelled"
End If
End If
End Sub
I want to replace !R46C181 to !R46C182, etc. Everytime i launch my macros, since it will take new column(month)
Right now , every month i manually change via find/replace (181 to 182) to move it to the next month before launching my macros.
Is there a way to put some - Input box? Like i where i just place 182, and it will update everything to it
Here is the part of that code
Range("BD31").Select
ActiveCell.FormulaR1C1 = _
"=SUM('[sales.xlsm]Market Share'!R46C181)"
Range("BD32").Select
ActiveCell.FormulaR1C1 = _
"=SUM('[sales.xlsm]Market Share'!R47C181:R49C181)"
Range("BD33").Select
And here is full code:
Sub Auto_ship()
'
' Auto_ship Macro
'
' Keyboard Shortcut: Ctrl+l
'
Range("BD31").Select
ActiveCell.FormulaR1C1 = _
"=SUM('[sales.xlsm]Market Share'!R46C181)"
Range("BD32").Select
ActiveCell.FormulaR1C1 = _
"=SUM('[sales.xlsm]Market Share'!R47C181:R49C181)"
Range("BD33").Select
ActiveCell.FormulaR1C1 = _
"=SUM('[sales.xlsm]Market Share'!R50C181)"
Range("BD34").Select
ActiveCell.FormulaR1C1 = _
"=SUM('[sales.xlsm]Market Share'!R51C181:R52C181)"
Range("BC31").Select
Selection.Copy
Range("BD31:BD35").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
Range("BD31:BD34").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("BG25").Select
Application.CutCopyMode = False
Range("BC30").Select
Selection.AutoFill Destination:=Range("BC30:BD30"), Type:=xlFillDefault
Range("BC30:BD30").Select
Range("BB3:BC3").Select
Selection.AutoFill Destination:=Range("BB3:BD3"), Type:=xlFillDefault
Range("BB3:BD3").Select
Range("BD3").Select
ActiveCell.FormulaR1C1 = "'Sep 2020"
Range("BE3").Select
Columns("BC:BC").EntireColumn.AutoFit
ActiveWindow.SmallScroll Down:=0
End Sub
You can use a
Dim month As String
month =InputBox("My Month")
save it to a string and then concat with & eg
"=SUM('[sales.xlsm]Market Share'!R46C"& month
of cause better ways to do this,error check etc, just a quick one here
The solution below features and InputBox where you can enter a column either by number (like 182) or by its alphabetic ID (like "FZ"). The specified column will then be used to create the formulas your code needs.
Option Explicit
Sub Auto_ship()
' 102
' Keyboard Shortcut: Ctrl+l
' include apostrophes and exclamation point in the string:-
Const Source As String = "'[sales.xlsm]Market Share'!"
Dim C As Variant ' target column
C = InputBox("Enter a column ID (Number or letter):", _
"Target column", "FA")
If Len(C) = 0 Then Exit Sub ' blank to exit
If Not IsNumeric(C) Then C = Columns(C).Column
With Application
.DisplayAlerts = False
.AskToUpdateLinks = False
End With
Cells(31, "BD").Formula = "=SUM(" & Source & RangeName(C, 46) & ")"
Cells(32, "BD").Formula = "=SUM(" & Source & RangeName(C, 47, 49) & ")"
Cells(33, "BD").Formula = "=SUM(" & Source & RangeName(C, 50) & ")"
Cells(34, "BD").Formula = "=SUM(" & Source & RangeName(C, 51, 52) & ")"
Cells(31, "BD").Copy ' copy the formats from BD31 to Bd32:Bd35
Range("BD32:BD35").PasteSpecial Paste:=xlPasteFormats
' if you want the formatsd to be copied to the current column use this line instead:-
' Range(Cells(32, C), Cells(35, C)).PasteSpecial Paste:=xlPasteFormats
' why would you copy the values from BD31:BD34 to that same address ?????
' Range("BD31:BD34").Copy ' copy the values
' Range("BD31:BD34").PasteSpecial Paste:=xlPasteValues
' Range("BG25").Select ' what's the purpose of this serlection?
With Application
.DisplayAlerts = True
.AskToUpdateLinks = True
.CutCopyMode = False
End With
End Sub
Private Function RangeName(ByVal C As Long, _
ByVal Rstart As Long, _
Optional ByVal Rend As Long)
' 102
Dim Rng As Range
Set Rng = Range(Cells(Rstart, C), Cells(IIf(Rend, Rend, Rstart), C))
RangeName = Rng.Address
End Function
The exact range address is created by the function RangeName which takes 2 or 3 arguments: the column, the start row and the end row. The latter can be omitted if you want to specify a single cell. I use A1 notations instead of R1C1. That's a matter of preference in this case.
My code looks radically different from yours because I removing all Select statements. They serve no useful purpose. Excel knows perfectly well where its cells are once you tell it the coordinates.
The second half of your code didn't make sense to me. I couldn't fathom why you would want to copy BD31:BD34 to Bd31:Bd34 every month. I gave one example how you might use the column you enter to address different cells each month directly. For the rest of the code I urge you to continue removing all Select statements and just address each range directly as you instruct what is to be done with it.
I am very new to the macro..
Basically I wanted to copy a row (E23 to H23) from worksheet named "Present month" of one workbook to a column of another worksheet named "ANA" (K4 to K7) in another workbook.
Please help me out!!
Edit1: Code from comment
Sub Copy_and_update_last_col_Census()
Range("K4:K7").Select
Selection.ClearContents
Application.WindowState = xlNormal
'the below line throws error
Windows("NOL_Support_Ticket_Status_Report").Activate
Range("E25:H25").Select
Selection.copy
Windows("Charts.xlsm").Activate
Range("K9").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Selection.copy
Range("K4").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Application.CutCopyMode = False
Range("K9:N9").Select
Selection.ClearContents
End Sub
This is a tip. Go to the Developers tab -> Record Macro -> do the actions you want -> stop recording and woila press alt + F11 and check out the module.
F8 is your friend and you can see what your recorded macro does!!!
try this:
Sub Copy_and_update_last_col_Census()
Dim wb As Workbook
Dim rng2copy As Range, rng2paste As Range
Dim query As Integer
Dim myfile
Dim filename As String
'~~> I assumed that Charts.xlsm is the workbook you are running the macro
Set rng2paste = ThisWorkbook.Sheets("ANA").Range("K4")
filename = "NOL_Support_Ticket_Status_Report.xlsx"
'~~> Handles the error if workbook is not open
On Error Resume Next
Set wb = Workbooks(filename)
'~~> check for error and execute action necessary
If Err.Number <> 0 Then
query = MsgBox("Source workbook not open." & vbNewLine & _
"Do you want to open it?", vbYesNo)
Else
GoTo proceedcopy
End If
If query = 6 Then
myfile = Application.GetOpenFilename(Filefilter:="Excel Files (*.xlsx), *.xlsx")
Else
MsgBox "Exiting now."
Exit Sub
End If
'~~> check if user selected the correct file
If myfile <> False Then
If Dir(myfile) = filename Then
Set wb = Workbooks.Open(myfile)
Else
MsgBox "Wrong file loaded." & vbNewLine & _
"Exiting now."
Exit Sub
End If
Else
MsgBox "No file loaded." & vbNewLine & _
"Exiting now."
Exit Sub
End If
'~~> this do the actual copying
proceedcopy:
Set rng2copy = wb.Sheets("Present Month").Range("E23", "H23")
rng2copy.Copy
rng2paste.PasteSpecial xlPasteValues, , , True
Application.CutCopyMode = False
wb.Close False
End Sub
This is tried and tested.
But i can't say that i've structured it well enough.
So i leave further testing to you.
Hi I have been trying to join together several macros to automate a process which involves importing data files from text and copying parts of the data to a "core sheet". My problem arises when i try to use the "For Each loop" to move through the sheets check a condition and if the condition is met run the data extraction macro. Basically the macro does not loop, i researched various solutions but nothing worked. It works fine the first time it is run (usualy the sheet that is displayed meets the conditions so it moves on to the "shima" macro) however then the "core sheet" is displayed and since this does not meet the conditions i just want it to move on to the next sheet but it doesn't. Code is below let me know if any of this is unclear.
Sub FullAuto()
Call Module1.Myfolderselector 'this macro imports all the text file in a given folder
Dim Msg, Style, Title, Response, MyString
Public ws As Worksheet
Msg = "Yes for Fluorescence, No for UV"
Style = vbYesNo + vbCritical + vbDefaultButton1
Title = "Choose data"
'this parts asks the user which type of Data they want to import
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
MyString = "Yes"
Else
MyString = "No"
End If
For Each ws In Worksheets 'this is the part with issues.
If MyString = "Yes" And Range("A1").Value <> "Core" Then
Call Module1.Detector_B_Shima_9_0
ElseIf MyString = "No" And Range("A1").Value <> "Core" Then
Call Module1.Detector_A_Shima_9_1
End If
Next ws
Worksheets.Add(After:=Worksheets(1)).Name = "Plot Sheet"
End Sub
Sub Detector_B_Shima_9_0()
Cells.Select
Selection.Find(What:="[LC Chromatogram(Detector B-Ch1)]", After:=ActiveCell _
, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False).Activate
ActiveCell.Offset(9, 1).Select
ActiveCell.Value = Range("B20")
Range(ActiveCell, Cells(ActiveCell.Row + 8401, ActiveCell.Column)).Select
Selection.Copy
Sheets("Core Sheet").Select
Range("C3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ActiveCell.EntireColumn.Insert
End Sub
Try to change this code:
For Each ws In Worksheets 'this is the part with issues.
If MyString = "Yes" And Range("A1").Value <> "Core" Then
Call Module1.Detector_B_Shima_9_0
ElseIf MyString = "No" And Range("A1").Value <> "Core" Then
Call Module1.Detector_A_Shima_9_1
End If
Next ws
to the next one
For Each ws In Worksheets
If MyString = "Yes" And ws.Range("A1").Value <> "Core" Then
Call Module1.Detector_B_Shima_9_0
ElseIf MyString = "No" And ws.Range("A1").Value <> "Core" Then
Call Module1.Detector_A_Shima_9_1
End If
Next ws
Note, that I've added ws. before Range("A1") : ws.Range("A1").Value. This little improvment helps VBA to understand, that Range("A1") belongs to worksheet ws.
I have a spreadsheet that calculates variances in column Z. At the end of the month I would like to copy and paste the values into another column in the same spreadsheet to keep track of the variances month to month.
I have a macro to copy from column Z to column BK.
I would like that each time I run the macro, to copy the values from column Z and paste it into a new column using the following schedule:
Month 1 = Values Should be Pasted in Column BK
Month 2 = Values Should be Pasted in Column BL
Month 3 = Values Should be Pasted in Column BM
Month 4 = Values Should be Pasted in Column BN
Month 5 = Values Should be Pasted in Column BO
Month 6 = Values Should be Pasted in Column BP
Month 7 = Values Should be Pasted in Column BQ
Month 8 = Values Should be Pasted in Column BR
Month 9 = Values Should be Pasted in Column BS
Month 10 = Values Should be Pasted in Column BT
Month 11 = Values Should be Pasted in Column BU
Month 12 = Values Should be Pasted in Column BV
After the 12th iteration, I would like the values from column Z to be copied into Column BK (the starting point). I believe this can be done using a loop?
I am having a difficult time coming up with the loop logic/coding.
Sub copyCurrentToPrevious()
Dim ans As String
On Error Resume Next
Application.ScreenUpdating = False
Sheets("Direct Materials").Activate
ans = MsgBox("Are you sure you want to copy Previous Month Variance to YTD Variance Tracking? This action can not be undone." & vbNewLine _
& vbNewLine & "Select Yes to proceed with the copy/paste operation or Select No to cancel.", vbYesNo + vbExclamation, "Product Costing")
If ans = vbNo Then Exit Sub
Range("Z9:Z220").Copy
Range("BK9").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("Z226:Z306").Copy
Range("BK226").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("Z311:Z471").Copy
Range("BK311").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("Z476:Z524").Copy
Range("BK476").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Range("A1").Select
MsgBox "Copy / paste operation is complete. Select OK to continue.", vbOKOnly + vbInformation, "Product Costing"
Application.ScreenUpdating = True
End Sub
Heres a refactor of your code, adding the required offsets, and addressing a number of other issues:
use correct data type for ans
don't use Resume Next. What that says is I don't care if I had and error, just carry on regardless. Who knows whats going to happen next
Don't use Activate or Select (unless you have a specific need to). Use Workbook, Worksheet, and Range objects instead. Note that Worksheets("Direct Materials") is implicity saying Activeworkbook.Worksheets("Direct Materials")
you don't actually need to Copy/Paste for this. Use the Variant Array that .Value returns instead. This will be faster and not vulnerable to interuption by other apps using the clipboard. Also its a good habit to get into as it's usefull in all sorts of ways.
Sub copyCurrentToPrevious()
Dim ans As VbMsgBoxResult
Dim rng As Range
On Error GoTo EH
ans = MsgBox("Are you sure you want to copy Previous Month Variance to YTD Variance Tracking? This action can not be undone." & vbNewLine _
& vbNewLine & "Select Yes to proceed with the copy/paste operation or Select No to cancel.", vbYesNo + vbExclamation, "Product Costing")
If ans = vbNo Then Exit Sub
Application.ScreenUpdating = False
With Worksheets("Direct Materials")
Set rng = .Range("Z9:Z220")
rng.Offset(0, Month(Now()) + 36).Value = rng.Value
Set rng = .Range("Z226:Z306")
rng.Offset(0, Month(Now()) + 36).Value = rng.Value
Set rng = .Range("Z311:Z471")
rng.Offset(0, Month(Now()) + 36).Value = rng.Value
Set rng = .Range("Z476:Z524")
rng.Offset(0, Month(Now()) + 36).Value = rng.Value
End With
MsgBox "Copy / paste operation is complete. Select OK to continue.", vbOKOnly + vbInformation, "Product Costing"
Application.ScreenUpdating = True
Exit Sub
EH:
MsgBox "Something went horribly wrong!"
End Sub