xBIM 基礎15 IFC導出Excel報表

  IFC導出Excel空間報表文件html

  本篇將向您展現從IFC文件讀取數據所需的一些概念。它使用IFC4接口,適用於IFC2x3和IFC4型號。要建立Excel文件,咱們使用NPOI。在這個例子中你只須要 xBIM Essentials 組件。包含樣本數據的全部代碼都可在此處得到git

此示例的結果以下所示:github

 

您將須要如下using聲明:編輯器

using NPOI.SS.UserModel;
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讀取數據併爲每一個空間寫入一行ui

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());
    }
}

要得到包含空間的樓層,您須要執行此操做:spa

private static IIfcBuildingStorey GetFloor(IIfcSpace space)
{
    return
        //獲取全部對象化的關係,這些關係將按此空間進行分解
        space.Decomposes

        //選擇分解的對象(這些對象多是其餘空間或建築樓層)
        .Select(r => r.RelatingObject)

        //僅獲取樓層 
        .OfType<IIfcBuildingStorey>()

        //獲取第一個
        .FirstOrDefault();
}

IFC包含數據基礎結構,用於存儲與產品及其類型相關的任意數據。這種基礎設施至關複雜。存儲數據的兩種主要方式是數量或屬性。數量是明確的,它們包含的值的類型,其中屬性能夠包含許多不一樣的數據類型做爲值。對於面積和體積,若是定義了數量,則最好從數量中獲取值code

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");
}

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

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;
}
 
相關文章
相關標籤/搜索