My subs change automatically into private subs when opening a workbook. So then they don't work anymore.
What is the solution or the cause?
Thisworkbook is used for workbook triggers like workbook open etc.
You need to place the sub in a normal module without the private keyword
Goto the module folder visible in your image to insert a new module
Related
I am using the following code to highlight spelling mistakes in the cell-on-cell change
Sub ColorMispelledCells()
For Each cl In ActiveSheet.UsedRange
If Not Application.CheckSpelling(Word:=cl.Text) Then _
cl.Interior.ColorIndex = 15
Next cl
End Sub
Now, the problem is that every time I have to run this code by pressing f5 and also this only works on a particular workbook (Workbook specific).
So, my question is, what is the process to make a universal/global macro that runs on every workbook and every sheet which is opened, and that too runs internally when the cell is changed? It should not open up with the VBA editor window again and again.
Along with this is there any way where I can make a enable and disable button highlighted on the excel toolbar for this macro?
see image to see my VBA editor project explorer hierarchy
I tried searching on the internet and also saw many sample codes but nob body explained to make a global/universal macro, I am unable to figure out how to develop a global/universal macro that runs automatically on cell changes. which is not bounded to any one workbook but works globally on any opened workbook on all sheets.
I'm interested in your case. I myself is not an expert, so just now I search the internet and playing around and try to "cheat" by making this kind of code - which I'm not so sure if that meets your requirement.
In PERSONAL.XLSB workbook - ThisWorkbook module :
Private WithEvents app As Application
Private Sub app_WorkbookOpen(ByVal Wb As Workbook)
On Error Resume Next
If Wb.Name <> "PERSONAL.XLSB" Then
Set src = Workbooks("PERSONAL.XLSB").VBProject.VBComponents("Sheet1").CodeModule
Set trg = Wb.VBProject.VBComponents("ThisWorkbook").CodeModule
trg.insertlines 1, src.Lines(1, src.countoflines)
End If
End Sub
Private Sub Workbook_Open()
Set app = Application
End Sub
In PERSONAL.XLSB workbook - Sheet1 module :
Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range)
If Not Application.CheckSpelling(Word:=Target.Text) Then _
Target.Interior.ColorIndex = 15 Else Target.Interior.ColorIndex = xlNone
End Sub
Source code from this link and this link
The sub in "ThisWorkbook" module of PERSONAL.XLSB will be triggered when opening any workbook. The sub will copy the macro in "Sheet1" module of PERSONAL.XLSB into "ThisWorkbook" module of the open workbook.
The sub in "Sheet1" module of PERSONAL.XLSB is an event handler to any sheet of the active workbook which will be triggered if there is a change on any cell of any sheet.
I noticed that if I edit the sub in the PERSONAL.XLSB to something else, then I open another workbook, the sub will not run. I need to close the Excel application first, then open it again. If I don't do any sub-editing, opening other workbook will trigger the sub to run.
The animation above is opening two xlsx workbook which for sure there can't be any code in that workbook. But because at the time it's opened the macro in PERSONAL.xlsb is triggered (copying a sub to "ThisWorkbook" module of that xlsx workbook), so then there is a sub in that xlsx workbook. If I close this xlsx workbook, it will prompt me if I want to save the workbook. If I click yes, it will complain because it can't be saved as xlsx while there is a macro in "ThisWorkbook" module of this workbook.
Still not sure though if this is the kind that you want. Also maybe what you want is something like this : in whatever computer which has Excel app, it can do the same thing without doing anything before hand. So it's not doable, because to any computer which has Excel app, the macro need to be copied to PERSONAL.XLSB on each computer before hand.
Please note, I don't test to open an xlsm workbook which already has Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range) in it's "ThisWorkbook" module. And I think most likely it will throw an error if the opened workbook has already Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range) in it's "ThisWorkbook" module
I'm creating an excel module to export any table inside a workbook as .csv
My module generate a UserForm where the user can chose which table to export inside a combobox and then click 'export'
Everything is working perfectly, but I have to create a button in my workbook and call my module on click.
However I want to keep it very simple to setup inside any workbook by just import the module and run it with a keyboard shortcut '''Ctrl+R''' for example.
I search a lot about that but I never find something, Is it something possible?
Yes you can what you want to. First import your module to your new excel workbook and then assign keyboard shortcut to Workbook_Open event by copying code to ThisWorkbook area.
Sub MyMacro()
MsgBox ("ok")
End Sub
In ThisWorkbook area (which is in Microsoft Excel Objects / Project Window)
Private Sub Workbook_Open()
Application.MacroOptions Macro:="MyMacro", Description:="", ShortcutKey:= _
"a"
End Sub
This code assign Ctrl+"Defined_Letter" shortcut to your MyMacro macro. In this case, the code's shortcut is [Ctrl+a].
I have a macro enabled workbook called import. When it opens a macro automatically runs; its main job is to import text files into each worksheet of a new workbook (this new workbook is called book1).
I have another macro that I required to run on book1 called runall.
Is it possible to configure Excel so that runall will then be activated when book1 is enabled?
Currently I have to go back into the original workbook called import and on the Developer tab activate runall.
What I have tried -
In the import workbook I have the following code:
Private Sub Workbook_Open()
Call CombineTextFiles
I have tried putting Call runall in the Private statement.
There are a lot of events you can tie your code to. One of them is Sheet Activate. In Book1 you can place the following code:
Private Sub Worksheet_Activate()
runall
End Sub
I am building a macro workbook in which ctl+D is deactivated.
Now, the issue is - When another workbook is opened when this macro workbook is still open, ctl+D is getting disabled in the other workbook as well, as this is an application level setting. I want to restrict disabling ctl+D only in the macro workbook.
For this, I can add a condition in the code which checks for the workbook name before disabling ctl+D. But, there is 90% chance that users would change the name of the workbook after saving to their desktop.
Is there a way I can use Workbook builtin properties instead of workbook name in code? Please advise.
Thank you!
https://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.workbook.builtindocumentproperties.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
Example (Pseudo code):
if ThisWorkbook.Title = 'TEST' Then
Application.OnKey "^d", ""
end if
Use workbook events to detect when the workbook is activated or not.
Private Sub Workbook_Activate()
Application.OnKey "^d", ""
End Sub
Private Sub Workbook_Deactivate()
Application.OnKey "^d"
End Sub
Put this in the ThisWorkbook module. You might also want to add the Ctrl+d deactivation line to a Workbook_Open event.
I have a workbook that is the main template for our group. Within this template I have several tabs that I would like to incorporate macros on for hiding and unhiding of rows based on values. I setup this macro on one tab, tested it out and it worked. However, when I went through the process of what the users will be doing the macro did not carry forward to the new workbook. I do not want to waste time doing the macro on the other sheets if I am unable to have the macro carry forward. Can someone please help as my template is due today?
In case more info is needed on the process of the template....The template opens up with a User form for the individual to enter in specific information and then during the process of the uploading of an information feed it creates a new workbook.
Write your template macro in a code module, then save and right-click the .bas module in the solution explorer, and export the module to a location you'll programmatically load it from later.
Then in another module, write the procedure that creates the workbook. Before saving the new workbook, load the exported module file into the workbook's VBProject.VBComponents collection, like this:
Dim targetWorkbook As Workbook
'...set up target workbook
targetWorkbook.VBProject.VBComponents.Import "module1.bas"
targetWorkbook.SaveAs "workbook.xls"
EDIT
If your macro code needs to listen to Excel's events (and/or worksheet events), you'll need to also add a class module where you're going to do exactly that. A code module will need to instantiate it for the class module's code to run.
Create a new class module and call it something like "clsExcelApp":
Private WithEvents xlApp As Excel.Application
Option Explicit
Private Sub Class_Initialize()
Set xlApp = Application
End Sub
Private Sub Class_Terminate()
Set xlApp = Nothing
End Sub
Then you can write event handlers for xlApp, such as:
Private Sub xlApp_SheetActivate(ByVal Sh As Object)
'do something whenever a worksheet gets activated.
End Sub
Private Sub xlApp_WorkbookBeforeSave(ByVal Wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)
'do something before a workbook gets saved.
End Sub
The code module would only need to instantiate it, like this:
private App As New clsExcelApp
Option Explicit
The rest of the module could be macros and/or functions:
Public Sub Macro1()
'do something
End Sub
Public Function Smurf(Range As Excel.Range) As Long
'Smurf the Range and then smurf a Long
End Function
Then save your hard work and export all modules and import them programmatically into the workbook you want to "inject" the functionality into.
Note You should always restrict access to VBProject, but to execute the Excel.Workbook.VBProject.VBComponents.Import(String)
method you'll need it enabled. Just remember to turn the security back
on when you're done - better safe than sorry!