Excel クエリ エディター や Power BI Desktopで SharePoint Online のカスタム リストをデータソースとしたとき列名がよくわからないことがある。SharaPoint リストコネクタでは、SharePoint REST APIが使用されていてクエリ エディターで表示される列名には EntityPropertyName が使用される。以前にはなかったのだけど、コードポイントから文字への変換が行われるようになったので見た目わかりやすくなったが、表示列名のと関連付けが面倒になってしまった。InternalName や EntityPropertyName は DisplayNameを変更しても変わらないので以前からわかりにくいことはあったのだけど。これを解決しておくPower Query のデモ的なお話。
まぁないですけどね。 |
ビューを指定できる関数にしておく
せっかくなのでカスタムリストのビューを指定して列を選択できるようにして、可能な限りデータ型を設定しておこう。(SPList as table, optional ViewName as text) as table => let // ConvertEntityPropertyName = (EntityPropertyName as text) as text => let Custom0 = {0 .. List.Count(Text.Split(EntityPropertyName, "_x"))}, Custom1 = List.Transform( Custom0, each Text.BetweenDelimiters( EntityPropertyName, "_x", "_", {_, RelativePosition.FromStart}) ), Custom2 = List.Select( Custom1, each Text.Length(_) = 4 or Text.Length(_) = 8 ), Custom3 = List.Transform( Custom2, each [ Old = "_x" & _ & "_", New = try Character.FromNumber( Expression.Evaluate("0x" & _) ) otherwise Old ] ), Custom4 = List.Distinct(Custom3), Titles = List.Generate( ()=> [Counter = 0, Title = EntityPropertyName], each [Counter] <= List.Count(Custom4), each [ Counter = [Counter] + 1, Title = Text.Replace( [Title], Custom4{[Counter]}[Old], Custom4{[Counter]}[New] ) ], each [Title] ) in List.Last(Titles), // TypeFromSchemaXml = (SchemaXml as text) as type => let ParsedXML = Xml.Tables(SchemaXml){0}, Branch = #table( type table [ DataType = Text.Type ,ResultType = Text.Type ,Percentage = Logical.Type ,Type = Type.Type ], { {"Text", null, false, Text.Type} ,{"DateTime", null, false, DateTimeZone.Type} ,{"Number", null, false, Decimal.Type} ,{"Number", null, true, Percentage.Type} ,{"Currency", null, false, Currency.Type} ,{"Boolean", null, false, Logical.Type} ,{"Integer", null, false, Int64.Type} ,{"Counter", null, false, Int64.Type} ,{"Calculated", "Text", false, Text.Type} ,{"Calculated", "DateTime", false, DateTimeZone.Type} ,{"Calculated", "Number", false, Decimal.Type} ,{"Calculated", "Number", true, Percentage.Type} ,{"Calculated", "Currency", false, Currency.Type} ,{"Calculated", "Boolean", false, Logical.Type} } ), Type = try Branch{[ DataType = ParsedXML[#"Attribute:Type"], ResultType = ParsedXML[#"Attribute:ResultType"]?, Percentage = ParsedXML[#"Attribute:Percentage"]? = "TRUE" and (DataType = "Number" or ResultType = "Number") ]}[Type] otherwise Any.Type in Type, // ParentList = SPList{0}[ParentList], Views = ParentList[Views], SelectedView = Table.SelectRows( Views, each if ViewName <> null and List.Contains(Views[Title], ViewName) then [Title] = ViewName else [DefaultView] = true ), ViewFieldsList = SelectedView{0}[ViewFields][Items], ChangeTitleName = List.ReplaceMatchingItems( ViewFieldsList, { {"LinkTitle", "Title"} ,{"LinkTitle2", "Title"} ,{"LinkTitleNoMenu", "Title"} } ), SPListFields = ParentList[Fields] [ [EntityPropertyName] ,[InternalName] ,[Title] ,[SchemaXml] ], FieldsNames = Table.SelectRows( SPListFields, each List.Contains(ChangeTitleName, [InternalName]) ), FieldNamesCombi = Table.TransformColumns( FieldsNames, { {"EntityPropertyName", ConvertEntityPropertyName} ,{"SchemaXml", TypeFromSchemaXml} } ), SelectedColumns = Table.SelectColumns( SPList, FieldNamesCombi[EntityPropertyName] ), ChangedType = Table.TransformColumnTypes( SelectedColumns, Table.TransformRows( FieldNamesCombi, each {[EntityPropertyName], [SchemaXml]} ) ), RenamedColumns = Table.RenameColumns( ChangedType, Table.TransformRows( FieldNamesCombi, each {[EntityPropertyName], [Title]} ) ) in RenamedColumns同時に取得できる情報を展開などしているだけ。日付時間のフィールドはSharePoint Online では UTC+0 なので TimeZone 付きにしておいて必要なときに変換する。フォルダが含まれるときは、FileSystemObjectType = 0 のフィルタをどこかで適用すればよいし、アイテムが 0件のときを考慮する場合 ParentList = SPList{0}[ParentList] を ParentList = try SPList{0}[ParentList] にして 最終ステップで確認すればよいかな。
とっつきにくいから触ってなかったけど、List.Generate を使えるようになってよかった。繰り返し処理でかなりイケてる。テーブルに列を追加する(Table.AddColumns) もしくは リストの値を変換する(List.Transform) だとややこしい処理も問題なくできる。