Issues accessing the user desktop using VBA - vba

I am trying to use VBA in order to save a file on a user's desktop. I have found people requesting similar things on this site and others and the answers usually recommend using the following function to get the file path of the user's desktop
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
However, I tried this and all I get is a 424 Object required error. The spreadsheet I am trying to add this to is long and complex so I created a new sheet with just the section of code I was interested in.
Sub TestMacro()
Dim Testy As String
Testy = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
MsgBox Testy
End Sub
When I run this macro I still get a 424 object required error. Am I doing something wrong? Or is there something locked down in my office environment preventing me from using this command?
Any help appreciated.

Try with below code
Sub TestMacro()
Set oWSHShell = CreateObject("WScript.Shell")
MsgBox (oWSHShell.SpecialFolders("Desktop"))
End Sub

Related

Run a MakeTable query in Access from Excel

I have an Excel file that I need to automate. When the user opens the Excel Report, it will prompt if they would like to refresh the data. If they say yes, then I need it to run a MakeTable query that is in an Access database to refresh all the underlying numbers for the report.
I have searched and haven't been able to find anything that actually works.
I tried to even create VBA code inside of Access that I could run that would handle the query, but I can't even get that to run from Excel VBA.
Here is the current code I have along with some of what I have tried that didn't work:
Sub RunAccessMTQuery(ByVal DBLocation As String)
Dim db As Object
Set db = CreateObject("Access.Application")
With db
.OpenCurrentDatabase DBLocation
.Visible = True
' .Run "Main.RunMTJobBond"
' .docmd.runmacro "Main.RunMTJobBond" '<---Module.Proc Name
' .docmd.runmacro "mMTJobBond" '<---Macro name that calls the Proc
.Application.Run "mMTJobBond"
.CloseCurrentDatabase
.Quit
End With
'Below was found on https://support.microsoft.com/en-us/help/131921/running-a-microsoft-access-macro-from-microsoft-excel
' Dim Chan as Long
'Opens Microsoft Access and the file nwind.mdb
' Shell("""C:\Program Files (x86)\Microsoft Office\Office12\MSACCESS.EXE"" """ & DBLocation & """")
'Initiates a DDE channel to Microsoft Access
' Chan = DDEInitiate("MSACCESS", "system")
'Activates Microsoft Access
' Application.ActivateMicrosoftApp xlMicrosoftAccess
'Runs the macro
' Application.DDEExecute Chan, "RunMTJobBond"
'Terminates the DDE channel
' Application.DDETerminate Chan
End Sub
Either I need to be able to run the MakeTable query from Excel, or launch Access and have it run the query. Nothing I have tried has worked...I have gotten numerous errors such as:
Runtime error 5 - Invalid procedure call or arguement
Runtime error 2517 - Application-defined or object-defined error
Others as well, but I don't recall them as I was able to work through those, and these are some of the ones I'm stuck on. Any help would be great, thanks.
The Application.Run() command runs a function or sub procedure, not a macro. That's why the attempts to run the macro do not work.
As for running the function or sub directly, the expected parameter format for Run() is "projectname.procedurename", NOT "modulename.procedurename". Unless you have multiple VBA projects within your database (which I assume you do not), then you don't even need projectname. See documentation here.
Try
Set dbApp = CreateObject("Access.Application")
With dbApp
...
.Run "RunMTJobBond"
This assume that RunMTJobBond is a public function or sub in a standard module.

Access autocad object properties without opening it by VBA

I have been using folder browser for VBA, I could paste the code of it, but bottom line is that I get returned file name as a string.
Is there any way to access drawing properties (i.e number of layouts) without open?
Public Sub TestFileDialog()
dwgname = FileBrowseOpen("C:", "*", ".dwg", 1) 'dwgname is typeof string
End Sub
Its only the first step (use of FileBrowseOpen function is shown, but also i can use FolderBrowse and collect all .dwg inside of folder),actually i had in mind to batch export all layouts of selected .dwgs to currenty open one. Is there any chance for that?
To effectively read a .dwg file you'll need to open AutoCAD, otherwise the information is not accessible. Some properties may be, such as author, but not number of layouts...
But you can use AutoCAD Console (accoreconsole.exe) to run a headless AutoCAD and use APIs to read any information you need. This is really fast for reading lot's of files and the user will not see it running (but it needs to be installed anyway).
http://aucache.autodesk.com/au2012/sessionsFiles/3338/3323/handout_3338_CP3338-Handout.pdf
you could stay in VBA and use ObjectDBX
it leads to a very similar approach as accoreconsole.exe on in .NET does, i.e you won't see any drawing open in UI since it works on the database itself
It requires adding library reference (Tools->References) to "AutoCAD/ObjectDBX Common XX.Y Type Library", where "XX.Y" is "19.0" for AutoCAD 2014
a minimal functioning code is
Sub main()
Dim myAxDbDoc As AxDbDocument
Dim FullFileName As String
FullFileName = "C:\..\mydrawing.dwg" '<== put here the full name of the file to be opened
Set myAxDbDoc = AxDb_SetDrawing(FullFileName)
MsgBox myAxDbDoc.Layers.Count
End Sub
Function AxDb_SetDrawing(FullFileName As String) As AxDbDocument
Dim DBXDoc As AxDbDocument
Set DBXDoc = Application.GetInterfaceObject("ObjectDBX.AxDbDocument.19") '<== place correct AutoCAD version numeber ("19" works for AutoCAD 2014)
On Error Resume Next
DBXDoc.Open FullFileName
If Err <> 0 Then
MsgBox "Couldn't open" & vbCrLf & vbCrLf & FullFileName, vbOKOnly + vbCritical, "AxDB_SetDrawing"
Else
Set AxDb_SetDrawing = DBXDoc
End If
On Error GoTo 0
End Function
Still, you must have one AutoCAD session running from which make this sub run! But you should have it since talked about "currently open" drawing

method 'comaddins' of object '_application' failed while looking for the registered COMAddins

We have this simple piece Where in we are registering an Addin and trying to find the Addin by looping through the list of Addins. This is not consistently reproducible on all the machines and we started seeing this on a client machine. We don't see anything wrong with the code either. We didn't see much on any of the forums. Please help.
When the code hits the for loop we get this error. Runtime Error -2147310770(8002801d). method 'comaddins' of object '_application' failed.
For Each oAddin In oWordApp.COMAddIns
Sub Main()
Call RegisterAddin
Dim oWordApp As New Word.Application
Dim oAddin As Office.COMAddIn
**For Each oAddin In oWordApp.COMAddIns**
If oAddin.DESCRIPTION = "TestingCom Addin" Then
oAddin.Connect = True
End If
Next
Try casting another Microsoft.Office.Interop.Word._Application variable to Word.Application, then use Microsoft.Office.Core.COMAddIn to get items in the _Application.COMAddIns collection.
I was able to fix this using the below link. Looks like the previous/latest version of Office was not uninstalled properly and was causing problems with Office 2007.
http://kb.palisade.com/index.php?pg=kb.page&id=528

Why doesn't code work in VB.net, but works in VBA; GetObject

VBA code works great:
Sub testVBA()
Dim wb As Object ' Lotus123.Document
Set wb = GetObject("S:\Temp\T\0375D.WK3", "Lotus123.Workbook")
End Sub
VB.net code fails:
Sub TestVBNet()
Dim wb As Object ' Lotus123.Document
wb = GetObject("S:\Temp\T\0375D.WK3", "Lotus123.Workbook")
End Sub
In VB.net I get a FileNotFoundException: "File name or class name not found during Automation operation."
As I can run it from VBA that means the file exists and that the class name exists. So why doesn't it work and how can I fix it in VB.net.
EDIT: I guess I'm not sure how to start diagnosing this: Obviously the class exists on my computer but somehow VB.net doesn't manage to find it. Maybe VB.net uses a different method to activate the class. Maybe a registry entry is missing. I am glad for any suggestions.
Edit 2: I also tried using CreateObject and got this error: "Cannot create ActiveX component." Not unexpected.
For some reason VB.net cannot find the class name "Lotus123.Workbook" so I tried getting the file without the class name and it works fine in XP.
Dim wb As Object ' Lotus123.Document
wb = GetObject("S:\Temp\T\0375D.WK3")
EDIT: In Win8 64bit the above doesn't work; just hangs.
The code below works in XP 32 bit as well as in Win8 64 bit. I checked with process monitor what is happening under the hood. CreateObject checks for the CLSID in the registry using the given object. Then it looks up the necessary info using the CLSID.
Public Shared Function GetLotusWB(ByVal sFile As String) As Object
'HKCU takes precedence if exists
'HKCU\Software\Classes\Lotus123.Workbook\CLSID
'HKCU\Software\Classes\CLSID\{29130007-2EED-1069-BF5D-00DD011186B7}
'normally this is used because Lotus123 doesn't create HKCU entries
'HKCR\Lotus123.Workbook\CLSID = {29130007-2EED-1069-BF5D-00DD011186B7}
'HKCR\CLSID\{29130007-2EED-1069-BF5D-00DD011186B7}\InprocHandler32 = ole32.dll
'HKCR\CLSID\{29130007-2EED-1069-BF5D-00DD011186B7}\LocalServer32 = C:\Lotus\123\123w.exe
'using object as that sometimes works better
Dim LotusObj As Object = CreateObject("Lotus123.Workbook")
'get application
'need a reference to Lotus 123 else declare as Object
Dim LotusApp As Lotus123.Application = LotusObj.Application
'FAILS: LotusApp.Visible = True
'open file; also works fine As Lotus123.Document
Dim ldoc As Object = LotusApp.OpenDocument(sFile)
'visible and activate (must declare as Object else gives exception)
Dim appObject As Object = ldoc.Application
appObject.Visible = True
ldoc.Activate()
Return ldoc
End Function
This works great because it creates the "Lotus123.Workbook" which is used to get the application object.
Load the file into an Excel workbook. It should be able to convert the lotus123 workbook on the fly.
First of all, check to make sure your inclusions (I think under Tools menu, includes or references or something like that) include the library that references Lotus123.Document. Chances are it's in the "Microsoft Excel 14.0 Object Library" or similar.
I've heard it said that VB is not VBA!

Calling an External VBA from VBScript

I am using a program called mathtype to pull some equation objects out of a word document. I've written code in VBA that works perfectly using their API, but I have to translate it to a VBScript file. I have looked all over google, but have not found any solution on how (If it is even possible) to call a VBA library from VBScript.
VBScript can't see the MathTypeSDK Objects/Functions.
If not possible, how would I encase the macro I need to run in a globally available word file and call it from the VBScript?
Edit: Got it! Unfortunately the approaches below, while helpful, did not work for my situation. I found something closer: Embedding the macro in a global file and calling it through the Word Objects Run command.
objWord.Run "Normal.NewMacros.RunMain"
Here is an approach which might work for you. I tested this simple example.
Class "clsTest" in file "Tester.docm":
Public Sub Hello()
MsgBox "Hello"
End Sub
Class "Instancing" is marked "PublicNotCreatable".
Module in "Tester.docm":
Public Function GetClass() As clsTest
Set GetClass = New clsTest
End Function
In your vbscript:
Dim fPath, fName
fPath = "C:\Documents and Settings\twilliams\Desktop\"
fName = "Tester.docm"
Dim wdApp, o
Set wdApp = CreateObject("word.application")
wdApp.visible=true
wdapp.documents.open fPath & fName
Set o = wdApp.Run("GetClass")
o.Hello
Set o=nothing
Again - I only tested this simple example: you'll have to adapt it to your situation and try it out.
Word-VBA was not made to create reusable libraries, I suppose (for usage in external programs).
One way to reuse existing Word-VBA code is, however, run Word via WScript.Shell.Run using the /m<macroname> command line switch (see http://support.microsoft.com/kb/210565/en-us for details). This, has the restriction that evertime you need to call a specific macro, a Word process is started again, running that macro, and ends afterwards. Means, if you need just one call to your Word.VBA for a specfific task, this may be ok, but if you need a lot of interprocess communication between your VBScript and your VBA macro, you should look for a different solution.