Inserting code into new worksheet with CodeModule requires VB editor to be open - vb.net

I'd like to be able to add code to a newly created worksheet. The following block of code does that, but will give me an error (pointing to the first line of the code below) if the Visual Basic editor is not open. And, if it is open in the background, it will activate the VB editor window after the macro finishes running.
With wb.VBProject.VBComponents(wb.Worksheets(newSheetName).CodeName).CodeModule
.InsertLines Line:=.CreateEventProc("FollowHyperlink", "Worksheet") + 1, _
String:=vbCrLf & _
"Call FindAllInSheet(Target.Range.Text, Range(Cells(2, 2),Cells(" & num_triple_combos + 1 & ", " & start_triples_col + 1 & ")))"
End With
Is there a way to avoid this behavior?

For now, what I've done that works is by surrounding my code with
Application.VBE.MainWindow.Visible = True
...
Application.VBE.MainWindow.Visible = False
The only issue now is that the macro will cycle through every single existing sheet before adding the code to the designated sheet. I'm not sure why.
Source for my lead: http://www.mrexcel.com/forum/excel-questions/31259-macro-call-visual-basic-editor.html

Related

Excel Macro VB Run-time error: Automation Error [duplicate]

I know I've seen references to this issue before, but I have tried several of the suggestions and I am still getting the error. I have a workbook that assembles data from another book and generates a report. I then want to make a new workbook, copy the report information into the new book, save the new book and close it, and then move on to the next report. It should do this around 10 times. In the part of my code where I am copying and pasting the sheets, I am getting an error
Error -2147417848 Automation error The object invoked has
disconnected from its clients
I have checked other postings about this error, and tried the suggested solutions without any results. the interesting thing is that sometimes it will make it through 5 cycles of code before breaking, sometimes only 2. The only consistency is that it always breaks in the same place
fromBook.Sheets("Report").Copy Before:=newBook.Sheets("Sheet1")
I have option Explicit at the top of the module, and I have checked to make sure that there are not any globals inside of the sub it is breaking in. That being said, It's entirely possible I have overlooked something. I also put a "timer" in at one point to make sure that the excel sheets were not walking over each other.
I could really use the help!
Here is my sub's code:
Sub CreateAndSave(ByRef Reg As Integer, ByVal j As Integer)
Dim fromBook As Workbook
Dim fromSheet As Worksheet
Dim newBook As Workbook
Dim fileExists As Boolean
Dim i As Integer
Dim Holder As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set fromBook = Application.Workbooks("Region_Audit_Report")
Set newBook = Workbooks.Add
With newBook
.SaveAs Filename:="G:\DataTeam\ExcelDev\Audit Report\Region Workbooks\Region" & Reg & " " & Month(Date) & "-" & Day(Date) & "-" & Year(Date) & ".xlsx" _
, FileFormat:=xlOpenXMLWorkbook
End With
Set newBook = Application.Workbooks("Region" & Reg & " " & Month(Date) & "-" & Day(Date) & "-" & Year(Date) & ".xlsx")
fromBook.Sheets("Report").Copy Before:=newBook.Sheets("Sheet1")
fromBook.Sheets("MonthData").Copy After:=newBook.Sheets("Report")
newBook.Sheets("MonthData").Range("A1") = "Month"
newBook.Sheets("MonthData").Range("B1") = "Store#"
newBook.Sheets("MonthData").Range("C1") = "District"
newBook.Sheets("MonthData").Range("D1") = "Region"
newBook.Sheets("MonthData").Range("E1") = "Due Date"
newBook.Sheets("MonthData").Range("F1") = "Comp Date"
newBook.Sheets("MonthData").Range("G1") = "# of Errors"
newBook.Sheets("MonthData").Range("H1") = "Late?"
newBook.Sheets("MonthData").Range("I1") = "Complete?"
newBook.Sheets("MonthData").Range("A1:I1").Interior.ColorIndex = 43
newBook.Save
newBook.Close
Application.DisplayAlerts = True
End Sub
I have had this problem on multiple projects converting Excel 2000 to 2010. Here is what I found which seems to be working. I made two changes, but not sure which caused the success:
1) I changed how I closed and saved the file (from close & save = true to save as the same file name and close the file:
...
Dim oFile As Object ' File being processed
...
[Where the error happens - where aArray(i) is just the name of an Excel.xlsb file]
Set oFile = GetObject(aArray(i))
...
'oFile.Close SaveChanges:=True - OLD CODE WHICH ERROR'D
'New Code
oFile.SaveAs Filename:=oFile.Name
oFile.Close SaveChanges:=False
2) I went back and looked for all of the .range in the code and made sure it was the full construct..
Application.Workbooks("workbook name").Worksheets("worksheet name").Range("G19").Value
or (not 100% sure if this is correct syntax, but this is the 'effort' i made)
ActiveSheet.Range("A1").Select
I have just met this problem today: I migrated my Excel project from Office 2007 to 2010. At a certain point, when my macro tried to Insert a new line (e.g. Range("5:5").Insert ), the same error message came. It happens only when previously another sheet has been edited (my macro switches to another sheet).
Thanks to Google, and your discussion, I found the following solution (based on the answer given by "red" at answered Jul 30 '13 at 0:27): after switching to the sheet a Cell has to be edited before inserting a new row. I have added the following code:
'=== Excel bugfix workaround - 2014.08.17
Range("B1").Activate
vCellValue = Range("B1").Value
Range("B1").ClearContents
Range("B1").Value = vCellValue
"B1" can be replaced by any cell on the sheet.
You must have used the object, released it ("disconnect"), and used it again. Release object only after you're finished with it, or when calling Form_Closing.
I had this same problem in a large Excel 2000 spreadsheet with hundreds of lines of code. My solution was to make the Worksheet active at the beginning of the Class. I.E. ThisWorkbook.Worksheets("WorkSheetName").Activate
This was finally discovered when I noticed that if "WorkSheetName" was active when starting the operation (the code) the error didn't occur. Drove me crazy for quite awhile.
Couple of things to try...
Comment out the second "Set NewBook" line of code...
You already have an object reference to the workbook.
Do your SaveAs after copying the sheets.
The error in the below line of code (as mentioned by the requestor-William) is due to the following reason:
fromBook.Sheets("Report").Copy Before:=newBook.Sheets("Sheet1")
The destination sheet you are trying to copy to is closed. (Here newbook.Sheets("Sheet1")).
Add the below statement just before copying to destination.
Application.Workbooks.Open ("YOUR SHEET NAME")
This will solve the problem!!

Is there a way to programatically add Form Controls?

I'm working on a spreadsheet with a Form Control that opens a Userform used for data entry purposes. The submit button of the form fills a row of cells and adds two buttons on the last two cells of the row. It will insert as many rows as the user does and each time the two new buttons are created with their own distinct name. However, these are ActiveX controls and they are giving me compatibility problems with other Windows/Office versions once colleagues open the file and try to use it on their laptop.
This is the code I'm using to add one of the command buttons on the spreadsheet (it is essentially the same for the other button, just different variables):
Dim i As Long, Hght As Long
Dim Name As String, NName As String
i = 0
Hght = 305.25
NName = "cmdAction" & i
For Each OLEObject In ActiveSheet.OLEObjects
If Left(OLEObject.Name, 9) = "cmdAction" Then
Name = Right(OLEObject.Name, Len(OLEObject.Name) - 9)
If Name >= i Then
i = Name + 1
End If
NName = "cmdAction" & i
Hght = Hght + 27
End If
Next
Dim UpdateEntry As OLEObject, N%
Set UpdateEntry = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _
, DisplayAsIcon:=False, Left:=Selection.Offset(0, 23).Left, Top:=Selection.Offset(0, 23).Top, Width:=72, Height _
:=24)
UpdateEntry.Name = NName
UpdateEntry.Object.Caption = "Edit Entry"
With ThisWorkbook.VBProject.VBComponents(ActiveSheet.CodeName).CodeModule
N = .CountOfLines
.InsertLines N + 1, "Private Sub " & NName & "_Click()"
.InsertLines N + 2, vbTab & "Code for button goes here"
.InsertLines N + 3, vbTab & "End Sub"
End With
I was wondering if it was possible to do the same thing, but that the buttons created are form control instead of ActiveX?
The error that is displayed is Run-time error 32809: Application-defined or object-defined error. After extensive research, I've found that it happens due to the sheet getting corrupted once a different version of Windows has altered it. The only way to fix it is to create a new sheet, copying all of the contents to the new sheet, deleting the corrupted sheet and renaming the new one to the name it had previously. This works, but it is not possible to copy the ActiveX Controls, because they will be renamed and the appropriate code will not be in them, however the Form Control on the spreadsheet used to open the UserForm will work just fine, which is why I think my only solution would be to change all ActiveX to Form Control.
Would appreciate some help.
Instead of using ActiveX buttons, use Shapes and set the Shape.OnAction property to call the macro that you would normally place behind the ActiveX button. In the macro you can use Application.Caller to get the name of the shape that was clicked, thus allowing you to know which button was clicked and to branch your code accordingly.

Excel 2010 - Error: Cannot run the macro SelectCell using .onAction

I have been looking all over the internet for a solution to this problem but for some reason I can never find anything directly related to using .onAction with selecting a specific cell.
I am using an answer to another question as a reference:
https://stackoverflow.com/a/18199035
In the section where it is looping through shapes, the script assigns an .onAction event to each shape. Whenever this is run in Excel 2010 I get the error:
Cannot run the macro "SelectCell "Sheet 1","$C$10"".
The macro may not be available in this workbook or all macros may be disabled.
I am new to VBA scripting for excel so I have no idea if it is the formatting, but I know it is related to this line.
.OnAction = "'SelectCell """ & ws.Name & """,""" & cll.Address & """'"
I created a sub-procedure for SelectCell to display the values being sent as a debug. Same error.
I tried having excel allow all macros and disable all macros but it had no effect on the error.
If anyone has any idea of where I am going wrong or any resources I can use to further educate myself, it would be greatly appreciated.
This (both subs in a regular module) works for me.
Sub SelectCell(sht As String, rng As String)
ThisWorkbook.Sheets(sht).Range(rng).Select
End Sub
Sub Assign()
ActiveSheet.Shapes(1).OnAction = "'SelectCell """ & _
Selection.Parent.Name & """, """ & _
Selection.Address() & """'"
End Sub
If SelectCell is in a sheet code module, then you need to include the sheet code name:
Sub Assign()
ActiveSheet.Shapes(1).OnAction = "'Sheet1.SelectCell """ & _
Selection.Parent.Name & """, """ & _
Selection.Address() & """'"
End Sub
If I'm reading this right, "SelectCell" is a macro name, and you're passing in "Sheet 1","$C$10" as parameters (as strings). Whenever you make a call on the right side of an assignment operator (equals sign) the parameters need to be passed in with parenthases. for example,
.OnAction = "SelectCell "Sheet 1","$C$10""
is wrong, and
.OnAction = "SelectCell ("Sheet 1","$C$10")"
is right.
Try that, but there's not much I can go off without much code. You could also try to use the fully qualified macro name, in case the Macro is in another module.

VB app to create multiple instances of Excel and run in background

I have a simple VB application which allows the user to select via a tick box a number of interfaces to generate.
I am looping through the ticked entries and for each, I am creating an instance of Excel and executing the appropriate Macro in the workbook.
I am looking to generate the Excel instance in the background for each ticked entry. Currently I have to wait for each Excel instance to run, before I can process the next.
Your help would be greatly appreciated.
Here's the Code Extract:
MsgBox("Starting")
parmExcelAppName = "..{Pathname}\Data Extract v1.4.xlsm"
xlapp = CreateObject("Excel.Application")
xlbook = xlapp.Workbooks.Open(parmExcelAppName)
xlapp.Application.Visible = True
xlapp.Visible = False
parmWorksheetName = "CURRENCY_RATE"
parmWorksheetOutputSaveName = "C:\Users\pete05\Downloads\Interfaces"
parmApplyFilter = "False"
parmRunMode = "REFRESH"
parmAddColumnHeadings = "True"
parmEmailRecipients = "someone#companyname.com"
xlapp.Application.Run("MOD00_RUNMODE.Run_BatchMode ", _
"" & parmWorksheetName & "", _
"" & parmWorksheetOutputSaveName & "", _
"" & parmApplyJDAFilter & "", _
"" & parmRunMode & "", _
"" & parmAddColumnHeadings & "", _
"" & parmEmailRecipients & "")
xlapp.Quit()
MsgBox("Finished")
Ideally the 'Starting' and 'Finished' messages would be displayed almost immediately and the Excel piece pushed into the background. I would then repeat for the next ticked entry.
I can only suggest at this stage that you try this. I don't know if it'll work. I suspect that even opening multiple files like this will open them in the same instance of Excel.
Create an excel file for each required input parameter
Add a startup macro to the excel file to call the macro above when the file opens
Open the excel file using a command line (i.e. excel.exe "c:\book1.xlsx") using the Shell command.
This is just a stab in the dark really. Everything I've read indicates that this either won't work or won't work very well. To make this reliable you need to get the code from MOD00_RUNMODE.Run_BatchMode. If it's just calling a web service for example or reading from a database then you shoud be able to reproduce it outside of Excel and run it in parallel if the feeding system allows it.

Selection.OnAction = "Workbookname!Macroname"

Say you have two Workbooks one called “MyWorkbook” and the other called “PatchMyWorkbook”. Both workbooks are open at the save time. The “PatchMyWorkbook” has a macro to add a button and assign an existing macro of “MyWorkbook” to “MyWorkbook” The existing macro in “MyWorkbook” is called “PrintPage”
Windows(“MyWorkbook”).Activate
Sheets("Sheet1").Activate
ActiveSheet.Buttons.Add(665.25, 43.5, 89.25, 45).Select
Selection.OnAction = "PrintPage"
This does not cause an error while the “PatchMyWorkbook” code executes but the newly added buttons macro will point to “’PatchMyWorkbook’!PrintPage” rather than just “PrintPage” of the “MyWorkbook”
Question: How can you set the “OnAction” for a macro button across workbooks so that the macro will point to the current workbook not the workbook from where the macro has been created?
In my opinion .OnAction property should be set in this way:
Selection.OnAction = myWbk.Name & "!PrintPage"
By the way, the idea from your comment (changed a bit below):
Selection.OnAction = "'" & myWbk.Name & "'" & "!" & "PrintPage"
is working for me as well (Excel 2010).
You need to include the name of the sheet or module where PrintPage is defined.
Dim methodName As String
With <module or sheet where 'PrintPage' is defined>
methodName = "'" & MyWbk.Name & "'!" & .CodeName & ".PrintPage"
End With
MyWbk.Sheets("Sheet1").Shapes("ButtonName").OnAction = methodName
The single quotes surrounding MyWbk.Name are important.
A quick and easy way is :
workbooks("name_of_workbook").Worksheets("name_of_sheet").Shapes("name_of_button").OnAction = "name_of_your_macro"
Just substitute the different "name_of_..." by your names.
Does it work?