有时需要将Revit模型的一些信息提取到Excel中进行处理或者是作为记录进行储存,但也许是因为Revit的数据结构相对复杂,并不支持直接将数据导出Excel,所以平时通过二次开发将信息输出到Excel中。
常使用的输出方法有三个,分别是com组件;NPOI库;Epplus库。
com组件需要电脑安装Excel软件,由于Excel版本比较多,导出的时候要注意版本的问题。下面的代码通过com组件的方法导出模型中的一张明细表。
//使用Excel2013,引用Microsoft Excel 15.0 Object Library
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using System.IO;
using System.Reflection;
using EXCEL = Microsoft.Office.Interop.Excel;
namespace RevitAddinTestClass
{
[Transaction(TransactionMode.Manual)]
class ViewScheduleExport : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document document = commandData.Application.ActiveUIDocument.Document;
//获取项目中的一张门明细表
FilteredElementCollector collector = new FilteredElementCollector(document);
foreach (ViewSchedule vs in collector.OfClass(typeof(ViewSchedule)))
{
if (vs.Name == "门明细表")
{
//Excel文件路径
string path = @"D:\LST\Test\ViewSchedule.xlsx";
//如文件已存在则删除
if (File.Exists(path)) File.Delete(path);
//创建Excel文件
object nothing = Missing.Value;
EXCEL.Application excelApplication = new EXCEL.ApplicationClass();
EXCEL.Workbook excelWorkBook = excelApplication.Workbooks.Add(nothing);
EXCEL.Worksheet excelWorkSheet = excelWorkBook.Sheets[1] as EXCEL.Worksheet;
//获取表格的行列数
int rows, cols;
TableSectionData data = vs.GetTableData().GetSectionData(SectionType.Body);
rows = data.NumberOfRows;
cols = data.NumberOfColumns;
//导入数据
for (int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
EXCEL.Range cell = excelWorkSheet.Cells[i + 1, j + 1] as EXCEL.Range;
//获取明细表中的字符串
cell.Value = vs.GetCellText(SectionType.Body, i, j);
//表头字体设置为粗体
if (cell.Row == 1)
{
cell.Font.Bold = true;
}
//添加边框线
cell.BorderAround2();
}
}
//保存文件
excelWorkBook.Close(true, path);
excelApplication.Quit();
excelApplication = null;
continue;
}
}
return Result.Succeeded;
}
}
}
NPOI与Epplus都是开源免费的,NPOI库用的比较少,因为它只支持03和07版的Excel,但它不需要电脑安装有Excel软件。下面的代码读取模型中的建筑标高,然后通过NPOI库在Excel中制作一个层高表。
using System;
using System.Collections.Generic;
using System.IO;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
namespace RevitAddinTestClass
{
[Transaction(TransactionMode.Manual)]
class LevelsScheduleExport : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document document = commandData.Application.ActiveUIDocument.Document;
//获取所有建筑标高
Dictionary levelDic = new Dictionary();
List elevationList = new List();
FilteredElementCollector collector = new FilteredElementCollector(document);
foreach(Level l in collector.OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType())
{
if (l.get_Parameter(BuiltInParameter.LEVEL_IS_BUILDING_STORY).AsInteger() == 1)
{
double elevation = Math.Round(UnitUtils.ConvertFromInternalUnits(l.Elevation, DisplayUnitType.DUT_METERS), 2);
string levelName = l.Name;
try
{
if (l.GetParameters("避难层")[0].AsInteger() == 1) levelName += "(避难层)";
}
catch
{
//to do
}
levelDic.Add(elevation, levelName);
elevationList.Add(elevation);
}
}
//按标高的高度排序
elevationList.Sort();
//Excel文件路径
string path = @"D:\LST\Test\LevelSchedule.xls";
//如文件已存在则删除
if (File.Exists(path)) File.Delete(path);
//创建Excel文件
HSSFWorkbook excelWorkBook = new HSSFWorkbook();
ISheet excelWorkSheet = excelWorkBook.CreateSheet("层高表");
//格式
ICellStyle cellStyle = excelWorkBook.CreateCellStyle();
cellStyle.BorderLeft = BorderStyle.Thin;
cellStyle.BorderTop = BorderStyle.Thin;
cellStyle.BorderRight = BorderStyle.Thin;
cellStyle.BorderBottom = BorderStyle.Thin;
cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");
//表头
IRow hRow = excelWorkSheet.CreateRow(0);
ICell hCell0 = hRow.CreateCell(0);
hCell0.SetCellValue("楼层");
hCell0.CellStyle = cellStyle;
ICell hCell1 = hRow.CreateCell(1);
hCell1.SetCellValue("层高");
hCell1.CellStyle = cellStyle;
ICell hCell2 = hRow.CreateCell(2);
hCell2.SetCellValue("标高(m)");
hCell2.CellStyle = cellStyle;
//计算高差并写入数据
for (int i = 0; i < elevationList.Count; i++)
{
double currentElve, upElve, height;
string currentLevel;
currentElve = elevationList[i];
currentLevel = levelDic[currentElve];
if (i == elevationList.Count - 1)
{
upElve = 0;
height = 0;
}
else
{
upElve = elevationList[i + 1];
height = upElve - currentElve;
}
//写入数据
IRow dRow = excelWorkSheet.CreateRow(i + 1);
ICell dCell0 = dRow.CreateCell(0);
dCell0.SetCellValue(currentLevel);
dCell0.CellStyle = cellStyle;
ICell dCell1 = dRow.CreateCell(1);
if (height == 0)
{
dCell1.SetCellValue("");
}
else
{
dCell1.SetCellValue(height);
}
dCell1.CellStyle = cellStyle;
ICell dCell2 = dRow.CreateCell(2);
dCell2.SetCellValue(currentElve);
dCell2.CellStyle = cellStyle;
}
//保存文件
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
excelWorkBook.Write(fs);
}
return Result.Succeeded;
}
}
}
Epplus库也不需要电脑安装Excel,但只支持xlsx格式的excel文件,网上的一些评论是导出的效率及稳定性都比NPOI好,但由于没进行过非常大数据量的导出,所以暂时没有体现出来。 下面代码将模型中的管道信息按照一定的规则处理后导出到Excel中,然后在Excel中简单的做个数据透视即可获得对应的工程量。
using System.IO;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB.Plumbing;
using OfficeOpenXml;
using OfficeOpenXml.Style;
namespace RevitAddinTestClass
{
[Transaction(TransactionMode.Manual)]
class PipeSchedule : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document document = commandData.Application.ActiveUIDocument.Document;
//Excel文件路径
string path = @"D:\LST\Test\PipeSchedule.xlsx";
//如文件已存在则删除
if (File.Exists(path)) File.Delete(path);
//创建Excel文件
ExcelPackage package = new ExcelPackage(new FileInfo(path));
ExcelWorksheet excelWorkSheet = package.Workbook.Worksheets.Add("管道数据");
//表头
string[] hearName = { "Id", "系统", "项目名称", "材质", "规格", "连接方式", "单位", "工程量" };
for(int i = 0; i< hearName.Length; i++)
{
ExcelRange hCell = excelWorkSheet.Cells[1, i + 1];
hCell.Value = hearName[i];
//格式
hCell.Style.Font.Bold = true;
hCell.Style.Border.BorderAround(ExcelBorderStyle.Thin);
}
//获得所有管道数据
List