I'm not a programmer for the profession, I'm a system administrator who usually brings together the puzzle when I try something. Now I would need help simplifying an Excel form to make it useful. It will be used by me.
I have a combobox that contains 4 columns. I also have a button. When you click the button, I want to save data from the four columns in my combobox to the next available row of cells starting from row 3. I want data to be saved only to row 30. I have tested back and forth but do not get it, so I've completely deleted the code. Any ideas?
Sheet named "Data"
I use ListFillRange in my ComBobox for the data source.
Private Sub CommandButton1_Click()
Call SaveComboBoxData
End Sub
Sub SaveComboBoxData()
End sub
Using ActiveX controls
ComboBox1
CommandButton1
You can tidy this up further,
Note:
You appear to be building a database so consider the preferred option of using an access database to store this data
If you have Excel 2016 you could be using Data Entry Forms instead which are dead simple.
Assume using ActiveX combobox. You will need to alter this
Set sourceCombo = sourceSheet.OLEObjects("Combobox1").Object
if working with a form control.
Code for the type of operation you are describing:
Code pane for Order sheet:
Option Explicit
Private Sub CommandButton1_Click()
AddRecords
End Sub
Standard module
Option Explicit
Public Sub AddRecords()
Dim wb As Workbook
Dim sourceSheet As Worksheet
Dim targetSheet As Worksheet
Set wb = ThisWorkbook
Set sourceSheet = wb.Worksheets("Order")
Set targetSheet = wb.Worksheets("Data")
Dim lastRowTarget As Long
Dim sourceCombo As ComboBox
Set sourceCombo = sourceSheet.OLEObjects("Combobox1").Object 'assume activex object
Dim lRow As Long
Dim lCol As Long
Dim nextRow As Long
With sourceCombo
For lRow = 0 To .ListCount - 1
If lRow = sourceCombo.ListIndex Then
nextRow = GetNextRow(targetSheet)
If nextRow = 31 Then
MsgBox "End row of 30 reached"
Exit Sub
End If
For lCol = 0 To .ColumnCount - 1
targetSheet.Cells(nextRow, lCol + 1) = .List(lRow, lCol)
Next lCol
Exit For
End If
Next lRow
End With
End Sub
Private Function GetNextRow(targetSheet As Worksheet) As Long
With targetSheet
GetNextRow = IIf(.Cells(.Rows.Count, "A").End(xlUp).Row < 3, 3, .Cells(.Rows.Count, "A").End(xlUp).Row + 1)
End With
End Function
Code in action:
References:
How to get selected value in multicolumn listbox
How can I find the index of the selected choice in a combobox?
How to create a data entry form
Related
on one sheet I have a list of suppliers and their details, I have a userfrom containing a combobox that automatically populates from the list of suppliers. In the columns next to the suppliers, I have details with address, phone number etc. What I am attempting to do is after the user makes the selection, I would like the code to take the details in the adjacent columns and fill in the form. I have tried using the lookup function however I am constantly being given an error stating that the object could not be found. Below is what I have so far
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Set ws = Worksheets("RFQ Information")
'Take supplier name from combobox
'Copy row data in supplier sheet and paste (transposed) into form
Dim xRg As Range
Set xRg = Worksheets("Suppliers").Range("A2:H15")
Set Cells(53, 1) = Application.WorksheetFunction.VLookup(Me.ComboBox1.Value, xRg, 2, False)
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim SupplierName As Range
Dim SupSheet As Worksheet
Dim tbl As ListObject
Dim SupArray As Variant
Dim SupString As String
Set SupSheet = Sheets("Suppliers")
Set tbl = SupSheet.ListObjects("Table1")
Set SupplierName = tbl.ListColumns(1).DataBodyRange
SupArray = SupplierName.Value
ComboBox1.List = SupArray
UserForm1.Show
MsgBox ("done")
End Sub
I would recommend using the ComboBox Change event instead of a button, since you want the info on list selection. You can also take advantage of the ComboBox.ListIndex property to get the selected item's location in the list, and then use that to get adjacent values from your data table. Here's a quick example of how to do so:
Private Sub ComboBox1_Change()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsSup As Worksheet: Set wsSup = wb.Worksheets("Suppliers")
Dim rData As Range: Set rData = wsSup.ListObjects("Table1").DataBodyRange
Dim i As Long: i = Me.ComboBox1.ListIndex + 1
If i = 0 Then Exit Sub 'Nothing selected
'Second number is the column
' Column 1 is the Supplier
' Column 2 is the next column (phone maybe?)
' Column 3 is the column after that (address maybe?)
MsgBox rData.Cells(i, 2) & Chr(10) & _
rData.Cells(i, 3)
'Load the values you want into the necessary form controls
End Sub
this might be answered already from other posts I have read but still struggling to figure it out.
I have a workbook with 85 worksheets on it. Each sheet is like an invoice format, meaning it is not formatted as a normal data set. In order for me to get the data only I need, i created helper columns which only selects the data I need for consolidation. So I have a range I13:N42 which contains the data I need to consolidate.
At the end of the workbook, I already set up a Master Sheet with all the necessary headers for the data set. And there are 2 more worksheets namely "Tracking" & "AppControl" but I dont want them to be included in the loop together with the Master sheet.
For my range (filled with cell references/formulae), I need to copy only the row that has data in it.
You might have some ideas to improve the code I am currently using.
Sub Combine()
Dim i As Integer
Dim ws As Worksheet
Dim rng As Range
On Error Resume Next
For i = 1 To Sheets.Count
Sheets(i).Activate
Range("I13:N42").Select
Selection.Copy Destination:=Sheets("Master").Range("A65536").End(xlUp)(2)
Next i
End Sub
First remove On Error Resume Next. This line hides all error messages but the errors still occour, you just cannot see their messages. So if there are errors you cannot see you cannot fix them. If you don't fix them your code cannot work. Remove that line and fix your errors! Also see VBA Error Handling – A Complete Guide.
Second Avoid using Select in Excel VBA. That is a very bad practice and makes your code unreliable!
Option Explicit
Public Sub Combine()
Dim wsMaster As Worksheet ' set master worksheet
Set wsMaster = ThisWorkbook.Worksheets("Master")
Dim ExcludeWorksheets As Variant ' define worksheets names to exclude
ExcludeWorksheets = Array(wsMaster.Name, "Tracking", "AppControl")
Dim i As Long
For i = 1 To ThisWorkbook.Worksheets.Count
If Not IsInArray(ThisWorkbook.Worksheets(i).Name, ExcludeWorksheets) Then 'exclude these worksheets
ThisWorkbook.Worksheets(i).Range("I13:N42").Copy Destination:=wsMaster.Cells(wsMaster.Rows.Count, "A").End(xlUp)(2)
End If
Next i
End Sub
Public Function IsInArray(ByVal StringToBeFound As String, ByVal Arr As Variant) As Boolean
IsInArray = (UBound(Filter(Arr, StringToBeFound)) > -1)
End Function
Alternatively you can use a For Each loop which looks a bit cleaner then
Option Explicit
Public Sub Combine()
Dim wsMaster As Worksheet ' set master worksheet
Set wsMaster = ThisWorkbook.Worksheets("Master")
Dim ExcludeWorksheets As Variant ' define worksheets names to exclude
ExcludeWorksheets = Array(wsMaster.Name, "Tracking", "AppControl")
Dim ws As Worksheet
For Each ws Is ThisWorkbook.Worksheets
If Not IsInArray(ws.Name, ExcludeWorksheets) Then 'exclude these worksheets
ws.Range("I13:N42").Copy Destination:=wsMaster.Cells(wsMaster.Rows.Count, "A").End(xlUp)(2)
End If
Next ws
End Sub
I have a button on my worksheet where on click I have a assigned macro which calls the userform.show. See below:
Sub newjoin()
UserForm.UserForm_Activate
NewJoinerEntry.Show
End Sub
I've added the UserForm.UserForm_Activate looking at you above post.
Firstly I'm getting an error on UserForm.UserForm_Activate Run-time error '424' : Object required.
Additionally In my user form I have:
Public Sub UserForm_Initialize()
Dim cntr As Integer
cntr = Application.WorksheetFunction.CountA(Sheets("SITES").Range("B2:B65536"))
Combosite.Clear
For obt = 2 To cntr
Me.Combosite.AddItem Cells(obt, 5)
Next obt
End Sub
which I'm using to populate the combobox values & it's not happening.
On the user form I have other code of on command button click to submit the form results and it's all fine there only if the combo box get the data when userform initializes.
You can loop in your range and add the values in a ComboBox like this:
Private Sub UserForm_Initialize()
Dim rng As Range
Dim SelectedRange As Range
Dim LastRow As Long
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("SITES")
LastRow = sh.Range("B" & Rows.Count).End(xlUp).Row
Set SelectedRange = sh.Range("G2:G" & LastRow)
ComboBox1.Clear
For Each rng In SelectedRange
ComboBox1.AddItem rng.Value
Next rng
End Sub
This code will set a dynamic range in your sheet based on column B. As I saw in your original code, you want the values from column G. So, the SelectedRange is getting the the values from column G and putting it in a ComboBox.
I want an user to select on which sheets he wants to create a new line of text. But the number of sheets he is able to select may vary over time and I don't want to hardcode the sheets' name.
Here is an example ("o" represents the checkbox) of what I aim to do:
o 01.2013
o 07.2013
o 01.2014
o 07.2014
I created an userform with an empty frame to put my checkboxes, and added this bit of code to the userform:
Private Tck(10) As MSForms.CheckBox
Private Sub UserForm_Initialize()
Dim ws As Worksheet
Dim i As Long
i = 1
For Each ws In ActiveWorkbook.Worksheets
If Left(ws.Name, 3) = "T2M" Then
Set Tck(i) = Frame1.Controls.Add("Forms.Checkbox.1", "Checkbox" & i)
Tck(i).Caption = Right(ws.Name, 7)
i=i+1
End If
Next
End Sub
But it only adds one checkbox with the last sheet which validates the if test.
I tried to make an offset between the two iterations but I can't modify the position of the Tck(i) using Tck(i).top for example.
I also tried the method from the answer of this question : Adding controls to a frame in an Excel userform with VBA but it dosen't work either.
Your checkboxes are there, you just can't see them because they're overlayed on top of each other. You had the right idea with changing the 'Top' value.
Public Sub addCheckboxes()
Dim ws As Worksheet
Dim i As Integer
Dim tck As MSForms.CheckBox
Dim offset As Integer: offset = 5
For i = 1 To Worksheets.Count
Set ws = Worksheets(i)
Set tck = Frame1.Controls.Add("Forms.Checkbox.1", "Checkbox" & i, True)
tck.Top = offset
offset = offset + 15
Next i
End Sub
I have kind of a basic question. I want to copy rows from workbook "WB1" to workbook "WB" if a cell (i,4) has an exact known value. The code I have tried to write is not working, what can I do do make it work? Hope someone can help me :)
Private Sub CommandButton1_Click()
Dim i As Integer
For i = 8 To 300
If Workbooks("WB1").Worksheets("Commodity Action Plan").Cell(i,4).Value = "Zamet" Then Workbooks("WB1").Worksheets("Commodity Action Plan").EntireRow.Copy
Workbooks("WB2").Worksheets("Action plan").EntireRow.Paste
End If
Next i
End Sub
I copied and checked your code and it wouldn't compile due to a few errors..
Your If statement was on one line, when it should be
If ValueToEvaluate = true Then
'code to execute goes here
End If
or
If ValueToEvaluate = True Then 'code to execute goes here
If you have the full statement on one line then you don't need the End If.
2nd problem is that you are trying to get the entirerow property of a sheet,
Workbooks("WB1").Worksheets("Commodity Action Plan").EntireRow.Copy
this exists on a range object, so you probably wanted something like
Workbooks("WB1").Worksheets("Commodity Action Plan").Rows(i).EntireRow.Copy
Rather than using Paste you can specify a destination (range) as the second argument for the Copy function, which is easier and less prone to errors than the copy & paste 2 stage method.
Try something like:
Private Sub CommandButton1_Click()
Dim i As Long 'Change to long so we don't get an error past row 32767
Dim outRow as Long
Dim sourceWs As Worksheet, destWs As Worksheet
Set sourceWs = Workbooks("WB1").Worksheets("Commodity Action Plan")
Set destWs = Workbooks("WB2").Worksheets("Action plan")
outRow = 1
'For testing
'Set sourceWs = Sheet1
'Set destWs = Sheet2
For i = 8 To 300
If sourceWs.Cells(i, 4).Value = "Zamet" Then
sourceWs.Rows(i).EntireRow.Copy destWs.Rows(outRow)
outRow = outRow + 1
Application.CutCopyMode = False
End If
Next i
End Sub