I have one "release" button which: assigns numbers to specific cells, counts numbers, creates PDF documents, makes history stamps and so on.
I need to automatically generate buttons based on number value with different macros.
For example:
If target cell value = 4, then create 4 buttons with assigned macro 1, 2, 3, 4.
If value = 5, then create 5 buttons and assign macro 1, 2, 3, 4, 5 and so on.
Every assigned macro will be different. (Max count of buttons should be 20.)
Within your sheet, you should create the 20 buttons. From here assign them to their macro of equal value, and hide each one. From here you can loop to enable visibility for your current target cell value. In this case A1.
Dim MyVal As Long
MyVal = Range("A1").Value
For i = 1 To MyVal
ActiveSheet.Buttons("Button " + CStr(i)).Visible = True
Next i
You'll have to sort the deleting etc, but something like this
Sub SortButtons()
Dim intButton As Integer
Dim cbNewButton As Button
Const intHeight = 30
For intButton = 1 To 4
Set cbNewButton = ActiveSheet.Buttons.Add(224.25, (intButton * intHeight) + 20, 90.75, intHeight)
cbNewButton.OnAction = "Macro" & intButton
cbNewButton.Text = "Button for Macro " & intButton
cbNewButton.Name = "OK_TO_DELETE_" & intButton
Next intButton
End Sub
Related
I have a list box (lbxStN) with 3 columns (0-fmMultiSelectSingle).
I would like to make a selection (only one) in this list, and have the data from each column of the list shown in a specific cell in a specific sheet (sheet: DeN). First column from the list F19, second column C22 and third column H22. After button (cmdBtnSelect2) is clicked.
Data for the list box is stored in a different sheet in the same workbook.
Private Sub cmdBtnSelect2_Click()
Dim i As Long
Dim myVar4 As String
Dim myVar5 As String
Dim myVar6 As String
For i = 0 To lbxStN.ListCount - 1
If lbxStN.Selected(i) = True Then
lbxStN.List(i, 0).Value = myVar4
lbxStN.List(i, 1).Value = myVar5
lbxStN.List(i, 2).Value = myVar6
End If
Next
ThisWorkbook.Sheets("DeN").Range("F19") = myVar4
ThisWorkbook.Sheets("DeN").Range("C22") = myVar5
ThisWorkbook.Sheets("DeN").Range("H22") = myVar6
End Sub
If I run the code, I get a '424' Object required error.
Which means I'm missing something basic.?
For what you intend to do, there is no need to create new variables. The value from the selected item can be assigned directly to the cells. As follows
Private Sub cmdBtnSelect2_Click()
Dim i as Integer
For i = 0 To lbxStN.ListCount - 1
If lbxStN.Selected(i) Then
ThisWorkbook.Sheets("DeN").Range("F19") = lbxStN.List(i, 0)
ThisWorkbook.Sheets("DeN").Range("C22") = lbxStN.List(i, 1)
ThisWorkbook.Sheets("DeN").Range("H22") = lbxStN.List(i, 2)
Exit For
End If
Next i
End Sub
The previous subroutine iterates for each iteam in the list, and checks if the item is selected. If the item is selected, then it assigns each column to each cell. Exit For will exit the iteration, because there is no need to continue looking for more selected items.
I tested the code with the following subroutine to add items to the list. I think it would be a good idea to compare it with yours in case you have tried to do a complex assignment.
Private Sub CommandButton1_Click()
lbxStN.Clear
lbxStN.AddItem "a"
lbxStN.List(lbxStN.ListCount - 1, 1) = "a2"
lbxStN.List(lbxStN.ListCount - 1, 2) = "a3"
lbxStN.AddItem "b"
lbxStN.List(lbxStN.ListCount - 1, 1) = "b2"
lbxStN.List(lbxStN.ListCount - 1, 2) = "b3"
lbxStN.AddItem "c"
lbxStN.List(lbxStN.ListCount - 1, 1) = "c2"
lbxStN.List(lbxStN.ListCount - 1, 2) = "c3"
End Sub
I usually get better at coding by reading someone elses code and trying to understand it
Cheers!
I am writing a VBA code that goes through a defined matrix size and filling cells randomly within its limits.
I got the code here from a user on stackoverflow, but after testing it I realized that it does not fit for avoiding duplicate filling, and for instance when filling 5 cells, I could only see 4 cells filled, meaning that the random filling worked on a previously filled cell.
This is the code I'm working with:
Dim lRandom As Long
Dim sCells As String
Dim sRandom As String
Dim rMolecules As Range
Dim i As Integer, j As Integer
Dim lArea As Long
lArea = 400 '20x20
'Populate string of cells that make up the container so they can be chosen at random
For i = 1 To 20
For j = 1 To 20
sCells = sCells & "|" & Cells(i, j).Address
Next j
Next i
sCells = sCells & "|"
'Color the molecules at random
For i = 1 To WorksheetFunction.Min(5, lArea)
Randomize
lRandom = Int(Rnd() * 400) + 1
sRandom = Split(sCells, "|")(lRandom)
Select Case (i = 1)
Case True: Set rMolecules = Range(sRandom)
Case Else: Set rMolecules = Union(rMolecules, Range(Split(sCells, "|")(lRandom)))
End Select
sCells = Replace(sCells, "|" & sRandom & "|", "|")
lArea = lArea - 1
Next i
rMolecules.Interior.ColorIndex = 5
Using this same exact code which works perfectly, WHAT can I insert and WHERE do I do that so that the code would check if a cell is previously already filled with a string or a color?
I feel as though this code I'm looking for should be right before
rMolecules.Interior.ColorIndex = 5
But I'm not sure what to type.
EDIT
From the comments I realized that I should be more specific.
I am trying to randomly fill cells with the blue color (.ColorIndex = 5), but what I need to check first is if the randomizing hadn't marked a cell twice, so that for instance in this case, if I want to mark 5 different cells, it marks only 4 of them because of a duplicate and thus fills only 4 cells with the blue color. I need to avoid that and make it choose another cell to mark/fill.
I'd appreciate your help.
Keep the cells you use in a Collection and remove them as you fill the random cells:
Sub FillRandomCells(targetRange As Range, numberOfCells As Long)
' populate collection of unique cells
Dim c As Range
Dim targetCells As New Collection
' make sure arguments make sense
If numberOfCells > targetRange.Cells.Count Then
Err.Raise vbObjectError, "FillRandomCells()", _
"Number of cells to be changed can not exceed number of cells in range"
End If
For Each c In targetRange.Cells
targetCells.Add c
Next
' now pick random 5
Dim i As Long, randomIndex As Long
Dim upperbound As Long
Dim lowerbound As Long
For i = 1 To numberOfCells
lowerbound = 1 ' collections start with 1
upperbound = targetCells.Count ' changes as we are removing cells we used
randomIndex = Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
Set c = targetCells(randomIndex)
targetCells.Remove randomIndex ' remove so we don't use it again!
c.Interior.Color = 5 ' do what you need to do here
Next
End Sub
Sub testFillRandomCells()
FillRandomCells ActiveSheet.[a1:t20], 5
FillRandomCells ActiveSheet.[b25:f30], 3
End Sub
EDIT: Changed to make the target range and number of changed cells configurable as arguments to a function. Also added error checking (always do that!).
Why not build a list of random numbers and place in a Scripting.Dictionary, one can use the Dictionary's Exist method to detect duplicates, loop through until you have enough then you can enter your colouring code confident that you have a unique list.
I have a button that takes the data from a listbox and puts it into specific cells of my table. My problem right now is when inserting the value into the cells it fills the whole column that cell is in instead of the specific cell.
Here is the code for the button:
Private Sub cbSubmit_Click()
Dim i As Long
Dim v As Variant
Dim vTable() As Variant
Set inventoryTable = cSheet.ListObjects("inventory_table")
colItemID = inventoryTable.ListColumns("Item #").Index
colSpecs = inventoryTable.ListColumns("Specs").Index
v = inventoryTable.DataBodyRange.Rows
ReDim vTable(1 To UBound(v, 1), 1 To 4)
For i = 0 To lbItemList.ListCount - 1
vTable(i + 1, 1) = "=DATA!" & lbItemList.List(i, 2)
If specLink = "" Then
Exit For
Else
vTable(i + 1, 4) = lbItemList.List(i, 1)
End If
inventoryTable.DataBodyRange(i + 1, colItemID).Value = vTable(i + 1, 1)
inventoryTable.DataBodyRange(i + 1, colSpecs).Value = vTable(i + 1, 4)
Next
Unload Me
End Sub
This is how it looks after I run the button.
I want it to only fill in the first cell in Item # and then the cell in Specs in that same row. Then go down the rows each cell and fill in the next item. Instead each item gets filled overtop the old items.
If you are targeting individual cells in a structured table (aka ListObject object) then you need to turn of the AutoCorrect.AutoFillFormulasInLists property.
Application.AutoCorrect.AutoFillFormulasInLists = False
This can also be achieved with Alt+F,T,P, Alt+A then go to the AutoFormat As You Type tab and uncheck Fill formulas in tables to create calculated columns.
Optionally turn it back on at the end of your sub procedure if you wish to have this application-wide option available.
Application.AutoCorrect.AutoFillFormulasInLists = True
I have a ListView with multiple columns. More precisely, the ListView contains 8 columns. 2 of them should be filled with checkboxes.
Currently only the first column contains checkboxes. It is defined as follows:
While Not rs.EOF
//first column with checkboxes
ListViewCustomer.ListItems.Add , , rs("Id")
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).tag = rs("Status")
//second column etc.
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).ListSubItems.Add , , rs("name")
....
//Here is the second column, which doesn't display the checkboxes
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).ListSubItems.Add , , IIf(IsNull(rs("date_from")), "", rs("date_from"))
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).tag = rs("Status2")
Wend
Do anyone have an idea how to add the checkboxes in the last column?
EDIT:
Is it possible to realize this column with adding via .Controls?
A ListView is a more expanded version of the ListBox control.
See ListBox control on msdn as well.
They both display records of rows (the ListView has more advanced formatting options). This however means that a record is a row. Therefore you select a row when you select one of the items.
The function of the checkbox is to allow the user to mark the row(s) that is the records(s) he selects.
Thus there is only one checkbox per row, at the front of the row.
Consider this code (this is Excel 2003 VBA, but gives you the idea):
Private Sub UserForm_Initialize()
Dim MyArray(6, 8)
'Array containing column values for ListBox.
ListBox1.ColumnCount = 8
ListBox1.MultiSelect = fmMultiSelectExtended
'Load integer values MyArray
For i = 0 To 5
MyArray(i, 0) = i
For j = 1 To 7
MyArray(i, j) = Rnd
Next j
Next i
'Load ListBox1
ListBox1.List() = MyArray
End Sub
You could do a custom ListBox or ListView if you really want. You could create a frame and put Labels and CheckBoxes on it. This is the only way to do this in Excel2003 where I tested. The ListBox object has no Controls child.
But this is more like a datagrid and not really a ListBox or ListView which by definition are a listing of records (rows).
Update:
I saw your update and that you really want to place the CheckBox at the end of the row.
If you only want one checkbox at the last row, you could do this custom checkbox. Again this is written for the ListBox, so need to convert it to your ListView if you want to.
Still requires a custom handling, but I had some time, so I did this code. See if you like it:
Private Sub ListBox1_Change()
For i = 0 To ListBox1.ListCount - 1
ListBox1.List(i, 3) = ChrW(&H2610)
Next i
ListBox1.List(ListBox1.ListIndex, 3) = ChrW(&H2611)
End Sub
Private Sub UserForm_Initialize()
Dim MyArray(5, 3)
'Array containing column values for ListBox.
ListBox1.ColumnCount = 4
ListBox1.MultiSelect = 0
ListBox1.ListStyle = 0
'Load integer values MyArray
For i = 0 To 5
MyArray(i, 0) = i
For j = 1 To 2
MyArray(i, j) = Rnd
Next j
MyArray(i, 3) = ChrW(&H2610)
Next i
'Load ListBox1
ListBox1.List() = MyArray
End Sub
I have 100 boxes, (box1, box2, etc) each box has 100 rows of values. (0,1,2,etc) So I have a total of 10,000 rows of data. I am counting number of cells in each box with a specific value. I set the range because I can then change the countif value, e.g. number of cells with value of 2, 3, etc.
However, to do this, I have to Dim boxes 100 times and set box= 100 times. Is there a way to simplify this? Each box always has 100 rows, total number of boxes is always 100.
Dim box1 As Range
Dim box2 As Range
Dim box 3 As Range
.....
Set box1 = Range("A1:A100")
Set box2 = Range("A101:200")
Set box3 = Range("A201:300")
.....
Range("C1").formula = "=COUNTIF(box1, "1")"
Range("C2").formula = "=COUNTIF(box2, "1")"
.....
This should get you started in the right direction:
Sub tgr()
Dim box(1 To 100) As Range
Dim i As Long
For i = 1 To UBound(box)
Set box(i) = Cells(100 * (i - 1) + 1, "A").Resize(100)
Cells(i, "C").Formula = "=COUNTIF(" & box(i).Address & ",""1"")"
Next i
End Sub