System.MissingMemberException when adding image to Excel through VB.NET - vb.net

Currently I'm trying to add a diagram/picture to an Excel file through VB.NET. When researching how, I often saw the format excelapplication.worksheet.Shapes.AddPicture(picture path). I'm trying to use this (with a bit of modification) but I keep running into the error:
System.MissingMemberException: 'Public member 'Shapes' on type 'Range' not found.'
In my code below you can see that I have a particular cell I want to add the image to. Just incase it was narrowing down what cells I wanted in was what was causing my issues, I tried removing Range("AU6") and the error was basically the same except now Shapes isn't a member of ApplicationClass.
System.MissingMemberException: 'Public member 'Shapes' on type 'ApplicationClass' not found.'
Here's my code:
MyExcel.Workbooks.Open(LoadDir & FileName.Text)
MyExcel.Sheets("Sheet1").activate()
MyExcel.Range("AL6").Activate()
MyExcel.Range("AL6").Value = Proj_Desc.Text
MyExcel.Range("AU6:BA46").Activate()
MyExcel.Range("AU6").Shapes.AddPicture(Proj_DiagramPath.Text) 'Error Appears Here
MyExcel.ActiveWorkbook.Close(SaveChanges:=True)
MyExcel.Quit()
Runtime.InteropServices.Marshal.ReleaseComObject(MyExcel.Workbooks)

Related

Using brackets when creating object in vba excel?

I have copied code from a vba project that I found to go from xml to excel but it gives me an error in my vba project, I have checked the reference libraries.
ruta = LCase(CreateObject([explorador]).BrowseForFolder(0, "selecciona la carpeta a procesar", 0, "").items.Item.Path)
I made the following change and it worked
ruta = LCase(CreateObject("shell.application").BrowseForFolder(0, "selecciona la carpeta a procesar", 0, "").Items.Item.Path)
but then it came back to this line
With CreateObject([openFile])
I get the error 13 that the execution times do not match. Variables do not match
I check the variables and they are correctly: unsure:
I don't understand why with the original file it runs smoothly and the replica doesn't. It has been very little I have found it with respect to the syntax of those lines of code when writing it [explorer] and [openFile]
Square brackets in VBA are used for what the language specification calls "foreign identifiers"; they're how you can explicitly invoke a Range object's default member, which is a hidden member named _Default - since VBA identifiers cannot begin with an underscore, doing MsgBox SomeRange._Default would be illegal. So we do MsgBox SomeRange.[_Default] instead and now the code can compile and run. Same with the SomeCollection.[_NewEnum] hidden member, when creating custom collection classes.
When the bracketed identifier doesn't contain any illegal-in-an-identifier characters, then they are purely redundant.
Various VBA hosts also implement some form of Evaluate mechanism; when hosted in Excel, you can do this MsgBox [A1] and you'll get the value of cell A1 from the active worksheet - in this context [A1] is an expression VBA takes and passes to the host application (here Excel), which evaluates it and returns a result to VBA - in this case a Range object reference.
So what CreateObject([explorador]) really does, is really this:
CreateObject(ActiveSheet.Range("explorador").Value)
Except Excel doesn't understand what explorador is referring to (is the sheet supposed to define a explorador named range? I can't imagine why you'd want to do that though), and comes back with what would show up as a #NAME? error on a worksheet, wrapped up in a Variant/Error value:
CreateObject(CVErr(XlErrName)) 'type mismatch error every time!
Lose the square brackets, you'll lose the headache with them!
Assuming explorador and openfile are String variables containing a valid/registered ProgID, CreateObject(explorador) should work as intended.
Consider using either string literals or declared constants with CreateObject: having a layer of indirection here is obscuring exactly what type of COM object is being created. With CreateObject("Scripting.FileSystemObject") can only fail if the Scripting.FileSystemObject isn't in the registry.

Access TempVars Don't Compile

I've used TempVars for some time, but am having some issues with one set in an Access 2010 database.
Whenever I try to compile, an error dialog stating "Method or data member not found" appears and the term TempVars is highlighted.
Here's the code snippet in question:
If TempVars("Connected") And TempVars("HasAccessBE") And Me.chkBackupOnExit Then MakeBackup
While I've successfully used TempVars("xx") previously where "xx" is the variable which has been defined elsewhere with TempVars.Add "xx", "yy"
In this instance the compiler somehow thinks TempVars isn't viable code.
These have been checked as well:
Application.TempVars("xx")
TempVars.Item("xx")
Search for user defined variables named TempVars (none found)
Desired variable has been defined via TempVars.Add "xx", "yy" (it was)
In case this is a corruption thing, the following tasks have also been completed:
Database Compact & Repair
Database Decompile
I'm trying to resolve this so I can compile and move forward. The code functions fine for users, however it still needs to be compiled.
Any ideas on how to resolve the issue?
Very interesting behavior.
This compiles for me:
If TempVars("Connected") And TempVars("HasAccessBE") Then Debug.Print "Yay!"
If the TempVars don't exist, I will get a runtime error, not a compile error.
Actually not even this, they just return Null.
This does not compile:
If TempVars("Connected") And TempVars("HasAccessBE") Then WrongFunction
but: The compiler selects the first TempVars and says "Sub or Function not defined". Instead of selecting WrongFunction where the problem is.
=> The error is not in TempVars, but in the rest of the statement.
Judging from the error message, I'd say that Me.chkBackupOnExit does not exist / is spelled wrong.
Edit: To see what's going on, change your code line to
If Me.chkBackupOnExit Then MakeBackup
and try to compile this.
When adding to TempVars collection, you need to define the name and value. Then you can retrieve the value by name.
TempVars.Add(name As String, value)
Working example:
Sub Test()
Dim b As Boolean
b = True
TempVars.Add "bool", b
Debug.Print TempVars("bool")
End Sub
'True

Wrong number of arguments in VBA (MS Access) with SOAP request created through wsl.exe

I've created a C# dll using the web service wsdl.exe. Based on that I have create both a C# and VB.Net application, and they both retrieve the data I expect and give me the result.
The VBA code that calls the same external dll fails. The dll returns an object that has a property 'DataArea' that is an array of objects.
Dim response As CustomerPrice.SimulatePriceResponseType
Set response = New CustomerPrice.SimulatePriceResponseType
Set response = CustPriceService.SimulatePrice(st)
Dim bob As String
bob = response.DataArea(0).bookPrice_Value
In C# and VB.Net the last line gives the value required.
In VBA the last line indicates a 'Wrong Number of arguments or invalid property assignment'
In 'Immediate mode debugging'
Print response gives SimulatePriceResponseType as expected.
Print response.DataArea gives Type Mismatch (error 13)
Print response.DataArea(0) gives wrong number of arguments (error 450)
Any ideas what is happening and what I can do to fix it?
It seems that it has something to do with the array, or with how VBA is interpreting it, although I am not sure exactly what.
I found the dll source code and added a property that returned only the first element of the array as an PriceData object, not an PriceData[] array.
Works as it should

VBA error in saving file using Format (date) function

I'm trying to save an activeworkbook but when I use the following code, I keep getting the error "compile error: expected function or variable" with the word "format" highlighted.
It boggles my mind because I used the exact same function and format in another macro and it saved the file perfectly. I also made sure they had the same types of variables defined already...
Here's the one line code
ActiveWorkbook.SaveAs Filename:=SavedPath & format(Date, "mmddyyyy") & " 4512 GLUpload.xlsm"
The variable savedpath is fine because when I run this line without the format part, it saves the file, but not sure why this screw it up. Also noticed in my other code, format is capitalized but it's not here.
The compiler error you are getting indicates that VBA is expecting an assignable value (either a literal, a variable, or the return value of a function). This means that one of the identifiers in the statement to the right of the equals sign doesn't fall into those categories. So, either SavedPath is defined somewhere as Sub SavedPath(), or there is a Sub Format(arg1, arg2) defined somewhere (if it had a different number of arguments you would get a "Wrong number of arguments or invalid property assignment" error). The second clue (in the comments) is that changing format to the strongly typed Format$ gave a "Type-declaration character does not match declared data type" error. This points to the compiler not treating the symbol format as a function call (Format$() is the strongly typed version of Format()). The solution is to track down the errant use of the VBA function name and re-name it.
A perfect example of why avoiding VBA keywords and function names is good practice.

Why isn't this a type mismatch?

I answered this question, apparently to OP's satisfaction, but still find their question puzzling. Their question involved an expression in which a workbook object was being concatenated with a string, triggering Run-time Error '438': Object doesn't support this property or method. You can reproduce this sort of error by simply typing
?"Hello, " & ThisWorkbook
In the Immediate Window.
My question is -- why does this raise that error, instead of a error 13 -- type mismatch? A reasonable guess is that VBA tries to find a default property for a workbook object and that a default property doesn't exist. But, if so, I would expect it to be the following error from Microsoft's list of Visual Basic 6.0 error codes: Automation object doesn't have a default value (Error 443).
It is mostly of academic interest, but if the result of concatenating an object without a default property with a string is always Error 438, and that is the only way of triggering Error 438 rather than possibly another error when concatenating a string with an object, then the following code might be of use:
Function HasDefault(O As Variant) As Boolean
Dim i As Long
If Not IsObject(O) Then Exit Function
On Error Resume Next
i = Len("Hello, " & O)
If Err.Number = 438 Then
HasDefault = False
Else
HasDefault = True
End If
End Function
I've tested this on a variety of objects, and for those I've tested it on it has returned False exactly when _Default doesn't show up as a (hidden) member of the object when viewed in the Object Browser. Nevertheless, I don't quite trust this function and am still puzzled by what is going on here.
VBA will try and convert the expressions on each side of the & operator to a data value. The language spec states that:
If the value type of the expression’s target variable is a class:
If the declared type of the target is Variant, runtime error 9
(Subscript out of range) is raised.
If the declared type of the target is not Variant, and the target has
a public default Property Get or function, the data value’s value is
the result of invoking this default member for that target with this
argument list. This consumes the argument list.
Otherwise, runtime error 438 (Object doesn’t support this property or
method) is raised.
As regards your function, I'd just use:
callbyname(O, "_Default", VbGet)
which will raise a 438 error as appropriate.