How do I display the value of a shared parameter using an Element collector in Revit? - vb.net

Thanks in advance for the help. I have no idea what I'm doing wrong and it's becoming very frustrating. First, a little background...
Program: Revit MEP 2015
IDE: VS 2013 Ultimate
I have created a Shared Parameter file and added the parameters in that file to the Project Parameters. These parameters have been applied to Conduit Runs, Conduit Fittings, and Conduits.
I'm using VB.NET to populate the parameters with no issue. After the code runs, I can see the expected text applied in the elements property window. Here is the code used to populate the values:
Populate:
Dim p as Parameter = Nothing
Dim VarName as String = "Parameter Name"
Dim VarVal as String = "Parameter Value"
p = elem.LookupParameter(VarName) <-- elem is passed in to the function as an Element
If p IsNot Nothing Then
p.Set(VarVal)
End if
Here's where I run into the error. When I attempt to retrieve the value, I am able to get the parameter by the parameter's definition name, but the value is always blank. Here is the code used to retrieve...
Try
For Each e As Element In fec.OfCategory(BuiltInCategory.OST_ConduitRun)
sTemp = sTemp & "Name: " & P.Definition.Name & vbCrLf & "Value: " & P.AsString & vbCrLf & "Value As: " & P.AsValueString & vbCrLf & vbCrLf
sTemp2 = sTemp2 & "Name: " & GetParamInfo(P, doc)
Next
MessageBox.Show(sTemp)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
The message box shows all of the parameter names correctly, and for the Revit parameters it gives me a value. The Shared parameters, however, only show the parameter names, the values are always blank. Is there another way that I'm supposed to be going about this? Oddly, I'm able to see the shared parameter values if I use a reference by user selection like so...
Dim uiDoc As UIDocument = app.ActiveUIDocument
Dim Sel As Selection = uiDoc.Selection
Dim pr As Reference = Nothing
Dim doc As Document = uiDoc.Document
Dim fec As New FilteredElementCollector(doc)
Dim filter As New ElementCategoryFilter(BuiltInCategory.OST_ConduitRun)
Dim sTemp As String = "", sTemp2 As String = ""
Dim elemcol As FilteredElementCollector = fec.OfCategory(BuiltInCategory.OST_ConduitRun)
Dim e As Element = Nothing, el As Element = Nothing
Dim P As Parameter
pr = Sel.PickObject(ObjectType.Element)
e = doc.GetElement(pr)
For Each P in e.Paramters
sTemp = sTemp & "Name: " & P.Definition.Name & vbCrLf & "Value: " & P.AsString & vbCrLf & "Value As: " & P.AsValueString & vbCrLf & vbCrLf
sTemp2 = sTemp2 & "Name: " & GetParamInfo(P, doc)
Next
MessageBox.Show(sTemp)
With the method above, when the user selects the object directly, I can see the values and the names of shared parameters. How are they different?
Is there some sort of binding that I should be looking at when the value is set to begin with? Thanks in advance for everyone's help.
Regards,
Glen

Holy Bejeesus... I figured it out, but I'm not sure why the methods are that different from each other... if anyone had any insight, that'd be great.
I wanted to post the answer here, just in case anyone else is fighting with the same thing, so... you can see the method I was using to try to read the parameters above. In the method being used now there are only a couple of things that are different... 1) An element set... 2) An active view Id was added as a parameter to the FilteredElementCollector... 3) A FilteredElementIterator was implemented.
As far as I can tell it's the iterator that's making it different... can anyone explain what it's doing differently?
Below is the method that actually works...
Public Sub Execute(app As UIApplication) Implements IExternalEventHandler.Execute
Dim prompt As String = ""
Dim uiDoc As UIDocument = app.ActiveUIDocument
Dim doc As Document = uiDoc.Document
Dim ElemSet As ElementSet = app.Application.Create.NewElementSet
Dim fec As New FilteredElementCollector(doc, doc.ActiveView.Id)
Dim fec_filter As New ElementCategoryFilter(BuiltInCategory.OST_Conduit)
fec.WhereElementIsNotElementType()
fec.WherePasses(fec_filter1)
Dim fec_i As FilteredElementIterator = fec.GetElementIterator
Dim e As Element = Nothing
fec_i.Reset()
Using trans As New Transaction(doc, "Reading Conduit")
trans.Start()
While (fec_i.MoveNext)
e = TryCast(fec_i.Current, Element)
ElemSet.Insert(e)
End While
Try
For Each ee As Element In ElemSet
GetElementParameterInformation(doc, ee)
Next
Catch ex As Exception
TaskDialog.Show("ERROR", ex.Message.ToString)
End Try
trans.Commit()
End Using
End Sub
At any rate, thanks for any help that was offered. I'm sure it won't be the last time that I post here.
Regards,
Runnin

Related

Open a file in a new instance of program

All;
I have a bit of code I've written that opens a design blueprint when I scan a bar code. It works well enough, but I'd like to open a new instance of the design software (Solidworks) and have the print display in the new instance. Right now, no matter how many Solidworks instances I have open, the print will only open in the first instance started.
The line commented out below is the line that works, just not in the right instance. The line below that is what I'd expect to work, but it returns a 'file not found' even though the path to solidworks and the print path are both correct.
Any explanation as to why this isn't working would be much appreciated as I'm obviously very new at this...and have no idea what I'm doing.
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim barcode As String = tb_barcode.Text
Dim filename As String = tb_barcode.Text
'Add File Extension to end of path
Dim ext As String = ".SLDDRW"
'Split job number from detail number in barcode textbox
barcode = Split(tb_barcode.Text, ".")(0)
filename = Split(tb_barcode.Text, ".")(1)
'- This works, just in primary instance
'System.Diagnostics.Process.Start("G:\Fixtures\" & barcode & "\Details\" & barcode & " DET " & filename & ext)
'- This does not work
System.Diagnostics.Process.Start("'C:\Program files\Solidworks Corp\Solidwork\SLDWORKS.exe' 'G:\Fixtures\" & barcode & "\Details\" & barcode & " DET " & filename & ext + "'")
Catch
MessageBox.Show("File Not Found")
End Try
End Sub
Sorry for naive approach but shouldn't there be a comma in Process.Start between 2 arguments?
Start(String, String)
Starts a process resource by specifying the name of an application and a set of command-line arguments, and associates the resource with a new Process component. docs
Why don't you use the Application.ExecutablePath.That returns the Application's path with its full name. Then your code should be
System.Diagnostics.Process.Start(Application.Executablepath, "G:\Fixtures\" & barcode & "\Details\" & barcode & " DET " & filename & ext + "'")
Also make sure that the second string argument is a valid path.

"IF" code is not working inside for each?

so im learning to use socket and thread things in the networking software. so far, the software (which is not created by me) is able to chat in multiple group, but i'm tasked to allow user to code whisper feature. However, im stuck in the coding area, which im sure will work if the "if" function work inside "for each" function, anyhow here is my code mainly
Private clientCollection As New Hashtable()
Private usernameCollection As New Hashtable()
clientCollection.Add(clientID, CData)
usernameCollection.Add(clientID, username)
oh and before i forgot, the code above and below is on the server form page
on the client side, i write the code:
writer.write("PMG" & vbnewline & txtReceiverUsername & Message)
then next is the checking part on the server reading the message:
ElseIf message.Substring(0, 3) = "PMG" Then
'filter the message, check who to send to
Dim newMessage As String = message.Substring(3)
Dim messagearray As String() = newMessage.Split(vbNewLine)
Dim receiver As String = messagearray(1)
'0 = "", 1 = receiver, 2 = message
as i write before, clientcollection contain (clientID , connection data*) and usernamecollection contain (clientID, username). In my case, i only have the username data, and i need to trace it until the connection data on clientcollection hash table.
'find realid from usernamecollection, then loop clientcollection
Dim clientKey As String = 0
For Each de As DictionaryEntry In usernameCollection
'''''
'this if part Is Not working
If de.Value Is receiver Then
clientKey = de.Key
End If
'''''
Next de
'match objKey with clientcollection key
For Each dec As DictionaryEntry In clientCollection
If dec.Key = clientKey Then
Dim clients As ClientData = dec.Value
If clients.structSocket.Connected Then
clients.structWriter.Write("PMG" & messagearray(2))
End If
End If
Next dec
End If
so, how do i know that the if part is the wrong one? simply i tried these code before the "next de" code
For Each client As ClientData In clientCollection.Values
If client.structSocket.Connected Then
client.structWriter.Write("PMG" & "receiver:" & messagearray(1))
client.structWriter.Write("PMG" & "loop username: " & de.Value)
client.structWriter.Write("PMG" & "loop key: " & de.Key)
client.structWriter.Write("PMG" & "receiver key:" & clientKey)
End If
Next
the code allow me to check the de.key and de.value. they were correct, however the only thing that did not work is the code inside the "if" area.
Can anyone suggest other code maybe beside "if de.key = receiver"? I've also tried using the if de.key.equal(receiver) and it did not work too

Retrieve CustomXMLParts in Excel Addin using VB.NET

I'm needing a little help retrieving the values stored in a CustomXMLPart in an Excel Addin using VB.NET. I've searched and haven't found a lot of detail on this. From what I've found, the code that I have should work. At first, I thought my xml part wasn't being added so to persist across sessions, but I displayed the count of the CustomXMLParts collection before (3) and after (4) adding my custom xml part and the count did increase by one. I, also displayed the count upon opening the saved Excel workbook and it was the same number (4) after adding my CustomXMLPart to the collection. Here's the pertinent code below. Any help would be greatly appreciated. Need more information just let me know.
In the Excel addin, I have a popup window where I ask for user input and that's the information that I need to persist. In the code behind, that's where I create the xml and add to the collection.
Code:
Dim workbook As Excel.Workbook = Globals.ThisAddIn.Application.ActiveWorkbook
Dim xml As String
xml = "<?xml version=""1.0"" encoding=""utf-8"" ?>" _
& "<refreshViewPointData xmlns=""http://refreshviewpointdata.com"">" _
& "<dataReference>" _
& "<system>" & cboSystem.Text & "</system>" _
& "<library>" & cboLibraries.Text & "</library>" _
& "<view>" & txtObject.Text & "</view>" _
& "<headers>" & chkInclColumnHdrs.Checked.ToString() & "</headers>" _
& "<numOfRecords>" & txtRowCount.Text & "</numOfRecords>" _
& "<reference>" & txtReference.Text & "</reference>" _
& "</dataReference>" _
& "</refreshViewPointData>"
workbook.CustomXMLParts.Add(xml, System.Type.Missing)
In the ThisAddIn_Startup() method of ThisAddIn.vb file is where I attempt to retrieve the CustomXMLPart. I call a RetrieveCustomXMLPart() method from ThisAddIn_Startup().
Code for RetrieveCustomXMLParts():
Dim parts As Microsoft.Office.Core.CustomXMLParts
parts = Application.ActiveWorkbook.CustomXMLParts.SelectByNamespace("http://refreshviewpointdata.com")
If parts.Count > 0 Then
RefreshData(parts.ToString())
End If
Code for RefreshData():
Dim r As New RibbonViewPoint
Dim viewXMLPart As New XmlDocument
Dim system, library, sObject, reference As String
Dim headers As Boolean
Dim numRecords As Integer
'Load the xml from the string.
viewXMLPart.LoadXml(part)
'Retrieve the values from the xml document.
system = viewXMLPart.SelectSingleNode("/dataReference/system").Value
library = viewXMLPart.SelectSingleNode("/dataReference/library").Value
sObject = viewXMLPart.SelectSingleNode("/dataReference/view").Value
headers = CType(viewXMLPart.SelectSingleNode("/dataReference/headers").Value, Boolean)
numRecords = CType(viewXMLPart.SelectSingleNode("/dataReference/numOfRecords").Value, Integer)
reference = viewXMLPart.SelectSingleNode("/dataReference/reference").Value
'Call method to run the object to refresh the data.
r.RunSelectedObject(system, library, sObject, headers, reference, numRecords)
In the RetrieveCustomXMLPart() method, the SelectByNamespace() method is not returning my CustomXMLPart that clearly has the same namespace as what I'm passing in. Anyone know what's wrong?
Also, if anyone has any insight on something else I didn't understand that would be great as well. In the RefreshData() method, I made the viewXMLPart variable as an XMLDocument to load the data and get the values from there. Prior to I had it defined as "Dim viewXMLPart As New Microsoft.Office.Core.CustomXMLPart", which kept giving me a syntax error saying that "'Microsoft.Office.Core.CustomXMLPartClass.Friend Sub New()' is not accessible in this context because it is Friend."
Thanks!!!
Found a solution. The below is what worked.
Dim workbook = Application.ActiveWorkbook
Dim customXMLParts = workbook.CustomXMLParts.SelectByNamespace("urn:viewpoint-refresh")
Dim customXMLPart = customXMLParts.Cast(Of CustomXMLPart)().FirstOrDefault()

Directory.Move isn't trying the correct folder

I have made some code intended to sort all my movies on my PC into subfolders for each letter of the alphabet (e.g. "An Example" would go in a subfolder containing only movies which start with the letter "A".
The code I've written looks to me like it should work without problems, although for some reason this code:
'Declarations
System.IO.Directory.CreateDirectory("D:\Vuze Downloads\Movies\.CAMS")
System.IO.Directory.CreateDirectory("D:\Vuze Downloads\Movies\.TS")
Dim TS As String = "D:\Vuze Downloads\Movies\.TS\"
Dim CAM As String = "D:\Vuze Downloads\Movies\.CAMS\"
Dim mainFolder As New System.IO.DirectoryInfo("D:\Vuze Downloads\Movies\")
For Each f As System.IO.DirectoryInfo In mainFolder.GetDirectories()
If Not UCase(f.ToString).Contains("(CAM)") And UCase(f.ToString).Contains("(TS)") Then
System.IO.Directory.Move(f.ToString, mainFolder.Name & UCase(Left(f.Name, 1)) & "\" & f.Name)
ElseIf UCase(f.Name.ToString).Contains("(CAM)") And Not UCase(f.Name.ToString).Contains("(TS)") Then
System.IO.Directory.Move(f.ToString, CAM.ToString & UCase(Mid(f.Name, 5)) & "\" & f.Name.Substring(5))
ElseIf UCase(f.Name.ToString).Contains("(TS)") And Not UCase(f.Name.ToString).Contains("(CAM)") Then
System.IO.Directory.Move(f.ToString, TS.ToString & UCase(Mid(f.Name, 6)) & "\" & f.Name.Substring(6))
End If
Next
Keeps throwing a exception at this line:
System.IO.Directory.Move(f.ToString, CAM.ToString & UCase(Mid(f.Name, 5)) & "\" & f.Name.Substring(5))
This is the exception:
An unhandled exception of type 'System.IO.DirectoryNotFoundException' occurred in
mscorlib.dll
Additional information: Could not find a part of the path
'D:\Users\Yorrick\documents\visual studio 2012\Projects\filmsort\filmsort\bin\Debug\(CAM)The Internship'.
As indicated by the declarations above, I have no idea how or why this code is trying to access that folder.
If anyone could take a look and hopefully spot the mistake I've made, that would be very much be appreciated.
Edit:
Having fixed the above problem, I encountered a new one.
Using the code below, I now get the same exception, except this time additional information says "Could not find a part of the path." All my variables seem to be correct while debugging, so I seriously can't see why this isn't working.
Note: The commented line is something I tried, which gives me the System.IO.IOException: Cannot create a file when that file already exists.
Code:
System.IO.Directory.CreateDirectory("D:\Vuze Downloads\Movies\.CAMS")
System.IO.Directory.CreateDirectory("D:\Vuze Downloads\Movies\.TS")
Dim TS As String = "D:\Vuze Downloads\Movies\.TS\"
Dim CAM As String = "D:\Vuze Downloads\Movies\.CAMS\"
Dim mainFolder As New System.IO.DirectoryInfo("D:\Vuze Downloads\Movies\")
For Each f As System.IO.DirectoryInfo In mainFolder.GetDirectories()
If Not UCase(f.ToString).Contains("(CAM)") And UCase(f.ToString).Contains("(TS)") Then
System.IO.Directory.Move(f.FullName, mainFolder.FullName & UCase(Left(f.Name, 1)) & "\" & f.Name)
ElseIf UCase(f.Name.ToString).Contains("(CAM)") And Not UCase(f.Name.ToString).Contains("(TS)") Then
'System.IO.Directory.CreateDirectory(CAM & UCase(Mid(f.Name, 6)) & "\" & f.Name.Substring(6))
System.IO.Directory.Move(f.FullName, CAM & UCase(Mid(f.Name, 6)) & "\" & f.Name.Substring(6))
ElseIf UCase(f.Name.ToString).Contains("(TS)") And Not UCase(f.Name.ToString).Contains("(CAM)") Then
System.IO.Directory.Move(f.FullName, TS.ToString & UCase(Mid(f.Name, 5)) & "\" & f.Name.Substring(5))
End If
Next
This happens when you don't specify a full path name, like "c:\foo\bar", but a relative path name, like "bar". Relative path names are turned into full ones by prepending Environment.CurrentDirectory. Which by default is the build directory of your project.
This happened because you used DirectoryInfo.Name. Which is "bar" for a directory whose path is c:\foo\bar. You must use the FullName property instead.
I just rewrote it a bit, i think that should suffice for your purpose.
System.IO.Directory.CreateDirectory("D:\Vuze Downloads\Movies\.CAMS")
System.IO.Directory.CreateDirectory("D:\Vuze Downloads\Movies\.TS")
Dim TS As String = "D:\Vuze Downloads\Movies\.TS\"
Dim CAM As String = "D:\Vuze Downloads\Movies\.CAMS\"
Dim mainFolder As New System.IO.DirectoryInfo("D:\Vuze Downloads\Movies\")
For Each f As System.IO.DirectoryInfo In mainFolder.GetDirectories()
If f.Name.ToUpper.Contains("(TS)") Then
System.IO.Directory.Move(f.FullName, System.IO.Path.Combine(TS, f.Name))
ElseIf f.Name.ToUpper.Contains("(CAM)") Then
System.IO.Directory.Move(f.FullName, System.IO.Path.Combine(CAM, f.Name))
End If
Next

How do I customize the auto commenting text in Visual Studio?

When I type the trigger the auto comment feature in Visual Studio (by typing "'''" or "///"), most of the XML commenting details show up that I like. However, I typically add the history tag to the documentation so I can track and changes that are made to the method over time.
Is there any way I can customize the auto commenting feature so that it will add the history tag, and potentially some generic Name - Date - Change placeholder text?
I'd suggest using GhostDoc. It generates very smart comments using /// based on your method names and parameters. Also, it is fully customizable.
I think that you could use a tool as dgarcia said but try to chose one that makes the version control insetad, Personally I'm not a huge fan of keep the "history" or track of the project using comments in the code.
If you like that way you could create your own customized version of the snippet, this is easier if you use a tool like Snippy
Copy this file to your
My Documents\Visual Studio 2005\Code Snippets[Language]\My Code Snippets\
Just be carefull to change the file if you gonna use it in VB.NET
Hope this help
Just as followup to the comment to Olivier. Here is a copy of the macro now, look for the '' Do History section to see where I inserted code.
''// InsertDocComments goes through the current document using the VS Code Model
''// to add documentation style comments to each function.
''
Sub InsertDocComments()
Dim projectItem As ProjectItem
Dim fileCodeModel As FileCodeModel
Dim codeElement As CodeElement
Dim codeElementType As CodeType
Dim editPoint As EditPoint
Dim commentStart As String
projectItem = DTE.ActiveDocument.ProjectItem
fileCodeModel = projectItem.FileCodeModel
codeElement = fileCodeModel.CodeElements.Item(1)
''// For the sample, don't bother recursively descending all code like
''// the OutlineCode sample does. Just get a first CodeType in the
''// file.
If (TypeOf codeElement Is CodeNamespace) Then
codeElement = codeElement.members.item(1)
End If
If (TypeOf codeElement Is CodeType) Then
codeElementType = CType(codeElement, CodeType)
Else
Throw New Exception("Didn't find a type definition as first thing in file or find a namespace as the first thing with a type inside the namespace.")
End If
editPoint = codeElementType.GetStartPoint(vsCMPart.vsCMPartHeader).CreateEditPoint()
''// Make doc comment start.
commentStart = LineOrientedCommentStart()
If (commentStart.Length = 2) Then
commentStart = commentStart & commentStart.Chars(1) & " "
ElseIf (commentStart.Length = 1) Then
commentStart = commentStart & commentStart.Chars(0) & commentStart.Chars(0) & " "
End If
''// Make this atomically undo'able. Use Try...Finally to ensure Undo
''// Context is close.
Try
DTE.UndoContext.Open("Insert Doc Comments")
''// Iterate over code elements emitting doc comments for functions.
For Each codeElement In codeElementType.Members
If (codeElement.Kind = vsCMElement.vsCMElementFunction) Then
''// Get Params.
Dim parameters As CodeElements
Dim codeFunction As CodeFunction
Dim codeElement2 As CodeElement
Dim codeParameter As CodeParameter
codeFunction = codeElement
editPoint.MoveToPoint(codeFunction.GetStartPoint(vsCMPart.vsCMPartHeader))
''//editPoint.LineUp()
parameters = codeFunction.Parameters
''// Do comment.
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.LineUp()
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart & "<summary>")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart & "Summary of " & codeElement.Name & ".")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart & "</summary>")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart)
For Each codeElement2 In parameters
codeParameter = codeElement2
editPoint.Insert("<param name=" & codeParameter.Name & "></param>")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart)
Next ''//param
''// Do history tag.
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.LineUp()
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart & "<history>")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart & "Name MM/DD/YYYY [Created]")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart & "</history>")
editPoint.Insert(Microsoft.VisualBasic.Constants.vbCrLf)
editPoint.Insert(Microsoft.VisualBasic.Constants.vbTab & commentStart)
End If ''//we have a function
Next ''//code elt member
Finally
DTE.UndoContext.Close()
End Try
End Sub
For some reason, after a save, rebuild, and a restart of Visual Studio, I'm not getting the history tag. Can anybody see something here I'm missing?
vb uses a xml file to load the defults. It is VBXMLDoc.xml and it depends on what version you are running as to the location of the file.