I have a UserForm which should be able to copy paste cells ideally. So firstly I would click the range I would want to copy, then activate the UserForm. The UserForm would have a combo box to choose which sheet I want to paste the data in, thereafter it would go to that sheet and user will click on the range or cell where he wants the data to be pasted.
I originally did an input box code to do this and it works perfectly, however when I do it in the UserForm it does not work as I am not able to incorporate the Type:=8 code in the textbox. Hence I would need some help on how can I enable my UserForm to paste cell data on the sheet, similarly to what I have done in application.inputbox.
This is the perfectly working code in the form of an input box:
Sub CopyPasteCumUpdateWithinSameSheet()
Dim rng As Range
Dim inp As Range
Selection.Interior.ColorIndex = 37
Set inp = Selection
On Error Resume Next
Set rng = Application.InputBox("Copy to", Type:=8)
On Error GoTo 0
If TypeName(rng) <> "Range" Then
Exit Sub
Else
inp.Copy
rng.Select
ActiveSheet.Paste Link:=True
'Cells(1,2).Font.ThemeColor =
End If
End Sub
This is the UserForm I have tried:
Dim Sh As Worksheet
Private Sub CommandButton1_Click()
On Error GoTo 0
If TypeName(rng) <> "Range" Then
Exit Sub
Else
inp.Copy
rng.Select
ActiveSheet.Paste Link:=True
End If
End Sub
Private Sub UserForm_Initialize()
CopyPasteUserform.Show vbModeless
For Each Sh In ThisWorkbook.Sheets
If Sh.Name <> "Inputs" Then
ComboBox1.AddItem Sh.Name
End If
Next
ComboBox1.Style = fmStyleDropDownList
End Sub
Private Sub ComboBox1_Change()
With ThisWorkbook.Sheets(ComboBox1.Text)
.Visible = xlSheetVisible
.Activate
End With
End Sub
Private Sub TextBox1_Change()
Dim rng As Range
Dim inp As Range
Selection.Interior.ColorIndex = 37
Set inp = Selection
On Error Resume Next
Set rng = TextBox.Value
End Sub
I tried incorporating the UserForm but all other functions stop responding apart from the RefEdit.
Dim Sh As Worksheet
Private Sub UserForm_Initialize()
CopyPasteUserform.Show vbModeless
For Each Sh In ThisWorkbook.Sheets
If Sh.Name <> "Inputs" Then
ComboBox1.AddItem Sh.Name
End If
Next
ComboBox1.Style = fmStyleDropDownList
Dim rng As Range
Dim inp As Range
Selection.Interior.ColorIndex = 37
Set inp = Selection
End Sub
Private Sub Combobox1_Change()
With ThisWorkbook.Sheets(ComboBox1.Text)
.Visible = xlSheetVisible
.Activate
End With
End Sub
Private Sub RefEdit1_Change()
Label1.Caption = ""
If RefEdit1.Value <> "" Then _
Label1.Caption = "[" & ComboBox1 & "]" & RefEdit1
Dim rng As Range
Dim inp As Range
On Error Resume Next
Set rng = RefEdit1.Value
On Error GoTo 0
If TypeName(rng) <> "Range" Then
Exit Sub
Else
inp.Copy
rng.Select
ActiveSheet.Paste Link:=True
End If
End Sub
You do not need the combobox to navigate to the sheets. That is the beauty of the Refedit
Is this what you are trying? I have not done any error handling. I am sure you can take care of that.
Create a userform and place 2 labels, 2 refedits and 1 commandbutton as shown below
Next paste this code in the userform code area
Code
Private Sub CommandButton1_Click()
Dim rngCopy As Range, rngPaste As Range
Dim wsCopy As Worksheet, wsPaste As Worksheet
If RefEdit1.Value <> "" And RefEdit2.Value <> "" Then
Set wsCopy = ThisWorkbook.Sheets(Replace(Split(RefEdit1.Value, "!")(0), "'", ""))
Set rngCopy = wsCopy.Range(Split(RefEdit1.Value, "!")(1))
Set wsPaste = ThisWorkbook.Sheets(Replace(Split(RefEdit2.Value, "!")(0), "'", ""))
Set rngPaste = wsPaste.Range(Split(RefEdit2.Value, "!")(1))
rngCopy.Copy rngPaste
Else
MsgBox "Please select Input and Output range"
End If
End Sub
In Action
The data will be copied from Sheet1!$A$1:$A$3 to Sheet2!$A$1:$A$3
Followup From Comments
However the pastelink feature has been missed out in the userform. Is it possible to incorporate it?:) – Niva 7 mins ago
Add a checkbox to the form as shown below
Use this code
Private Sub CommandButton1_Click()
Dim rngCopy As Range, rngPaste As Range
Dim wsCopy As Worksheet, wsPaste As Worksheet
If RefEdit1.Value <> "" And RefEdit2.Value <> "" Then
Set wsCopy = ThisWorkbook.Sheets(Replace(Split(RefEdit1.Value, "!")(0), "'", ""))
Set rngCopy = wsCopy.Range(Split(RefEdit1.Value, "!")(1))
Set wsPaste = ThisWorkbook.Sheets(Replace(Split(RefEdit2.Value, "!")(0), "'", ""))
Set rngPaste = wsPaste.Range(Split(RefEdit2.Value, "!")(1))
If CheckBox1.Value = True Then
wsPaste.Activate
rngPaste.Select
rngCopy.Copy
ActiveSheet.Paste Link:=True
Else
rngCopy.Copy rngPaste
End If
Else
MsgBox "Please select Input and Output range"
End If
End Sub
Description: Type:=8 will check that user input correct range name or not? In UserForm the TextBox not have this function. But we can detect this error when user click button. see my code.
No need to check when textbox is change, I delete code of textbox_change.
Replace below in your user form code area.
Option Explicit
Dim Sh As Worksheet
Dim inp As Range
Dim rng As Range
Private Sub CommandButton1_Click()
ActiveCell.Value = Me.TextBox1.Text
'On Error Resume Next
'If TypeName(Range(Me.TextBox1.Text)) <> "Range" Then
' MsgBox "Invalid range name!", vbCritical
' Exit Sub
'Else
' inp.Copy
' rng.Select
'
' ActiveSheet.Paste Link:=True
' MsgBox "Copy and paste finish.", vbInformation
'End If
'On Error GoTo 0
End Sub
Private Sub UserForm_Initialize()
For Each Sh In ThisWorkbook.Sheets
If Sh.Name <> "Inputs" Then
ComboBox1.AddItem Sh.Name
End If
Next
ComboBox1.Style = fmStyleDropDownList
End Sub
Private Sub ComboBox1_Change()
With ThisWorkbook.Sheets(ComboBox1.Text)
.Visible = xlSheetVisible
.Activate
End With
End Sub
Related
I have used a macro to track changes in a workbook, but I would now like to run this macro in over a 100 excel files within a particular folder using a Do While Loop.
I am very new to VBA and will appreciate all the help I can get.
I have come across some code that should enable me to loop through excel files in a folder and run the macro in each one.
However it requires me to get rid of the 'sub' and 'end sub' from the macro when I copy and paste it into the do while loop, but I have 3 of them within the macro; some variables will be undefined if I delete all 3.
Therefore I tried 'Call Tracker' within the loop ('Tracker' being the macro name) and hoped it would run in each excel file.
Sub LoopThroughFiles()
Dim xFd As FileDialog
Dim xFdItem As Variant
Dim xFileName As String
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
If xFd.Show = -1 Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
xFileName = Dir(xFdItem & "*,xls*")
Do While xFileName <> ""
With Workbooks.Open(xFdItem & xFileName)
'Your code here
Call Tracker
End With
xFileName = Dir
Loop
End If
End Sub
Below is the code inside 'Tracker'
Option Explicit
Dim sOldAddress As String
Dim vOldValue As Variant
Public Sub Workbook_TrackChange(Cancel As Boolean)
Dim Sh As Worksheet
For Each Sh In ActiveWorkbook.Worksheets
Sh.PageSetup.LeftFooter = "&06" & ActiveWorkbook.FullName & vbLf & "&A"
Next Sh
End Sub
Public Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim wSheet As Worksheet
Dim wActSheet As Worksheet
Dim iCol As Integer
Set wActSheet = ActiveSheet
'Precursor Exits
'Other conditions that you do not want to track could be added here
If vOldValue = "" Then Exit Sub 'If you comment out this line *every* entry will be recorded
'Continue
On Error Resume Next ' This Error-Resume-Next is only to allow the creation of the tracker sheet.
Set wSheet = Sheets("Tracker")
'**** Add the tracker Sheet if it does not exist ****
If wSheet Is Nothing Then
Set wActSheet = ActiveSheet
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "Tracker"
End If
On Error GoTo 0
'**** End of specific error resume next
On Error GoTo ErrorHandler
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
With Sheets("Tracker")
'******** This bit of code moves the tracker over a column when the first columns are full**'
If .Cells(1, 1) = "" Then '
iCol = 1 '
Else '
iCol = .Cells(1, 256).End(xlToLeft).Column - 7 '
If Not .Cells(65536, iCol) = "" Then '
iCol = .Cells(1, 256).End(xlToLeft).Column + 1 '
End If '
End If '
'********* END *****************************************************************************'
.Unprotect Password:="Secret"
'******** Sets the Column Headers **********************************************************
If LenB(.Cells(1, iCol).Value) = 0 Then
.Range(.Cells(1, iCol), .Cells(1, iCol + 7)) = Array("Cell Changed", "SAP ID", "Field Name", "Old Field Value", _
"New Field Value", "Time of Change", "Date Stamp", "User")
.Cells.Columns.AutoFit
End If
With .Cells(.Rows.Count, iCol).End(xlUp).Offset(1)
If Target.Count = 1 Then
.Offset(0, 1) = Cells(Target.Row, 2) 'SAPID
End If
'.Offset(0, 1) = Cells(Target.Row, 2) 'SAPID
If Target.Count = 1 Then
.Offset(0, 2) = Cells(Target.Column) 'Field name
End If
'.Offset(0, 2) = Cells(Target.Column) 'Field name
.Value = sOldAddress
.Offset(0, 3).Value = vOldValue
If Target.Count = 1 Then
.Offset(0, 4).Value = Target.Value
End If
.Offset(0, 5) = Time
.Offset(0, 6) = Date
.Offset(0, 7) = Application.UserName
.Offset(0, 7).Borders(xlEdgeRight).LineStyle = xlContinuous
End With
.Protect Password:="Secret" 'comment to protect the "tracker tab"
End With
ErrorExit:
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
wActSheet.Activate
Exit Sub
ErrorHandler:
'any error handling you want
'Debug.Print "We have an error"
Resume ErrorExit
End Sub
Public Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
With Target
sOldAddress = .Address(external:=True)
If .Count > 1 Then
vOldValue = "Multiple Cell Select"
Else
vOldValue = .Value
End If
End With
End Sub
'Call Tracker' in the loop does not produce an error. In fact the code seems to execute and loops through all the files but it does not run the macro in each one it opens.
Attempting a macro that will set all selected sheets to have same cells visible as in the active sheet.
Example: if top-left cell is L76 on active sheet, then running this macro will set all selected worksheets to show L76 as the top left cell.
Cobbled this code together from examples found online but not sufficiently advanced in VBA to make it work.
Sub SetAllSelectedSheetsToSameRowColCell()
Dim rngSel As Range
Dim intScrollCol As Integer
Dim intScrollRow As Long
Dim oSheet As Object
If TypeName(Sh) = "Worksheet" Then
Set oSheet = ActiveSheet
Application.EnableEvents = False 'Unsure what this line is for
Sh.Activate
With ActiveWindow
intScrollCol = .ScrollColumn
intScrollRow = .ScrollRow
Set rngSel = .RangeSelection
End With
oSheet.Activate
Application.EnableEvents = True
End If
'Loop thru rest of selected sheets and update to have same cells visible
Dim oWs As Worksheet
For Each oWs In Application.ActiveWindow.SelectedSheets
On Error Resume Next
oWs.Range(rngSel.Address).Select
.ScrollColumn = intScrollCol
.ScrollRow = intScrollRow
Next
End Sub
References:
https://excel.tips.net/T003860_Viewing_Same_Cells_on_Different_Worksheets.html
VBA Macro To Select Same Cell on all Worksheets
Try this:
Sub ResetAllSheetPerspectives()
Dim ws As Worksheet
Dim lRow As Long
Dim lCol As Long
Dim dZoom As Double
lRow = ActiveWindow.ScrollRow
lCol = ActiveWindow.ScrollColumn
dZoom = ActiveWindow.Zoom
For Each ws In Application.ActiveWindow.SelectedSheets
ws.Activate
ActiveWindow.Zoom = dZoom
Application.Goto ws.Cells(lRow, lCol), True
Next ws
End Sub
Maybe this will help. Sets the top left cell of other sheets depending on the first sheet.
Sub Macro1()
Dim r As Range, ws As Worksheet
Sheets(1).Activate
Set r = ActiveWindow.VisibleRange.Cells(1)
For Each ws In Worksheets
If ws.Index > 1 Then
ws.Activate
ActiveWindow.ScrollRow = r.Row
ActiveWindow.ScrollColumn = r.Column
End If
Next ws
End Sub
This procedure sets the same visible range as the active worksheet for all selected worksheets. It excludes any Chart sheet in the selection and adjusts the zoom of the selected sheets to ensure all worksheets have the same visible area.
Sub SelectedWorksheets_ToSameVisibleRange()
Dim ws As Worksheet
Dim oShs As Object, oSh As Object
Dim sRgAddrs As String
On Error Resume Next
Set ws = ActiveSheet
On Error GoTo 0
If ws Is Nothing Then
MsgBox "Active sheet must be a worksheet type" & String(2, vbLf) _
& String(2, vbTab) & "Process will be cancelled.", _
vbCritical, "Worksheets Common Range View"
Exit Sub
End If
With ActiveWindow
Set oShs = .SelectedSheets
sRgAddrs = .VisibleRange.Address 'Get address of Active Sheet visible range
End With
For Each oSh In oShs
If TypeName(oSh) = "Worksheet" And oSh.Name <> ws.Name Then 'Excludes any chart sheet and the active sheet
With oSh.Range(sRgAddrs)
Application.Goto .Cells, 1 'Activate Worksheet targeted visible range
ActiveWindow.Zoom = True 'Zoom Worksheet to make visible same range as the "active worksheet"
Application.Goto .Cells(1), 1 'Activate 1st cell of the visible range
End With: End If: Next
ws.Select 'Ungroups selected sheets
End Sub
I keep getting an error:
Run-time error '91; Object variable or with block variable not set.
My script runs fine and does what it needs to do but I can't figure out how to get rid of this error.
Thank you for the help.
Public Sub CommandButton1_Click()
Dim rng As Range
Set rng = Range("F24:I24")
rng.Select
If TextBox1.Text = "" Then
MsgBox ("Must insert Temperature you dingus!")
Else
rng = TextBox1.Text
Call GetCabinet1
End If
Unload Me
End Sub
Public Sub UserForm_Initialize()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets("Executive Summary")
wb.Activate
ws.Select
UserForm1.Show
Unload Me
End Sub
remove all those Unload.Me from both your subs and place it in the sub calling that userform
place a Me.Hide by the end of CommandButton1_Click(), instead
finally remove UserForm1.Show from UserForm_Initialize since it'd make it repeat twice
so your "Main" sub would look like:
Sub main()
Dim UF As UserForm1
Set UF = New UserForm1
UF.Show
Unload UF ' unload the userform from here
End Sub
and your userform1 code like:
Private Sub CommandButton1_Click()
Dim rng As Range
Set rng = Range("F24:I24")
rng.Select
If TextBox1.Text = "" Then
MsgBox ("Must insert Temperature you dingus!")
Else
rng = TextBox1.Text
Call GetCabinet1
End If
Me.Hide
End Sub
Public Sub UserForm_Initialize()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets("Executive Summary")
wb.Activate
ws.Select
End Sub
Simply replacing the unload me with me.hide fixed my problem... Thank you to all of those who gave their input....
I am trying to embed applying a chart template into a macro and require help.
I have this code for the Macro that I am using to create scatter plots:
Option Explicit
Public Sub Test()
' Keyboard Shortcut: Ctrl+Shift+X
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1") 'change as appropriate
Application.ScreenUpdating = False
BuildChart ws, SelectRanges(ws)
Application.ScreenUpdating = True
End Sub
Private Function SelectRanges(ByRef ws As Worksheet) As Range
Dim rngX As Range
Dim rngY As Range
ws.Activate
Application.DisplayAlerts = False
On Error Resume Next
Set rngX = Application.InputBox("Please select X values. One column.",
Type:=8)
If rngX Is Nothing Then GoTo InvalidSelection
Set rngY = Application.InputBox("Please select Y values. One column.",
Type:=8)
If rngY Is Nothing Then GoTo InvalidSelection
If rngX.Columns.Count > 1 Or rngY.Columns.Count > 1 Then GoTo
InvalidSelection
On Error GoTo 0
Set SelectRanges = Union(rngX, rngY)
Application.DisplayAlerts = True
Exit Function
InvalidSelection:
If rngX Is Nothing Or rngY Is Nothing Then
MsgBox "Please ensure you have selected both X and Y ranges."
ElseIf rngX.Rows.Count <> rngX.Rows.Count Then
MsgBox "Please ensure the same number of rows are selected for X and Y
ranges"
ElseIf rngX.Columns.Count > 1 Or rngY.Columns.Count > 1 Then
MsgBox "Please ensure X range has only one column and Y range has only
one column"
Else
MsgBox "Unspecified"
End If
Application.DisplayAlerts = True
End
End Function
Private Sub BuildChart(ByRef ws As Worksheet, ByRef unionRng As Range)
With ws.Shapes.AddChart2(240, xlXYScatter).Chart
.SetSourceData Source:=unionRng
End With
ActiveChart.ApplyChartTemplate ( _
"C:\Users\maaro\AppData\Roaming\Microsoft\Templates\Charts\1.crtx")
End Sub
And would like to embed this code below into the above code so that it applies the template to the chart I create whenever I run this Macro. My initial guess would be to put it underneath "Private Sub BuildCharts". How would I be able to do this? Thank you.
ActiveChart.ApplyChartTemplate ( _
"C:\Users\XXXXX\AppData\Roaming\Microsoft\Templates\Charts\1.crtx")
Perhaps modify Sub BuildChart like this:
Private Sub BuildChart(ByRef ws As Worksheet, ByRef unionRng As Range)
With ws.Shapes.AddChart2(240, xlXYScatter).Chart
.SetSourceData Source:=unionRng
.ApplyChartTemplate ( _
"C:\Users\maaro\AppData\Roaming\Microsoft\Templates\Charts\1.crtx")
End With
End Sub
I am trying to write a macro that will ask user to provide workbook, macro opens workbook. Than user selects the range for copy and specifies the worksheet to which paste data in Userform. Macro copy selected Range to the specified worksheet.
But I face some problems with it.
Here is code:
Public Sub copy_WB()
Application.DisplayAlerts = False
Dim wbk As Workbook, answer As String,lrow as long, lcol as long
Dim UserRange As Range
Prompt = "Select a cell for the output."
Title = "Select a cell"
answer = MsgBox("Would you like to clear all data?", vbYesNo, "Confirmation")
If answer = vbYes Then
Call clear_all
End If
Set wbk = Get_workbook
If wbk Is Nothing Then
Exit Sub
End If
' Display the Input Box
On Error Resume Next
Set UserRange = Application.InputBox( _
Prompt:=Prompt, _
Title:=Title, _
Type:=8) 'Range selection
' Was the Input Box canceled?
If UserRange Is Nothing Then
MsgBox "Canceled."
Exit Sub
Else
UserRange.Parent.Parent.Activate
UserRange.Parent.Activate
lrow = UserRange(UserRange.Count).Row
lcol = UserRange(UserRange.Count).Columns
If lrow > 1000000 Or lcol > 15000 Then
ActiveSheet.UsedRange.Copy
Else
UserRange.Copy
End If
sh_sel.Show
Do While IsUserFormLoaded("sh_sel")
DoEvents
Loop
ActiveSheet.Range("A2").PasteSpecial xlPasteValues
Application.CutCopyMode = False
End If
ThisWorkbook.Worksheets(3).Range("A1") = lrow
ThisWorkbook.Worksheets(3).Range("A2") = lcol
wbk.Close False
Application.DisplayAlerts = True
End Sub
Private Sub clear_all()
Dim wb As Workbook, shs As Worksheet, lrow As Single, lcol As Single
Set wb = ThisWorkbook
For Each shs In wb.Worksheets
With shs.UsedRange
lrow = .Rows(.Rows.Count).Row
lcol = .Columns(.Columns.Count).Column
End With
If Not (lrow = 0 Or lrow = 1) Then
With shs
.Range(.Cells(2, 1), .Cells(lrow, lcol)).clear
End With
End If
Next shs
End Sub
Function Get_workbook() As Workbook
Dim wbk As Workbook, pathb As String
pathb = ThisWorkbook.path
ChDir pathb
wbk_name = Application.GetOpenFilename(Title:="Please choose File:", FileFilter:="Excel Files *.xls*(*.xls*),")
On Error Resume Next
If Len(Dir(wbk_name)) = 0 Then
MsgBox "The file was not chosen - macro off."
Exit Function
Else
Set wbk = Workbooks.Open(wbk_name)
End If
Set Get_workbook = wbk
End Function
Function IsUserFormLoaded(ByVal UFName As String) As Boolean
Dim UForm As Object
IsUserFormLoaded = False
For Each UForm In VBA.UserForms
If UForm.Name = UFName Then
IsUserFormLoaded = True
Exit For
End If
Next
End Function 'IsUserFormLoaded
The first problem that I am facing is when user press
The button which locates in the upper left corner of the sheet to select the entire sheet range, it will not be copied. I was trying to correct it somehow by adding the condition of last row of selected range is bigger then...(see code please).
But it does not actually works. sometimes it copy range, sometimes no.
The second problem: inputbox is disappears when macro run. Have no idea why it happans.
Userform code:
Private Sub UserForm_Initialize()
Dim sh As Worksheet
For Each sh In ThisWorkbook.Sheets
ListBox1.AddItem sh.Name
Next sh
Me.StartUpPosition = 0
Me.Left = Application.Left + (0.5 * Application.Width) - (0.5 * Me.Width)
Me.Top = Application.Top + (0.5 * Application.Height) - (0.5 * Me.Height)
HideTitleBar.HideTitleBar Me
End Sub
Private Sub ListBox1_Click()
ThisWorkbook.Sheets(ListBox1.Value).Activate
Unload Me
End Sub
User forms contains list of sheets in current workbook, after user selection of the sheet data would be pasted.