在某些报表迁移或合并等场景中,一般都需要批量导入度量值。但可惜的是,在PowerBI中没有批量导入的功能,只能逐个进行创建。因此,本篇文章将介绍利用外部工具进行批量导入度量值的方法。
批量导入度量值
1、安装外部工具Tabular Editor与DAX Studio
2、按以下模板在Excel中准备度量值,其中表头名称可以不一致,但列顺序必须一致,按顺序分别为:度量值所在主表、度量值名称、度量值表达式、度量值格式、显示文件夹
3、在Excel中,将数据导入到PowerQuery中
4、替换度量值表达式中的换行符,鼠标右键选择替换值选项
5、关闭并上载,将数据导入到PowerPivot
6、在Excel中启动DAX Studio,并连接至PowerPivot
7、点击DAX Studio左上角的文件菜单,按下图所示配置CSV文档的自定义导出格式
8、在DAX Studio中导出成CSV文档
9、打开需要导入度量值的PowerBI报表文件,在外部工具中启动Tabular Editor
10、在Tabular Editor中切换到Advanced Scripting窗口,粘贴以下代码并运行
var measureMetadata = ReadFile("MeasuresImport.csv"); // c:/Test/AllMeasures.csv is a tab-separated file
// Split the file into rows by CR and LF characters:
var tsvRows = measureMetadata.Split(new[] {'\r','\n'},StringSplitOptions.RemoveEmptyEntries);
// Loop through all rows but skip the first one:
foreach(var row in tsvRows.Skip(1))
{
var tsvColumns = row.Split('\t'); // Assume file uses tabs as column separator
var tblName = tsvColumns[0]; // 1st column contains table name, index start at 0
var name = tsvColumns[1]; // 2st column contains measure name
var expression = tsvColumns[2]; // 3rd column contains measure expression
var format= tsvColumns[3]; // 4rd column contains measure format
var display = tsvColumns[4]; // 5st column contains measure display folder
// This assumes that the model does not already contain a measure with the same name (if it does, the new measure will get a numeric suffix):
var measure = Model.Tables[tblName].AddMeasure(name);
measure.Expression = expression;
measure.FormatString = format;
measure.DisplayFolder = display;
measure.FormatDax();
}
其中,第一行的路径为Step8中导出的CSV文档的路径。若该CSV文档与PowerBI报表文件在同一文件夹,则可以使用相对路径,否则必须使用全局路径。
11、至此,度量值的批量导入已经完成。
由于度量值的表达式中可能含有逗号或换行符,并且一行即为一个度量值的信息,因此导出CSV文档时必须以制表符为分隔符,并且需要去掉表达式中的换行符。只要CSV文档符合这两个要求,那么用其它工具进行处理也是可以的,不一定要按照上面给出的步骤进行导出。
此外,在批量导入时,度量值所在的主表必须存在于模型中,否则将报错。
配套的度量值导出方法
在批量导入度量值时需要先获得包含度量值信息的CSV文档,该CSV文档必须以制表符为分隔符,并且一行即为一个度量值的信息。在上面的介绍中,度量值信息先是以Excel的形式进行存储的,需要经过多个转换步骤才能得到合适的CSV文档。因此下面介绍一个配套的度量值导出方法,直接一步到位将所有度量值导出成合适的CSV文档,在后续导入到其它报表中即可直接使用该CSV文档。
度量值的导出
在PowerBI报表的外部工具中打开Tabular Editor,切换到Advanced Scripting窗口,复制以下代码并运行即可导出成合适的CSV文档。
// Export properties for all measures:
// Remove LF character
foreach(var m in Model.AllMeasures){
m.Expression=m.Expression.Replace("\n"," ");
}
List<ITabularNamedObject> lst = new List<ITabularNamedObject>();
lst.AddRange(Model.AllMeasures);
// Add CalculateColumns
//foreach(var tbl in Model.Tables){
// foreach(var CalColumn in tbl.CalculatedColumns){
// lst.Add(CalColumn);
// }
//}
var csv = ExportProperties(lst,"Table,Name,Expression,FormatString,DisplayFolder");
SaveFile("AllMeasures.csv", csv);
度量值的导入
下面是导出的CSV文档的部分内容:
其中,第一列的Object字段是自动添加的,并且第二列的度量值所在主表字段有一个Model前缀,因此需要稍微修改导入代码中各属性的索引,以从第二列开始导入并去掉主表的Model前缀。修改的地方如下图所示:
修改后的完整代码如下:
var measureMetadata = ReadFile("MeasuresImport.csv"); // c:/Test/AllMeasures.csv is a tab-separated file
// Split the file into rows by CR and LF characters:
var tsvRows = measureMetadata.Split(new[] {'\r','\n'},StringSplitOptions.RemoveEmptyEntries);
// Loop through all rows but skip the first one:
foreach(var row in tsvRows.Skip(1))
{
var tsvColumns = row.Split('\t'); // Assume file uses tabs as column separator
var tblName = tsvColumns[1].Replace("Model.",""); // 1st column contains table name, index start at 0
var name = tsvColumns[2]; // 2st column contains measure name
var expression = tsvColumns[3]; // 3rd column contains measure expression
var format= tsvColumns[4]; // 4rd column contains measure format
var display = tsvColumns[5]; // 5st column contains measure display folder
// This assumes that the model does not already contain a measure with the same name (if it does, the new measure will get a numeric suffix):
var measure = Model.Tables[tblName].AddMeasure(name);
measure.Expression = expression;
measure.FormatString = format;
measure.DisplayFolder = display;
measure.FormatDax();
}
总结
通过上面介绍的方法即可批量导入度量值到报表中,在某些特定场景下有奇效,能够大幅提升开发效率。此外,在批量导入时需要注意,度量值的主表以及表达式中引用的表或列均需要存在于PowerBI模型中,并且DAX表达式的语法也要保持正确,否则将报错。