• 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;
    }

     最终结果如下

  • 相关阅读:
    ES6/5比较
    Javascript中的var和let
    git中remotes/origin/HEAD指向的分支丢失
    js实用篇之数组、字符串常用方法
    JS设计模式一:单例模式
    Linux C 面试题总结 .
    深入理解javascript原型和闭包(15)——闭包
    一些有意思的面试题(持续更新) .C语言编程技巧札记
    一个三流大学生的北京三年 .
    C 字节对齐.我的算法学习之路
  • 原文地址:https://www.cnblogs.com/w2011/p/8424405.html
Copyright © 2020-2023  润新知