i am trying to make a character creator tool for a game.
im almost done but i wanted to add a button the saves the character
code looking like this
Sub Save_character()
Dim ws As Worksheet
Worksheets("character creator").Copy _
After:=ActiveWorkbook.Sheets("character creator")
Set ws = ActiveSheet
ws.Name = Range("b14")
End Sub
but i dont want this button to be added to the copied sheet.
Any idea how i may do that?
thx in advence.
a VBA/excel rookie
There's a setting for this:
Application.CopyObjectsWithCells = False
'copy your sheet
Application.CopyObjectsWithCells = True 'reset
Same as:
Options >> Advanced >> Cut, Copy and Sort inserted objects with their parent cells (uncheck)
You can delete the button using
ws.Shapes("YourButtonName").Delete
Do what Scott recommended, or do what you are doing now, and delete the button object after you have copied the sheet. Something like this should do it for you . . .
ActiveSheet.Objects.Delete
Related
I have a spreadsheet completely locked down and control all sorting and filtering through VBA. I also have another script that hides the sheet on close and saves the file automatically to keep that sheet hidden.
I've been trying to figure out how I can use VBA to 'click' on one button (shape) which would clear anything that's been filtered and then 'click' on another button (shape) which would sort the spreadsheet alphabetically. The buttons (shapes) already work perfectly with user-interaction but I would also like these buttons (shapes) to automatically get triggered when the sheet is opened.
The first button is assigned to macro, SearchBox, associated with the following VBA -
Sub SearchBox()
Dim myButton As OptionButton
Dim SearchString As String
Dim ButtonName As String
Dim sht As Worksheet
Dim myField As Long
Dim DataRange As Range
Dim mySearch As Variant
Set sht = ActiveSheet
On Error Resume Next
sht.ShowAllData
On Error GoTo 0
Set DataRange = sht.ListObjects("DataTable").Range
mySearch = sht.Shapes("UserSearch").TextFrame.Characters.Text
If IsNumeric(mySearch) = True Then
SearchString = "=" & mySearch
Else
SearchString = "=*" & mySearch & "*"
End If
For Each myButton In sht.OptionButtons
If myButton.Value = 1 Then
ButtonName = myButton.Text
Exit For
End If
Next myButton
myField = Application.WorksheetFunction.Match(ButtonName, DataRange.Rows(1), 0)
DataRange.AutoFilter _
Field:=myField, _
Criteria1:=SearchString, _
Operator:=xlAnd
sht.Shapes("UserSearch").TextFrame.Characters.Text = ""
End Sub
The second one is much more simple which just sorts the data table by that specific column -
Sub Sort_Name()
Dim oneRange As Range
Dim aCell As Range
Set oneRange = Range("A4:H1162")
Set aCell = Range("A4")
oneRange.Sort Key1:=aCell, Order1:=xlAscending, Header:=xlYes
End Sub
Basically, I'm still learning and I feel it's possible to just trigger these buttons with a script but I've yet to figure it out. Any help would be appreciated.
In the code-behind for ThisWorkbook, you will be able to handle workbook events, including the Open event, which is fired by the workbook when it is opened.
Navigate to the module (double-click ThisWorkbook in the VBE's project explorer [Ctrl+R]), then locate the dropdowns at the top of the editor's code pane. From the left-hand dropdown, select Workbook; then, from the right-hand dropdown, select the Open event; the VBE automatically creates a method stub with the correct signature for you:
Private Sub Workbook_Open()
End Sub
Notice that the underscore has a very special meaning in VBA; when naming your procedures (especially implicitly or explicitly Public ones), consistently stick to PascalCase and avoid Snake_Case; this may not matter now, but as you progress as a developer you'll come to appreciate consistency in naming, and when you start working with interfaces, that underscore-in-public-members thing will start making the difference between code that works and code that doesn't even compile: taking the good habits early will save you headaches later.
Now, you need to invoke two procedures in that handler.
When you do this:
oneRange.Sort Key1:=aCell, Order1:=xlAscending, Header:=xlYes
You're invoking the Sort method of the oneRange object, which is an instance of the Range class.
When you do this:
MsgBox "Hi!"
You're invoking the MsgBox function that's in the VBA library, under the Interaction module (find it in the object browser [F2]). This would be equivalent:
VBA.Interaction.MsgBox "Hi!"
So, to invoke your SearchBox and then your SortName method, all you need to do is this:
Private Sub Workbook_Open()
SearchBox
SortName 'formerly known as Sort_Name
End Sub
Procedures do something - their names should always start with a verb, they're actions. "SearchBox" looks like a name, not an action. In programming, names are more like classes - a Range, a Workbook, etc.; consider renaming SearchBox to better convey what it does. If that's hard to do, it's likely because your procedure does too many things - like getting the name to use for filtering, and then applying a filter to a specific table, and then clearing the text of some shape.
You'll also want to watch out for implicit ActiveSheet references; currently SortName is assuming what the ActiveSheet is, and this is very likely to cause issues down the line.
So the best way to explain how I did what I was wanting to do is to look at what the button itself is calling to by right clicking it and clicking assign macro again. You'll see it look like this -
'YourSpreadSheetName.xlsm'!Sheet2.SearchBox
For me, what was throwing me off is I wasn't including the Sheet2 which is where the code is I'm trying to call.
By placing this code within the ThisWorkbook section with the Workbook_Open script, I was able to get it working the way I wanted it to -
Call Sheet2.SearchBox
Thanks again for the help all who commented.
Is there a way in VBA to disable the alert that pops up when MANUALLY deleting a sheet (right click sheet and delete)? I have seen Application.DisplayAlerts = False, however this seems to only work for me when deleting a sheet using VBA (Sheets("Sheet1").delete). I am trying to disable the alert for the whole workbook when you manually right click on a sheet and click delete. Thanks.
In case anyone else is looking for the same scenario:
...eliminate the need to confirm deleting a sheet when presenting the
workbook in meetings. While going through the sheets I often double
click on pivot tables to view detail, and I would like to eliminate
the pop-up alert when I delete the generated sheet...
If new sheets are generated only when double-clicking a pivot table, this might be a suitable solution
Placed in ThisWorkbook, the code bellow will delete any new sheets, when selecting a different sheet
Option Explicit
'Place this code in ThisWorkbook module
'Expects that all new sheets are generated by double-clicking a pivot table
Private pivotWs As Worksheet
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Set pivotWs = Sh
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
If Not pivotWs Is Nothing Then
If Sh.Name = pivotWs.Name Then
Application.DisplayAlerts = False
pivotWs.Delete
Set pivotWs = Nothing
Application.DisplayAlerts = True
End If
End If
End Sub
I am currently trying to create a sub (Excel VBA) that generates a form that displays a line chart for months and letters I want to freely select in a 2 entries table.
I want my sub to start when I click on a button that I already created (called Display Chart or Button1_Click).
Here is the code I came out with :
Sub Button1_Click()
GenerateChart.Show
End Sub
Sub GenerateChart()
On Error Resume Next
Dim MyChart As Chart
Dim DataRange As Range
If ActiveSheet.Name = "Sheet3" And Selection.Cells.Count > 0 Then
Set DataRange = Selection
Set MyChart = ActiveSheet.Shapes.AddChart.Chart
MyChart.SetSourceData Source:=DataRange
MyChart.ChartType = xlBarStacked
End If
End Sub
For some reason, this does not seem to work. I think I did something wrong regarding the button click part. Indeed, I do not understand how this event is called (Display Chart or Button1_Click) and how to code it. Therefore I cannot check if my other lines of codes are correct.
I hope someone will be able to help me out, thanks a lot !
Assign a Macro GenerateChart with the button and Select the data for which you need to create a Chart and click the button, I think you are not selected the data while you clicking the button here you used
Set DataRange = Selection
I am trying to show the filter columns to users in the report. Excel gives a different icon but for large no. columns it will be good to color the columns in another color like blue.
I found code at Is there a way to see which filters are active in Excel, other than just the funnel icons?
It works for me, but how do start this code without any button
SheetChange and selection change do not work.
code
Sub test()
Call markFilter(ActiveSheet)
End Sub
Sub markFilter(wks As Worksheet)
Dim lFilCol As Long
With wks
If .AutoFilterMode Then
For lFilCol = 1 To .AutoFilter.Filters.Count
'/ If filter is applied then mark the header as bold and font color as red
If .AutoFilter.Filters(lFilCol).On Then
.AutoFilter.Range.Columns(lFilCol).Cells(1, 1).Font.Color = vbRed
.AutoFilter.Range.Columns(lFilCol).Cells(1, 1).Font.Bold = True
Else
'/ No Filter. Column header font normal and black.
.AutoFilter.Range.Columns(lFilCol).Cells(1, 1).Font.Color = vbBlack
.AutoFilter.Range.Columns(lFilCol).Cells(1, 1).Font.Bold = False
End If
Next
Else
'/ No Filter at all. Column header font normal and black.
.UsedRange.Rows(1).Font.Color = vbBlack
.UsedRange.Rows(1).Font.Bold = False
End If
End With
End Sub
I will use the same example I used in the answer that you mentioned in your post. I answered that. :)
There is no filter change event in excel. One work-around that I would use is trapping the calculate method of the worksheet or better the workbook.
So, in the worksheet with filter add a dummy formula like this: =SUBTOTAL(3,Sheet2!$A$1:$A$100) this counts only visible cells. But its up to you. Feel free to use any formula that responds to filter change.
After that, go to workbook's code and add this :
Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
Call markFilter(Sh)
MsgBox "Filter changed"
End Sub
Boom. Now you are trapping the filter change events and it will update the filtered columns by firing the vba code.
Note markFilter is coming from the answer that you mentioned.
The key points from my article Trapping a change to a filtered list with VBA
A "dummy" WorkSheet is added with a single SUBTOTAL formula in A1 pointing back to the range being filtered on the main sheet.
A Worksheet_Calculate() Event is added to the "dummy" WorkSheet, this Event fires when the SUBTOTAL formula updates when the filter is changed.
The next two steps are only needed if it is desired to run the Workbook Calculation as Manual
Add a Workbook_Open Event to set the EnableCalculation property of all sheets other than "Dummy" to False.
Run the Workbook in Calculation mode
I have created an excel macro which allows a user to insert a new client and based off the clients name a worksheet is created. How I have this created is by using the following code: Sheets("Template").Copy After:=Sheets("Template")
Sheets("Template (2)").Visible = True
Sheets("Template (2)").Name = ClientAbbrev
So what this does is create a copy of the template sheet which is hidden and creates a new tab which is named after the client abbreviation. This new 'entry' is generally inserted between two 'book-ends' - Template and Template End. So the newly inserted tab would go here:
Template, NEW TAB HERE, Template End.
Now that I've hidden both Template and Template End, when I Insert New Clients instead of having it appear like above, it appears like this:
Template, Template End, NEW TAB HERE.
This is a problem as I have a summing array which takes all the data between the Start and End Tabs and now it doesn't seem to work unless the Book-End Tab isn't hidden. Can anyone shed some light on this or tell me how to write a macro to insert tabs specifically between those two tabs?
Thanks!
Try this:
Option Explicit
Public Sub addNewSheet()
Dim t As Worksheet, ws As Worksheet
Set t = ThisWorkbook.Worksheets("Template")
t.Copy After:=t
Set ws = ThisWorkbook.Worksheets(t.Index + 1)
With ws
.Visible = True
.Name = "New client"
End With
End Sub