I have a user form and on a click of a button it is supposed to access or open a user form. But every time code gets to that part,
Run-time error '424':
Object required
pops up. Here is my code:
If CheckSheet(TextBoxValue) = True Then
Sheets(TextBoxValue).Select
UserForm.Show
Else
Set Worksheet = ThisWorkbook.Sheets.Add(After:=Sheets(Sheets.Count))
Worksheet.Name = TextBoxValue
Dim label As Control
For Each label In UserForm.Controls
If TypeName(label) = "Label" Then
With ActiveSheet
i = i + 1
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Cells(lastRow, i).Value = label.Caption
End With
End If
Next
UserForm.Show
End If
Every time it gets to the part with UserForm.Show and For Each label In UserForm.Controls
I checked the spelling of the form multiple times already and it is very much the same.
You may have had something like this in mind:-
Sub TestCode()
Dim Ws As Worksheet ' "Worksheet" is a reserved word
Dim MyForm As UserForm1 ' "UserForm" is a reserved word
Dim MyLabel As Control ' "Label" is a reserved word
Dim C As Long ' better name for a column than "i"
Set MyForm = New UserForm1
If GetSheet(Ws) Then
For Each MyLabel In MyForm.Controls
If TypeName(MyLabel) = "Label" Then
With Ws ' true, Ws is the ActiveSheet but
' always use the same name for the same sheet
C = C + 1
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Cells(LastRow, C).Value = MyLabel.Caption
End With
End If
Next
End If
MyForm.Show
End Sub
Private Function GetSheet(Ws As Worksheet) As Boolean
' return True if Ws didn't exist
Dim Ws As Worksheet
On Error Resume Next
Set Ws = Worksheets(TextBoxValue)
If Err Then ' Err = doesn't exist
Set Ws = ThisWorkbook.Sheets.Add(After:=Sheets(Sheets.Count))
Ws.Name = TextBoxValue
GetSheet = True
End If
End Function
Private Function TextBoxValue() As String
TextBoxValue = "MySheetName"
End Function
In order to test if a word is a "reserved" word, select it in your VB Editor and press F1. If MS Office uses it, don't argue.
Related
Currently this macro splits worksheets based on a cell.
It works well, however I am putting it as a button on a different page but this selects the active page, I want it to run this macro on a specific sheet.
Sub SplitToWorksheets_step4()
'Splits the workbook into different tabs
Dim ColHead As String
Dim ColHeadCell As Range
Dim icol As Integer
Dim iRow As Long 'row index on Fan Data sheet
Dim Lrow As Integer 'row index on individual destination sheet
Dim Dsheet As Worksheet 'destination worksheet
Dim Fsheet As Worksheet 'fan data worksheet (assumed active)
Again:
'ColHead = Worksheets("Diversion Report") 'this ask the user to enter a colunm name
ColHead = InputBox("Enter Column Heading", "Identify Column", [c1].Value) 'this ask the user to enter a colunm name
If ColHead = "" Then Exit Sub
Set ColHeadCell = Rows(1).Find(ColHead, LookAt:=xlWhole)
If ColHeadCell Is Nothing Then
MsgBox "Heading not found in row 1"
GoTo Again
End If
Set Fsheet = ActiveSheet
icol = ColHeadCell.Column
'loop through values in selected column
For iRow = 2 To Fsheet.Cells(65536, icol).End(xlUp).Row
If Not SheetExists(CStr(Fsheet.Cells(iRow, icol).Value)) Then
Set Dsheet = Worksheets.Add(after:=Worksheets(Worksheets.Count))
Dsheet.Name = CStr(Fsheet.Cells(iRow, icol).Value)
Fsheet.Rows(1).Copy Destination:=Dsheet.Rows(1)
Else
Set Dsheet = Worksheets(CStr(Fsheet.Cells(iRow, icol).Value))
End If
Lrow = Dsheet.Cells(65536, icol).End(xlUp).Row
Fsheet.Rows(iRow).Copy Destination:=Dsheet.Rows(Lrow + 1)
Next iRow
End Sub
Function SheetExists(SheetId As Variant) As Boolean
' This function checks whether a sheet (can be a worksheet,
' chart sheet, dialog sheet, etc.) exists, and returns
' True if it exists, False otherwise. SheetId can be either
' a sheet name string or an integer number. For example:
' If SheetExists(3) Then Sheets(3).Delete
' deletes the third worksheet in the workbook, if it exists.
' Similarly,
' If SheetExists("Annual Budget") Then Sheets("Annual Budget").Delete
' deletes the sheet named "Annual Budget", if it exists.
Dim sh As Object
On Error GoTo NoSuch
Set sh = Sheets(SheetId)
SheetExists = True
Exit Function
NoSuch:
If Err = 9 Then SheetExists = False Else Stop
End Function
Change your Sub to:
Sub SplitToWorksheets_step4(SheetName as String)
and in the line:
Set Fsheet = ActiveSheet
to:
Set Fsheet = Worksheets(SheetName)
on a different page but this selects the active page, I want it to run
this macro on a specific sheet.
Well that is simple enough.
Set your Worksheet Object to a specific Sheet.Name - eg:
Dim Fsheet As Worksheet: Set Fsheet = Sheets("Your sheet name")
In a more practical usage, you could for example pass the sheet name as a procedure argument:
Private Sub SplitToWorksheets_step4(ByVal sheetName as String)
Dim fsheet as Worksheet: Set fsheet = Sheets(sheetName)
' ... do something
End Sub
Last but not least a practical way to apply a macro for every Worksheet:
Private Sub for_every_ws()
Dim ws as Worksheet
For Each ws In ThisWorkbook.Sheets
ws.Range("A1") = "I was here!" ' i.e.
Next ws
End Sub
I'm trying to select an item in a ComboBox in a UserForm. I found the .Selected(index)=True code almost everywhere but for me it sais:
Compile error: Method or data member not found.
My code:
Private Sub UserForm_Initialize()
Dim worksheetList As New ArrayList
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
worksheetList.Add ws.Name
Next ws
sourceWorksheets.List = worksheetList.toArray
destinationWorksheets.List = worksheetList.toArray
sourceWorksheets.Selected(1) = True 'Error here
End Sub
Am I doing something wrong? I couldn't really find any other function which would set the "default" item.
As #Rory keeps saying - use ListIndex to select an item in the list control.
This piece of code will add each sheet name to the list control and then select the first item:
Private Sub UserForm_Initialize()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Me.worksheetList.AddItem ws.Name
Next ws
Me.worksheetList.ListIndex = 0
End Sub
I think the OP was trying to use the code similar to below, but this still needs the ListIndex=0.
Private Sub UserForm_Initialize()
Dim ws As Worksheet
With CreateObject("System.Collections.ArrayList")
For Each ws In ThisWorkbook.Worksheets
.Add ws.Name
Next ws
Me.worksheetList.List = .ToArray
End With
Me.worksheetList.ListIndex = 0
End Sub
Edit: The code assumes the list control is called worksheetList.
Edit 2: A slightly different version. It reverses the items in the list when you click the form.
It's still Me.worksheetList.ListIndex = 0 to select the item in the list control though.
Option Explicit
Public MyArrayList As Variant
Private Sub UserForm_Initialize()
Dim ws As Worksheet
Set MyArrayList = CreateObject("System.Collections.ArrayList")
With MyArrayList
For Each ws In ThisWorkbook.Worksheets
.Add ws.Name
Next ws
.Sort
Me.worksheetList.List = .ToArray
End With
Me.worksheetList.ListIndex = 0
''This will only work in a listbox, not a combobox.
''Select items in row numbers that are even (ListIndex 0,2,4, etc)
''MultiSelect must be 1 - fmMultiSelectMulti or 2 - fmMultiSelectExtended
' Dim x As Long
' For x = 0 To Me.worksheetlist.ListCount - 1
' If x Mod 2 = 0 Then
' Me.worksheetlist.Selected(x) = True
' End If
' Next x
End Sub
Private Sub UserForm_Click()
With MyArrayList
.Reverse
Me.worksheetList.List = .ToArray
End With
Me.worksheetList.ListIndex = 0
End Sub
To check whether particular element (indicated by index) is selected you should do workaround like this:
ComboBox1.Value = ComboBox1.List(i)
where i is given index. It has to be done like that, because there is no propertry like SelectedIndex in VBA ComboBox.
Keep in mind, that indexing starts with 0 !
I have a very old Excel spreadsheet within a macro in it.
Usage is: start the spreadsheet, push button, select a few other spreadsheets, complete copy and paste in one spreadsheet file.
It works with Office Excel 2007, but not with Office 2013.
When the macro starts, once the files to be appended have been selected, Excel reports:
Run-Time error: 1004
Unable to get the ListIndex property of the ListBox Class
then, when I click on debug, it mark this VBA row in yellow:
Set wbData = Workbooks.Open(wbLauncher.Worksheets("config").Cells(Worksheets("config").Range("Program1").Row - 1 + shtActive.Shapes(1).ControlFormat.ListIndex, Worksheets("config").Range("Program1").Column), , True)
edit adding the whole code
Sub btnSelectData()
Dim fd As FileDialog, shtActive As Worksheet, fItem As Variant, cID As Integer, rID As Integer
Set shtActive = ActiveSheet
shtActive.Range("D:D").ClearContents
Set fd = Application.FileDialog(msoFileDialogOpen)
fd.AllowMultiSelect = True
fd.InitialFileName = Worksheets("config").Range("dataPath")
fd.Show
cID = Worksheets("GUI").Range("Data1").Column
rID = Worksheets("GUI").Range("Data1").Row
For Each fItem In fd.SelectedItems
shtActive.Cells(rID, cID) = fItem
rID = rID + 1
Next
End Sub
Public Sub LoadData(ByVal fName As String)
Dim shtActive As Worksheet, wbData As Workbook
Set shtActive = ActiveSheet
shtActive.Cells(1, 1).Select
If fName <> "" Then
Set wbData = Workbooks.Open(fName, , True)
If wbData.Worksheets.Count < 1 Then
MsgBox "No data found in " & fName
Else
wbData.Worksheets(1).Cells.Select
Selection.Copy
shtActive.Activate
ActiveSheet.Paste
shtActive.Cells(1, 1).Select
End If
Selection.Clear
wbData.Close
End If
End Sub
Sub btnLaunch()
Dim wbLauncher As Workbook, shtActive As Worksheet, wbData As Workbook, shtItem As Worksheet
Set wbLauncher = ActiveWorkbook
Set shtActive = ActiveSheet
Application.WindowState = xlMinimized
Set wbData = Workbooks.Open(wbLauncher.Worksheets("config").Cells(Worksheets("config").Range("Program1").Row - 1 + shtActive.Shapes(1).ControlFormat.ListIndex, Worksheets("config").Range("Program1").Column), , True)
For Each shtItem In wbData.Worksheets
If UCase(Left(shtItem.Name, 5)) = "DATA_" Then
shtItem.Activate
LoadData wbLauncher.Worksheets("GUI").Cells(wbLauncher.Worksheets("GUI").Range("Data1").Row - 1 + Val(Right(shtItem.Name, Len(shtItem.Name) - 5)), wbLauncher.Worksheets("GUI").Range("Data1").Column)
End If
Next
wbData.Worksheets(1).Activate
Application.WindowState = xlNormal
End Sub
Edit
I've added a loop which goes through the listbox and checks if it is selected, if it is it executes the code as before but then continues until all listbox items are checked.
Sub btnLaunch()
Dim wbLauncher As Workbook, shtActive As Worksheet, wbData As Workbook, shtItem As Worksheet
Dim i As Long
Set wbLauncher = ActiveWorkbook
Set shtActive = ActiveSheet
Application.WindowState = xlMinimized
For i = 1 To shtActive.ListBoxes(1).ListCount
If shtActive.ListBoxes(1).Selected(i) Then
Set wbData = Workbooks.Open(wblauncer.Worksheets("Config").Cells(Worksheets("confige").Range("Program1") - 1 + i, Worksheets("Config").Range("Program1").Column), , True)
For Each shtItem In wbData.Worksheets
If UCase(Left(shtItem.Name, 5)) = "DATA_" Then
shtItem.Activate
LoadData wbLauncher.Worksheets("GUI").Cells(wbLauncher.Worksheets("GUI").Range("Data1").Row - 1 + Val(Right(shtItem.Name, Len(shtItem.Name) - 5)), wbLauncher.Worksheets("GUI").Range("Data1").Column)
End If
Next shtItem
wbData.Worksheets(1).Activate
Next i
Application.WindowState = xlNormal
End Sub
End of edit
You must set the selection type of your listbox on the worksheet to "Single", the reason you're getting the error is because currently it is set to either "Multi" or "Extend". You can right click the listbox and click on "Format Control"
All the information I found, states that the FormatControl.ListIndex property does not work when the selection type is set to anything but "Single"
Looking at your code, it would seem illogical to select multiple lines anyway. The Workbook.Open can only open one file at the time. You can of course incorporate it in a loop to open multiple workbooks, but that is not the case.
With the line that the debugger highlights:
Set wbData = Workbook.Open("Filename as String", ,"Read only")
The Filename in your code is set as follows:
bLauncher.Worksheets("config").Cells(Worksheets("config").Range("Program1").Row - 1 + shtActive.Shapes(1).ControlFormat.ListIndex, Worksheets("config").Range("Program1").Column)
The Code refers to a worksheet called "Config". On this worksheet a cell is referred to by the
Cells(Rowindex, Columnindex)
The Row- and Columnindex are numbers which refer to the rownumber and column the cell is on. e.g. cell A2 is Cells(2, 1) cell E34 is ` Cells(34,5)
You're code is setting the Rowindex as follows
Worksheets("config").Range("Program1").Row - 1 + shtActive.Shapes(1).ControlFormat.ListIndex
This bit refers to a named range named "Pgrogam1" on the worksheet "Config" the .row returns the rownumber this range is on. 1 is then subtracted from this number and then the listindex of the selection is added to arrive at the cell which holds the filename which corresponds to the selection in the listbox.
Multiple selections in the listbox would mean that you're trying to open multiple cells and with your current code that is impossible, even under office 2007.
I am having trouble with populating a combo box on a excel ribbon dynamically.
I wish for the combo box to be populated using the names of the sheets of the workbook dynamically.
I am able to select the sheet names already presentin the combo box that is placed on the ribbon however I do not seam to be able to code the VBA to populate the combo box with the sheet names if I add them or modify the name.
I have written below code but its not working :
Sub SelectionFeuille_GetItemLabel(control As IRibbonControl, index As Integer, ByRef returnedVal)
Dim dTime As Date
dTime = Now + TimeValue("00:00:01") 'hh:mm:ss
Application.OnTime dTime, "Refresh_all"
returnedVal = ActiveWorkbook.Worksheets(index + 1).Name
End Sub
Please help me....
The simplest way I've found to do this is to capture the Calculate event, and I do that by having a hidden worksheet with formulae to each sheet in its cells. It's far from perfect and, if truth be told, is a pretty ugly workaround, but at least it's food for thought for you. I guess a timer would also work but that seems just as ugly.
All of this code goes in the code behind your workbook:
Option Explicit
Private Const NAMES_SHEET As String = "Hidden|Sheet|Names"
Private mNamesSheet As Worksheet
Private Sub Workbook_Open()
Dim b As Boolean
b = Application.ScreenUpdating
On Error Resume Next
Set mNamesSheet = ThisWorkbook.Worksheets(NAMES_SHEET)
On Error GoTo 0
If mNamesSheet Is Nothing Then
Application.ScreenUpdating = False
Set mNamesSheet = ThisWorkbook.Worksheets.Add
mNamesSheet.Name = NAMES_SHEET
mNamesSheet.Visible = xlSheetVeryHidden
End If
WriteNamesOfSheets
Application.ScreenUpdating = b
End Sub
Private Sub WriteNamesOfSheets()
Dim v() As Variant
Dim ws As Worksheet
Dim i As Integer
Dim b As Boolean
b = Application.EnableEvents
Application.EnableEvents = False
ReDim v(1 To ThisWorkbook.Worksheets.Count, 1 To 1)
mNamesSheet.Cells.Clear
i = 0
For Each ws In ThisWorkbook.Worksheets
If ws.Visible = xlSheetVisible Then
i = i + 1
v(i, 1) = "=" & ws.Name & "!A1"
End If
Next
mNamesSheet.Range("A1").Resize(UBound(v, 1)).Formula = v
Application.EnableEvents = b
End Sub
Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
Dim ws As Worksheet
Dim b As Boolean
On Error GoTo EH
b = Application.EnableEvents
Application.EnableEvents = False
WriteNamesOfSheets
For Each ws In ThisWorkbook.Worksheets
If ws.Visible = xlSheetVisible Then
'
'Populate your combobox here with ws.Name
'
End If
Next
Application.EnableEvents = b
Exit Sub
EH:
Err.Clear
End Sub
This code is trying to print just one worksheet called NQLD Print, then cycle through all the options in a data validation list in cell B2 on that worksheet:
Sub PrintAll()
Dim strValidationRange As String
Dim rngValidation As Range
On Error GoTo errhandler
Dim rngDepartment As Range
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
If (sh.Name = "NQLD PRINT") Then
' Turn off screen updating
Application.ScreenUpdating = False
' Identify the source list of the data validation
strValidationRange = Range("B2").Validation.Formula1
Set rngValidation = Range(strValidationRange)
' Set the value in the selection cell to each selection in turn
' and print the results.
For Each rngDepartment In rngValidation.Cells
Range("B2").Value = rngDepartment.Value
ActiveSheet.PrintOut
Next
Application.ScreenUpdating = True
Exit Sub
errhandler: MsgBox Err.Description
End If
Next
End Sub
I'm getting the error Method 'Range' of object '_Worksheet' failed.
Cycling through the worksheets does not automatically confer parentage to cell ranges referenced within the worksheets.
Reference sh for each worksheet's ranges.
strValidationRange = sh.Range("B2").Validation.Formula1
Set rngValidation = sh.Range(strValidationRange)
Alternately, use a With ... End With statement.
For Each sh In ActiveWorkbook.Worksheets
With sh
If (.Name = "NQLD PRINT") Then
' Turn off screen updating
Application.ScreenUpdating = False
' Identify the source list of the data validation
strValidationRange = .Range("B2").Validation.Formula1
Set rngValidation = .Range(strValidationRange)
' more stuff here
End If
Next sh
Note the .Name and .Range and not sh.Name and Range.
You need to place "sh." as a prefix to every occurrence of Range().