Remove part of the VBA code before saving - vba

I use two macros in my workbook as there are some data manipulation required in between macros.
I can run Macro 1 and save the file as a *.xlsm and after data manipulation, need to run Macro 2.
I want to know the possibility of Remove Macro 1 before saving?

Probably easiest way is to store the macro in a separate module, and this code removes the entire module:
Sub DeleteModule()
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Set VBProj = ActiveWorkbook.VBProject
Set VBComp = VBProj.VBComponents("Module1")
VBProj.VBComponents.Remove VBComp
End Sub
This code is from www.cpearson.com/excel/vbe.aspx , where you can find other useful information too.

Related

Remove/ List all Keyboard Shortcuts VBA excel

Someone in our office has assigned a macro to Ctrl+D. This is frustrating, as it already has a function in Excel.
Excel makes it easy for you to assign a macro in Developer> Macros, and I'm aware that if I push options in this menu I can see which keys are assigned where. The list of macros in this workbook is sizable, and I don't want to open each separately.
Is this listed anywhere? I assume there's a log with this somewhere? This is the closest I can find on msdn, but I need macros assigned in a macroworkbook: https://msdn.microsoft.com/en-us/library/hh179479(v=nav.90).aspx
Thanks to #GSerg for pointing this out, I will post this here for completeness to close the question. Source is here:
https://groups.google.com/forum/#!topic/microsoft.public.excel.worksheet.functions/TwcT-IlWjVk
To use this Macro (Sub), <alt-F8> opens the macro dialog box. Select the macro by name, and <RUN>.
===================================================
Option Explicit
'MUST set to Trust Access to the VBA Project Object Model
' in Excel Options
'Set reference to:
'Microsoft Visual Basic for Applications Extensibility
'Microsoft Scripting Runtime
'Microsoft VBScript Regular Expressions 5.5
Sub ListMacroShortCutKeys()
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Dim CodeMod As CodeModule
Dim LineNum As Long
Dim ProcKind As VBIDE.vbext_ProcKind
Dim sProcName As String, sShortCutKey As String
Const FN As String = "C:\Temp\Temp.txt"
Dim S As String
Dim FSO As FileSystemObject
Dim TS As TextStream
Dim RE As RegExp, MC As MatchCollection, M As Match
Set RE = New RegExp
With RE
.Global = True
.IgnoreCase = True
.Pattern = "Attribute\s+(\w+)\.VB_ProcData\.VB_Invoke_Func = ""(\S+)(?=\\)"
End With
Set FSO = New FileSystemObject
Set VBProj = ActiveWorkbook.VBProject
For Each VBComp In VBProj.VBComponents
Select Case VBComp.Type
Case Is = vbext_ct_StdModule
VBComp.Export FN
Set TS = FSO.OpenTextFile(FN, ForReading, Format:=TristateFalse)
S = TS.ReadAll
TS.Close
FSO.DeleteFile (FN)
If RE.Test(S) = True Then
Set MC = RE.Execute(S)
For Each M In MC
Debug.Print VBComp.name, M.SubMatches(0), M.SubMatches(1)
Next M
End If
End Select
Next VBComp
End Sub
==============================
Press ALT+F11 goto your project module. You can find here shortcuts vba macro coding. if you want to keep it then no need to do otherwise you can select all and delete and save and close the file.

VBA procedure cannot save file including dynamically created procedure

I am creating a series of files automatically, although these files are yet only drafts I have to show them to relevant managers. So I want to be sure that they understand files they get are only first drafts.
I tried to include code into "Open, Workbook" event for each new created file using code from http://www.cpearson.com/Excel/VBE.aspx to show messagebox with some warning for the managers:
Sub CreateEventProcedure(wb, code)
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Dim CodeMod As VBIDE.CodeModule
Dim LineNum As Long
Const DQUOTE = """" ' one " character
Set VBProj = wb.VBProject
Set VBComp = VBProj.VBComponents("ThisWorkbook")
Set CodeMod = VBComp.CodeModule
With CodeMod
LineNum = .CreateEventProc("Open", "Workbook")
LineNum = LineNum + 1
.InsertLines LineNum, " MsgBox " & DQUOTE & code & DQUOTE
End With
End Sub
When I am running the script I see, while the screen is updating or during debugging, that it creates the code correctly without an error...However when i open any of the newly created files the code is not there (i.e. the messagebox is not shown when the file is opened). Just fyi, I save files as .xlsm (macro-enabled)
wb.SaveAs Filename:=file_path, FileFormat:=xlOpenXMLWorkbookMacroEnabled
My tip is that somehow the files are saved without a VBA part...
Can you please help me?
So your file doesnt contain any vba code at all? I think you are overcomplicating it or im just missing the intention but I always just use something like:
Private Sub Workbook_Open()
MsgBox "oi managers this is a draft"
End Sub

Copy VBA code from one Worksheet to another using VBA code

Ok here is what I want to accomplish: I am trying to copy all the VBA code from "Sheet2" to "Sheet 3" code pane. I'm NOT referring to copying a Module from one to another but the excel sheet object code.
I already added a Reference to MS VB for Applications Extensibility 5.3
I'm not sure where to start but this is what I have started with and its not going anywhere and probably all wrong. Please Help - Simply want to programmatically copy sheet vba code to another sheet vba pane.
Dim CodeCopy As VBIDE.CodePane
Set CodeCopy = ActiveWorkbook.VBProject.VBComponents("Sheet2").VBE
ActiveWorkbook.VBProject.VBComponenets("Sheet3").CodeModule = CodeCopy
Use the CodeModule object instead of the CodePane, then you can create a second variable to represent the destination module (where you will "paste" the code).
Sub test()
Dim CodeCopy As VBIDE.CodeModule
Dim CodePaste As VBIDE.CodeModule
Dim numLines As Integer
Set CodeCopy = ActiveWorkbook.VBProject.VBComponents("Sheet2").CodeModule
Set CodePaste = ActiveWorkbook.VBProject.VBComponents("Sheet3").CodeModule
numLines = CodeCopy.CountOfLines
'Use this line to erase all code that might already be in sheet3:
'If CodePaste.CountOfLines > 1 Then CodePaste.DeleteLines 1, CodePaste.CountOfLines
CodePaste.AddFromString CodeCopy.Lines(1, numLines)
End Sub
In addition to adding a reference to "Reference to MS VB for Applications Extensibility 5.3"
You'll also need to enable programmatic access to the VBA Project.
In Excel 2007+, click the Developer item on the main Ribbon and then
click the Macro Security item in the Code panel. In that dialog,
choose Macro Settings and check the Trust access to the VBA project
object model.
Thank you all! After testing multiple suggestions above, where "b" is the Worksheet name, you must use .CodeName, NOT .Name
Set CodePaste = ActiveWorkbook.VBProject.VBComponents(WorkShe‌ets(b).CodeName).Cod‌​eModule
If you have set your target worksheet as an object:
Dim T As Worksheet
Set T = Worksheets("Test")
Then you simply need:
Set CodePaste = ActiveWorkbook.VBProject.VBComponents(Worksheets(T.Name).CodeName).Cod‌​eModule

Import lines of code

Can we read scripts or lines of code to a module in vba? Like we have the include function in php.
For example:
We store this in Excel somewhere and call the range as xyz
line 1 of code
line 2 of code
line 3 of code
Then while running a macro we call this like
Sub my_macro()
xyz
End Sub
Basically I want to run a few lines of code repetitively but don't want to create another macro and pass the parameters.
This can be done using the Microsoft Visual Basic for Applications Extensibility 5.3 (VBIDE) library. There's some great examples at CPearson.com. I typically use this to insert snippets of code while I'm developing. I would personally be uncomfortable executing code stored in an excel sheet, but I tested this and it does work.
My worksheet:
A
1 MsgBox "I'm a test."
2 MsgBox "So am I."
I set up an empty subroutine that we will then insert into from the excel sheet.
Private Sub ProcToModify()
End Sub
And the subroutine that will actually insert the code into ProcToModify:
Sub ModifyProcedure()
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Dim CodeMod As VBIDE.CodeModule
Dim StartLine As Long
Dim NumLines As Long
Dim ProcName As String
Set VBProj = ActiveWorkbook.VBProject
Set VBComp = VBProj.VBComponents("Module1") ' specify module to modify
Set CodeMod = VBComp.CodeModule
Dim ws As Worksheet
Dim rng As Range
Dim cell As Range
Set ws = ThisWorkbook.ActiveSheet 'change this accordingly
Set rng = ws.Range("A1:A2") 'and this
For Each cell In rng
ProcName = "ProcToModify"
With CodeMod
StartLine = .ProcStartLine(ProcName, vbext_pk_Proc)
NumLines = .ProcCountLines(ProcName, vbext_pk_Proc)
.InsertLines StartLine + NumLines - 2, cell.Value 'insert each line at the end of the procedure to get them in the correct order.
End With
Next cell
End Sub
Called at runtime like this:
Public Sub main()
ModifyProcedure
ProcToModify
End Sub
One Big Gotchya:
Before running this code, you need to go to Excel>>File>>Options>>Trust Center>>Trust Center Settings>>Macro Settings and check the "Trust access to the VBA project object model".
I would imagine that's because allowing access to the project object is a fairly concerning security risk.
From the cpearson.com site I linked to earlier:
CAUTION: Many VBA-based computer viruses propagate themselves by
creating and/or modifying VBA code. Therefore, many virus scanners may
automatically and without warning or confirmation delete modules that
reference the VBProject object, causing a permanent and irretrievable
loss of code. Consult the documentation for your anti-virus software
for details.

Worksheet.CodeName empty

I am trying to reference newly added Worksheet by it's CodeName property. The problem is that CodeName returns empty string unless run from debugger.
Set tableSheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
MsgBox tableSheet.CodeName
Even this simple example doesn't work unless I put a break point on MsgBox line.
What is the problem with this?
I was able to duplicate your issue. Some googling revealed this answer:
Sub test()
Dim tablesheet As Excel.Worksheet
Set tablesheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
MsgBox ThisWorkbook.VBProject.VBComponents(tablesheet.Name).Properties("Codename")
End Sub
I think you have to check Microsoft Visual Basic for Applications Extensibility 5.3 in Tools>References.
I also needed to read codename for new sheet. This solution worked for me:
Go to Trust Center, under Macro settings check "Trust access to VBA project model".
Now just put this three lines before the line where you need code name. It won't work without this. It is a VBA quirk.
On Error Resume Next
Debug.Print ActiveWorkbook.VBProject.VBComponents(Worksheets(ActiveSheet.Name).CodeName).Properties("Codename")
On Error GoTo 0
Now use your code name like this:
strActiveSheetCodeName = ActiveWorkbook.VBProject.VBComponents(Worksheets(ActiveSheet.Name).CodeName).Properties("Codename")
I can confirm this behavior. I have never used CodeName before, I use sometimes Name to reference a sheet.
Sub Test()
Dim tableSheet As New Worksheet
Set tableSheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
MsgBox tableSheet.Name
End Sub
This gives the name of the sheet in the MsgBox and it is not only readable, you can change the name of the sheet if you want.
I have a similar problem for a new sheet that created by macro (it would have a blank codename unless you open the Macro Editor).
For my case, since I need the code name to insert some macro to the new sheet. So I use the following code, and it works. It seems the codeName would have value, due to my code access Name attribute of 'VBComponents.item', which is codeName attribute for sheet.
Note: I am not sure why, below code would open the VBA Editor automatically.
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Set VBProj = ActiveWorkbook.VBProject
Dim i
For i = 1 To VBProj.VBComponents.Count
If VBProj.VBComponents.Item(i).Name = ActiveSheet.CodeName Then
Set VBComp = VBProj.VBComponents.Item(i)
End If
Next