Here is the C# code for an app I wrote that copies and pastes Revit elements, and gives the pasted elements the same phase and workset of the copied elements.
A compiled dll file for Revit 2019, an add-in manifest file, and a image file for the icon, and a Readme file for installation instructions can be found on GitHub at:
https://github.com/stever854/Copy-Similar-Revit-2019-Addin
References need to be added for PresentationCore, System.Xaml, System.Xml.Linq, Windows.Base, and of course the RevitAPI and Revit APIUI references. It also needs a 32 x 32 image file for the ribbon icon.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Windows.Media.Imaging;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace RevitAPI123CopySame
{
/// <remarks>
/// This application's main class. The class must be Public.
/// </remarks>
public class CsCopySameAddPanel : IExternalApplication
{
// Both OnStartup and OnShutdown must be implemented as public method
public Result OnStartup(UIControlledApplication application)
{
// Add a new ribbon panel
RibbonPanel ribbonPanel = application.CreateRibbonPanel("API-123");
// Create a push button to trigger a command add it to the ribbon panel.
string thisAssemblyPath = Assembly.GetExecutingAssembly().Location;
PushButtonData buttonData = new PushButtonData("cmdCopySame",
"Copy Same", thisAssemblyPath, "RevitAPI123CopySame.CopySame");
PushButton pushButton = ribbonPanel.AddItem(buttonData) as PushButton;
// Optionally, other properties may be assigned to the button
// a) tool-tip
pushButton.ToolTip = "Copy Same Copies Elements and puts them on the same Phase Created, Phase Demolished, and Workset as the original elements.";
// b) large bitmap
// -----next 4 lines for installation in revit bundle-----
//string ProgramDataFolder= Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
//ProgramDataFolder = ProgramDataFolder + @"\Autodesk\ApplicationPlugins\API-123 Copy Similar.bundle\Contents\Source\CopySameIcon32x32.png";
//TaskDialog.Show("Revit", ProgramDataFolder);
//Uri uriImage = new Uri(ProgramDataFolder);
//For standard installation in the revit addins folder:
Uri uriImage = new Uri(@"C:\ProgramData\Autodesk\Revit\Addins\2018\CopySameIcon32x32.png");
BitmapImage largeImage = new BitmapImage(uriImage);
pushButton.LargeImage = largeImage;
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication application)
{
// nothing to clean up in this simple case
return Result.Succeeded;
}
}
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class CopySame: IExternalCommand
{
public Autodesk.Revit.UI.Result Execute(ExternalCommandData revit,
ref string message, ElementSet elements)
{try
{
Document doc = revit.Application.ActiveUIDocument.Document ;
UIDocument uidoc = revit.Application.ActiveUIDocument;
Autodesk.Revit.DB.View pView = revit.Application.ActiveUIDocument.Document.ActiveView;
Autodesk.Revit.DB.Transaction t = new Autodesk.Revit.DB.Transaction(doc, "API-123 Copy Same");
// Select some elements in Revit before invoking this command
// Get the element selection of current document.
Selection selection = uidoc.Selection;
ICollection<ElementId> selectedIds = uidoc.Selection.GetElementIds();
IList<Reference> postselected = new List<Reference>();
Element elementcopy = null;
Element elementpaste = null;
// if there are no selected elements, show error message
if (0 == selectedIds.Count)
{
TaskDialog.Show("API-123 Copy Same", "You didn't select any elements.");
}
//elements selected and ready to start copy operation
else
{
Phase[] createsource = new Phase[selectedIds.Count + 1];
Phase[] demosource = new Phase[selectedIds.Count + 1];
int[] worksetsource = new int[selectedIds.Count + 1];
XYZ point1 = new XYZ(0, 0, 0);
XYZ point2 = new XYZ(0, 0, 0);
XYZ point3 = new XYZ(0, 0, 0);
point1 = selection.PickPoint("Please pick a base point.");
while (true)
{
point2 = selection.PickPoint("Please pick a point to place elements");
point3 = point2.Subtract(point1);
t.Start();
ICollection<ElementId> pastedIds = ElementTransformUtils.CopyElements(doc, selectedIds, point3);
t.Commit();
int n = 0;
foreach (ElementId id in selectedIds)
{
n = n + 1;
elementcopy = doc.GetElement(id);
if (elementcopy.HasPhases())
{
if (elementcopy.Document.GetElement(elementcopy.CreatedPhaseId) != null)
{
createsource[n] = elementcopy.Document.GetElement(elementcopy.CreatedPhaseId) as Phase;
}// end if
if (elementcopy.Document.GetElement(elementcopy.DemolishedPhaseId) != null)
{
demosource[n] = elementcopy.Document.GetElement(elementcopy.DemolishedPhaseId) as Phase;
}// end if
}// end HasPhases
worksetsource[n] = elementcopy.WorksetId.IntegerValue;
if (elementcopy.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM) != null)
{
//worksetsource [n]= elementcopy.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM ) as Parameter;
}// end if
}// end foreach
n = 0;
t.Start();
int createderrcount = 0;
int demoerrcount = 0;
int wserrcount = 0;
foreach (ElementId id in pastedIds)
{
n = n + 1;
elementpaste = doc.GetElement(id);
if (elementpaste.HasPhases() && elementpaste.ArePhasesModifiable())
{
if (createsource[n] != null)
{
elementpaste.get_Parameter(BuiltInParameter.PHASE_CREATED).Set(createsource[n].Id);
}// end if
}// end if
else createderrcount = createderrcount + 1;
if (elementpaste.HasPhases() && elementpaste.ArePhasesModifiable())
{
if (demosource[n] != null)
{
elementpaste.get_Parameter(BuiltInParameter.PHASE_DEMOLISHED).Set(demosource[n].Id);
}// end if
}// end if
else demoerrcount = demoerrcount + 1;
try
{
//TaskDialog.Show("Revit", "Setting Workset");
elementpaste.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM).Set(worksetsource[n]);
}// end else
catch
{
wserrcount = wserrcount + 1;
continue;
}// end catch
}// end foreach
t.Commit();
if (wserrcount + createderrcount + demoerrcount > 0)
{
String messagestring =
"Some objects phases or worksets were not changed." + "\n" + "\n"
+ n + " Elements Copied." + "\n" + createderrcount +
" Object's Phase Created were not changed." + "\n" + demoerrcount +
" Object's Phase Demo'd were not changed." + "\n" + wserrcount +
" Object's Worksets were not changed.";
TaskDialog.Show("Revit CopySame Message: ", messagestring);
}// end if
}// end else selectedids > 0
}// end while
selectedIds.Clear();
selectedIds = null;
uidoc.Selection.Dispose();
uidoc.RefreshActiveView();
} // End try
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
//TaskDialog.Show("Revit Add-in Error.", "User Canceled.");
}// end cath Operation Canceled
catch (Autodesk.Revit.Exceptions.InvalidOperationException)
{
TaskDialog.Show("Revit Add-in Error.", "Error. Please make sure the workplane is set in the current view.");
}// end catch invalid operation
catch (Exception e)
{
TaskDialog.Show("Revit Add-in Error.", "General Undefined Add-in Error: " + e.ToString());
}// end catch exception
return Result.Succeeded;
}//end execute
}// end class copy same
}// end namespace copy same