Announcements

The Autodesk Community Forums has a new look. Read more about what's changed on the Community Announcements board.

CADLinks

stephen_harrison
Advocate

CADLinks

stephen_harrison
Advocate
Advocate

Apologies for the simplistic nature of the question and thank you in advance for any clarification.

 

First a little background I am using Revit 2018 and programming in C#.

 

As I understand it CAD Links can be made to files of the following format DWG, DXF, DGN, SAT & SKP.

When I utilise the following:

IList<Element> Revitlist = (IList<Element>)new FilteredElementCollector(openDoc).OfClass(typeof(RevitLinkType)).WhereElementIsElementType().ToList<Element>();

This provides me with a list of these Linked files.

I can create (Reload) a link to a DWG file utilising:

 

trans.Start();
cadLinkType.LoadFrom(string Path);
trans.Commit();

 if I try the same for any other supported CAD Link types i.e. DXF it returns an error stating it is not a DWG.

 

Question

How do you create (Reload) a link to none DWG CadLinkType formats.

 

What am I missing?

 

Again thank you for your assistance.

0 Likes
Reply
Accepted solutions (1)
2,819 Views
12 Replies
Replies (12)

aignatovich
Advisor
Advisor

Hi!

 

First of all, you should get CADLinkType, it represents both CAD links and CAD imports, dwgs, dxfs and others.

It has Reload method, but be careful, CAD imports are not ExternalFileReferences; they are brought completely into the document and maintain no connection to their original file. Check IsLink to distinguish between links and imports.

 

Reload method arrived in the API since Revit 2018, there is no appropriate method in older Revit versions

0 Likes

stephen_harrison
Advocate
Advocate

Thank you for your prompt response and apologies for my error.

You are correct that I should be using CADLinkType. 

This is what I should have posted within my original question:

 

IList<Element> CADlist = (IList<Element>)new FilteredElementCollector(openDoc).OfClass(typeof(CADLinkType)).WhereElementIsElementType().ToList<Element>();

 

I looking to utilise Reload as you suggest but I am now struggling with how to set the new location for the link.

 

An example would be much appreciated.

0 Likes

stephen_harrison
Advocate
Advocate

Am I correct in my understanding that using Reload link has to be undertaken as part of TransmissionData?

If this is the case my understanding is that any links created (Reloaded) will only be implemented next time the document is opened, thus resulting in the document being updated next time it is opened?

 

My preferred option would be to update the link to avoid this update, which I have achieved for DWG only using

 

trans.Start();
cadLinkType.LoadFrom(string Path);
trans.Commit();

 Is it possible to achieve the same for the remaining CADLinkTypes?

0 Likes

aignatovich
Advisor
Advisor

You can perform operation with transmission data, using specific facilities or just work in current document, loading and reloading links is immediate operation in the last case.

 

This is a sample, that reloads linked cadlinks:

var uiapp = commandData.Application;
var uidoc = uiapp.ActiveUIDocument;
var doc = uidoc.Document;

var collector = new FilteredElementCollector(doc);

var cadLinkTypes = collector
	.OfClass(typeof (CADLinkType))
	.OfType<CADLinkType>()
	.Where(x => x.IsExternalFileReference())
	.ToList();

using (var transaction = new Transaction(doc, "reload all"))
{
	transaction.Start();

	foreach (var cadLinkType in cadLinkTypes)
		cadLinkType.Reload();

	transaction.Commit();
}

return Result.Succeeded;

stephen_harrison
Advocate
Advocate

Again thank you for your response and the code sample.

 

It is a much neater and compact solution than I was currently working on, however in some cases the location or name of the linked files has changed and this does not allow for these changes.

 

I assume there must be a way to update the file name or location and utilise this within the reload.

The API chm suggests to me that this should be possible by utilising the IExternalResourceServer  and again I am clearly missing the obvious as I have not been able to achieve this.

Your help and any code guidance would be much appreciated.

 

 

0 Likes

aignatovich
Advisor
Advisor

You can retrieve CAD file name from:

var path = ModelPathUtils.ConvertModelPathToUserVisiblePath(cadLinkType.GetExternalFileReference().GetAbsolutePath());

and use this path in LoadFrom method.

 

But I have no idea, how to deal with actual file path changes.

 

Don't waste your time looking for IExternalResourceServer, this thing is for completely other tasks. If you have a system, such as A360, that stores CAD files in some manner, you can tie it with Revit using IExternalResourceServer

0 Likes

stephen_harrison
Advocate
Advocate

Thanks, unfortunately this is were I started.

I was utilising the LoadForm method and it works beautifully for DWG file types. Regrettably all  other CADTypeLinks (DXF, DGN, SAT & SKP) return a warning  stating it is not a DWG.

 

Thanks for stopping me wasting my time looking at IExternalResourceServer. 

0 Likes

aignatovich
Advisor
Advisor

As a workaround:

call Reload if it is available, e.g. file path did not change

call ReloadFrom for dwgs

completely recreate CADLinkType and its instances in other cases

0 Likes

stephen_harrison
Advocate
Advocate

That was my thoughts.

But again it appears to be a dead end.

The only ways to I can find to create a CADLinkType are LoadFrom and Reload, unlike RevitLinkType which appears to provide a number of ways to create new links.

 

Its possible the only way may be to utilise TransmissionData, which then sets me on a new quest to figure out how to do that.

 

0 Likes

aignatovich
Advisor
Advisor
Accepted solution

There is a sample in SDK:

void UnloadRevitLinks(ModelPath location)
///  This method will set all Revit links to be unloaded the next time the document at the given location is opened. 
///  The TransmissionData for a given document only contains top-level Revit links, not nested links.
///  However, nested links will be unloaded if their parent links are unloaded, so this function only needs to look at the document's immediate links. 
{
   // access transmission data in the given Revit file
   TransmissionData transData = TransmissionData.ReadTransmissionData(location);

   if (transData != null)
   {
      // collect all (immediate) external references in the model
      ICollection<ElementId> externalReferences = transData.GetAllExternalFileReferenceIds();

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

         if (extRef.ExternalFileReferenceType == ExternalFileReferenceType.RevitLink)
         {
            // we do not want to change neither the path nor the path-type
            // we only want 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
   {
      Autodesk.Revit.UI.TaskDialog.Show("Unload Links", "The document does not have any transmission data");
   }
}

Looks like you can set any desired reference data and control external reference path. The document should not be opened in Revit UI

stephen_harrison
Advocate
Advocate

Thanks for all your help.

Although not the way I had hoped, this has provided the output required.

0 Likes

Anonymous
Not applicable

This is great! 

Thanks

0 Likes