//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
namespace Revit.SDK.Samples.RoomSchedule
{
///
/// Iterates through the rooms in the project and get the information of all the rooms
///
public class RoomsData
{
#region Class Constant Variables
///
/// Constant name for RoomID, this column must exist in first row.
///
public const String RoomID = "ID";
///
/// Constant name for room area, this column must exist in first row
///
public const String RoomArea = "Room Area";
///
/// Constant named for room name, this column must exist in first row
///
public const String RoomName = "Room Name";
///
/// Constant name for room number, this column must exist in first row
///
public const String RoomNumber = "Room Number";
///
/// Constant name for room number, this column must exist in first row
///
public const String RoomComments = "Room Comments";
///
/// Constant name for shared parameter,
/// the mapped room id of spread sheet will saved in this parameter.
///
public const String SharedParam = "External Room ID";
#endregion
#region Class Member Variables
///
/// Active document to which this RoomsData instance belongs
///
Document m_activeDocument;
///
/// a list to store all rooms in the project
///
List m_rooms = new List();
///
/// parameters which will be displayed in DataGridView
///
List m_parameters = new List();
///
/// a list to store column names of Rooms
///
List m_columnNames = new List();
#endregion
#region Class Properties
///
/// A list of all the rooms in the project
///
public ReadOnlyCollection Rooms
{
get
{
return new ReadOnlyCollection(m_rooms);
}
}
#endregion
#region Class Constructor Method
///
/// Constructor
///
/// Revit project.
public RoomsData(Document activeDocument)
{
m_activeDocument = activeDocument;
// initialize the output parameters
InitializeParameters();
// get all the rooms in the project
GetAllRooms(activeDocument);
}
#endregion
#region Class Public Methods
///
/// Update rooms data after room creation happens in Revit
///
public void UpdateRoomsData()
{
// clear all rooms and re-retrieve data from Revit
m_rooms.Clear();
GetAllRooms(m_activeDocument);
}
///
/// Get all parameters to be displayed in DataGridView.
///
/// all parameters specified by user.
public void UpdateParameters(ReadOnlyCollection specifiedParams)
{
// if there is no instance, parameter setting is not allowed
if (m_rooms.Count <= 0)
{
throw new Exception("No element instance to set parameters");
}
// clear old parameters data
m_parameters.Clear();
m_columnNames.Clear();
// get column names of room by specified parameters
Room firstRoom = m_rooms[0];
foreach (BuiltInParameter param in specifiedParams)
{
// add this parameter
m_parameters.Add(param);
// store all specified parameter names of room.
Parameter toomPara = firstRoom.get_Parameter(param);
m_columnNames.Add(toomPara.Definition.Name);
}
}
///
/// Generate all rooms which are located in specified level.
/// A DataTable data object will be generated after this method call.
///
/// the specified level to retrieve rooms
/// DataTable generated from rooms
public DataTable GenRoomsDataTable(Level level)
{
// get all Rooms information and generate a DataTable
if (m_rooms.Count == 0)
{
return null;
}
// generate columns by all parameters
DataTable newTable = new DataTable();
foreach (String col in m_columnNames)
{
DataColumn column = new DataColumn();
column.ColumnName = col;
column.ReadOnly = true;
column.DataType = System.Type.GetType("System.String");
newTable.Columns.Add(column);
}
// add constant column: External Room ID
DataColumn constantCol = new DataColumn();
constantCol.ColumnName = SharedParam;
constantCol.ReadOnly = true;
constantCol.DataType = System.Type.GetType("System.String");
newTable.Columns.Add(constantCol);
// filter rooms by level
foreach (Room room in m_rooms)
{
// check whether room is located at specified level
if ((null == level) || (m_activeDocument.GetElement(room.LevelId) != null && room.LevelId.IntegerValue == level.Id.IntegerValue))
{
DataRow dataRow = newTable.NewRow();
for (int i = 0; i < m_parameters.Count; i++)
{
dataRow[i] = GetProperty(m_activeDocument, room, m_parameters[i], true);
}
// add constant column value: External Room ID
Parameter param = null;
bool bExist = ShareParameterExists(room, SharedParam, ref param);
if (bExist && null != param && false == String.IsNullOrEmpty(param.AsString()))
{
dataRow[m_parameters.Count] = param.AsString();
}
else
{
dataRow[m_parameters.Count] = "";
}
// add this row
newTable.Rows.Add(dataRow);
}
}
return newTable;
}
///
/// Get the room property value according the parameter name
///
/// Current active document.
/// an instance of room class
/// the parameter used to get parameter value
/// convert parameter to value type or not.
/// if true, the value of parameter will be with unit.
/// if false, the value of parameter will be without unit.
/// the string value of property specified by shared parameter
public static String GetProperty(Document activeDoc, Room room, BuiltInParameter paraEnum, bool useValue)
{
String propertyValue = null; //the value of parameter
// Assuming the build in parameter is legal for room.
// if the room is not placed, some properties are not available, i.g. Level name, Area ...
// trying to retrieve them will throw exception;
// however some parameters are available, e.g.: name, number
Parameter param;
try
{
param = room.get_Parameter(paraEnum);
}
catch (Exception)
{
// throwing exception for this parameter is acceptable if it's a unplaced room
if (null == room.Location)
{
propertyValue = "Not Placed";
return propertyValue;
}
else
{
throw new Exception("Illegal built in parameter.");
}
}
// get the parameter via the built in parameter
if (null == param)
{
return "";
}
// get the parameter's storage type and convert parameter to string
StorageType storageType = param.StorageType;
switch (storageType)
{
case StorageType.Integer:
int iVal = param.AsInteger();
propertyValue = iVal.ToString();
break;
case StorageType.String:
propertyValue = param.AsString();
break;
case StorageType.Double:
// AsValueString will make the return string with unit, it's appreciated.
if (useValue)
{
propertyValue = param.AsValueString();
}
else
{
propertyValue = param.AsDouble().ToString();
}
break;
case StorageType.ElementId:
Autodesk.Revit.DB.ElementId elemId = param.AsElementId();
Element elem = activeDoc.GetElement(elemId);
propertyValue = elem.Name;
break;
default:
propertyValue = param.AsString();
break;
}
return propertyValue;
}
///
/// Check to see whether specified parameter exists in room object.
///
/// Room object used to get parameter
/// parameter name to be checked
/// shared parameter returned
/// true, the parameter exists; false, the parameter doesn't exist
public static bool ShareParameterExists(Room roomObj, String paramName, ref Parameter sharedParam)
{
// get the parameter
try
{
sharedParam = roomObj.LookupParameter(paramName);
}
catch
{
}
return (null != sharedParam);
}
#endregion
#region Class Implementation
///
/// Get all rooms in current Revit project
///
private void GetAllRooms(Document activeDoc)
{
// get all room elements
// try to find all rooms in the project and add to the list
RoomFilter filter = new RoomFilter();
FilteredElementCollector collector = new FilteredElementCollector(activeDoc);
m_rooms = collector.WherePasses(filter).ToElements().Cast().ToList();
// sort rooms by number
m_rooms.Sort(CompRoomByNumber);
}
///
/// Sort the rooms by number
///
///
///
///
private static int CompRoomByNumber(Room room1, Room room2)
{
if (null == room1 || null == room2)
{
return -1;
}
return room1.Number.CompareTo(room2.Number);
}
///
/// Initialize the parameters displayed in DataGridView control
///
private void InitializeParameters()
{
// Room name
m_parameters.Add(BuiltInParameter.ROOM_NAME);
m_columnNames.Add("Name");
// Room Number
m_parameters.Add(BuiltInParameter.ROOM_NUMBER);
m_columnNames.Add("Number");
// Room Area
m_parameters.Add(BuiltInParameter.ROOM_AREA);
m_columnNames.Add("Area");
// Room Comments
m_parameters.Add(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
m_columnNames.Add("Comments");
// Level
m_parameters.Add(BuiltInParameter.LEVEL_NAME);
m_columnNames.Add("Level");
// Phase
m_parameters.Add(BuiltInParameter.ROOM_PHASE);
m_columnNames.Add("Phase");
}
#endregion
}
}