I have compiled the latest source code for RevitLookup 2017 from Jeremy Tammik's GitHub (https://github.com/jeremytammik/RevitLookup).
Note: I did not create or edit this Revit Addin. I am only compiling it for those that don't understand or want to compile it for themselves.
Here is the download link: RevitLookup2017.zip
It is also listed on the right-hand column under downloads.
Monday, May 02, 2016
Wednesday, March 16, 2016
PDQ Deploy and Inventory for Autodesk and other applications
I have been using PDQ Deploy and Inventory for about 2 years
now. It has been one of the highest ROIs on a product I have ever used. The
ease, speed, and reliability of being able to push a product, product updates,
and custom product settings out to 350+ PCs from a $1000 pair of tools has been
a game changer for my company.
What is PDQ?
My Setup
PDQ Inventory
PDQ Inventory is used to create reports about which systems have which software as well as the version of the software. These reports are easy to build using the built-in report creator.
PDQ Inventory also has what are called “collections”. The collections are live reports of PCs that meet the criteria of the collection. For instance in the next image, it shows all the PCs that have an Autodesk product installed, then the PCs that have Revit 2016 installed, and finally the PCs in each office that have Revit 2016 installed. These collections can be used as a source of PCs that PDQ Deployment can use to deploy a package to.

Creating a package in PDQ Deploy is as easy as specifying the msi, exe, bat, etc file that you want to deploy. By combing several steps (see image) you end up with a full blown package like the image below for Revit 2016, Dynamo, several addins, ini files and updates.

Once you have a package built, you choose the PCs to push the package to. This can be from Active Directory, from a collection in PDQ Inventory, or even from a text file. We typically push out to about 10 PCs at a time. For PCs in other offices, we use a DFSR share to replicate all of the installation files to each office. Then the packages use a DFS namespace that is identical in each office to do the install from.
Here is the output for a package that installs AutoCAD Architecture 2016 (w/ SPs and hotfixes), uninstalls all pre-2015 Autodesk software on the PC, installs Revit 2016 (w/ addins, updates, ini files, etc), and Bluebeam PDF.

There are lots of other features that I won't touch on that include scheduling, automatic (start install when computer comes on), pre-made packages, and lots more.
The pair of applications have saved us countless hours for deploying software that the savings are probably immeasurable. If you want to try this out, the company has trial versions available. And if you have more questions about how we use it, please feel free to leave a comment.
What is PDQ?
PDQ Deploy and PDQ Inventory (by Admin Arsenal) are a pair of applications that
allow BIM Mangers, IT Admins, etc to deploy software and files silently across
many PCs as well as keep an inventory of all the PCs software, hardware, and
more. The programs do not require any pre-installation of software on the PCs
and can install just about anything most companies need across a single office
or multiple offices.
My Setup
My company currently uses PDQ to inventory well over 400 PCs
and pushes deployments across 7 offices in 2 countries. We use PDQ inventory to
track which PCs have which versions and service packs of all software applications,
then use PDQ Deployment to automatically push updates to them. We also use PDQ
to push out new versions of applications as they become available. Lastly, we
use PDQ to deploy suites of applications to new systems within the company,
gone are the old days of having a system image with everything installed.
PDQ Inventory
PDQ Inventory can tie into your Active Directory (AD) to
quickly learn about all of the PCs within your company. My company has PCs in
an AD container system like in the image below. By having PCs grouped based on office
and whether it is a desktop/laptop/conference room/server, allows us to only
inventory the PCs we want to use for deployments. We do not currently use PDQ
Inventory or Deploy for servers.
PDQ Inventory is used to create reports about which systems have which software as well as the version of the software. These reports are easy to build using the built-in report creator.
PDQ Inventory also has what are called “collections”. The collections are live reports of PCs that meet the criteria of the collection. For instance in the next image, it shows all the PCs that have an Autodesk product installed, then the PCs that have Revit 2016 installed, and finally the PCs in each office that have Revit 2016 installed. These collections can be used as a source of PCs that PDQ Deployment can use to deploy a package to.

PDQ Deploy
PDQ Deploy allows you to create packages of applications, patches, and settings than you can then push remotely and silently to any number of PCs.Creating a package in PDQ Deploy is as easy as specifying the msi, exe, bat, etc file that you want to deploy. By combing several steps (see image) you end up with a full blown package like the image below for Revit 2016, Dynamo, several addins, ini files and updates.

Once you have a package built, you choose the PCs to push the package to. This can be from Active Directory, from a collection in PDQ Inventory, or even from a text file. We typically push out to about 10 PCs at a time. For PCs in other offices, we use a DFSR share to replicate all of the installation files to each office. Then the packages use a DFS namespace that is identical in each office to do the install from.
Here is the output for a package that installs AutoCAD Architecture 2016 (w/ SPs and hotfixes), uninstalls all pre-2015 Autodesk software on the PC, installs Revit 2016 (w/ addins, updates, ini files, etc), and Bluebeam PDF.

Conclusion
There are lots of other features that I won't touch on that include scheduling, automatic (start install when computer comes on), pre-made packages, and lots more.
The pair of applications have saved us countless hours for deploying software that the savings are probably immeasurable. If you want to try this out, the company has trial versions available. And if you have more questions about how we use it, please feel free to leave a comment.
Tuesday, April 21, 2015
RevitLookup for Revit 2016
With Revit 2016 officially out, I am working on updating my addins for 2016. One of the most invaluable addins has already been updated. Per Jeremy Tammik on his website, http://thebuildingcoder.typepad.com/blog/2015/04/revit-2016-api-news-and-devdays-online-recording.html, RevitLookup has been updated for Revit 2016.
You can get the source code here: https://github.com/jeremytammik/RevitLookup/releases/tag/2016.0.0.6 and build it yourself.
Or you can download a zip with a version that I have already built here: https://app.box.com/s/5hxbjrtgk77a80uwvycvfxinjvo9tzvt
Just extract the contents of the zip file into your Revit 2016 addins folder ( C:\ProgramData\Autodesk\Revit\Addins\2016\ )
You can get the source code here: https://github.com/jeremytammik/RevitLookup/releases/tag/2016.0.0.6 and build it yourself.
Or you can download a zip with a version that I have already built here: https://app.box.com/s/5hxbjrtgk77a80uwvycvfxinjvo9tzvt
Just extract the contents of the zip file into your Revit 2016 addins folder ( C:\ProgramData\Autodesk\Revit\Addins\2016\ )
Thursday, April 02, 2015
Convert View Names on Sheets to UPPERCASE
Here is a quick little Revit Macro that will change all the View names on Sheets to UPPERCASE. This helps when browsing through the Project Browser to identify which views are placed on Sheets. It is one directional at the moment, so if a view that is already UPPERCASE is not on a sheet anymore it won't change it back to lowercase. If I add this in the future I will post an update then.
public void SheetViewNamesToUppercase()
{
Document doc = this.ActiveUIDocument.Document;
using(Transaction t = new Transaction(doc, "Sheet View Names to Uppercase"))
{
t.Start();
foreach(ViewSheet vs in new FilteredElementCollector(doc).OfClass(typeof(ViewSheet)))
{
foreach(ElementId eid in vs.GetAllPlacedViews())
{
try
{
View v = doc.GetElement(eid) as View;
v.Name = v.Name.ToUpper();
}
catch
{
}
}
}
foreach (ViewSchedule vsc in new FilteredElementCollector(doc).OfClass(typeof(ViewSchedule)))
{
foreach (ScheduleSheetInstance ssi in new FilteredElementCollector(doc).OfClass(typeof(ScheduleSheetInstance)))
{
if (vsc.Name == ssi.Name)
{
try
{
vsc.Name = vsc.Name.ToUpper();
}
catch
{
}
}
}
}
t.Commit();
}
}
public void SheetViewNamesToUppercase()
{
Document doc = this.ActiveUIDocument.Document;
using(Transaction t = new Transaction(doc, "Sheet View Names to Uppercase"))
{
t.Start();
foreach(ViewSheet vs in new FilteredElementCollector(doc).OfClass(typeof(ViewSheet)))
{
foreach(ElementId eid in vs.GetAllPlacedViews())
{
try
{
View v = doc.GetElement(eid) as View;
v.Name = v.Name.ToUpper();
}
catch
{
}
}
}
foreach (ViewSchedule vsc in new FilteredElementCollector(doc).OfClass(typeof(ViewSchedule)))
{
foreach (ScheduleSheetInstance ssi in new FilteredElementCollector(doc).OfClass(typeof(ScheduleSheetInstance)))
{
if (vsc.Name == ssi.Name)
{
try
{
vsc.Name = vsc.Name.ToUpper();
}
catch
{
}
}
}
}
t.Commit();
}
}
Friday, February 20, 2015
Quick Macro for Duplicating an Existing Sheet and Views
I had someone recently ask me if it was possible to duplicate a sheet and it's views in Revit. It isn't possible within Revit by default, but with a little bit of code, I was able to get a macro that would duplicate the sheet and it's views. Give the macro a try, just make sure you are in a sheet view before running the macro.
Note: the duplicated views and sheets are renamed with "-DUP" since they need to be unique in Revit. You can change this in the code to be anything you want.
public void DuplicateSheet()
{
UIDocument uidoc = this.ActiveUIDocument;
Document doc = uidoc.Document;
ViewSheet vs = doc.ActiveView as ViewSheet;
using(Transaction t = new Transaction(doc, "Duplicate Sheet"))
{
t.Start();
FamilyInstance titleblock = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance))
.OfCategory(BuiltInCategory.OST_TitleBlocks).Cast<FamilyInstance>()
.First(q => q.OwnerViewId == vs.Id);
ViewSheet newsheet = ViewSheet.Create(doc, titleblock.GetTypeId());
newsheet.SheetNumber = vs.SheetNumber + "-DUP";
newsheet.Name = vs.Name;
// all views but schedules
foreach(ElementId eid in vs.GetAllPlacedViews())
{
View ev = doc.GetElement(eid) as View;
View newview = null;
// legends
if (ev.ViewType == ViewType.Legend)
{
newview = ev;
}
// all non-legend and non-schedule views
else
{
ElementId newviewid = ev.Duplicate(ViewDuplicateOption.WithDetailing);
newview = doc.GetElement(newviewid) as View;
newview.Name = ev.Name + "-DUP";
}
foreach (Viewport vp in new FilteredElementCollector(doc).OfClass(typeof(Viewport)))
{
if (vp.SheetId == vs.Id && vp.ViewId == ev.Id)
{
BoundingBoxXYZ vpbb = vp.get_BoundingBox(vs);
XYZ initialCenter = (vpbb.Max + vpbb.Min) / 2;
Viewport newvp = Viewport.Create(doc, newsheet.Id, newview.Id, XYZ.Zero);
BoundingBoxXYZ newvpbb = newvp.get_BoundingBox(newsheet);
XYZ newCenter = (newvpbb.Max + newvpbb.Min) / 2;
ElementTransformUtils.MoveElement(doc, newvp.Id, new XYZ(
initialCenter.X - newCenter.X,
initialCenter.Y - newCenter.Y,
0));
}
}
}
// schedules
foreach (ScheduleSheetInstance si in (new FilteredElementCollector(doc).OfClass(typeof(ScheduleSheetInstance))))
{
if (si.OwnerViewId == vs.Id)
{
if (!si.IsTitleblockRevisionSchedule)
{
foreach (ViewSchedule vsc in new FilteredElementCollector(doc).OfClass(typeof(ViewSchedule)))
{
if (si.ScheduleId == vsc.Id)
{
BoundingBoxXYZ sibb = si.get_BoundingBox(vs);
XYZ initialCenter = (sibb.Max + sibb.Min) / 2;
ScheduleSheetInstance newssi = ScheduleSheetInstance.Create(doc, newsheet.Id, vsc.Id, XYZ.Zero);
BoundingBoxXYZ newsibb = newssi.get_BoundingBox(newsheet);
XYZ newCenter = (newsibb.Max + newsibb.Min) / 2;
ElementTransformUtils.MoveElement(doc, newssi.Id, new XYZ(
initialCenter.X - newCenter.X,
initialCenter.Y - newCenter.Y,
0));
}
}
}
}
}
t.Commit();
}
}
Note: the duplicated views and sheets are renamed with "-DUP" since they need to be unique in Revit. You can change this in the code to be anything you want.
public void DuplicateSheet()
{
UIDocument uidoc = this.ActiveUIDocument;
Document doc = uidoc.Document;
ViewSheet vs = doc.ActiveView as ViewSheet;
using(Transaction t = new Transaction(doc, "Duplicate Sheet"))
{
t.Start();
FamilyInstance titleblock = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance))
.OfCategory(BuiltInCategory.OST_TitleBlocks).Cast<FamilyInstance>()
.First(q => q.OwnerViewId == vs.Id);
ViewSheet newsheet = ViewSheet.Create(doc, titleblock.GetTypeId());
newsheet.SheetNumber = vs.SheetNumber + "-DUP";
newsheet.Name = vs.Name;
// all views but schedules
foreach(ElementId eid in vs.GetAllPlacedViews())
{
View ev = doc.GetElement(eid) as View;
View newview = null;
// legends
if (ev.ViewType == ViewType.Legend)
{
newview = ev;
}
// all non-legend and non-schedule views
else
{
ElementId newviewid = ev.Duplicate(ViewDuplicateOption.WithDetailing);
newview = doc.GetElement(newviewid) as View;
newview.Name = ev.Name + "-DUP";
}
foreach (Viewport vp in new FilteredElementCollector(doc).OfClass(typeof(Viewport)))
{
if (vp.SheetId == vs.Id && vp.ViewId == ev.Id)
{
BoundingBoxXYZ vpbb = vp.get_BoundingBox(vs);
XYZ initialCenter = (vpbb.Max + vpbb.Min) / 2;
Viewport newvp = Viewport.Create(doc, newsheet.Id, newview.Id, XYZ.Zero);
BoundingBoxXYZ newvpbb = newvp.get_BoundingBox(newsheet);
XYZ newCenter = (newvpbb.Max + newvpbb.Min) / 2;
ElementTransformUtils.MoveElement(doc, newvp.Id, new XYZ(
initialCenter.X - newCenter.X,
initialCenter.Y - newCenter.Y,
0));
}
}
}
// schedules
foreach (ScheduleSheetInstance si in (new FilteredElementCollector(doc).OfClass(typeof(ScheduleSheetInstance))))
{
if (si.OwnerViewId == vs.Id)
{
if (!si.IsTitleblockRevisionSchedule)
{
foreach (ViewSchedule vsc in new FilteredElementCollector(doc).OfClass(typeof(ViewSchedule)))
{
if (si.ScheduleId == vsc.Id)
{
BoundingBoxXYZ sibb = si.get_BoundingBox(vs);
XYZ initialCenter = (sibb.Max + sibb.Min) / 2;
ScheduleSheetInstance newssi = ScheduleSheetInstance.Create(doc, newsheet.Id, vsc.Id, XYZ.Zero);
BoundingBoxXYZ newsibb = newssi.get_BoundingBox(newsheet);
XYZ newCenter = (newsibb.Max + newsibb.Min) / 2;
ElementTransformUtils.MoveElement(doc, newssi.Id, new XYZ(
initialCenter.X - newCenter.X,
initialCenter.Y - newCenter.Y,
0));
}
}
}
}
}
t.Commit();
}
}
Subscribe to:
Posts (Atom)






