I am really new to VBA. I know C,C++ python etc. but I am unable to get grasp of VBA. How to start learning Microstation VBA from the scratch.
Learning VBA from scratch
[CONNECT] Shared Cell Instance and Text Field
I'm seeking advice on the use of text fields in a shared cell.
Suppose I create a normal cell that contains text fields. When that cell is placed, I can programmatically hook up each text field with a property of a target element. The text fields display the properties of that target element, and update automatically if those properties change. I can place multiple normal cell instances, each instance being associated with a different target element.
Suppose I want to place that same cell as a shared cell instance. What happens if I perform the same hook up? Does each shared cell instance break, because it's now changed from the shared cell definition? Or, can multiple instances of the same shared cell contain text fields that are associated with different host elements?
VBA and Feature Solids
I am using MicroStation CE Update 9 and writing VBA code to get level and colour information from cells placed on the drawing. This code works well until it encounters a feature solid as part of the cell. The element.type is reported as type 2 (CellHeader) and I can get the colour but it is not relevant to me for the cell header element. I need the level and colour combination of the cell components, so I recurse through the sub elements of the cell, which works for the usual graphics element types but fails for feature solids.
I have attempted to get the sub elements of the feature solid. I have also tried to drop the feature solid to access the sub elements, but VBA does not allow me to drill any deeper. I receive the error message 'Run-time error 430: Class does not support Automation or does not support expected interface'. I am half expecting that the VBA interface does not support feature solids, but seek clarification on this.
It is important to me to be able to get the level and colour information on a feature solid, and important for me to be able to set this information also. Can anyone advise me on whether VBA will allow me to achieve this goal. I could previously achieve this using MDL. Will .NET allow me to get and set this information, or am I required to be using Visual Studio and the full development environment?
I do not expect you to need sample code to answer this, but just in case it helps, I have a mock up of code to demonstrate what I am doing. The graphics that I am working with has the common structure as shown below. Any advice will be greatly appreciated.
Cell Header
- line (level 25)
- line (level 26)
- arc (level 27)
or
Cell Header
- feature solid (level 25)
- feature solid (level 26)
- feature solid (level 27)
Sub CountColours() Dim oCellElement As CellElement Dim oElement As Element Dim ee As ElementEnumerator Dim esc As ElementScanCriteria Set esc = New ElementScanCriteria esc.ExcludeNonGraphical esc.ExcludeAllTypes esc.IncludeType msdElementTypeCellHeader Set ee = ActiveModelReference.Scan(esc) Do While ee.MoveNext Set oElement = ee.Current If oElement.Type = msdElementTypeCellHeader Then Set oCellElement = oElement.asCellElement Call CountColoursByLevel(oElement) End If Loop End Sub Private Sub CountColoursByLevel(oElement As Element) Dim oCellElement As CellElement Dim oee As ElementEnumerator Dim ose As Element Dim oLevel As Level Dim iColour As Long If oElement.Type = msdElementTypeCellHeader Then Set oCellElement = oElement.AsCellElement Set oee = oCellElement.GetSubElements Do While oee.MoveNext Set ose = oee.Current If ose.Type = msdElementTypeCellHeader Then Set oLevel = ose.Level If oLevel Is Nothing Then 'this may be a feature solid Set oLevel = GetLevelFromDropped(ose) End If End If If ose.Type = msdElementTypeBsplineSurface Then GoTo nextelement End If If ose.Type = msdElementTypeBsplineBoundary Then GoTo nextelement End If If ose.Type = msdElementTypeBsplineKnot Then GoTo nextelement End If If ose.Type = msdElementTypeBsplineCurve Then GoTo nextelement End If If ose.Type = msdElementTypeBsplineWeight Then GoTo nextelement End If If ose.Type = msdElementTypeSurface Then GoTo nextelement End If Set oLevel = ose.Level iColour = ose.Color'code to count colours based on the level has been removed from here nextelement: Loop End If End Sub Private Function GetLevelFromDropped(oElement As Element) Dim ode As DroppableElement Dim oeed As ElementEnumerator Dim osed As Element Dim oLevel As Level Set GetLevelFromDropped = Nothing If oElement.IsDroppableElement Then Set ode = oElement.AsDroppableElement Set oeed = ode.Drop Do While oeed.MoveNext Set osed = oeed.Current Set oLevel = osed.Level If oLevel Is Nothing Then 'do nothing Else Set GetLevelFromDropped = oLevel Exit Function End If Loop End If End Function
[MSCE C#]How can i get the DgnTextStyle?
I'd like to get a DgnTextStyle from an TextElement ,but that returns IsNull().
TextElement txtElement = dgnmodel.FindElementById(el.ElementId) as TextElement; DgnTextStyle textstyle = DgnTextStyle.GetSettings(dgnfile); DgnTextStyle dgntext = DgnTextStyle.GetById(txtElement.ElementId,dgnfile);
Error code 77842 of function mdlSystem_newDesignFile
Hello,
what could mean error code 77842 of function mdlSystem_newDesignFile (Bentley::MstnPlatformNET::Session::Instance->NewDesignFile)? Nowhere I found a link to possible error codes of this function.
I'm using MS CE Update 10 (and prerelease of Update 11).
Thank you for your answer
Jaroslav Omasta
[Connect] How to save application specific data in a dgn document
Hi
I would like to save some application specific data in the design file. In V8i it was possible to save data in an ApplicationElement. I haven't found any way to do that in the new API in C#. Then I looked for a way to do it in the C++ API but the only way I've found so far is the applcelm example but the documentation sais: "It should be noted that this API is no longer recommended.". Now my question is: What is the preferred / recommened way to save application specific data in a design file ?
TIA
Regards Evan
VBA - Why wont this work after initial use?
I'm working on a userform that will allow you to quickly change the dimension accuracy just for learning purposes.
The code works the first time its ran but will not work again UNLESS I use the "Change Dimension" tool to set the dimension('s) back to default. Why wont this update every time I hit OK?
I imagine its something simple that I'm over looking.
Keep in mind I did not provide any code for the userform functions, that is were "oDimAcc" is declared.
Sub Test()'Scan all dimensions & change dimension accuracy Dim ee As ElementEnumerator Dim sc As New ElementScanCriteria Dim oDimension As DimensionElement Dim oDimstyle As DimensionStyle Set ee = ActiveModelReference.GetSelectedElements Do While ee.MoveNext Loop sc.ExcludeAllTypes sc.IncludeType msdElementTypeDimension Set ee = ActiveModelReference.Scan(sc) Do While ee.MoveNext Set oDimension = ee.Current For I = 1 To oDimension.SegmentsCount Set oDimstyle = oDimension.DimensionStyle If oDimAcc = "Zero" Then oDimstyle.PrimaryAccuracy = msdDimAccuracy0 End If If oDimAcc = "Half" Then oDimstyle.PrimaryAccuracy = msdDimAccuracyHalf End If If oDimAcc = "4th" Then oDimstyle.PrimaryAccuracy = msdDimAccuracy4th End If If oDimAcc = "8th" Then oDimstyle.PrimaryAccuracy = msdDimAccuracy8th End If If oDimAcc = "16th" Then oDimstyle.PrimaryAccuracy = msdDimAccuracy16th End If If oDimAcc = "32th" Then oDimstyle.PrimaryAccuracy = msdDimAccuracy32nd End If If oDimAcc = "64th" Then oDimstyle.PrimaryAccuracy = msdDimAccuracy64th End If oDimension.DimensionStyle = oDimstyle oDimension.Rewrite oDimension.Redraw Next I Loop End Sub
[CONNECT DLLs] Where is mdlSystem_getTaskStatistics() Implemented?
With V8i, mdlSystem_getTaskStatistics
was implemented in stdmdlbltin.dll
. In 32-bit VBA, this declaration works:
Declare Function mdlSystem_getTaskStatistics Lib "stdmdlbltin.dll" ( _ ByVal statisticsP As Long, _ ByVal taskIdP As String) As Long
With CONNECT I use a modified declaration for 64-bit VBA:
Declare PtrSafe Function mdlSystem_getTaskStatistics Lib "stdmdlbltin.dll" ( _ ByVal statisticsP As LongPtr, _ ByVal taskIdP As String) As Long
However, VBA can't find that function's implementation. Neither do I see it when I examine the exports from that DLL. Where is it?
Openroads Designer MDL - Changing feature definition using C# ?
Hi All,
I am trying to find a way to set the feature definition of geometry objects based on their feature names.
So a centreline with a feature name starting with 'CL' would be given the 'Geom Centreline' feature definition etc..
I don't think it can be done in Openroads itself automatically? I could do it manually but there are hundreds of objects with varying names.
I have looked through both the Microstation and Openroads Designer API docs that are provided with the Openroads SDK, but I can't find ANY references to feature definitions or Openroads-specific properties of geometry objects.
Can anyone help?
Many thanks
Travis
[CONNECT C++] How to Set Item Type Property to Read Only
I noticed that DgnECInstance has a function IsPropertyReadOnly(), but I don't see a corresponding SetPropertyReadOnly(). Is there a way to set a property within an Item Type grouping to read-only? I have tried SetReadOnly thinking this would be applied to all properties in the DgnECInstance, but this doesn't seem to work.
The function doc indicates "...it may be ignored if implementation does not support...". Since it didn't work I'm going to assume my implementation doesn't support it. Any ideas how to implement a DgnECInstance that supports read-only? This would be a work-around as I would prefer to set permissions on individual props. Any thoughts welcome!
[CONNECT C#/C++/VBA] OpenRoads - Model Flags/Properties - Annotation Cell
Versions: OpenRoads Designer and SDK Update 4: 10.04.00.48. And MicroStation Update 10 (10.10.00.32 and SDK 10.10.00.23).
I am trying to create a model (a cell) that can be placed as annotation cell. The model gets created as expected, but fails to set CanBePlacedAsAnnotationCell to true. I have set this as a discussion since I found a solution. But I do have a basic question - that is, why doesn't the C# or C++ versions work? Or, what did I miss? Suggestions welcome!
Here's my C# code...
DgnFile df = Session.Instance.GetActiveDgnFile(); // to-do: delete model if it already exists DgnModelStatus error; ModelInfo mi = df.CreateNewModel(out error, modeName, DgnModelType.Normal, false, null).GetModelInfo(); mi.IsAnnotationCell = true; mi.IsUseAnnotationScaleOn = true; mi.PropagateAnnotationScale = true;
Based on what I've been able to determine from other posts, this should be enough to set the model to place an annotation cell. What am I missing?
I also tried to create the model in C/C++. Basically the same thing - and same result.
DgnModelP tmpMdl = CreateTemp2DDesignModel(m_assemblyTypeData[0]); DgnFileP dgnFileP = ISessionMgr::GetActiveDgnFile(); mdlModelRef_setModelFlag(tmpMdl, MODELFLAG_IS_ANNOTATION_CELL | MODELFLAG_USE_ANNOTATION_SCALE, TRUE); // I thought above should be enough, but it was not. // Attempted the following based on ModelExampleHelper.cpp // looks pretty much like c# - still fails to set the CanPlaceAsAnnotationCell to true DgnModelPtr dgnModelPtr = dgnFileP->LoadModelById(tmpMdl->GetModelId()); ModelInfoPtr modelInfoPtr = dgnModelPtr->GetModelInfo().MakeCopy(); modelInfoPtr->SetIsAnnotationCell(TRUE); modelInfoPtr->SetPropagateAnnotationScale(TRUE); modelInfoPtr->SetIsUseAnnotationScaleOn(TRUE);
I didn't give up - MVBA does what I want.
Sub TestCreateModel() Dim mdl As ModelReference, template As ModelReference On Error GoTo ERRORHANDLER Set template = ActiveDesignFile.DefaultModelReference Set mdl = ActiveDesignFile.Models.Add(template, "testmodel", "na", msdModelTypeNormal, False) mdl.CanBePlacedAsAnnotationCell = True Exit Sub ERRORHANDLER: Debug.Print "Exception: " + Err.Description End Sub
So, since MVBA worked, I have implemented the COM solution in C#.
BCOM.ModelReference template = App.Context.ActiveDesignFile.DefaultModelReference; BCOM.ModelReference mdl = App.Context.ActiveDesignFile.Models.Add(template, modelName, "na", BCOM.MsdModelType.Normal, false); mdl.CanBePlacedAsAnnotationCell = true;
And this produces what I want. My concern - based on several CONNECT programming posts, COM is discouraged and MstnPlatformNet, DgnPlatformNet are encouraged. But, it works so I'll stick with it for now.
Please discuss.
[CONNECT C++] Place Nested Cell with Annotation Scale
I am trying to place a nested cell (cell model containing cells) with annotation scale. The placement works, and when viewed in properties, the cell and its children show as annotation cells. When I change the annotation scale however, the cells do not change size. I also placed this cell using place cell command in MicroStation with the same results. This question was asked earlier this year, but there was no response. Does anyone know if this is a reported issue? Or is there a way to place cells so that they respect annotation scale?
I don't know if there is much to gain from my code, but here are the dynamics and create functions...
void Ds_DragSection ( DPoint3dCP ptP, int view, DgnPlatform::DgnDrawMode drawMode ) { DgnFileP dgnFileP = ISessionMgr::GetActiveDgnFile(); MSElementDescr *cellDescr = NULL; // not sure if model in current file will be found - try first we can add the filename to the library later mdlCell_getElmDscr(&cellDescr, NULL, ptP, NULL, true, NULL, NULL, 0, 0, false, m_assemblyTypeData[0], dgnFileP); if (cellDescr) { if (cellDescr->el.hdr.dhdr.props.b.is3d) { Cell_3d *cell = (Cell_3d *) &(cellDescr->el); cell->flags.isAnnotation = TRUE; } else { Cell_2d *cell = (Cell_2d *) &(cellDescr->el); cell->flags.isAnnotation = TRUE; } Transform tMatrix; memset(&tMatrix, 0, sizeof(Transform)); mdlTMatrix_fromPointAndScale(&tMatrix, ptP, annoScale); mdlElmdscr_transform(&cellDescr, &tMatrix); mdlElmdscr_display(cellDescr, mdlModelRef_getActive(), drawMode); mdlElmdscr_freeAll(&cellDescr); } } void Ds_CreateSection ( DPoint3dCP ptP, int view ) { DgnFileP dgnFileP = ISessionMgr::GetActiveDgnFile(); MSElementDescr *cellDescr = NULL; // m_assemblyTypeData[0] comes from gui mdlCell_getElmDscr(&cellDescr, NULL, ptP, NULL, true, NULL, NULL, 0, 0, false, m_assemblyTypeData[0], dgnFileP); if (cellDescr) { // required for mdlCell_getElmDscr? Not required with mdlCell_placeCell if (cellDescr->el.hdr.dhdr.props.b.is3d) { Cell_3d *cell = (Cell_3d *) &(cellDescr->el); cell->flags.isAnnotation = TRUE; } else { Cell_2d *cell = (Cell_2d *) &(cellDescr->el); cell->flags.isAnnotation = TRUE; } // applying scale transform because anno scale does not work Transform tMatrix; memset(&tMatrix, 0, sizeof(Transform)); mdlOutput_printf(MSG_MESSAGE, L"annoScale = %f", annoScale); mdlTMatrix_fromPointAndScale(&tMatrix, ptP, annoScale); mdlElmdscr_transform(&cellDescr, &tMatrix); mdlElmdscr_display(cellDescr, mdlModelRef_getActive(), DRAW_MODE_Normal); mdlElmdscr_add(cellDescr); mdlElmdscr_freeAll(&cellDescr); } mdlState_startDefaultCommand(); }
I have also tried using the mdlCell_placeCell method with the same result.
I also set the model flags/properties before starting the primitive command.
mdlModelRef_setModelFlag(mdlModelRef_getActive(), MODELFLAG_USE_ANNOTATION_SCALE | MODELFLAG_USE_ANNOTATION_SCALE, TRUE);
If the sub elements are not nested then the cell placed by this code respects annotation scale - that is, it changes size when annotation scale is changed.
[CONNECT C#] Model Flags/Properties - Annotation Cell
Version: MicroStation Update 10 (10.10.00.23 and SDK 10.10.00.32).
I don't know why, but the forum admin decided my previous post on this subject was better suited for the Civil forum - and moved it. I suppose it is my fault since I included the product title that I was using to run my code in the subject line. So, I am posting again - this time as a question, and this time specifically about the MicroStation SDK and C#.
Why doesn't the following create a new model with the CanPlaceAsAnnotationCell set to true? Am I missing a step?
DgnFile df = Session.Instance.GetActiveDgnFile(); DgnModelStatus error; ModelInfo mi = df.CreateNewModel(out error, "TESTMODEL", DgnModelType.Normal, false, null).GetModelInfo(); mi.IsAnnotationCell = true; mi.IsUseAnnotationScaleOn = true; mi.PropagateAnnotationScale = true;
So, this fails to create the model I want in both the civil app I am using and in MicroStation Update 10.
I can reproduce the same issue with MicroStation API in C++.
The interesting thing is that the following COM object code does what I want (my work around):
BCOM.ModelReference template = App.Context.ActiveDesignFile.DefaultModelReference; BCOM.ModelReference mdl = App.Context.ActiveDesignFile.Models.Add(template, modelName, "na", BCOM.MsdModelType.Normal, false); mdl.CanBePlacedAsAnnotationCell = true;
Las file loading without converting into pod
Hi Team,
Programmatically can i load las file directly into MicroStation V8i (SELECTseries 4) Version 08.11.09.829 without converting into pod format ?
Thank you,
B Daniel.
Error in Microstation V8i macro: "VBA interface error
We are using Microstation V8i on Win 10, we were using a simple macro to update title block information but it stopped working, we are getting this error: "VBA interface error: unable to run macro-project, module, or macro not found. We checked VBA project manager and the path is correct and all files are there. We uninstalled Microstation and installed again an macro files as well still not working. Any ideas?
Macro name is EBT, it is in VBA project manager
Still getting same error:
Thanks,
Curve by formula help, syntax entered incorrectly?
Good afternoon,
I'm attempting to write a formula for the Curve by Formula tool, but can't seem to get it right. Was wondering where my syntax error is occurring. I've double checked the formula on a graphing site and it creates a curve, so I should be getting the tool to create something. I can't seem to figure out where I'm going wrong.
The original function is:
y = 9.5 * SquareRoot(1-(x^2/23.75^2))
and the syntax I'm trying to use in Microstation Curve by Formula box is:
x=23.75*t;
y=9.5*sqrt((1-(pow(x,2)/pow(23.75,2))));
where x is the total length.
Thoughts and/or input?
Much thanks,
Jeremy
[CONNECT C#] CellLibraryInfo Performance
Versions: OpenRoads Designer and SDK Update 4: 10.04.00.48. And MicroStation Update 10 (10.10.00.32 and SDK 10.10.00.23).
I am using CellLibraryCollection and CellLibraryInfo to find cells and I've noticed that it is slow - meaning it takes at least 350ms but I have measurements as high as 1s 485ms.
Bentley.MstnPlatformNET.CellLibraryCollection clc = new Bentley.MstnPlatformNET.CellLibraryCollection(Bentley.MstnPlatformNET.CellLibraryOptions.DefaultAll); Bentley.MstnPlatformNET.CellLibraryInfo ci = clc.FirstOrDefault(a => a.Name == blockName);
Normally this would not be an issue, but I am trying to build a validation routine that checks a cellname against MS_CELLLIST. And, I have 2000 of these to check. Even at the low end that's about 12 minutes to run the process.
I've also tried using a C++ function to test. In this case I get faster times, but I 50% plus searches take more than a second. Not sure what gives there. The overall time to complete still seems to be about 12 minutes. I suppose it could be the overhead imposed by pinvoke. Here's the C++, maybe there is something up with it.
extern "C" bool CellExistsInCellList(wchar_t* cellname) { bool result = false; MSElementDescr *cellDescr = NULL; DPoint3d p = { 0.0, 0.0, 0.0 }; mdlCell_getElmDscr(&cellDescr, NULL, &p, NULL, true, NULL, NULL, 0, 0, true, cellname, NULL); if (cellDescr) { result = true; mdlElmdscr_freeAll(&cellDescr); } return result; }
I will try adding the cell library file to the call to see if that will speed things up - just wanted to get this out there in case someone else had an idea.
[CONNECT C++] mdlTag_create always fails with error
Hi,
i want to add a tag containing a string to a shared cell, which is currently selected. The shared cell was created using a DWG file which i had imported using "Place active cell". Below you can see my code. Unfortunately mdlTag_create always returns BentleyStatus::ERROR. I am not sure what is wrong here. You can see in my comments, that i tried several things already.
My goal is to add a special serial number string to shared cells, which originated from DWG files from my company. This will allow me to identify our parts in Microstation after they have been placed by the user. For certain reasons it is technically not possible for me to add the serial number inside the DWG file before it is imported to Microstation as a shared cell.
SelectionSetManagerR selectionSetManager = SelectionSetManager::GetManager(); size_t numElements = selectionSetManager.NumSelected(); for (int i = 0; i < numElements; i++) { // Get the next elementreference ElementRefP pElement; DgnModelRefP pModelRef; int status = selectionSetManager.GetElement(i, &pElement, &pModelRef); int elementType = elementRef_getElemType(pElement); if (elementType == 35) // Shared cell instance { // Get the selected element and its id MSElement msElement; size_t numBytes = elementRef_getElement(pElement, &msElement, sizeof(msElement)); ElementId elementID = mdlElement_getID(&msElement); // Create a set (TODO: Free the tag defintion) DgnTagDefinitionP tagDef = (DgnTagDefinition*)dlmSystem_mdlCalloc(1, sizeof(DgnTagDefinition)); memset(tagDef, 0, sizeof(DgnTagDefinition)); mdlTag_createSetDef(L"MyNewSet", NULL, 0, tagDef, 1, ACTIVEMODEL); // Create the tag spec DgnTagSpec spec; //memset(&spec, 0, sizeof(DgnTagSpec)); wcscpy(spec.tagName, L"MyNewtag"); wcscpy(spec.set.setName, L"MyNewSet"); //wcscpy(spec.set.reportName, L"MyReport"); spec.set.modelRef = ACTIVEMODEL; spec.set.ownerID = 0; DgnTagValue tagValue(L"Teststring"); //UShort tagProps = ~TAG_PROP_DISPOFF; UShort tagProps = TAG_PROP_DISPOFF; //UShort tagProps = 0; // Create the tag element MSElement tagElement; int ret = mdlTag_create(&tagElement, NULL, &spec, &tagProps, &tagValue, &elementID, NULL, NULL, NULL, NULL, NULL); if (ret == SUCCESS) { // Add the tag element if (!mdlElement_add(&tagElement)) ret = mdlErrno; } } }
[CONNECT C++] How to create a new OptionButtonSubItem
I'm attempting to instantiate a OptionButtonSubItem object, but I can figure it out - What I'm doing will compile/link but it crashes MicroStation:
OptionButtonSubItem subItem = OptionButtonSubItem(); // this isn't correct either // OptionButtonSubItem subItem();
Batch find String and change color
Hello all,
Using the following sample code, I would I find batch find a specific string and change that string to a specific color?
MDL SILENTLOAD FINDREPLACETEXT,CHNGTXT CHANGE DIALOGTEXT
FIND DIALOG SEARCHSTRING XX/XX/XX
FIND DIALOG REPLACESTRING 9/28/18
CHANGE TEXT ALLFILTERED
Thank you