前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >xBIM 基础15 IFC导出Excel报表

xBIM 基础15 IFC导出Excel报表

作者头像
张传宁IT讲堂
发布2019-09-17 17:37:58
8490
发布2019-09-17 17:37:58
举报
文章被收录于专栏:.NET企业级解决方案应用与咨询

  IFC导出Excel空间报表文件

  本篇将向您展示从IFC文件读取数据所需的一些概念。它使用IFC4接口,适用于IFC2x3和IFC4型号。要创建Excel文件,我们使用NPOI。在这个例子中你只需要 xBIM Essentials 组件。包含样本数据的所有代码均可在此处获得

此示例的结果如下所示:

您将需要以下using声明:

代码语言:javascript
复制
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;

主要功能如下:

代码语言:javascript
复制
//从模板初始化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读取数据并为每个空间写入一行

代码语言:javascript
复制
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());
    }
}

要获得包含空间的楼层,您需要执行此操作:

代码语言:javascript
复制
private static IIfcBuildingStorey GetFloor(IIfcSpace space)
{
    return
        //获取所有对象化的关系,这些关系将按此空间进行分解
        space.Decomposes

        //选择分解的对象(这些对象可能是其他空间或建筑楼层)
        .Select(r => r.RelatingObject)

        //仅获取楼层 
        .OfType<IIfcBuildingStorey>()

        //获取第一个
        .FirstOrDefault();
}

IFC包含数据基础结构,用于存储与产品及其类型相关的任意数据。这种基础设施相当复杂。存储数据的两种主要方式是数量或属性。数量是明确的,它们包含的值的类型,其中属性可以包含许多不同的数据类型作为值。对于面积和体积,如果定义了数量,则最好从数量中获取值

代码语言:javascript
复制
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");
}

更常见的属性在属性集中搜索

代码语言:javascript
复制
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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-06-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档