How to Unload a revit link file or how to set the revit link file invisible ?

How to Unload a revit link file or how to set the revit link file invisible ?

Anonymous
Not applicable
5,513 Views
16 Replies
Message 1 of 17

How to Unload a revit link file or how to set the revit link file invisible ?

Anonymous
Not applicable

Hi all,

 

I've got 2 question when I try to unload and set the revit link file invisible, please give me a hand.

 

Question1:

I want to unload a revit link file using the RevitLinkType's method Unload() method, but the RevitLinkType's method Unload() need a parameter called "ISaveSharedCoordinatesCallback" and I don't know what should be the parameter.

 

Question2:

I want to set the revit linked file to be invisible, but the following code will clash when run:

Category cat = doc.Settings.Categories.get_Item(BuiltInCategory.OST_RvtLinks);

 

so the following code curView.setVisibility(cat, false);   cannot run.

 

Any one can give me a hand ? 

Thx & rgds,

 

Davix

0 Likes
5,514 Views
16 Replies
Replies (16)
Message 2 of 17

Anonymous
Not applicable

Hello Davix,

 

1. I havn't used ISaveSharedCoordinatesCallback or looked in to it, but if you are not using shared coordinates/ don't want to save coordinates to your link, you can set this value to null. Another way to unload a link is to access TransmissionData and collect all external refrences in the model. I'm pretty sure there are an example of this in the revit Developer guide you can look at if you're not familiar with this.

 

2. From what I know, curView.setVisibility(cat, false); would only work for Model categories, annotation categories, Import Categories and Analytical Model Categories. The only way to uncheck the visibility of a link would be by applying a view template that you had manually unchecked before applying it. You could ofcourse use View.HideElements() in the view if that servres your purpose.

 

Hope that helped

 

/Martin

0 Likes
Message 3 of 17

jeremytammik
Autodesk
Autodesk

Dear Davix,

 

The simplest way to find out more about the ISaveSharedCoordinatesCallback interface is to look it up the Revit API help file RevitAPI.chm.

 

You have installed the Revit SDK and set up a shortcut to the help file, haven't you?

 

I will not answer a single other question from you before you have!

 

🙂

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 4 of 17

Anonymous
Not applicable

Hello maer6427,

 

Firstly, for your reply.

However, I encounter two problems when test your two suggestions respectly:

 

1, when I test to use the TransmissionData to get the revit link file, I can not get the file. I test to prompt the ID of the revit link file when link it and get the it in the TransmissionData, it turn out that the IDs are different. And in the TransmissionData, I get the extRef.ExternalFileReferenceType.ToString()) from the TransmissionData is Keynotetable but not ExternalFileReferenceType.RevitLink. The codes are as below:

 

// ---------Create the revit link file ------------------------------
public bool CreateRevitLink(Document doc, string pathName)
{
FilePath path = new FilePath(pathName);
RevitLinkOptions options = new RevitLinkOptions(false);
RevitLinkLoadResult result = RevitLinkType.Create(doc, path, options);
TaskDialog.Show("Load Link", result.ElementId.ToString());                                // show the ID here
RevitLinkInstance.Create(doc, result.ElementId);
return true;
}

// ------end of ---Create the revit link file ------------------------------

 

// --------unload the revit file -------------------------------------------------

path = @"C:\04 study\BIM Project\CityBIM\models\2014\PM5113_2014_A0123413X_XueHuaBin.rvt";
UnloadRevitLinks(ModelPathUtils.ConvertUserVisiblePathToModelPath(path));

 

void UnloadRevitLinks(ModelPath location)
{
TransmissionData transData = TransmissionData.ReadTransmissionData(location);
TaskDialog.Show("unlink", "in UnloadRevitLinks -----" + transData.ToString());
if (transData != null)
{
// collect all(immediate) external references in the model
ICollection<ElementId> externalReferences = transData.GetAllExternalFileReferenceIds();

TaskDialog.Show("unlink", "count ----- " + externalReferences.Count().ToString());

// find every reference that is a link
foreach (ElementId refId in externalReferences)
{
ExternalFileReference extRef = transData.GetLastSavedReferenceData(refId);

TaskDialog.Show("unlink", "in UnloadRevitLinks -----" + refId.ToString()); // prompt keynotetable
TaskDialog.Show("unlink", "in UnloadRevitLinks -----" + extRef.ExternalFileReferenceType.ToString());
TaskDialog.Show("unlink", "in UnloadRevitLinks -----" + extRef.GetPath().ToString());
TaskDialog.Show("unlink", "in UnloadRevitLinks -----" + extRef.PathType.ToString());

transData.SetDesiredReferenceData(refId, extRef.GetPath(), extRef.PathType, false);

// ---- can not go inside here
if (extRef.ExternalFileReferenceType == ExternalFileReferenceType.RevitLink)
{
TaskDialog.Show("unlink", "in UnloadRevitLinks -----4");
// set the links to be unloaded (shouldLoad == false)
transData.SetDesiredReferenceData(refId, extRef.GetPath(), extRef.PathType, false);
}

}

// make sure the IsTransmitted property is set
transData.IsTransmitted = true;

// modified transmission data must be saved back to the model
TransmissionData.WriteTransmissionData(location, transData);
}
else
{
TaskDialog.Show("Unload Links", "The document does not have any transmission data");
}
}

 

// -------------------------------------------------------------------------------

 

 

2, When I try to find the categories of the revit link file, it turn out that it can not be get, please read this problem I raised this evening

http://forums.autodesk.com/t5/revit-api/a-strange-problem-intesting-the-revit-link-file/td-p/5508484

 

Please help to find the problems.

 

Thx & rgds,

 

Davix

0 Likes
Message 5 of 17

Anonymous
Not applicable

Dear Jeremy,

 

I have not installed the the Revit SDK but I did search in the "RevitAPI 2015.chm", it tells :

Syntax:

C#

public void Unload(
	ISaveharedCoordinatesCallback callback
)

 

Because I've stopped coding for several years until recently, I'm not so familiar how to apply the method.

Really struggling !

 

Thx & rgds !

 

Davix

 

0 Likes
Message 6 of 17

arnostlobel
Alumni
Alumni

I believe there is no need to get touchy. On one hand I perfectly well understand the frustration API users sometimes get through. Programming with the Revit API is not always simple (though we never promised it would be) and I too very well am aware that the documentation is often lacking. On the other hand, however, I too understand Jeremy’s point – he suggests searching the Revit SDK and the RevitAPI.CHM documentation in particular not becasue he does not want to answer (he is Jeremy, after all), but rather because reading the RevitAPI help is often the fastest and most satisfactory approach.

 

For example, in the case of the RevitLinkType.Unload method and its callback argument, the documentation has the following to statement:

 

A callback indicating what to do if Revit encounters links which have changes in shared coordinates. If null reference (Nothing in Visual Basic), Revit will not save any shared coordinates changes to the link before unloading.

 

Forgive me, but I find it rather self-explanatory, particularly because the approach tightly corresponds to Revit UI for the same action. If a Revit link is to be unloaded via the UI, there might also be a message box shown asking the end-user whether or not modified shared coordinates are to be saved. The callback argument, if provided, serves the very same purpose in the API version. If the argument is not null, it is an instance of a class that implements the ISaveSharedCordinatesCallback. If during the Unload action Revit find a resolution is needed for the “shared coordinates question”, it will call the GetSaveModifiedLinksOption method on the callback object, and the programmer can make a desired response.

 

Cheers

Arnošt Löbel
0 Likes
Message 7 of 17

Anonymous
Not applicable

Dear Arnošt Löbel,

 

Thx !

I'll try it.

 

rgds,

 

Davix

0 Likes
Message 8 of 17

Anonymous
Not applicable

Dear Arnošt Löbel,

 

It's Davix again.

Still I cannot find what parameters to be used when try the RevitLinkType.unload() method.

I cannot find what can be used if I want to save or do not want to save when unload the link file in the RevitAPI.htm.

 

I did understand what you mean, but just cannot find what parameters can be used.

 

Thx & Regards,

 

Davix

0 Likes
Message 9 of 17

Anonymous
Not applicable

Dear Dear Arnošt Löbel,

 

It can work now.

Sorry to trouble you.

 

Regards,

Davix

 

0 Likes
Message 10 of 17

jeremytammik
Autodesk
Autodesk

Dear Davix,

 

So what was the problem, please?

 

How did you resolve it?

 

In case anyone else runs into the same issue...

 

Thank you!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 11 of 17

Anonymous
Not applicable

Dear Jeremy,

 

What I need to do is to:

1) load a revit link file to the current document;

2) unload the link file;

3) reload the link file.

Now the codes can work.

 

The codes are:

1) load a revit link file to the current document;

-------------------------------------------------------------------------

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class OpenLinkDoc : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
// get document objects
UIApplication uiApp = commandData.Application;
UIDocument uiDoc = uiApp.ActiveUIDocument;
// Get the handle of current document.
Document doc = uiDoc.Document;

using (Transaction transaction = new Transaction(doc))
{
if (transaction.Start("create a link file") == TransactionStatus.Started)
{

string linkFile = FileManager.GetPath("link_file");

CreateRevitLink(doc, linkFile);

if (TransactionStatus.Committed != transaction.Commit())
{
TaskDialog.Show("Failure", "Transaction could not be comitted");
}
}
else
{
transaction.RollBack();
return Result.Failed;
}
}

return Result.Succeeded;
}

// ---------------------------------------
// Code Region: Create new Revit Link
// create a new Revit link type and load the linked document
// ---------------------------------------
public bool CreateRevitLink(Document doc, string pathName)
{
FilePath path = new FilePath(pathName);
RevitLinkOptions options = new RevitLinkOptions(false);
RevitLinkLoadResult result = RevitLinkType.Create(doc, path, options);
RevitLinkInstance.Create(doc, result.ElementId);
return true;
}
}

------------------------------------------------------------------------- end of 1)

 

2) unload the link file;

-------------------------------------------------------------------------

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class UnloadLinkedDoc : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
// get document objects
UIApplication uiApp = commandData.Application;
UIDocument uiDoc = uiApp.ActiveUIDocument;
// Get the handle of current document.
Document doc = uiDoc.Document;

try
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(RevitLinkInstance));

string tmpstr = "";
foreach (Element elem in collector)
{
RevitLinkInstance instance = elem as RevitLinkInstance;
Document linkDoc = instance.GetLinkDocument();
RevitLinkType type = doc.GetElement(instance.GetTypeId()) as RevitLinkType;
type.Unload(null);
}

}
catch (Exception e)
{
TaskDialog.Show("in doc:", "err" + e.Message);
message = e.Message;
return Result.Failed;
}

return Result.Succeeded;
}
}

------------------------------------------------------------------------- end of 2)

 

3) reload the link file.

-------------------------------------------------------------------------

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class ReloadLinkedDoc : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
// get document objects
UIApplication uiApp = commandData.Application;
UIDocument uiDoc = uiApp.ActiveUIDocument;
// Get the handle of current document.
Document doc = uiDoc.Document;
try
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(RevitLinkInstance));

foreach (Element elem in collector)
{
RevitLinkInstance instance = elem as RevitLinkInstance;
Document linkDoc = instance.GetLinkDocument();
RevitLinkType type = doc.GetElement(instance.GetTypeId()) as RevitLinkType;
type.Load();
}

}
catch (Exception e)
{
TaskDialog.Show("in doc:", "err" + e.Message);
message = e.Message;
return Result.Failed;
}

return Result.Succeeded;
}

}

------------------------------------------------------------------------- end of 3)

 

Regards,

Davix

Message 12 of 17

Anonymous
Not applicable

Dear Jeremy,

 

And the FileManager is another class which read the xml config file:

 

---------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace NUS.DOB
{
class FileManager
{
/* ------------------------------------------
* used for read the config file, conf.xml
* list the file or the file path in the conf.xml
* read the file or path from the conf.xml with the Node Name as input
* the conf.xml is C:\Users\a0123413\BIM Project\CityBIM_2014\CityBIM_2014\conf\conf.xml
------------------------------------------*/
public static string GetPath(string strFile)
{
XmlDocument xmlDoc = new XmlDocument();
string path = @"C:\Users\a0123413\BIM Project\CityBIM_2014\CityBIM_2014\conf\conf.xml"; // the xml config file path
xmlDoc.Load(path);

XmlNode root = xmlDoc.SelectSingleNode("config"); // get the root node
XmlNode enqNode = root.SelectSingleNode(strFile); // get the enquiry node
string retPath = "initempty"; // set the return path to be "initempty", which should not be used in the conf.xml
if (enqNode != null)
{
retPath = enqNode.InnerText; // get the string of the enquiry node
}
return retPath;
}
}
}

---------------------------------------------------------------------------

 

Regards,

Davix

 

0 Likes
Message 13 of 17

jeremytammik
Autodesk
Autodesk

Dear Davix,

 

Thank you very much for sharing your solution!

 

Kudos!

 

By the way, you could display your code more readably by using the'Insert Code' button, '<>'.

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 14 of 17

Anonymous
Not applicable

Dear Jeremy,

 

You are welcome !

 

Regards,

Davix

 

0 Likes
Message 15 of 17

arnostlobel
Alumni
Alumni

I have nothing to add to the subject of loading linked files as discussed here, but I have noticed a mistake that - while uncommon - I've seen not for the first time: In one part of the code above, there is this:

 

if (transaction.Start() == TransactionStatus.Started)
{
   // use the transaction
}
else
{
    transaction.RollBack();
}

That just does not work and may throw, because if a new transaction could not be started for whatever reason, it would definitely not get committed either!

 

I also have seen the following (not here, elsewhere, but since I am on the subject):

 

if (transaction.Commit() == TransactionStatus.Committed)
{
   return success;
}
else
{
    transaction.RollBack();
}

In this case too the ELSE block would always throw. Once we try to finish a transaction, we cannot call another finishing request on it anymore (neither another Commit nor RollBack) regardless of the status of the initial commit.

Arnošt Löbel
0 Likes
Message 16 of 17

jeremytammik
Autodesk
Autodesk

Dear Arnošt,

 

Thank you for pointing this out, once again.

 

Are the recommendations given by The Building Coder still valid, or is there anything to add?

 

http://thebuildingcoder.typepad.com/blog/2012/04/using-using-automagically-disposes-and-rolls-back.h...

 

http://thebuildingcoder.typepad.com/blog/2014/11/handling-transaction-status-and-errors.html

 

http://thebuildingcoder.typepad.com/blog/2015/02/using-transaction-groups.html

 

I would like to be able to point to a complete and comprehensive solution to save you the effort of repeating yourself  🙂

 

Thank you!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 17 of 17

Anonymous
Not applicable

The ISaveSharedCoordinatesCallback thing is very confusing for an amateur, and there aren't many examples online. rvtLink.Unload(null); got me un-stuck with my addin, so thanks for sharing!

0 Likes