Hi
Thanks for your reply! Your methodology suggestion did actually put me on the right path and I managed to make the tool working!
The problem was that my revLinkType parameter was not pointing to the right thing so the script didn't know what to reload. I fixed the issue by pairing the ModelPath and the RevitLinkType through the Zip and Tuple.Create methods. I think it might be a bit of an overkill but I'm not much of an expert right now so I'm just glad it works. Any suggestion/comment is more than welcome
I'm copying here my final working script so that everyone with the same issue can have a look and it will maybe help someone:
namespace BatchReloadRVTLinks
{
[Transaction(TransactionMode.Manual)]
public class Command : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
// Get application and document objects
UIApplication uiapp = commandData.Application;
UIDocument uidoc = uiapp.ActiveUIDocument;
Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
Autodesk.Revit.DB.Document doc = uidoc.Document;
// NO TRANSACTION NEEDS TO BE OPENED
try
{
using (Transaction tx = new Transaction(doc))
{
// Collect files linked in current project
FilteredElementCollector collector = new FilteredElementCollector(doc);
ICollection<Element> linkInstances = collector.OfClass(typeof(RevitLinkType)).ToElements();
// Convert ICollection into a list of RevitLinkTypes
List<RevitLinkType> revLinkType = new List<RevitLinkType>();
foreach (RevitLinkType i in linkInstances)
{
revLinkType.Add(i);
}
// Put names of linked files into a list of strings
List<string> linkNames = new List<string>();
foreach (Element i in linkInstances)
{
linkNames.Add(i.Name.Split(' ')[0]);
}
// Prompt user with files selection dialog
Start:
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = (@"P:\");
openFileDialog1.Filter = "RVT|*.rvt";
openFileDialog1.Multiselect = true;
openFileDialog1.RestoreDirectory = true;
// If you select the files and hit OK (in the file browser)
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Show which files (path + version) has been selected before linking them
StringBuilder userSelectionWVersion = new StringBuilder();
foreach (string fp in openFileDialog1.FileNames)
{
userSelectionWVersion.AppendLine(
fp.ToString()
+ " which was created with " +
BasicFileInfo.Extract(fp).SavedInVersion.ToString().ToUpper());
}
// Recap the user with his selection + Revit version of the file
DialogResult linkCorrect = MessageBox.Show(
userSelectionWVersion.ToString(),
"You selected the files:",
MessageBoxButtons.OKCancel);
// Put paths of files selected by user into a list
if (linkCorrect == DialogResult.OK)
{
List<string> userSelectionNames = new List<string>();
foreach (string fp in openFileDialog1.FileNames)
{
userSelectionNames.Add(fp.ToString());
}
// Check which of the files that the user selected have the same name of the files linked in the project
IEnumerable<string> elementsToReload = userSelectionNames.Where(a => linkNames.Exists(b => a.Contains(b)));
// Show which files need to be reloaded
StringBuilder intersection = new StringBuilder();
foreach (string fp in elementsToReload)
{
intersection.AppendLine(fp.ToString());
}
DialogResult temp = MessageBox.Show(intersection.ToString(), "The following files need to be roloaded");
// Initialize + populate list of ModelPaths > path from where to reload
List<ModelPath> modPaths = new List<ModelPath>();
foreach (string fp in elementsToReload)
{
FileInfo filePath = new FileInfo(fp);
ModelPath linkpath = ModelPathUtils.ConvertUserVisiblePathToModelPath(filePath.ToString());
modPaths.Add(linkpath);
}
// Zip together file (as RevitLinkType) and the corresponding path to be reloaded from > Reload
foreach(var ab in revLinkType.Zip(modPaths, Tuple.Create))
{
ab.Item1.LoadFrom(ab.Item2, new WorksetConfiguration());
}
}
return Result.Succeeded;
}
catch (Exception ex)
{
// If something went wrong return Result.Failed
DialogResult genericException = MessageBox.Show(ex.Message, "Oops there was problem!");
return Result.Failed;
}
}
}
}Any comment is highly appreciated as it will help me get better in the future!
Also, find attached the test file I was using in case you guys want to give it a try.
PS do you know if there is a class/method to get the status of a linked file? (as it appears in the Manage Links window inside of Revit where it says Status = Not Loaded). This would help me optimise the script so I could reload only the files with the Not Loaded Status and avoid useless calculations for the files that are already correctly loaded.
Thanks again for the advice.
Ciao,
Andrea