答应过的全盘分享,也必承诺到底,此篇PowerBI功能分享的最后一篇,讲述如何导出数据模型的元数据,笔者定义其为模型的数据字典。

此篇对应功能实现出自:第6波-导出PowerbiDesktop模型数据字典https://www.jianshu.com/p/bc26a8dcdfce

关系型数据库有数据字典,分析型数据库更加要有数据字典,DAX建模过程中,若模型的关系复杂,引用的表过多,生成的度量值、计算列过多,单单从PowerBIDeskTop去查看模型关系非常低效。

当然最好的查看方式,在全宇宙里,只能找到Excel了,没有其他敢跟它叫板,所以理所当然地将PowerBIDeskTop模型的元数据,存放到Excel单元格里,结合Excel的排序、筛选、条件格式、单元格格式等友好的操作方式辅助加工查阅模型元数据。

先上代码,同样地此代码也包含了许多Excel的VSTO开发的精髓-使用ListObject对象返回数据。

        public static void OutputDataDic(string cnnString, string dbName, string fileName)
{ string shtName = "数据字典_" + fileName;
shtName = shtName.Length > 31 ? shtName.Substring(0, 31) : shtName;
Excel.Worksheet wht;
try
{
wht = Common.ExcelApp.ActiveWorkbook.Worksheets[shtName];
Common.ExcelApp.DisplayAlerts = false;
wht.Delete();
Common.ExcelApp.DisplayAlerts = true;
}
catch (Exception)
{ }
wht = Common.ExcelApp.Worksheets.Add();
wht.Name = shtName;
var vstoSht = Globals.Factory.GetVstoObject(wht); ListObject listMeasures = vstoSht.Controls.AddListObject(vstoSht.Range["A1"], "度量值表_" + fileName);
ListObject listDims = vstoSht.Controls.AddListObject(vstoSht.Range["C1"], "维度表_" + fileName);
ListObject listRelationShips = vstoSht.Controls.AddListObject(vstoSht.Range["E1"], "关系表_" + fileName); using (AMO.Server server = new AMO.Server())
{
server.Connect(cnnString);
AMO.Database pbidDb = server.Databases[dbName]; ////获取度量值
GetMeasuresTable(pbidDb, listMeasures);
//获取列字段
GetDimsTable(pbidDb, listDims);
////获取关系
GetRelationsTable(pbidDb, listRelationShips); };
vstoSht.Activate();
}

获取元数据,主要有度量值、维度字段、及表间关系三类元数据。核心代码如下(上方的方法中,最开始是为了访问Sqlserver的SSAS元数据,有区分1200及1100的不同兼容模型版本写了两套代码,因PowerBIDeskTop只会存在1200及以上的兼容模型,故1100的版本已经清除了):

        private static DataSet.DataSet1.MeasuresOfLevel1200DataTable GetMeasuresTableOfLevel1200(AMO.Database tabularDb)
{
TOM.Model model = tabularDb.Model;
DataSet.DataSet1.MeasuresOfLevel1200DataTable measuresTable = new DataSet.DataSet1.MeasuresOfLevel1200DataTable();
foreach (TOM.Table table in model.Tables)
{
foreach (TOM.Measure measure in table.Measures)
{
DataSet.DataSet1.MeasuresOfLevel1200Row dr = measuresTable.NewMeasuresOfLevel1200Row();
dr.Measure = $"[{measure.Name}]";
dr.TableName = table.Name;
dr.DisplayFolder = measure.DisplayFolder;
dr.Description = measure.Description;
dr.FormatString = measure.FormatString;
dr.MeasureExpression = measure.Expression;
dr.Visible = !measure.IsHidden;
dr.DataType = measure.DataType.ToString();
measuresTable.AddMeasuresOfLevel1200Row(dr);
}
} return measuresTable;
}
 private static DataTable GetDimsTableOfLevel1200(AMO.Database tabularDb)
{
TOM.Model model = tabularDb.Model;
DataSet.DataSet1.ColumnNamesDataTable dtColumns = new DataSet.DataSet1.ColumnNamesDataTable();
foreach (TOM.Table table in model.Tables)
{
foreach (TOM.Column col in table.Columns)
{
if (!col.Name.Contains("RowNumber"))
{
TOM.CalculatedColumn calCol = col as TOM.CalculatedColumn;
DataSet.DataSet1.ColumnNamesRow dr = dtColumns.NewColumnNamesRow();
dr.TableName = table.Name;
dr.FieldName = col.Name;
dr.FieldType = col.DataType.ToString();
if (calCol != null)
{
dr.DaxExpression = calCol.Expression;
} dr.Description = col.Description;
dr.Visible = !col.IsHidden;
dtColumns.AddColumnNamesRow(dr);
} }
}
return dtColumns.Cast<DataSet.DataSet1.ColumnNamesRow>().Where(s => !s.TableName.StartsWith("LocalDateTable"))
.Where(s => !s.TableName.StartsWith("DateTableTemplate"))
.CopyToDataTable<DataSet.DataSet1.ColumnNamesRow>();
}
        private static DataTable GetRelationsTableOfLevel1200(AMO.Database tabularDb)
{
TOM.Model model = tabularDb.Model;
DataSet.DataSet1.关系表DataTable dt = new DataSet.DataSet1.关系表DataTable();
foreach (TOM.Relationship relationship in model.Relationships)
{
TOM.SingleColumnRelationship singleRelationShip = relationship as TOM.SingleColumnRelationship;
DataSet.DataSet1.关系表Row dr = dt.New关系表Row();
dr.ToTable = relationship.ToTable.Name;
dr.FromTable = relationship.FromTable.Name;
dr.IsActive = relationship.IsActive;
if (singleRelationShip != null)
{
dr.FromColumn = singleRelationShip.FromColumn.Name;
dr.ToColumn = singleRelationShip.ToColumn.Name;
dr.FromCardinality = singleRelationShip.FromCardinality.ToString();
dr.ToCardinality = singleRelationShip.ToCardinality.ToString();
}
dt.Add关系表Row(dr);
}
return dt.Cast<DataSet.DataSet1.关系表Row>().Where(s => !s.ToTable.StartsWith("LocalDateTable")).CopyToDataTable<DataSet.DataSet1.关系表Row>();
}

结语

连续四篇高质量开源文章,带大家进走Excel催化剂深水区,国际领先的Excel与PowerBIDeskTop互通互联的高级、极高商业价值的核心代码全放送。

最后再次祝愿PowerBI中国社区越来越好,繁荣发展,更多乐于分享的后来者再接再厉。

技术交流QQ群

QQ群名:Excel催化剂开源讨论群, QQ群号:788145319

关于Excel催化剂

Excel催化剂先是一微信公众号的名称,后来顺其名称,正式推出了Excel插件,插件将持续性地更新,更新的周期视本人的时间而定争取一周能够上线一个大功能模块。Excel催化剂插件承诺个人用户永久性免费使用!

Excel催化剂插件使用最新的布署技术,实现一次安装,日后所有更新自动更新完成,无需重复关注更新动态,手动下载安装包重新安装,只需一次安装即可随时保持最新版本!

Excel催化剂插件下载链接:https://pan.baidu.com/s/1Iz2_NZJ8v7C9eqhNjdnP3Q

取名催化剂,因Excel本身的强大,并非所有人能够立马享受到,大部分人还是在被Excel软件所虐的阶段,就是头脑里很清晰想达到的效果,而且高手们也已经实现出来,就是自己怎么弄都弄不出来,或者更糟的是还不知道Excel能够做什么而停留在不断地重复、机械、手工地在做着数据,耗费着无数的青春年华岁月。所以催生了是否可以作为一种媒介,让广大的Excel用户们可以瞬间点燃Excel的爆点,无需苦苦地挣扎地没日没夜的技巧学习、高级复杂函数的烧脑,最终走向了从入门到放弃的道路。

最后Excel功能强大,其实还需树立一个观点,不是所有事情都要交给Excel去完成,也不是所有事情Excel都是十分胜任的,外面的世界仍然是一个广阔的世界,Excel只是其中一枚耀眼的明星,还有其他更多同样精彩强大的技术、工具等。*Excel催化剂也将借力这些其他技术,让Excel能够发挥更强大的爆发!

关于Excel催化剂作者

姓名:李伟坚,从事数据分析工作多年(BI方向),一名同样在路上的学习者。

服务过行业:零售特别是鞋服类的零售行业,电商(淘宝、天猫、京东、唯品会)

技术路线从一名普通用户,通过Excel软件的学习,从此走向数据世界,非科班IT专业人士。

历经重重难关,终于在数据的道路上达到技术平原期,学习众多的知识不再太吃力,同时也形成了自己的一套数据解决方案(数据采集、数据加工清洗、数据多维建模、数据报表展示等)。

擅长技术领域:Excel等Office家族软件、VBA&VSTO的二次开发、Sqlserver数据库技术、Sqlserver的商业智能BI技术、Powerbi技术、云服务器布署技术等等。

2018年开始职业生涯作了重大调整,从原来的正职工作,转为自由职业者,暂无固定收入,暂对前面道路不太明朗,苦重新回到正职工作,对Excel催化剂的运营和开发必定受到很大的影响(正职工作时间内不可能维护也不可能随便把工作时间内的成果公布于外,工作外的时间也十分有限,因已而立之年,家庭责任重大)。

和广大拥护者一同期盼:Excel催化剂一直能运行下去,我所惠及的群体们能够给予支持(多留言鼓励下、转发下朋友圈推荐、小额打赏下和最重点的可以和所在公司及同行推荐推荐,让我的技术可以在贵司发挥价值,实现双赢(初步设想可以数据顾问的方式或一些小型项目开发的方式合作)。

Excel催化剂开源第50波-Excel与PowerBIDeskTop互通互联之第四篇的更多相关文章

  1. Excel催化剂开源第49波-Excel与PowerBIDeskTop互通互联之第三篇

    在PowerBIDeskTop开启的SSAS服务,和Sqlserver所开启的一个本质的区别是,前者其端口号是随机生成的,即上一次打开获得的端口号,下一次关闭后再打开,系统分配给它新的端口号,而后者因 ...

  2. Excel催化剂开源第51波-Excel催化剂遍历单元格操作性能保障

    在Excel催化剂推出的这一年多时间里,经常性听到一种声音,大概意思是真正会写代码的人,都不会看上Excel催化剂写出来的功能,自己造一个更舒服贴心,仿佛会一点VBA就可以天下无敌一般,也好像Exce ...

  3. Excel催化剂开源第47波-Excel与PowerBIDeskTop互通互联之第一篇

    当国外都在追求软件开源,并且在GitHub等平台上产生了大量优质的开源代码时,但在国内却在刮着一股收割小白智商税的知识付费热潮,实在可悲. 互联网的精神乃是分享,让分享带来更多人的受益. 在Power ...

  4. Excel催化剂开源第48波-Excel与PowerBIDeskTop互通互联之第二篇

    前一篇的分享中,主要谈到Excel透视表连接PowerBIDeskTop的技术,在访问SSAS模型时,不止可以使用透视表的方式访问,更可以发数据模型发起DAX或MDX查询,返回一个结果表数据,较透视表 ...

  5. Excel催化剂开源第40波-Excel插入图片做到极致的效果

    不知道是开发人员的自我要求不高还是用户的使用宽容度足够大,在众多Excel插入图片的版本中,都没有考虑到许多的可大幅度提升用户体验的细节处理. Excel催化剂虽然开发水平有限,但也在有限的能力下,尽 ...

  6. Excel催化剂开源第43波-Excel选择对象Selection在.Net开发中的使用

    Excel的二次开发有一极大的优势所在,可以结合用户的交互进行程序的运行,大量用户的交互,都是从选择对象开始,用户选择了单元格区域.图形.图表等对象,之后再进行程序代码的加工处理,生成用户所需的最终结 ...

  7. Excel催化剂开源第27波-Excel离线生成词云图

    在数据分析领域,词云图已经成为在文本分析中装逼的首选图表,大家热烈地讨论如何在Python上做数据分析.做词云图. 数据分析从来都是Excel的主战场,能够让普通用户使用上的技术才是最有价值的技术,一 ...

  8. Excel催化剂开源第26波-Excel离线生成二维码条形码

    在中国特有环境下,二维码.条形码的使用场景非常广泛,因Excel本身就是一个非常不错的报表生成环境,若Excel上能够直接生成二维码.条形码,且是批量化操作的,直接一条龙从数据到报表都由Excel完成 ...

  9. Excel催化剂开源第25波-Excel调用百度AI,返回AI结果

    现成的这些轮子,无需调用网页,直接本地离线即可生成). 当然在AI时代,少不了各种AI接口的使用场景,普通开发者只需聚焦在自己的业务场景上,这些AI底层技术,只需类似水煤电一般去BAT这些大厂那里去消 ...

随机推荐

  1. React Native v0.4 发布,用 React 编写移动应用

    React Native v0.4 发布,自从 React Native 开源以来,包括超过 12.5k stars,1000 commits,500 issues,380 pull requests ...

  2. mysql自动安装教程说明

    这里只说明了思路和方法 我们在安装程序里面可能需要安装的时候将mysql一起安装,那么我们就按照下面的顺序思路来. 首先我们安装的电脑上可能已经安装了mysql,所以我们的mysql服务就起一个名字, ...

  3. Qt之QGraphicsEffect阴影、模糊效果

    Qt之QGraphicsEffect阴影.模糊效果 Qt之QGraphicsEffect阴影模糊效果 效果图 阴影和模糊效果 正常效果 代码 customshadoweffecth customsha ...

  4. qt+opencv对两幅图片进行融合

    本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 源代码: #include "widget.h" #include "ui ...

  5. 获取函数的地址(三种方法,分别是@,Addr,MethodAddress)

    问题来源: http://www.cnblogs.com/del/archive/2008/07/30/1039045.html#1272783 在编译器看来, 重载函数根本就是完全不同的几个函数, ...

  6. 【操作系统】关于Linux桌面操作系统

    以前是Win+Ubuntu+黑苹果,周末想体验一下deepin,于是简单安装了一下,安装过程很简单,这里不再描述.安装之后,第一次打开系统,确实很惊艳,赏心悦目的操作系统. 之前用Ubuntu时候,C ...

  7. netty中的发动机--EventLoop及其实现类NioEventLoop的源码分析

    EventLoop 在之前介绍Bootstrap的初始化以及启动过程时,我们多次接触了NioEventLoopGroup这个类,关于这个类的理解,还需要了解netty的线程模型.NioEventLoo ...

  8. 移动IM开发指南1:如何进行技术选型

    <移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问 ...

  9. idea+mvc项目转换小记

    经过大家协商,决定还是紧跟时代潮流,把项目转到idea下,并且重新组织项目结构.项目环境原本为myeclipse+maven+springMVC,由于本人提议的boot+cloud变化太大,成本巨大, ...

  10. CentOS 7更新系统时间

    Linux系统在安装的时候,总是会出现时区,时间的错误. 将Linux系统时间和本地区网络时间同步,ntpdate可以从网络同步时间, 需要安装sudo yum install ntp ntpdate ...