I would have a question regarding VisualBasics for Application (VBA) in Excel.
I need to include two buttons on my worksheet(add and delete).
When pressing the add button a new block of values should be added below one existing block, separated by a blank row.
When pressing the delete button the a block should become deleted.
-> see pictures
My current state is the following one.
Copy and paste works, but only for one single line not for multiple lines
Sub AddLibs()
Dim r As ListObject
Dim c As Integer
ActiveSheet.Unprotect "test"
ActiveSheet.ListObjects("data").ListRows(ActiveCell.Row).Range.Select
Set r = ActiveSheet.ListObjects("data")
c = r.Range.Rows.Count
ActiveSheet.ListObjects("data").Resize Range("A1:B" & c)
Selection.Copy
Selection.Insert Shift:=xlToDown, CopyOrigin:=xlFormatFromRightorAbove
Application.CutCopyMode = False
ActiveSheet.Protect "test", True, True
End Sub
I found an appropriate solution.
Implementation looks like this
Adding a block
Sub AddLibs()
If Cells(Selection.Row, 1).Value = "name" Then
ActiveSheet.Unprotect "test"
For counter = 0 To 3
ActiveCell.Offset(counter + 4, 0).EntireRow.Insert
ActiveCell.Offset(counter + 4, -1).Value = ActiveCell.Offset(counter, -1)
Next counter
ActiveSheet.Protect "test", True, True
Else
MsgBox "Please klick into a library Cell to add a new one!", , "Not possible action"
End If
End Sub
deleting a block
Sub DeleteLibs()
If Cells(Selection.Row, 1).Value = "name" Then
ActiveSheet.Unprotect "test"
For counter = 3 To 0 Step -1
ActiveCell.Offset(counter, 0).EntireRow.Delete
Next counter
ActiveSheet.Protect "test", True, True
Else
MsgBox "Please klick into the library Cell and push button again to delete!", , "Not possible action"
End If
End Sub
Why are you copy-pasting?
I have just put three values in A1, A2 and A3, and I have run this piece of code:
Range("B1:B3").Value = Range("A1:A3").Value
The values from A1:A3 have been copied to B1:B3. As you see, there's a very easy way to copy ranges without using the clipboard (.Copy, .Paste).
Related
Using VBA in excel, trying to understand how I can use a checkbox to hide/unhide any row that has a specific value in a specific column. My VBA skills are getting better more I practice but I am still not good with loops just yet. Appreciate any help you can provide. Here is what I have so far.
Private Sub CkBx_ShowAllRecords_Click()
If Me.CkBx_ShowAllRecords = True Then
For Each Row In Range("Table1").ListObject.ListColumns
If Row.Cells(1, "column5").Value = "Submission Complete" Then
Application.EntireRow.Visible=True
Next
End if
End Sub
Additionally when I uncheck the box I would want all rows where column 5 cell value equals "submission complete" would be hidden (just the opposite of what I put above when I check the box control).
Hope this may help you:
Private Sub CkBx_ShowAllRecords_Click()
Dim i As Long
If Me.CkBx_ShowAllRecords = True Then
For i = 1 To ActiveSheet.ListObjects("Table1").Range.Rows.Count
If ActiveSheet.ListObjects("Table1").DataBodyRange(i, 5).Value = "Submission Complete" Then
Rows((i + 1) & ":" & (i + 1)).Select
Selection.EntireRow.Hidden = True
End If
Next i
Else
ActiveSheet.Rows.EntireRow.Hidden = False
End If
Me.Hide
End Sub
I will admit to being a terrible at code, and have always struggled with Macros... forgive my ignorance.
What I am working on building is a part number index that will create a new sequential number within a numerical series after a macro-button is pressed.
I'd like each button to scan between a range [i.e. 11-0000 (MIN) and 11-9999 (MAX)] and select the max value cell that exists. At that selection point insert an entire new row below with the next + 1 sequential number in the "B" column.
I have my button creating the table row as I would like, however I need help in defining the ".select(=Max(B:B))" and as I understand Max will also limit the # of line items it queries?
I have also been playing with .Range("B" & Rows.CountLarge) with little to no success.
Ideally the 11-**** button [as seen in the screen cap] should insert a sequential number below the highlighted row.
Maybe I'm way over my head, but any guidance even in approach or fundamental structure of the code would help be greatly appreciated!
Private Sub CommandButton1_Click()
Sheets("ENGINEERING-PART NUMBERS").Range("B" & Rows.CountLarge).End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveCell.EntireRow.Insert Shift:=xlDown
ActiveCell.Value = "=ActiveCell + 1"
End Sub
Screen Cap of Spread Sheet
Perhaps there is a simpler solution that I've overlooked, but the below will work.
Insert a module into your workbook and add this code:
Public Sub AddNextPartNumber(ByVal FirstCellInColumn As Range, Optional ByVal PartMask As Variant = "")
Dim Temp As Variant, x As Long, MaxValueFound(1 To 2) As Variant
'Some error checking
If PartMask = "" Then
MsgBox "No part mask supplied", vbCritical
Exit Sub
ElseIf Not PartMask Like "*[#]" Then
MsgBox "Invalid part mask supplied; must end in ""#"".", vbCritical
Exit Sub
ElseIf PartMask Like "*[#]*[!#]*[#]" Then
MsgBox "Invalid part mask supplied; ""#"" must be continuous only.", vbCritical
Exit Sub
End If
'Get the column of data into an array
With FirstCellInColumn.Parent
Temp = .Range(FirstCellInColumn, .Cells(.Rows.Count, FirstCellInColumn.Column).End(xlUp))
End With
'Search through the array and find the largest matching value
For x = 1 To UBound(Temp, 1)
If Temp(x, 1) Like PartMask Then
If MaxValueFound(1) < Temp(x, 1) Then
MaxValueFound(1) = Temp(x, 1)
MaxValueFound(2) = x
End If
End If
Next x
'Output new part number
If MaxValueFound(2) = 0 Then
'This part mask doesn't exist, enter one with 0's at the end of the list
With FirstCellInColumn.Offset(x - 1, 0)
.Value = Replace(PartMask, "#", 0)
.Select
End With
Else
'Get the length of the number to output
Dim NumberMask As String, NumFormatLength As Long
NumFormatLength = Len(PartMask) - Len(Replace(PartMask, "#", ""))
NumberMask = String(NumFormatLength, "#")
'Determine the new part number
MaxValueFound(1) = Replace(MaxValueFound(1), Replace(PartMask, NumberMask, ""), "")
MaxValueFound(1) = Replace(PartMask, NumberMask, "") & Format((MaxValueFound(1) * 1) + 1, String(NumFormatLength, "0"))
'Insert row, add new part number and select new cell
FirstCellInColumn.Offset(MaxValueFound(2), 0).EntireRow.Insert
With FirstCellInColumn.Offset(MaxValueFound(2), 0)
.Value = MaxValueFound(1)
.Select
End With
End If
End Sub
Then, for each button, you write the code like this:
Private Sub CommandButton1_Click()
'this is the code for the [ADD 11-****] button
AddNextPartNumber Me.Range("B16"), "11-####"
End Sub
Private Sub CommandButton2_Click()
'this is the code for the [ADD 22-****] button
AddNextPartNumber Me.Range("B16"), "22-####"
End Sub
This has been written assuming that inserting a new row onto your sheet won't affect other data and that adding new data to the bottom of the table without inserting a row also won't affect other data.
Assuming you're working with a table, by default it should auto-resize to include new data added to the last row.
Good luck learning the ropes. Hopefully my comments help you understand how what I wrote works.
I have 80 rows where the user can enter a predetermined value under column Ward. This unhides a button next to it. Upon clicking it, it empties the adjacent value and increments (+1) a particular cell in another sheet depending on the original value.
Currently, I have 80 ActiveX buttons next to the Ward cells that hides/unhides depending on the value of the Ward cells. I've noticed that adding more buttons slows down the spreadsheet because of the sheer volume of If Then statements I have.
If Range("F8").Value = 0 Then
Sheets("Admissions").EDAdmit1.Visible = False
Else
Sheets("Admissions").EDAdmit1.Visible = True
End If
If Range("L8").Value = 0 Then
Sheets("Admissions").ElecAdmit1.Visible = False
Else
Sheets("Admissions").ElecAdmit1.Visible = True
End If
If Range("F9").Value = 0 Then
Sheets("Admissions").EDAdmit2.Visible = False
Else
Sheets("Admissions").EDAdmit2.Visible = True
End If
If Range("L9").Value = 0 Then
Sheets("Admissions").ElecAdmit2.Visible = False
Else
Sheets("Admissions").ElecAdmit2.Visible = True
End If
.. and so on.
Not to mention the If Then statements I have for every button click.
Private Sub EDAdmit1_Click()
If Range("F8") = "ICU" Then
Worksheets("Overview").Range("AD11").Value = Worksheets("Overview").Range("AD11") + 1
ElseIf Range("F8") = "HDU" Then
Worksheets("Overview").Range("AF11").Value = Worksheets("Overview").Range("AF11") + 1
ElseIf Range("F8") = "DPU" Or Range("F8") = "Other" Then
Else
Col = WorksheetFunction.VLookup(Range("F8"), Range("U1:V27"), 2)
Worksheets("Overview").Range(Col).Value = Worksheets("Overview").Range(Col).Value + 1
End If
Range("F8").ClearContents
End Sub
Is there a more efficient way of doing this?
Admission List:
You could consider using "admit" hyperlinks in the cells next to the Ward selections: that way you only need one handler (Worksheet_FollowHyperlink in the worksheet module). Note you need to use Insert >> Hyperlink and not the HYPERLINK() formula-type links here (because formula-based links don't trigger the FollowHyperlink event).
You can ditch the hide/show code and instead use conditional formatting to change the link font color to hide the links when there's no Ward selected. If a user clicks on one of the hidden links then you can just do nothing.
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim rngSrc As Range, addr, ward
Set rngSrc = Target.Range '<< the cell with the link
ward = rngSrc.Offset(0, 1).Value '<< cell with Ward
'only do anything if a ward is selected
If Len(ward) > 0 Then
'find the cell to update
Select Case ward
Case "ICU"
addr = "AD11"
Case "HDU"
addr = "AF11"
Case "DPU", "Other"
addr = ""
Case Else
addr = Application.VLookup(ward, Me.Range("U1:V27"), 2, False)
End Select
'if we have a cell to update then
If Len(addr) > 0 Then
With Worksheets("Overview").Range(addr)
.Value = .Value + 1
End With
End If
rngSrc.Offset(0, 1).ClearContents
End If
rngSrc.Select '<< select the clicked-on link cell
' (in case the link points elsewhere)
End Sub
At the beginning of your code put this line:
Application.ScreenUpdating = False
this will disable all screen updates. Let your code do changes, and then enable screen updating, and all your changes will appear.
Application.ScreenUpdating = True
Disabling screen updating usually makes the execution of code faster.
I have an ActiveX Checkbox in Excel that when clicked will change a cell value to add 1.
I need to repeat this VBA code when I use the same Checkbox in a different Cell Value, which I need to repeat many times.
How do I reference the automatically generated checkbox name variable in the VBA code for each new cell value?
This is for a Excel spreadsheet that I use to update a database when new reports are turned in with "checked" information on it.
Private Sub CheckBox21_Click()
Range("L2").Activate
'Don't want to type CheckBoxXX each time, just find way to automatically reference?'
If CheckBox21.Value = True Then
ActiveCell.Value = ActiveCell.Value + 1
Else
If ActiveCell.Value > 0 Then
ActiveCell.Value = ActiveCell.Value - 1
Else
End If
End If
_____________________________________________________________________________
'Next line'
Private Sub CheckBox22_Click()
Range("L2").Activate
If CheckBox22.Value = True Then
ActiveCell.Value = ActiveCell.Value + 1
Else
If ActiveCell.Value > 0 Then
ActiveCell.Value = ActiveCell.Value - 1
Else
End If
End If
End Sub
I don't want to type CheckBoxXX each time, just to automatically reference?
The routine below allows the user to toggle where they have completed/not completed the required entry. The button text changes to Complete/Incomplete and the adjacent cell goes green/red using simple conditional formatting on the 0 or 1 value. Works fine for updating a single line.
The number of data entry rows will vary for each user (say 10 to 100) and I am trying to find a way of selecting and then changing all the buttons in the sheet to "Complete" and updating the adjacent cell to 0 or 1 in one go, should the user want to do that.
Each row is a data entry line and each cell in Column B has a button, and a 0/1 in adjacent cell in Column C.
Sub complete()
'Complete / Incomplete Buttton and Flag
Dim buttontext As String
buttontext = Application.Caller
ActiveSheet.Buttons(Application.Caller).TopLeftCell.Select
ActiveCell.Select
If ActiveSheet.Buttons(buttontext).Caption = "Mark as Incomplete" Then
ActiveSheet.Buttons(buttontext).Caption = "Mark as Complete"
ActiveCell.Offset(0, 1).Value = 1
Else
ActiveSheet.Buttons(buttontext).Caption = "Mark as Incomplete"
ActiveCell.Offset(0, 1).Value = 0
End If
End Sub
Following code works:
Sub MarkAllComplete()
Dim btn As Button
For Each btn In ActiveSheet.Buttons
btn.Caption = "Mark as Complete"
Cells(btn.TopLeftCell.Row, btn.TopLeftCell.Column + 1) = 0
Next
End Sub
Use this concept:
For Each btn In ActiveSheet.Buttons
Debug.Print btn.Name, btn.TopLeftCell.Column, btn.TopLeftCell.Row
Next