Copy View Templates between projects and overwrite duplicates

Copy View Templates between projects and overwrite duplicates

Kevin.Bell
Advisor Advisor
2,409 Views
4 Replies
Message 1 of 5

Copy View Templates between projects and overwrite duplicates

Kevin.Bell
Advisor
Advisor

Hi,

 

I've created an addon in c# to copy view templates between projects - this lets the user pick from a list the exact View Template to copy rather than copying all templates as Transfer Project Standard does.

 

So the routine works fine, except, if there is a template in the target project with the same name then it places (1) in the name of the template copied.

 

I would like the routine to overwrite the template, or prompt the user to overwrite or cancel the copy - I don't mind which.

 

The copy works by calling:

 

ElementTransformUtils.CopyElements(current document, IDs of view templates, target document, transformation, CopyPasteOptions);

 

Reading the documents the CopyPasteOptions parameter controls how the copy handles duplicates, but I'm struggling to get this to work and I can't find any good examples on the internet.

 

I'd appreciate some pointers on how to set up CopyPasteOptions.

 

Thanks.

 

 

0 Likes
2,410 Views
4 Replies
Replies (4)
Message 2 of 5

RPTHOMAS108
Mentor
Mentor

I don't know if there is an easier way but it occurs to me you could probably do the following:

 

1) Check for duplicate names in target project

2) Build a list of views they are applied to

3) Delete the originals that are duplicated

4) Copy the new view templates in (none will now get names assigned (#))

5) Reassign templates to views according to 2 

 

Alternatively implement a version of IDuplicateTypeNamesHandler within CopyPasteOptions (CopyPasteOptions.SetDuplicateTypeNamesHandler).

 

You then implement OnDuplicateTypeNamesFound and review the DuplicateTypeNamesHandlerArgs to get the ElementIDs of the duplicates. You may then use this to do the above procedure.

 

 

Message 3 of 5

Kevin.Bell
Advisor
Advisor

But doesn't that mean that I'm doing the work myself, I assumed the point of CopyPasteOptions.SetDuplicateTypeNamesHandler would tell Revit to use the destination view templates.

 

I'm happy to do the whole thing manually as you suggest, but I'd rather use a Revit built in method if possible.

 

 

I found these posts:

 

https://forums.autodesk.com/t5/revit-api-forum/how-to-implement-iduplicatetypesnamehandler-for-the/t...

 

http://adndevblog.typepad.com/aec/2014/08/handling-duplicate-types-on-copyelements.html

 

It seems that I can set up the interface thus:

 

public class CustomCopyHandler : IDuplicateTypeNamesHandler
{
  public DuplicateTypeAction OnDuplicateTypeNamesFound(
    DuplicateTypeNamesHandlerArgs args)
  {
    return DuplicateTypeAction.UseDestinationTypes;
  }
}

And then call 

 

ElementTransformUtils.CopyElements(doc1, ids, doc2, Transform.Identity, copyOptions);

The options available seem to only be cancel or use destination types.

 

 

Strangely it doesn't seem possible to either overwrite the destination view types or get Revit to prompt the user on the cause of action to take...

 

Surely, overwriting destination types should be one of the options...

 

unless I'm missing something.

 

Cheers.

0 Likes
Message 4 of 5

floretti
Advocate
Advocate

Hi @Kevin.Bell , just wondering what your solution was here as I'm facing the same thing and it seems the developers still haven't added the option to overwrite the existing ones (the request goes back to 2014).

 

I would really appreciate it if you could share a few blocks of code, it would save me a lot of time working it out myself. Thank you.

0 Likes
Message 5 of 5

floretti
Advocate
Advocate

Never mind, I worked it out in case anybody else needs it in the future. Note I deleted a bunch of logging lines from the code but there are still a few left, just replace it or delete it.

 

 

var allViews = new FilteredElementCollector(doc).
					OfClass(typeof(View)).
					WhereElementIsNotElementType().
					ToList();

// Create a dictionary of view template names and their assigned views
// Note unused view templates will not be here
var viewTempViewDict = new Dictionary<string, List<View>>();

foreach (View view in allViews)
{
	if (!view.IsTemplate && view.ViewTemplateId != ElementId.InvalidElementId)
	{
		var viewTempName = doc.GetElement(view.ViewTemplateId).Name;

		if (!viewTempViewDict.Any(x => x.Key == viewTempName))
		{
			viewTempViewDict.Add(viewTempName, new List<View>() { view });
		}
		else viewTempViewDict[viewTempName].Add(view);
	}
}

// Delete existing view templates
var elemIdsToDelete = new List<ElementId>();

foreach (View view in allViews)
{
	foreach (string viewTempName in vtToCopyNames)
	{
		if (view.IsTemplate && view.Name == viewTempName)  // Check if view template exists
		{
			var viewName = view.Name;

			try
			{
				elemIdsToDelete.Add(view.Id);
				templatesDeleted++;
			}
			catch
			{
				continue;
			}
		}

		else Log.Debug((className + ": ") + $"View {view.Name} is either not a template or not part of the user selection.");
	}
}

try
{
	doc.Delete(elemIdsToDelete);
}
catch { Log.Debug((className + ": ") + $"Could not delete list of existing view templates."); }

// Copy view templates into document
var newViewTempIds = ElementTransformUtils.CopyElements(newDoc, vtToCopyIds, doc, null, options).ToList();

// Assign new view templates to views
foreach (var elemId in newViewTempIds)
{
	var newViewTempName = doc.GetElement(elemId).Name;

	if (viewTempViewDict.Any(x => x.Key == newViewTempName))
	{
		foreach (var view in viewTempViewDict[newViewTempName])
		{
			view.ViewTemplateId = elemId;
		}
	}
	else Log.Debug((className + ": ") + $"View template {newViewTempName} was not assigned to any views.");
}

 

  

0 Likes