Why VBA Runtime error 13 Type mismatch while starting DDE conversation - excel

I have this code:
Public channel As Long
Sub Button1_Click()
MsgBox "all is OK"
' Application.ActiveCell.Font.Bold = True
channel = Application.DDEInitiate("Excel", "System")
MsgBox "Conversation started"
End Sub
Why DDEInitiate expression gives error 13?

The registry keys shown in the office-watch blog mentioned by #VincentG were only relevant for Writer. Excel has its own set of keys (which one can check using Sysinternals ProcMon, both when Excel starts, and when DDEInitiate is called from VBA), which are at least:
In HKCU\SOFTWARE\Microsoft\Office\16.0\Excel\Options - DDEAllowed:REG_DWORD=1
In HKCU\SOFTWARE\Microsoft\Office\16.0\Excel\Security - DisableDDEServerLaunch:REG_DWORD=0, DisableDDEServerLookup:REG_DWORD=0.
I didn't check which of them are the minimum requirement. Anyway, indeed, enabling DDE would be a security risk.

Related

Excel 2011 for Mac: Compile error on line that should not be compiling

I am creating an Excel Macro-Enabled Workbook for both Windows & Mac. One platform on the Mac I want it to run on is Excel 2011.
My workbook uses a custom Ribbon tab. Sometimes, depending on what the user does, I want the text of the ribbon buttons to change. So I have code that does this.
I know that a custom Ribbon tab is not possible in Excel 2011. That is okay. However, there is a line in my code that is giving me a compile error on that version of Excel. I thought I had it set that it would not compile the code if running on this version of Excel, but it doesn't seem to be working.
I am defining a variable of type IRibbonUI for use inside a standard module. (The module is Module3, and it is dedicated to code having to do with the Ribbon.) I wrap the variable definition code (along with the rest of the code in this module) in an #IF statement, like so:
#If Not Mac or MAC_OFFICE_VERSION >=15 Then
Dim ribbonUI As IRibbonUI
... rest of the code in Module3 ...
#End If
This means it should not compile at run-time on Excel 2011.
When the workbook opens, I do not get any errors. However, when I am running a sub (let's call it "UpdateOptions", and it is in Module1) that calls a sub that changes the Ribbon (let's call that one "ChangeRibbon", which is in Module3*), I get a compile error on the ribbonUI line: User-defined type not defined
I don't understand why, because as far as I understand, the code in that module shouldn't be compiling at run-time.
*ChangeRibbon should never actually be run on Excel 2011. I have an IF statement that makes sure it is not, like so:
Sub UpdateOptions()
... some code ...
#If Not Mac or MAC_OFFICE_VERSION >=15 Then
Module3.ChangeRibbon
End If
... some other code ...
End Sub
When I step through the code, the error happens when UpdateOptions is first called by another sub. The step-through highlights the name of the sub as the line that is causing the error:
Sub UpdateOptions()
Does anyone know why this is happening? It doesn't make any sense to me.
I'll post it as an answer since it won't fit into the comment section.
It seems that you enter your code, even thought it should not. The easiest explanation is, that your if statement is not evaluated properly. You should check the values of Mac and MAC_OFFICE_VERSION, this should already show you what went wrong. Another reason could be that you made a wrong assumption about how VBA evaluates logic clauses: https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/operator-precedence
If you split/nest the the If-Block it is easier to see which evaluation goes wrong:
Public Sub testVer()
#If Not Mac Then
Debug.Print "Not a Mac"
#Else
#If MAC_OFFICE_VERSION >= 15 Then
Debug.Print "Mac Version equal or above 15: ", MAC_OFFICE_VERSION
#Else
Debug.Print "Mac Version below 15: ", MAC_OFFICE_VERSION
#End If
#End If
End Sub
Here is a small example to see how your if clause gets evaluated:
In VBA the clause Not A Or B is the same as (Not A) Or B, so maybe you just mixed up logic.
Sub testOrNot()
printNotAOrB True, True
printNotAOrB True, False
printNotAOrB False, True
printNotAOrB False, False
End Sub
Private Sub printNotAOrB(A As Boolean, B As Boolean)
Debug.Print "A = " & A, "B = " & B
Debug.Print "Not A Or B :", Not A Or B
Debug.Print "Not (A Or B):", Not (A Or B)
Debug.Print "(Not A) Or B:", (Not A) Or B
Debug.Print
End Sub
I had the thought of if I could possibly "fake out" Excel 2011 into thinking I had created a custom data type for IRibbonUI (and, as it turned out, I had to do it for another type, too) and that worked. In my module dealing with all my Ribbon code, I put this at the top:
#If Mac And MAC_OFFICE_VERSION < 15 Then
Type IRibbonUI
ribbontype As String
End Type
Type IRibbonControl
ribboncontrol As String
End Type
#End If
I no longer receive the compile error.
In regards to L8n's answer, I don't believe the logic of the IF statement was a problem. I had also tried calling on a Function I created long ago to test if the version of Excel was Excel 2011 for Mac. So my IF statement started like this:
#IF ExcelForMac2011 = False Then
I know my function works properly, because I call it many other times in my workbook, and it has always worked correctly. So I don't think it was a logic problem in the IF statement. I think this was a bug in Excel 2011. Unfortunately, it has MANY, MANY bugs.

Any posibility to modify the sub and function bodies created via VBA IDE

I am willing to add some code to the begining and end of each sub or function for enabling flow tracing / debugging.
Now I copy this (almost standard code manually into the beginig of each sub / function, and also before each exit sub/function and end sub / function statement.
Something like this
public sub a()
...
**logging_successful = pushCallIntoStack("sub a")**
...
On Error Goto errorOccured
...
**logging_successful = popCallFromStack("sub a")**
Exit Sub
...
errorOccured:
...
**logging_successful = popCallFromStack("sub a")**
...
End Sub
Being able to insert these standart codes via VBIDE as default - at least in the standard entry and exit points - will save me sometime.
What you want to do is technically doable but are you sure you want to add boilerplate code with hard-coded strings to all of your procedures? That is lot of maintenance which also makes it much harder to refactor your code. I've seen lot of error messages saying it came from "Foo" but they came from "Bar" because at one point the code was in Foo but then it got moved or renamed to Bar, but they forgot to update the string constant. There is no such guarantees that the string constants are in sync with the actual procedure names.
Before sinking potentially hours into this solution, I would encourage you to first consider third-party addins that can do a much better job of helping you getting the detailed error output you need. One such solution would be vbWatchDog which provides you not only the stack tracing but also much extended diagnostics... without any changes to your source code. Precisely because it can do without any embedding constants, it won't be liable to give you outdated information.
I should note that there are also other third-party addin such as MZ-Tools which provides a one click button for adding an error template that could conceivably be used to provide what you want. However, the operation is not reversible, which adds to your maintenance burden; changing a procedure would mean you'd have to strip away the old error template, then re-add, and if there's any customization, to re-add it.
If in spite of all, you insist on continuing doing it by your own hand, you can do something like the following:
Public Sub AddBoilerPlate(TargetComponent As VBIDE.VBComponent)
Dim m As VBIDE.CodeModule
Dim i As Long
Set m = TargetComponent.CodeModule
For i = m.CountOfDeclarationLines + 1 To m.CountOfLines
Dim ProcName As String
Dim ProcKind As VBIDE.vbext_ProcKind
ProcName = m.ProcOfLine(i, ProcKind)
Dim s As Long
s = m.ProcBodyLine(ProcName, ProcKind) + 1
m.InsertLines s, <your push code>
'Loop the lines within the procedure to find the End *** line then insert the pop code
Next
End Sub
This is an incomplete sample, does not perform checks for pre-existing template. A more complete sample would probably delete any previous template before inserting.
You may need to amend the codes for your own needs but below's the general idea (e.g. change "Module2" to the name of your module and include more checks to determine where to add in new codes)
Public Sub sub_test()
Dim i As Long
With ThisWorkbook.VBProject.VBComponents("Module2").CodeModule
For i = 1 To .Countoflines
If InStr(.Lines(i, 1), "End Sub") > 0 Then
.Insertlines i, "**logging_successful = popCallFromStack(""sub a"")**"
End If
Next i
End With
End Sub

SAP Error handling by SAP GUI Scripting

I m using SAP GUI Scripting code for bulk record submission through SAP form. It picks records one by one from excel file and submits in SAP system.
My Question:
I want to include error handling into it. So that if any error occurs at any particular record submission, Script shouldn't stop. It should move to the next line after putting appropriate message in Comment field.
Can anyone throw some light how to identify whether SAP is facing some Error or Warning?
And if Error occurs how to get out of it i.e., how to handle that and move to next record submissions.
Yes, You can do that.
Look for the status bar at botton
GUI Scripting help section in SAP is very helpful it will explain you things in very details.
GuiStatusBarObject --> Members --> Message Type
Us can use those properties as per your needs, If You need to move next , halt or notify user You can use these messages type and work accordingly.
SAP scripting does not throw error if error occurs in SAP itself , It will only throw error when it can not find elements or some other issue.
Sample Code :
Public Sub get_status_bar_value_exit_if_Error()
Dim usr_resp As String
If (session.findById("wnd[0]/sbar").messagetype = "E" Or session.findById("wnd[0]/sbar").messagetype = "W") Then
usr_resp = MsgBox(session.findById("wnd[0]/sbar").Text & Chr(13) & "Show the Error in SAP ?", vbYesNo)
If usr_resp = vbYes Then
Else
Call go_to_Sap_home
End If
End
End If
End Sub
Here I chose to exit the current task and go to home if user chose not to see error in SAP ,else SAP will halt and user can see error in the status bar. You can do anything you want to do.
unfortunately on error resume next will not help due to the fact that it can not find the object,
If (session.findById("wnd[0]/sbar").messagetype = "E" Or session.findById("wnd[0]/sbar").messagetype = "W") Then
usr_resp = MsgBox(session.findById("wnd[0]/sbar").Text & Chr(13) & "Show the Error in SAP ?", vbYesNo)
If usr_resp = vbYes Then
Else
Call go_to_Sap_home
End If
this helped
The answer is basically On Error Resume Next but you can read more here... https://scn.sap.com/thread/3270803. On Error Resume Next alone will ignore all of your errors. You can make conditions through If.

vb6 trying to get old program working with excel 2013

I have this code from a program that was created to take data and export it into excel it is in vb6 and I dont know much about vb6 I started coding in vb.net could someone tell me why this isnt working with excel 2013 it opens but then closes right away and i am unsure as to why.
Sub GetExcel()
Dim MyExcel As Object ' Variable to hold reference
' to Microsoft Word.
Dim ExcelWasNotRunning As Boolean ' Flag for final release.
' Test to see if there is a copy of Microsoft Excel already running.
10 On Error Resume Next ' Defer error trapping.
' Getobject function called without the first argument returns a
' reference to an instance of the application. If the application isn't
' running, an error occurs.
20 Set MyExcel = GetObject(, "XLMAIN")
30 If Err.Number <> 0 Then ExcelWasNotRunning = True
40 Err.Clear ' Clear Err object in case error occurred.
' Check for Microsoft Excel. If Microsoft Excel is running,
' enter it into the Running Object table.
50 DetectExcel
' Set the object variable to reference the file you want to see.
60 Set MyExcel = GetObject(App.Path & "\test.xls")
' Show Microsoft Word through its Application property. Then
' show the actual window containing the file using the Windows
' collection of the MyWord object reference.
' MyExcel.Application.Visible = True
' MyExcel.document(1).Visible = True
70 MyExcel.Show , f1
'//////////////////////////////////////////////
' Do manipulations of your file here.
'//////////////////////////////////////////////
' ...
' If this copy of Microsoft Excel was not running when you
' started, close it using the Application property's Quit method.
' Note that when you try to quit Microsoft Excel, the
' title bar blinks and a message is displayed asking if you
' want to save any loaded files.
80 If ExcelWasNotRunning = True Then
90 MyExcel.Application.Quit
100 End If
110 Set MyExcel = Nothing ' Release reference to the
' application and spreadsheet.
End Sub
Sub DetectExcel()
' Procedure dectects a running Word and registers it.
Const WM_USER = 1024
Dim hwnd As Long
' If Excel is running this API call returns its handle.
10 hwnd = FindWindow("XLMAIN", 0)
20 If hwnd = 0 Then ' 0 means Word not running.
30 Exit Sub
40 Else
' Word is running so use the SendMessage API
' function to enter it in the Running Object Table.
50 SendMessage hwnd, WM_USER + 18, 0, 0
60 End If
End Sub
even if i can get some direction on how to rewrite this it would be appreciated.
It's been a long time since I've used it, so you may need to address some of the finer points... But:
First and foremost - get rid of the On Error Resume Next it masks whatever happens next.
This is not a situation where you want to have errors ignored. Capture the error, show something useful (not debug information and not details that can be used for hacking) to the user, and resume or return (after cleanup of assigned object variables to avoid memory leaks).
Then step through the code to see what errors you get.
Some of the things that may help:
Change the specification in your GetObject to be "Excel.Application" i.e.
Set MyExcel = GetObject(, "Excel.Application")
Instead of MyExcel.Show which may or may not be supported, use actual Excel objects and their methods and properties, for instance the commented MyExcel.Application.Visible = True works, while I question the MyExcel.document(1).Visible = True.
Look up the Excel object model help for details. And never hardcode the index - obtain the actual reference that you want and use it.
You can still find articles about Excel and VB6 on line. Use your search engine of choice and good luck.
Beware of those who say something is impossible - first see if it works. Some say you can's install VB6 on a 64-bit system - that is not true, but there are some issues getting it to work. Some say you can't interact with 64-bit Office from VB6, but that is not true. Maybe you can't do some things - I haven't done much with it, just enough to know it is possible to do some things.
Consider developing and testing with typed objects in VB6. It can be very helpful, but to make the application version independent, you will need to remove the object typing before final test and deployment.

ADODB.Connection undefined

Reference Excel VBA to SQL Server without SSIS
After I got the above working, I copied all the global variables/constants from the routine, which included
Const CS As String = "Driver={SQL Server};" _
& "Server=****;" _
& "Database=****;" _
& "UID=****;" _
& "PWD=****"
Dim DB_Conn As ADODB.Connection
Dim Command As ADODB.Command
Dim DB_Status As Stringinto a similar module in another spreadsheet. I also copied into the same module
Sub Connect_To_Lockbox()
If DB_Status <> "Open" Then
Set DB_Conn = New Connection
DB_Conn.ConnectionString = CS
DB_Conn.Open ' problem!
DB_Status = "Open"
End If
End SubI added the same reference (ADO 2.8)
The first spreadsheet still works; the seccond at DB_Conn.Open pops up "Run-time error '-214767259 (80004005)': [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified"
Removing the references on both, saving files, re-opening, re-adding the references doesn't help. The one still works and the other gets the error.
?!?
I observed the same error message and in my case nothing had changed. I wondered if my odbc driver needed to be reinstalled (based on what i read online). In any case, restarting excel did the trick. Sometimes the solution is much simpler. :-)
When the error pops up, check your "locals" windows to see what the CS holds. View > Locals Window
Problem: Your constant isn't found by the compiler.
Solution: With the constant being located in a separate module, you'll need to set it as Public for the other code to see it.
Proof:
In order to prove this theory you can do the following:
Open a new Excel spreadsheet
Go to the VBA designer and add a new module
In this module put:
Const TestString As String = "Test String"
Then add the following code to ThisWorkbook:
Public Sub TestString()
MsgBox (TestString)
End Sub
After adding this return to the workbook and add a button, selecting "TestString" as the macro to run when clicked.
Click the button and a blank message box will appear.
Go back to the VBA designer and change the const in Module1 to Public
Click the button on the spreadsheet and you should now see "Test String" in the message box.
I realize that this question is really old. But for the record I want to document my solutions for the error here: It was a data related error in a spreadsheet! A column was formatted as date and contained a value 3000000. Changing the Format to numbers solved the Error 80004005.

Resources