I recently creating a workbook which contains a userform with a combobox, named "combobox1"
I have a code that brings data from other workbook in direction shown below whith range "B2:B...."
now i want to make it how to have a tow columns in a combobox the other column shuld bring data from same directory but the range for exp: "A1:A...."
i need your help
thx.
[Private Sub UserForm_Initialize()
`Dim ListItems As Variant, i As Integer
`Dim SourceWB As Workbook
With Me.ComboBox1
.Clear ' remove existing entries from the listbox
' turn screen updating off,
' prevent the user from seeing the source workbook being opened
Application.ScreenUpdating = False
' open the source workbook as ReadOnly
Set SourceWB = Workbooks.Open("C:\Users\Mohsen\Desktop\new prj\Data base\partlist.xls", _
False, True)
ListItems = SourceWB.Worksheets(1).Range("B2:B1468").Value
' get the values you want
SourceWB.Close False ' close the source workbook without saving changes
Set SourceWB = Nothing
Application.ScreenUpdating = True
ListItems = Application.WorksheetFunction.Transpose(ListItems)
' convert values to a vertical array
For i = 1 To UBound(ListItems)
.AddItem ListItems(i) ' populate the listbox
Next i
.ListIndex = -1 ' no items selected, set to 0 to select the first item
End With
End Sub
Your question is not clear about where the second column of data should come from so I have assumed that the first combobox column is from SourceWB, Sheet1, column B and that the second combobox column is from the same sheet in the column to the left of column B. You can change these to suit.
I have also coded to identify the last datarow in column B. This will prevent searching 1468 rows unnecessarily. Again, please change if this is not helpful.
Option Explicit
Private Sub UserForm_Initialize()
Dim ListItems As Variant
Dim i As Integer
Dim SourceWB As Workbook
Dim listVal As Range
Dim srcLastRow As Long
'for testing purposes
Dim srcName As String
srcName = "C:\Users\Mohsen\Desktop\new prj\Data base\partlist.xls"
With Me.ComboBox1
'Set the number of columns by code
.ColumnCount = 2
.Clear
Application.ScreenUpdating = False
Set SourceWB = Workbooks.Open(srcName, False, True)
'find the last row of data to prevent searching 1468 rows unnecessarily
srcLastRow = SourceWB.Sheets(1).Cells(Rows.Count, "B").End(xlUp).Row
For Each listVal In SourceWB.Sheets(1).Range("B2:B" & srcLastRow)
.AddItem listVal.Value
'Offset(0,-1) gets second column of data from cell to the left
.List(.ListCount - 1, 1) = listVal.Offset(0, -1).Value
Next listVal
SourceWB.Close False
Set SourceWB = Nothing
Application.ScreenUpdating = True
.ListIndex = -1
End With
End Sub
Take a look at the Properties window for Combobox1, for other properties that you may require to set within the code.
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
I have a workbook with two sheets.
First is called "Forma"
Second is called "Prices"
I go to Forma, with some VBA shapes I choose a product category. I tag this category name in A1 cell of sheet Prices and then filter products according to this category and then copy filtered ones in Forma again.
Because of activating and deactivating sheets the procedure is working but it is blinking screens between activations. Any better way?
That is a part of my code:
With ActiveSheet
range("j7: m30").ClearContents
End With
'Tag the category in Prices Table
ThisWorkbook.Sheets("Prices").Cells(1, 1).Value = "CategoryName.ex.Computers"
'Filtering and selecting products comparing A1 with Column 3 Categories
Worksheets("Prices").Activate
range("A1:K300").Select
Selection.AutoFilter
Selection.AutoFilter Field:=3, Criteria1:=range("a1").Value
'Copy filtered in Forma Sheet
Dim DbExtract, DuplicateRecords As Worksheet
Set DbExtract = ThisWorkbook.Sheets("Prices")
Set DuplicateRecords = ThisWorkbook.Sheets("Forma")
DbExtract.range("D3:f5000").SpecialCells(xlCellTypeVisible).Copy
DuplicateRecords.Cells(7, 10).PasteSpecial
Copy Filtered Range
Not activating and not selecting will increase performance.
Turning off Application.ScreenUpdating will stop the screen from 'blinking'.
Using variables will increase readability.
Something like the following code could put you on the right track.
The Code
Option Explicit
Sub copyCategory()
Const Criteria As String = "CategoryName.ex.Computers"
Dim wb As Workbook
Set wb = ThisWorkbook
Dim src As Worksheet
Set src = wb.Worksheets("Prices")
Application.ScreenUpdating = False
If src.AutoFilterMode Then
src.AutoFilterMode = False
End If
src.Range("A1").Value = Criteria
src.Range("A1:K300").AutoFilter Field:=3, _
Criteria1:=Criteria
Dim dst As Worksheet
Set dst = wb.Worksheets("Forma")
dst.Range("J7: M30").ClearContents
src.Range("D3:F300").SpecialCells(xlCellTypeVisible).Copy dst.Range("J7")
' If you need some special pasting then rather use the following 3 lines.
'src.Range("D3:F300").SpecialCells(xlCellTypeVisible).Copy
'dst.Range("J7").PasteSpecial
'Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox "Data copied.", vbInformation, "Success"
End Sub
I have a sheet of raw data that includes vehicle counts over multiple days. Each date is a row representing vehicle counts taken during a 60 minute period (so 24 rows per day).
I have a model that creates a new sheet using the report template for each day. I just can't figure out how to get the actual vehicle count data for each day to populate each sheet for each hour.
Each new tab that is created is named for the date. If we have vehicle counts for 8 day then 8 new tabs would be created. Within that new tab I need to be able to take all 24 vehicle counts and paste them into the template report in the appropriate cells.
Option Explicit
Sub SheetsFromTemplate()
Dim wsMASTER As Worksheet, wsTEMP As Worksheet, wasVISIBLE As Boolean
Dim shDates As Range, Item As Range, NmStr As String
'keep focus in this workbook
With ThisWorkbook
'sheet to be copied
Set wsTEMP = .Sheets("Template")
'check if it's hidden or not
wasVISIBLE = (wsTEMP.Visible = xlSheetVisible)
'make it visible
If Not wasVISIBLE Then wsTEMP.Visible = xlSheetVisible
'sheet with dates and data
Set wsMASTER = .Sheets("Raw Data")
'range to find names to be checked
Set shDates = wsMASTER.Range("C9:C" & Rows.Count).SpecialCells(xlConstants)
Application.ScreenUpdating = False
'check one data at a time
For Each Item In shDates
NmStr = FixStringForSheetName(CStr(Item.Text))
'if sheet does not exist...
If Not Evaluate("ISREF('" & NmStr & "'!A1)") Then
'...create it from template
wsTEMP.Copy After:=.Sheets(.Sheets.Count)
'...rename it
ActiveSheet.Name = NmStr
End If
Next Item
'return to the master sheet
wsMASTER.Activate
'hide the template if necessary
If Not wasVISIBLE Then wsTEMP.Visible = xlSheetHidden
'update screen one time at the end
Application.ScreenUpdating = True
End With
MsgBox "All Reports created"
Hard to answer without seeing your worksheets (layout/position of data), but something like the below might give you an idea on how to achieve what you're after.
Option Explicit
Sub SheetsFromTemplate()
Dim templateSheet As Worksheet
Set templateSheet = ThisWorkbook.Worksheets("Template")
Dim originalSheetState As XlSheetVisibility
originalSheetState = templateSheet.Visible
'sheet with dates and data
Dim masterSheet As Worksheet
Set masterSheet = ThisWorkbook.Worksheets("Raw Data")
templateSheet.Visible = xlSheetVisible
Dim lastRowOnMasterSheet As Long
lastRowOnMasterSheet = masterSheet.Cells(masterSheet.Rows.Count, "C").End(xlUp).Row
Debug.Assert lastRowOnMasterSheet >= 9
'range to find names to be checked
Dim datesToLoopThrough As Range
Set datesToLoopThrough = masterSheet.Range("C9:C" & lastRowOnMasterSheet)
Dim toFilterIncludingHeaders As Range
Set toFilterIncludingHeaders = datesToLoopThrough.Offset(-1).Resize(datesToLoopThrough.Rows.Count + 1)
Application.ScreenUpdating = False
'check one data at a time
Dim item As Range
For Each item In datesToLoopThrough
Dim nmStr As String
nmStr = FixStringForSheetName(CStr(item.Text))
' The IF condition below might be problematic if sheet
' already exists, but has not yet had dates
' transferred/copy-pasted to it.
If Not DoesWorksheetExist(nmStr) Then
With CreateSheetFromTemplate(templateSheet)
.Name = nmStr
.Move After:=.Parent.Worksheets(.Parent.Worksheets.Count)
toFilterIncludingHeaders.AutoFilter Field:=1, Criteria1:=item
Intersect(datesToLoopThrough.SpecialCells(xlCellTypeVisible).EntireRow, mastersheet.range("D:Q")).Copy .Range("F13") ' You haven't shown your template sheet, so don't know where to paste to.
End With
End If
Next item
masterSheet.Activate
templateSheet.Visible = originalSheetState
'update screen one time at the end
Application.ScreenUpdating = True
MsgBox "All Reports created"
End Sub
Private Function CreateSheetFromTemplate(ByVal someTemplateSheet As Worksheet) As Worksheet
' Creates a copy of template sheet and returns an object reference to the newly created sheet.
' Newly created sheet is at index 1 (for deterministic/reliability reasons).
' Call site can name/move as needed.
someTemplateSheet.Copy Before:=someTemplateSheet.Parent.Worksheets(1)
Set CreateSheetFromTemplate = someTemplateSheet.Parent.Worksheets(1)
End Function
Private Function DoesWorksheetExist(ByVal sheetNameToCheck As String) As Boolean
' Checks if sheet of a given name exists in ThisWorkbook.
Dim targetSheet As Worksheet
On Error Resume Next
Set targetSheet = ThisWorkbook.Worksheets(sheetNameToCheck)
On Error GoTo 0
DoesWorksheetExist = Not (targetSheet Is Nothing)
End Function
I am creating a userform that is entering data on a form. And in that userform I have a Combobox that list out all the products. For each product there a row and the data that is being inputted in would only be on that row.
Private sub cwbSave_Click()
Dim ws as Worksheet
Set ws = ActiveWorkbook.ActiveSheet
with ws
Select Case cbProduct
Case Is = "Apple"
With ActiveSheet.Range("A14:P14")
.Font.Bold = True
End With
ws.Cell(14,4) = Me.tbPrice
ws.Cell(14,5) = Me.tbColor
ws.Cell(14,6) = Me.tbSell
Case Is = "Pineapple"
With ActiveSheet.Range("A15:P15")
.Font.Bold = True
End With
ws.Cell(15,4) = Me.tbPrice
ws.Cell(15,5) = Me.tbColor
ws.Cell(15,6) = Me.tbSell
End Select
End With
End Sub
But the thing is, I got like 30 products. And it a lot of manually putting in. I was wondering if there an easier way to code this.
Thank you
There are several ways to do this.. here is one:
In the UserForm_Initialize, add the below code:
Private Sub UserForm_Initialize()
Dim aValues As Variant: aValues = WorksheetFunction.Transpose(ThisWorkbook.Worksheets("Sheet2").Range("A2:A5")) ' Change sheet name and range to where your products are
Dim iRow As Long
' Clear combobox
Me.cmbCmbBox.Clear
' Fill combobox with the values from product range
For iRow = LBound(aValues) To UBound(aValues)
Me.cmbCmbBox.AddItem aValues(iRow)
Next
End Sub
Above code uses your product range to populate the combobox. Now in cmbCmbBox_Change, add the following code:
Private Sub cmbCmbBox_Change()
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet2")
Dim rProdRange As Range: Set rProdRange = oWS.Range("A2:A5")
Dim rItemRange As Range
' Find the selected item
Set rItemRange = rProdRange.Find(Me.cmbCmbBox.Value)
' Set value in the sheet
If Not rItemRange Is Nothing Then
oWS.Cells(rItemRange.Row, 4) = Me.tbPrice
oWS.Cells(rItemRange.Row, 5) = Me.tbColor
oWS.Cells(rItemRange.Row, 6) = Me.tbSell
End If
End Sub
You can add validation for when product is not found
I am looking to use multiple (5) checkboxes to filter a single column in an excel table. The column to be filtered contains several markers namely
"","r","x","s","t"
Here a picture of the boxes:
My aim is to tick several boxes and include all the columns with said marker. Using straightforward methods results in the previous filter being cleared instead of being "added".
Here a picture of my (now two) tracking columns, one containing the identifier and another hidden converting that too the checkbox captions using ifs statements so #zac's solution works.
I have a looked around a lot and found a thread on MrExcel where some code was provided however I was unable to adapt it to my exact needs. Sadly whichever button I press it keeps defaulting to the blank ("") marker.
Below is my code for a sub that should be called by each checkbox.
Background info:
The identifier value are defined in a table and assigned a dynamic named range "tracking"
The column to be filtered is called ("Project Flag")
The code is contained in a seperate module
Sub Project_Filter()
Dim objcBox As Object
Dim cBox As Variant
Set Dbtbl = Sheets("Database").ListObjects("Entire")
ReDim cBox(0)
Dim trackers() As String
Dim i As Integer
Dim x As Variant
i = -1
For Each x In Range("Tracking").Cells 'reading named range into array
i = i + 1
ReDim Preserve trackers(i) As String
trackers(i) = x.Value
Next x
Application.ScreenUpdating = False
With Sheets("Database")
For Each objcBox In .OLEObjects
If TypeName(objcBox.Object) = "CheckBox" Then 'looking for checkboxes
If objcBox.Object.Value = True Then
cBox(UBound(cBox)) = trackers(i) 'setting cbox array as nth trackers value
i = i + 1
ReDim Preserve cBox(UBound(cBox) + 1)
End If
End If
Next
If IsError(Application.Match((cBox), 0)) Then
MsgBox "Nothing Selected"
Exit Sub
End If
ReDim Preserve cBox(UBound(cBox))
If Not .AutoFilterMode Then
Dbtbl.Range.AutoFilter
Dbtbl.Range.AutoFilter Field:=Dbtbl.HeaderRowRange.Find("Project Flag").Column, Criteria1:=Array(cBox)
End If
End With
Application.ScreenUpdating = True
End Sub
So after some trial and error i found out that the array cbox() only contains the first value of my trackers array, hence it only filtering the blank entries. No idea what causes that but thought it might be noteworthy
Based on our conversation and the picture of your checkboxes in your description, we can get the filter text from the caption:
Option Explicit
Sub Project_Filter()
Dim oOLE As Object
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet1") ' <--- Remeber to change this
Dim aFilter As Variant
Dim sFilterChar As String
' Referenc the sheet
With oWS
' If 'All Projects' checkbox is selected, unselect all other checkboxes
If .OLEObjects("chkAll").Object.Value Then
ClearCheckboxes
End If
' Loop to capture all selected check boxes
For Each oOLE In .OLEObjects
If TypeName(oOLE.Object) = "CheckBox" And oOLE.Object.Value And oOLE.Object.Caption <> "All Projects" Then
If Not IsArray(aFilter) Then
ReDim aFilter(0)
Else
ReDim Preserve aFilter(UBound(aFilter) + 1)
End If
sFilterChar = Mid(oOLE.Object.Caption, 2, 1)
If sFilterChar = "]" Then
aFilter(UBound(aFilter)) = ""
Else
aFilter(UBound(aFilter)) = sFilterChar
End If
End If
Next
' Set the filter based on selection
If IsArray(aFilter) Then
.ListObjects("Table1").Range.AutoFilter field:=2, Criteria1:=aFilter, Operator:=xlFilterValues
Else
.ListObjects("Table1").Range.AutoFilter
End If
End With
' Clear Object
Set oWS = Nothing
End Sub
' Clear all checkboxes other than 'All Projects' checkbox
Private Sub ClearCheckboxes()
Dim oOLE As Object
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet1") ' <--- Remeber to change this
With oWS
' Clear checkboxes
For Each oOLE In .OLEObjects
If TypeName(oOLE.Object) = "CheckBox" And oOLE.Object.Caption <> "All Projects" Then
If oOLE.Object.Value Then
oOLE.Object.Value = False
End If
End If
Next
End With
' Clear object
Set oWS = Nothing
End Sub
NOTE: I have All Projects as a checkbox as well