What method would be best if I had the following.
3 checkboxes that if selected will populate 3 cells A1, A2 & A3. I need code that will check the 3 cells for data and create a singular string of info. I can use this with formula but need VBA to do the following to the cells as per below.
So my end result will be "cell1" (if only 1 checkbox is selected) or "cell1 & cell2" (if 2 checkboxes are selected) but if all 3 are selected I want the string to read "cell1, cell2 & cell3". There will only ever be 3 cells in this section.
I want the Concatenate Text to then go into a single cell. AA13 where it can be copied at a later stage.
I have another scenario where I have 6 checkboxes and I need the same thing as above, the 6 checkboxes populate 6 cells B1:B6. but, I need some code that makes sure a minimum of 2 check box's are selected. I can't work out how to get VBA to check for the number of tick boxes and report an error if it doesn't meet the criteria of 2 minimum.
I will have an active x button to run the code as per above to concatenate but when a check box is selected the cell will auto populate with the string i need.
Help would be much appreciated. I'm struggling to find code online to help me for these two scenarios
Consider:
Sub konkat()
Dim N As Long
With Application.WorksheetFunction
N = .CountA(Range("A1:A3"))
Select Case N
Case 0
Exit Sub
Case 1
Range("AA13").Value = Range("A1") & Range("A2") & Range("A3")
Case 2
Range("AA13").Value = .TextJoin(" & ", True, Range("A1:A3"))
Case 3
Range("AA13").Value = Range("A1").Value & " , " & Range("A2").Value & " & " & Range("A3").Value
End Select
End With
End Sub
Related
I've created a userform with a couple of list boxes in. Listbox1 has all items in it, the user can select multiple values to then move into Listbox2. once they are in listbox2 I need them to populate some cells. With 1 list item per cell.
I'm having a pain trying to work out how to do it. So far all I've got is:
Private Sub CommandButton1_Click()
Dim tmpMsg As String
Dim t As Long
tmpMsg = "Selected categories:"
For t = 1 To ListBox2.ListCount
tmpMsg = tmpMsg & vbNewLine & ListBox2.List(t - 1)
Next
Worksheets("Specialist Prices").Activate
Range("a1").Select
ActiveCell.Value = tmpMsg
End Sub
This populates cell A1 with the entire set of list items. but I don't know how to put 1 value in a1 then move down and put the next in A2 and so on until all items are accounted for.
Any help would be appreciated.
Right now you are creating one string. It has linebreaks in it, but it´s still one text. If you are not using the tmpmsg for something else, you could use the for-loop to populate your sheet
For t = 1 To ListBox2.ListCount
Thisworkbook.sheets("Specialist Prices").Range("A" & t).value = ListBox2.List(t - 1)
Next
You can even do it faster by adding an array to the entire range. ListBox2.List is an array of values and you can paste that array into a range of cells:
ThisWorkbook.sheets("Specialist Prices").Cells(1,1).Resize(ListBox2.ListCount,1) = ListBox2.List
The Resize method here makes sure that the range contains the same amount of cells as there are elements in ListBox2. It resizes the range from 1 cell to a range of ListBox2.ListCount amount of rows and 1 column.
I want to be able to build a table based upon the answer to 2 questions, with Question 1 "How many risks are in the current process?" to determine the number of columns (i.e. one per risk) and the second question "How many controls in the current process?" determines the number of rows to use (i.e one per control). Is there an easy way to build a table to show a matrix that can then be used for risk/control relationships?
This was a fun one, so I'll plan to make a YouTube tutorial on this later tonight and come back here to post my link. But here's a quick explanation of what I did.
I started by using A2 cell for # of rows, and the B2 cell for # of columns. Then I created a button of which I will assign it to a macro, explained in a bit.
Next I created the base layout for the table. This includes:
D5 to hold "Control ID"
E5 to hold "Control Description"
F3 to hold "Risk ID"
F4 to hold "Risk Description"
Also, let's start by adding the first Control and Risk blocks, as every table would presumably start with at least 1 control and 1 risk. So
D6 will have "C1"
E6 will have "Control 1 Description"
G3 will have "R1"
G4 will have "Risk 1 Description"
Then to keep consistent with your table, I put a black highlight on cells F5 and G5.
Now we can create the macro, using the following code:
Sub CreateTable()
' create variable x to hold # of rows from A2
Dim x As Integer
x = Range("A2").Value
' calculate the row range from x
Let RowRange = "7:" & 7 + x - 2
' copy row 6 into each row in the calculated range
Rows("6:6").Copy Range(RowRange)
' update the text in the newly created rows to match
' the corresponding control number
For i = 2 To x
Let ControlIdRow = 5 + i
Cells(ControlIdRow, 4).Value = "C" & i
Cells(ControlIdRow, 5).Value = "Control " & i & " Description"
Next i
Dim y As Integer
y = Range("B2").Value
Columns("G:G").Copy Range(Columns(8), Columns(8 + y - 2))
For i = 2 To y
Let RiskIdCol = 6 + i
Cells(3, RiskIdCol).Value = "R" & i
Cells(4, RiskIdCol).Value = "Risk " & i & " Description"
Next i
End Sub
Basically what's happening is that we create a variable x and assign it to be the number of rows, as input from cell A2. Then we use that to calculate the row range starting at row 7 (which will start as Control 2 since Control 1 is on row 6). Then we just copy the entire row 6 up until the specified range. Now (starting at the For loop), we need to edit the text in the cells to match the corresponding names (i.e. the second control will be C2, Control 2 Description, the third will be C3, Control 3 Description 3, and so on). Then just essentially repeat that same block, changing the respective values to match the Risks.
Then don't forget to assign the button to the new macro. Now you should be able to enter in a value for rows (A2) and a value for columns (B2) and click the button, and it should automatically create the table for you.
As mentioned, I'll create a YouTube video later tonight detailing this more and update this answer to point there.
Update
I noticed your picture has a checkmark in it, so here's the code to be able to just select a cell and have a green checkmark appear in the cell. Then clicking the cell again will remove the checkmark.
Open up the visual basic editor, and click the Sheet 1 code from the left. Then apply the following code in there:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If ActiveCell.Row > 5 And ActiveCell.Column > 6 Then
If ActiveCell.Value = "" Then
Target.Value = ChrW(&H2713)
Else
If ActiveCell.Value = ChrW(&H2713) Then
Target.Value = ""
End If
End If
End If
End Sub
Link to YouTube Tutorial on this answer
I need some help with an excel problem.
It is a combination of the two problems below:
1) Excel - Popup message with sound alert when cell value meets certain criteria
2) VBA code to show Message Box popup if the formula in the target cell exceeds a certain value
In Sheet1, I have a range of products and sales figure.
Example: Sheet1
In Sheet2, I have multiple columns of sumif() functions. Example: Sheet2.
It contains a column of names in (A:A) and data in (B:B) & (C:C) which are linked to cells in other sheets. I would like a pop up notification saying ("Text in column A" sold is > 20) when the value of any cell in column B exceeds 20 or column C exceeds 40.
For example: If one of the cell value in column "B" gets updated to 33 (which is >20) and the corresponding cell value in column "A" contains text as "Charlie", excel sheet should popup message saying "Charlie sold is > 20".
The below VBA code accomplishes this IF it was raw data. However, it does not work when the cells are linked to data from other sheets, as in the case of this workbook.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.column = 2 and target.value > 1 Then
MsgBox target.offset(0,-1).text & " sold is > 20"
End If
End Sub
This alternative code works with data linked from other sheets, however it only applies to a specific cell, not an entire column.
Private Sub Worksheet_Calculate()
If Sheets("Sheet2").Range("B2").Value > 20 Then
MsgBox "B2 is >20", vbOKOnly
End If
End Sub
What I'm trying to achieve is this: As I input my raw data in Sheet1, the figures in Sheet2 column(B:B) and column(C:C) get updated. Once any of the cells in Sheet2 column(B:B) exceed 20 or column(C:C) exceed 40, there will be a popup notification that links back to column A text such as MsgBox target.offset(0,-1).text & " sold is > 20". Is there a way to combine the above two codes to achieve this?
Any alternative solutions are welcome too, thank you!
Compare all the Sums in Summary table
Private Sub Worksheet_Calculate()
Dim RangeToCheck As Range
Dim Cell As Range
Set RangeToCheck = Sheets("Sheet2").Range("B2:B5") 'See comment #1
For Each Cell In RangeToCheck.Cells
With Cell
If .Value2 > 20 Then
MsgBox "Product: " & .Offset(columnoffset:=-1).Value2 & _
" in cell: " & .Address & " is " & .Value2 & ">20", vbOKOnly
End If
End With
Next
End Sub
Comments
I recommend turning the range on Sheet2 to Excel table and using ListObject and Listcolumns instead.
Off topic hint: You can also use some counter, put the range into an VBA array and loop through array, it will be faster, than refering to sheet cell one after another. See Writing efficient VBA UDFs (Part 1).
I would like to tell an excel sheet to put, for each row, the sum of the values between B and G cells in the H cell.
For exemple:
H1 must contain the SUM(B1:G1),
H2 must contain SUM(B2:G2)
...
I want to make this process automatic instead of specifying on each H cell that is the SUM of the corresponding values between B and G.
Thanks.
If you double-click the little black box in the bottom-right hand corner of the cell, excel will automatically replicate the contents of that cell to the bottom of your current list revelant to the cell references within the cell. You can also click-and-drag the little black box to specify the range yourself
This block will fill the entire acvitvated sheet when ran.
Sub FillSums
Dim I as Integer
I=0
While Err.Description = ""
I=I+1
Application.ActiveSheet.Range("H" & I).Formula = "=SUM(B" & I & ":G" & I & ")"
Wend
End Sub
Dim I as Integer
Started with a data validation list and I like that it is in the cell where I want the data to appear. Tried combo box and active X combo box and don't like that they do not reside in the cell. This is very different than Access. This is what I am trying to accomplish:
My named range (Employee) is A4:C100, 3 columns, with headings Title, MI, and LN on a sheet named "Emp".
My form location is C6. I wanted to be able to show 3 columns and end up with data from the three columns. For example, Officer J. Doe.
Currently I am using data validation list entering data into one column as Doe, J., Officer and it works. The list can be long and I will need it to be in alphabetical order.
Is this the best way or am I confused with combo box and active X combo box?
The only way to show a combination of all 3 columns in a dropdown list is to concatenate the data in a 4th column e.g. use the following formula in Cell D4
=A4&" "&B4&" "&C4
...then you can name the range D4:D100. You may wish to hide this column for presentational reasons
Actually, you will probably want to avoid naming the whole range as the bottom cells may be blank/make scrolling more awkward than strictly necessary. I would recommend dynamic ranges
The next extension exercise might be to develop your formula to allow for e.g. a missing middlename e.g.
=A4&" "&IF(B4<>"",B4&" ","")&C4
The above assumes you can sort the data manually. If the data is not being sorted manually, you will need to use VBA e.g. ensure Column D gets completed and the named range created each time a user moves off Sheet("Emp"). You can embed the following code in the Emp sheet...
Private Sub Worksheet_Deactivate
For n = 4 to 100
If Cells(n, 1) <> "" Then
Cells(n, 4) = Cells(n, 1) & " " & Cells(n, 2) & " " & Cells(n, 3)
End If
Next n
Range(Cells(4,4),Cells(100,4)).Sort Key1:=Cells(4,4), Order1:=xlAscending, Header:=xlNo
LastRow = 4
Do Until Cells(LastRow + 1, 4) = ""
LastRow = LastRow + 1
Loop
ActiveWorkbook.Names.Add Name:="Employee", RefersTo:=Range(Cells(4,4),Cells(LastRow,4))
End Sub
The expressions for sorting/adding range names can be found by recording macros and eliminating code as in this expert Excel support video. Your data validation would refer to 'Employee' which is the range name created in the 4th column
There are a number of assumptions made above such as the idea that all employees have data in the first column and you would need to add logical tests if you do not always have data in all three columns
It may also be that you would prefer to create the Employee range when a user clicks in cell C6 of your form, as this may be more robust. My assumption in using Worksheet_Deactivate is that 'Employee' may be used elsewhere in your spreadsheet
Something like this. Put this code in your worksheet where the comboBox is
Private Sub Worksheet_Change(ByVal Target As Range)
Dim topY As Integer, leftX As Integer
topY = ComboBox1.top
leftX = ComboBox1.left
Dim c As Range
Set c = Cells(5, 5)
c.Left = topY
c.Top = leftX
c.Width = ComboBox1.Width
c.Height = ComboBox1.Height
End Sub
It should keep it locked in place if you move things around. Or you could try it in your Private Sub Worksheet_SelectionChange(ByVal Target As Range) event.