How to Link a VBA code with opened ETABS OAPI? - vba

a project on ETABS 2015 is open on my PC. I want to do some change and process on it by a VBA code automatically. but all the sample code that I found was like this:
Public Sub Example()
Dim SapModel As cSapModel
Dim EtabsObject As cOAPI
Dim FileName as String
Dim ret As Integer = -1
'create ETABS object
EtabsObject = CreateObject("CSI.ETABS.API.ETABSObject")
'start ETABS application
ret = EtabsObject.ApplicationStart()
'create SapModel object
SapModel = EtabsObject.SapModel
'initialize model
ret = SapModel.InitializeNewModel()
'open an existing file - If no file exists, run the Save example first.
FileName = "c:\CSI_API_temp\example.edb"
ret = SapModel.File.OpenFile(FileName)
This code just open a new ETABS in my PC. but my ETABS project is already running and I want to connect to it but I don't know how!
please help me.

Your sample code is basically and typically the one needed to open ETABS ITSELF and to initialize a new model,
ETABSObject = CreateObject("CSI.ETABS.API.ETABSObject") followed by the invocation of ApplicationStart method are the direct means for that.
If you refer to the ETABS API documentation file in the installation destination (e.g "C:\Program Files\Computers and Structures\ETABS 2015\CSi API ETABS 2015.chm" ) Under the section "Release Notes>Attaching to a manually started instance of ETABS", or if you see the same section from the link
http://docs.csiamerica.com/help-files/etabs-api-2015/html/3ceb8889-9028-4de3-9c87-69a12055ade7.htm
you'll find code (in VB.Net) close to what you aim to, but it will not work with vba, so, what you will simply do is this
'The ret variable, just for method invocation convenience
Dim ret As Integer
'Create an instance of the currently opened Program
Dim myETABSObject As ETABS2015.cOAPI
Set myETABSObject = GetObject(, "CSI.ETABS.API.ETABSObject")
'Create an instance to the model
Dim myETABSModel As ETABS2015.cSapModel
Set myETABSModel = myETABSObject.SapModel
'Now, after the "reference instances" are obtained
'Initialize the model (using the model's instance of course)
ret = myETABSModel.InitializeNewModel() 'default units in kip_in_F
'Set the model templete, which is "Blank"
ret = myETABSModel.File.NewBlank()
And You can normally proceed in your coding.
Note: 1- GetObject(CSI.ETABS.API.ETABSObject) method will raise an error if ETABS is not opened.
2- you still can use GetObject even if ETABS is not opened and if you want to open it from windows shell (like using command prompt to open programs instead of double clicking on their respective icons), but this of course needs some Error Handling and the use of "Windows Script Host Object Model".
3- The examples in the documentation (under the documented methods and properties) may not be complete in terms of initiating input data, in cases like this they are just to create an impression of how to use their respective methods and properties.

The code below does as you asked. It uses VBA to connect to a currently running instance of ETABS. Please note if you're running multiple instances of ETABS it may not attach to the one you want.
You'll need to add a reference to 'ETABSv1.tlb' to your VBA project. If you're using VBA Editor for Excel, on the Tools menu select References, then click Browse then add C:\Program Files\Computers and Structures\ETABS 19\ETABSv1.tlb
Sub Main()
'create API helper object
Dim myHelper As ETABSv1.cHelper
Set myHelper = New ETABSv1.Helper
'dimension the ETABS Object as cOAPI type
Dim myETABSObject As ETABSv1.cOAPI
Set myETABSObject = Nothing
'attach to a running instance of ETABS
'get the active ETABS object
Set myETABSObject = myHelper.GetObject("CSI.ETABS.API.ETABSObject")
'get a reference to cSapModel to access all API classes and functions
Dim mySapModel As ETABSv1.cSapModel
Set mySapModel = myETABSObject.SapModel
' DO YOUR WORK BELOW.
MsgBox "Do your work here."
' DO YOUR WORK ABOVE.
'clean up variables
Set mySapModel = Nothing
Set myETABSObject = Nothing
Exit Sub
ErrHandler:
MsgBox "Cannot run API script: " & Err.Description
End Sub
ETABS comes with API documentation that you can find in the installation folder. On my machine it is here: C:\Program Files\Computers and Structures\ETABS 19\CSA API ETABS v1.chm

Related

msoFileDialogFilePicker not displaying

I'm having issues with trying to display the file picker using the FileDialog property in MS Access 2016. I've tried both early and late binding but the file picker never displays. No errors are detected nor messages displayed. When I try to debug it line by line, the .show doesn't trigger the form. I've also tried If .show=-1 in lieu of .show but that does not work either. I've tried removing the library reference to Microsoft Office 16.0 Object Library, and even using late binding the window still does not display. Any ideas as to what is going wrong, and how to remedy it? I'm adding both early and late binding examples below.
Public Sub FP_EarlyBinding()
Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
For Each vrtSelectedItem In .SelectedItems
Debug.Print vrtSelectedItem
Next vrtSelectedItem
End With
End Sub
Public Sub FP_LateBinding()
Const msoFileDialogFilePicker As Long = 3
Dim fd As Object
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
For Each vrtSelectedItem In .SelectedItems
Debug.Print vrtSelectedItem
Next vrtSelectedItem
End With
End Sub
--------------EDIT-------------------------
Per comments, I was instructed to not to do this in a class module. I've since edited the code, as below. This still does not allow for the form to appear.
This is in a standard module:
Public Function filePicker() As Variant
Dim fd As FileDialog
Dim sFiles$
Dim vrtSelectedItem As Variant
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
For Each vrtSelectedItem In .SelectedItems
sFiles = sFiles & vrtSelectedItem & ","
Next vrtSelectedItem '-----------loops again to attach other files
End With
filePicker = sFiles
End Function
I call this procedure from a class module:
Public Sub Test()
Dim vFileList As Variant, vFile As Variant
vFileList = Split(filePicker(), ",")
For Each vFile In vFileList
Attachments.Add vFile
Next vFile
End Sub
-------------FINAL EDIT---------------------
Turns out the problem here was the Access install...I went to the installation directory and found MSACCESS.EXE, right-clicked, and repaired.
What you have looks almost good.
I recommend you ALWAYS, but ALWAYS ALWAYS ALWAYS put option explicit t the start of your code modules.
eg this:
Option Compare Database
Option Explicit
With above, your code does not compile. I mean, after you type in your code, I assume you do from the code menu a debug->compile. I will do that 100's of time in a typical day (after editing code). so, make that a habit.
Also, to set the default for NEW code modules (setting does not effect existing), set this option in the VBA code editor: tools->Options
So, your code snip looks ok, but, with above option explicit, then you have to declare all variables (and bonus is compile will cast incorrect spellings or miss typed variable names).
So, your code like this should work fine:
Public Sub FP_LateBinding()
Const msoFileDialogFilePicker As Long = 3
Dim fd As Object
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
Dim vrtSelectedItem As Variant
For Each vrtSelectedItem In .SelectedItems
Debug.Print vrtSelectedItem
Next vrtSelectedItem
End With
End Sub
Now, it also not clear how you are test/running the above. But, we assume you create a new code module (NOT class module)
You will then type/paste in above. Save it
do a debug->compile from the VBA editor menu - does it compile ok?
(and if other errors in other places - fix those first).
Now, to run it, place cursor anywhere inside of that code stub, hit f5.
Or you can type in the name of the above sub in the debug window like this:
FP_LateBinding
So your posted code - looks really nice! - all good. Try the above option explcit. And of course now in your example, add the declare for vrtSelectedItem
Edit: ============================================================
Now, of course if this is a class module, then just like code in a form/report, you can't just hit f5 in the code module, nor can you JUST type in the name of the sub.
In fact, if you place your cursor in the code and hit F5, then you get this:
So, it not that the code or file does not appear, you get the above - a big WHOPPER of a difference issue.
And if it is a class module as opposed to a regular code module?
Then to test or use the code, you have to write in test code into a REGULAR code module. You can't use the debug/VBA editor to JUST run a class.
This not different then creating any other object.
So, if we create a new class module, paste in above code, say we save the class code module as MyClassTest ?
Then you have to write code in another standard code module like this:
Sub Test1()
Dim clsTest As New MyClassTest
clsTest.FP_LateBinding
End Sub
So, you can't run class code (even code in a forms code behind module), or any custom class module, you have to FIRST create a instance.
Now it is "possbile" that you used VBA, VB5, VB6. And in fact used "early" versions of Access (before access 2000 - 21 years ago).
you will find by default, it is possbile to use + call class module code without first creating a instance of the class module. This ability was and is for keeping compatibility for pre access 2000 VBA, in which class code modules did not require to be delcared as a new instance. This so called "base" class instance thus was possbile.
it turns out, that if you been importing code for the last 20 years from previous verisons of Access? This flag setting - and option STILL exists in Access 2019 - over 20 years later!!!!
I doubt that you are/did import code from such older versions of Access, but it is in fact still possible to set a class module to NOT require a instance of the class to be created in code. However, I don't recommend doing this, despite the fact that this is still possible.

How to get data in Access VBA from a C# method that returns an object List

I'm calling a C# WebService method called getInterventions() on a VBA Access 2003 application through a custom DLL. The signature of this method is as follows:
List<Item> getInterventions(string, string, string, string, string, string)
Item is a custom defined class.
When I try to retrieve the result of getInterventions() on VBA Access code, it pops a VBA Runtime error 242 : object required
The following is my code:
Dim WsObject As Object
Dim result As Object
Set WsObject = CreateObject("Namespace1.Path.To.Class") 'This isn't the actual DLL path as I cannot share that
'Set result = WsObject .getSingleIntervention("123, "0", "123456789", "") ' this works
Set result = WsObject .getInterventions("", "", "123456789", "", "", "") 'this doesn't work
If result Is Nothing Then
'do some stuff
Else
'do some other stuff
End If
getSingleIntervention() is a similar method which returns a single object rather than a list of objects. Returning the result of this method works without issues (see commented line). This proves that both the WS & DLL calls work. This method is defined as follows:
Item getSingleIntervention(string, string, string, string)
I have tested calling getInterventions() directly from the C# code via Visual Studio 2015 with the same parameters I'm passing in my VBA code and it worked. This proves that it's not an issue with parameters or the method content.
My conclusion:
I am guessing it's something to do with the fact that I can't simply store a C# List of objects into a VBA Object.
Any help would be appreciated, thank you.
Please, automatically add mscorlib.tlb reference, running the next code:
Sub addMscorlibRef() 'necessary to use ArrayList
'Add a reference to 'Mscorlib.dll':
'In case of error ('Programmatic access to Visual Basic Project not trusted'):
'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
' check "Trust access to the VBA project object model"
If dir("C:\Windows\Microsoft.NET\Framework64\v4.0.30319", vbDirectory) = "" Then _
MsgBox "You need to install ""Framework version 3.5"".": Exit Sub
On Error Resume Next
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.tlb"
If err.Number = 32813 Then
err.Clear: On Error GoTo 0
MsgBox "The reference already exists...": Exit Sub
Else
On Error GoTo 0
MsgBox """Mscorlib"" reference added successfully..."
End If
End Sub
Then try declaring Dim result As ArrayList.
The ArrayList is the same one that is used in C#. Then, adapt the dll to use such an object. As you deduced, no any object able to be used in VBA can receive the C# list object content.

VB 2013, modify word document property/custom property

I wish to make an add-in to update word document properties. I’m all ready to go with the addin / ribbon / etc. as I have other ribbon functions that are working. I used the MSVS wizard to create the word ribbon project.
I’m stuck on how to; access the active word document, and access the properties/custom properties. I can’t figure out the; declarations, calls, library, etc. I have not been able to make any of the MSDN samples work…. I’m totally missing something.
For example: ‘ActiveDocument.CustomDocumentProperties’ does not work.
Disclaimer - I’m not a coder. I had this all working with vba, I’m trying to port it over to vb. I’m also still reading through the posted help, and trying samples.
Any suggestions would be appreciated. Kind regards,
I got it figured.
Outside the module declare:
Imports moDoc = Microsoft.Office.Interop.Word
Within the sub - This associates the open app with an object:
Dim oActiveApp As moDoc.Application
oActiveApp = GetObject(, "Word.Application")
Now to associate the open app as a document:
Dim mocCustProperties As Microsoft.Office.Core.DocumentProperties
Dim odpProp As Office.DocumentProperty
Now odpProp is an available to read/add properties:
For Each odpProp In mocCustProperties
If odpProp.Name = “something” Then
‘do dtuff
End If
Next
There must be a way to do this by referencing the active document as a document rather than an application, but I was unable to make this work.
Cheers,
Drat - missed a couple lines above - please ignore.
I got it figured.
Outside the module declare:
Imports moDoc = Microsoft.Office.Interop.Word
Within the sub, This associated the open app with the object
Dim oActiveApp As moDoc.Application
oActiveApp = GetObject(, "Word.Application")
oDocCustomProperty = oActiveApp.ActiveDocument.CustomDocumentProperties
Now to associate the open app as a document
Dim mocCustProperties As Microsoft.Office.Core.DocumentProperties
Dim odpProp As Office.DocumentProperty
mocCustProperties = CType(oDocCustomProperty, Office.DocumentProperties)
Now odpProp is an available to read/add propoeties
For Each odpProp In mocCustProperties
If odpProp.Name = “something” Then
‘do dtuff
End If
Next
Learned some more.
I no longer need the:
Imports moDoc = Microsoft.Office.Interop.Word
Using the Office.Core. rather than the Office.Core.Interop
Dim Prop As Microsoft.Office.Core.DocumentProperty
Dim oBuiltInProperties As Microsoft.Office.Core.DocumentProperties
Dim oCustomProperties As Microsoft.Office.Core.DocumentProperties
oBuiltInProperties = DirectCast(Globals.DocSelect.Application.ActiveDocument.BuiltInDocumentProperties, Microsoft.Office.Core.DocumentProperties)
oCustomProperties = DirectCast(Globals.DocSelect.Application.ActiveDocument.CustomDocumentProperties, Microsoft.Office.Core.DocumentProperties)
For Each Prop In oBuiltInProperties
'do stuff
Prop.Name = sx
sy=Prop.Value.ToString
next
'create properties
sx="New Property"
sy="New Property Value"
oCustomProperties.Add(sx, False, Microsoft.Office.Core.MsoDocProperties.msoPropertyTypeString, sy)
All works now.

VBA: Get Excel FileDialogOpen to point to "My Computer" by default

I'm trying to get excels save and open dialog boxes to open to "my computer" by default so the user can select a drive from there.
I have got the dialog boxes to open to any path on any drive or my documents etc but can't seem to find a way for it to open to my computer.
This is the code i'm using at the moment and it works fine for a known path:
MsgBox objFolders("desktop")
ChDrive objFolders("desktop")
ChDir objFolders("desktop")
strFileName = appRemoteApp.Workbooks("Export Template.xlsm").Application.GetSaveAsFilename(objFolders("desktop") & "\Replica Export " & UserName & " " & Format(Date, "yymmdd") & ".xlsm", FileFilter:="Excel Macro Enabled Workbook (*.xlsm), *.xlsm,")
Also, I have found this from this site.
If you paste ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} into windows explorers address bar it takes you to my computer but if I use this in my VBA code
ChDir "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
it says it cant find the directory or something. So not sure if there is a work around for this or something.
This did not work either:
ChDir "C:\WINDOWS\explorer.exe /root,,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
The reason i'm wanting to have the dialog boxs open to computer is that we will be hosting the excel doc on a windows server with access though RemoteApp and remote desktop. The users will not have access (rights) to the servers drives and folders etc, they will only have access to their own drives on their local machines which will be mapped and are visible under the servers "My Computer" folder for lack of a better word. The master document on the server generates a replica using VBA code and is then saved to the users local hard drive.
AFAIK there is no pure VBA solution to override the original behaviour. You can use an alternative from Robert Mearns answer but it doesn't show the windows form so it's less customizable.
Follow this answer if you want to achieve the exact effect - FileOpenDialog.
You can print all the environmental variables using the Environ$() function. This will not show any variable directly pointing to MyComputer therefore you can't pass it to the .InitialFileName property.
MyComputer is not a physical location that you can access through cmd. I think of it as an abstract Interface and it's quite difficult to explain how VBA and .InitialFileName uses a string to access a location.
Well, the only workaround the problem I can think of it's to use an external library written in for example C# that can access the MyComputer.
It's easier than it sounds!
Follow the below steps to create your Custom OpenFileDialog.
You need a Visual Studio Express For Desktop - it's free to download and use.
After installation - run as Administrator! (it's necessary for the libraries to get registered)
Select File and New Project. Rename it to CustomOFD and and hit the OK.
Right-click the CustomOFD Project in the Solution Explorer and Select Add References
Add references to the System.Windows.Forms as shown in the below img
Right-click Class1.cs in the Solution Explorer and rename it to CustomOFD.cs.
Double click your CustomOFD and replace the code with the one from below
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CustomOpenFileDialog
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("541EDD34-4CDC-4991-82E9-6FC23F904B5B")]
public interface ICustomOFD
{
DialogResult ShowDialog();
string FileName();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("E33102F0-B3C0-441C-8E7A-B9D4155A0D91")]
public class CustomOFD : ICustomOFD
{
private OpenFileDialog box = new OpenFileDialog();
public CustomOFD()
{
box.Multiselect = false;
box.Title = "Select file";
box.InitialDirectory = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
}
public DialogResult ShowDialog()
{
return box.ShowDialog();
}
public string FileName()
{
return box.FileName;
}
}
}
Note: you can generate a new GUID for your own class using the Tools => Create GUID and replace it with your own, if you wanted to...
Right-click the CustomFileOpenDialog in the Solution Explorer and select Properties
In the Properties window go to Application tab and click Assembly Info and tick the Make COM-Visible box
Then go to the Build tab and tick Register for COM interop
Right-click the project and select Build from the menu
Now look in the Output tab as it shows you where the library was compiled to
usually its
c:\users\administrator\documents\visual studio 2012\Projects\CustomOpenFileDialog\CustomOpenFileDialog\bin\Debug\CustomOpenFileDialog.dll
Ok. Now save and close VS.
Open Excel and go into VBE ALT+F11 and insert a standard module
Click Tools on the menu bar and select References
Click the Browse button and navigate to the CustomOpenFileDialog.tlb file and click OK add to the list of references
Copy paste the code for module
Option Explicit
Sub Main()
Dim ofd As New CustomOFD
Set ofd = New CustomOFD
ofd.ShowDialog
Debug.Print ofd.Filename
End Sub
finally, run the sub and enjoy the computer as the default location for the customized OpenFileDialog box!
I cannot see a way to use the GetSaveAsFilename or similar dialogs to open on Computer or My Computer.
It is possible to prompt the user to select a folder using VB Script.
The root displayed is Computer and the user can select a folder.
The file can then be saved to the selected folder programatically.
Sub Test()
MsgBox BrowseForFolder(MyComputer)
End Sub
http://technet.microsoft.com/library/ee176604.aspx
Function MyComputer() As Variant
Dim objShell As Object, objFolder As Object
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(&H11&)
MyComputer = objFolder.self.Path
Set objShell = Nothing
Set objFolder = Nothing
End Function
http://www.vbaexpress.com/kb/getarticle.php?kb_id=405
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
Dim ShellApp As Object
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
Set ShellApp = Nothing
End Function
.InitialFileName = "Computer"
Works for me with FileDialog(msoFileDialogFolderPicker)
Tested on Windows Vista - Excel 2007

Previous Excel instance not getting through IIS

I am using VB.NET to open the Excel files but dont want to create excel object every time.
My code is working perfectly in debug mode, but after publish, it never gets the existing instances and always create new instances which we can see from Task Manager. Here is my code which always returns false in published mode.
My OS is Windows Server 2008. Please guide how to solve this.
Function IsExcelRunning() As Boolean
Dim xlApp As Excel.Application
On Error Resume Next
xlApp = GetObject(, "Excel.Application")
IsExcelRunning = (Err.Number = 0)
MyHelper.writeLog("Excel Instance found=" & IsExcelRunning)
xlApp = Nothing
Err.Clear()
End Function
Here is how I call.
If IsExcelRunning() Then
excelApp = GetObject(, "Excel.Application")
Else
excelApp = Server.CreateObject("Excel.Application")
End If
We used to use Excel Interop and I remember it always being difficult to work with (clunky.) Due to the Interop opening an Excel process and not closing it every time you use it, makes it difficult to work with.
The Interop opens Excel automatically, so all we needed to do was close it. This is what we used to use to kill the Process. Replace YourProcessName with Excel.exe.
Dim proc As System.Diagnostics.Process
Dim info As ManagementObject
Dim search As New ManagementObjectSearcher("SELECT ProcessId FROM Win32_process WHERE caption = 'YourProcessName'")
For Each info In search.Get()
Dim TheString As String = info.GetText(TextFormat.Mof).ToString
proc = System.Diagnostics.Process.GetProcessById(Mid$(TheString, _
(Len(TheString) - 8), 4))
proc.CloseMainWindow()
proc.Refresh()
If proc.HasExited Then GoTo NoKill
proc.Kill()
NoKill:
Next
You'll need to import
Imports System.Management
You'll also need to add the reference 'System.Management' to your project.
See: http://msdn.microsoft.com/en-us/library/vstudio/wkze6zky.aspx for adding a reference to a project.
If you can rather work with CSV, I would suggest you try to. If you are creating the Excel file yourself, try to find a report creator that let's you create / export to Excel. You'll save yourself a lot of time in the long run.