xBIM IFC 輸出 Excel 報表

     目錄

    IFC 輸出Excel 空間報告文件

   本示例將展現從IFC文件讀取數據所需的一些概念。它使用IFC4 接口,能夠同時用於IFC2x3和IFC4版本。建立EXCEL文件,咱們使用開源的組件NPOI。這個例子只須要xBIM Essentials。

 引用命名空間:

using NPOI.SS.UserModel;   // EXCEL 組件
using NPOI.XSSF.UserModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;

主要的功能以下所示:

//從模板初始化NPOI工做簿
var workbook = new XSSFWorkbook("template.xlsx");
var sheet = workbook.GetSheet("Spaces");//用單位建立漂亮的數字格式。 現實中須要更多的關心的是單位。
//咱們只知道咱們如今的模型有空間面積以立方米和空間體積爲單位
//請注意從Revit導出的原始數據是錯誤的,由於數據量比應該大1000倍。
//在這個例子中,數據是使用xBIM修復的。
var areaFormat = workbook.CreateDataFormat();
var areaFormatId = areaFormat.GetFormat("# ##0.00 [$m²]");
var areaStyle = workbook.CreateCellStyle();
areaStyle.DataFormat = areaFormatId;
var volumeFormat = workbook.CreateDataFormat();
var volumeFormatId = volumeFormat.GetFormat("# ##0.00 [$m³]");
var volumeStyle = workbook.CreateCellStyle();
volumeStyle.DataFormat = volumeFormatId;
//打開IFC模型。 不會改變模型中的任何東西,因此咱們能夠把編輯器的信息保留下來。
using (var model = IfcStore.Open("SampleHouse.ifc"))
{
    //獲取模型中的全部空間. 
    //須要 ToList() 方便使用 Foreach
    var spaces = model.Instances.OfType<IIfcSpace>().ToList();
    //設置報表標題
    sheet.GetRow(0).GetCell(0)
        .SetCellValue($"Space Report ({spaces.Count} spaces)");
    foreach (var space in spaces)
    {
        //寫報表數據
        WriteSpaceRow(space, sheet, areaStyle, volumeStyle);
    }
}
//保存 報表
using (var stream = File.Create("spaces.xlsx"))
{
    workbook.Write(stream);
    stream.Close();
}
//打開保存的EXCEL 文件
Process.Start("spaces.xlsx");

從IFC 讀取數據,併爲每一個空間寫一行

private static void WriteSpaceRow(IIfcSpace space, ISheet sheet, ICellStyle areaStyle, ICellStyle volumeStyle)
{
    var row = sheet.CreateRow(sheet.LastRowNum + 1);

    var name = space.Name;
    row.CreateCell(0).SetCellValue(name);

    var floor = GetFloor(space);
    row.CreateCell(1).SetCellValue(floor?.Name);

    var area = GetArea(space);
    if (area != null)
    {
        var cell = row.CreateCell(2);
        cell.CellStyle = areaStyle;
        //若是來自於其餘的類型 不保證是數字 (如財產 等)
        if (area.UnderlyingSystemType == typeof(double))
            cell.SetCellValue((double)(area.Value));
        else
            cell.SetCellValue(area.ToString());
    }

    var volume = GetVolume(space);
    if (volume != null)
    {
        var cell = row.CreateCell(3);
        cell.CellStyle = volumeStyle;
        if (volume.UnderlyingSystemType == typeof(double))
            cell.SetCellValue((double)(volume.Value));
        else
            cell.SetCellValue(volume.ToString());
    }
}
WriteSpaceRow

如何獲取包含空間的地板,須要執行如下操做

private static IIfcBuildingStorey GetFloor(IIfcSpace space)
{
    return
        //獲得這個模型空間全部關係
        space.Decomposes
        //選擇分解對象 (這些多是其餘空間或建築層)
        .Select(r => r.RelatingObject)
        //建築樓層
        .OfType<IIfcBuildingStorey>()
        .FirstOrDefault(); //獲取第一個
}

IFC 包含數據基礎架構, 用於存儲與產品及其類型相關的任意數據。此基礎結構至關複雜。存儲數據的兩種主要方法是做爲數量或做爲屬性。數量對於它們所包含的值的類型是明確的, 其中屬性能夠包含許多不一樣的數據類型做爲值。對於面積和體積, 最好從數量中獲得值, 若是它們被定義。在這種狀況下, 屬性是回退。

private static IIfcValue GetArea(IIfcProduct product)
{
    //嘗試先從數量中獲取
    var area =
        //獲取能夠定義屬性和數量集的全部關係
        product.IsDefinedBy
        //在全部屬性和數量集之間搜索。
        //您可能還但願按名稱搜索特定數量
        .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions)
        //數量集合
        .OfType<IIfcElementQuantity>()
        //從數量集獲取全部數量
        .SelectMany(qset => qset.Quantities)
        //咱們只對面積感興趣 
        .OfType<IIfcQuantityArea>()
        //咱們將採起第一個。顯然有一個以上的面積屬性
        //因此, 要檢查的名稱。可是,咱們將保持它簡單的這個例子。
        .FirstOrDefault()?
        .AreaValue;
    if (area != null)
        return area;
    //從屬性中獲取值
    return GetProperty(product, "Area");
}

private static IIfcValue GetVolume(IIfcProduct product)
{
    var volume = product.IsDefinedBy
        .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions)
        .OfType<IIfcElementQuantity>()
        .SelectMany(qset => qset.Quantities)
        .OfType<IIfcQuantityVolume>()
        .FirstOrDefault()?.VolumeValue;
    if (volume != null)
        return volume;
    return GetProperty(product, "Volume");
}

更常見的屬性在屬性集中搜索

private static IIfcValue GetProperty(IIfcProduct product, string name)
{
    return
        //獲取能夠定義屬性和數量集的全部關係
        product.IsDefinedBy
        //在全部屬性和數量集之間搜索。您可能還但願在特定屬性集中搜索
        .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions)
        //在這種狀況下, 只考慮屬性集。
        .OfType<IIfcPropertySet>()
        //從全部屬性集中獲取全部屬性
        .SelectMany(pset => pset.HasProperties)
        //只容許考慮單個值屬性。還有枚舉屬性,
        //表屬性、引用屬性、複雜屬性和其餘
        .OfType<IIfcPropertySingleValue>()
        .Where(p =>
            string.Equals(p.Name, name, System.StringComparison.OrdinalIgnoreCase) ||
            p.Name.ToString().ToLower().Contains(name.ToLower()))
        .FirstOrDefault()?.NominalValue;
}

 最終結果以下

相關文章
相關標籤/搜索