问题描述
我最近遇到了一个希望可以解决的问题。
当前,我有一个强大的查询,指向一个包含几个CSV文件的文件夹。这通常没有问题,但是,在这种情况下,并非所有文件都具有相同的列。
有没有一种方法可以让Power查询返回在文件夹中找到的每个唯一列,并用空值填充空数据观察值?
假设我的文件夹中的csv文件类似于以下文件(请注意,使用字母对行进行了索引以便于参考)
我希望我的决赛桌看起来像这样:
这似乎很简单,但我无法终生解决!任何帮助将不胜感激!
解决方法
假设您正在使用Folder.Files
,我想您可以:
- 获取
Content
返回的表的Folder.Files
列-应该会为您提供二进制值列表。 - 使用
List.Transform
和Csv.Document
将列表中的每个项目解析为CSV文档-应该会为您提供表列表。 - 然后将表列表与
Table.Combine
合并-应该可以为您提供一个表。Table.Combine
应该注意细节(例如对齐列名)。
您尚未在问题中提供任何代码,因此很难举一个相关的例子,但是我认为下面的代码给了您您期望的输出。
我已将行索引转换为ID
列,只是为了使最终表更易于验证/关注。
let
firstCsv =
"ID,one,two,three
A,1,4,7
B,2,5,8
C,3,6,9",secondCsv =
"ID,three,four
D,11,16
E,7,12,17
F,8,13,18
G,9,14,19
H,10,15,20",thirdCsv =
"ID,yes,no,maybe
I,1
J,2
K,3
L,4
M,5",// For example's sake,let's suppose that the contrived table below was
// returned by calling Folder.Files
filesInFolder = Table.FromColumns({
List.Transform({firstCsv,secondCsv,thirdCsv},Text.ToBinary),List.Transform({"1".."3"},each "CSV file " & _ & ".csv"),List.Repeat({"someFolderPath"},3)
},type table [Content = binary,Name = text,Folder = text]),parsed = List.Transform(filesInFolder[Content],each
let
csv = Csv.Document(_,[Delimiter = ",",QuoteStyle = QuoteStyle.Csv]),promoted = Table.PromoteHeaders(csv,[PromoteAllScalars = true])
in promoted
),// The step below should match the expected output in your question.
combined = Table.Combine(parsed)
in
combined
很显然,您需要调整自己的文件夹路径并实际调用Folder.Files
,因为您大概已经在自己的代码中了。
我一直都这样使用
//read all files in specified directory you fill in here
let Source = Folder.Files("C:\directory\subdirectory"),//filter only csv files
#"Filtered Rows" = Table.SelectRows(Source,each ([Extension] = ".csv")),//Pull contents of each file into table with an index
#"Added Custom1" = Table.AddColumn(#"Filtered Rows","Custom",each Table.AddIndexColumn(Csv.Document(File.Contents([Folder Path]&"\"&[Name]),[Delimiter=",Encoding=1252,QuoteStyle=QuoteStyle.None]),"Index")),#"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom1",{"Column1","Index"},"Index"}),#"Removed Other Columns" = Table.SelectColumns(#"Expanded Custom","Index","Name"}),#"Pivoted Column" = Table.Pivot(#"Removed Other Columns",List.Distinct(#"Removed Other Columns"[Name]),"Name","Column1"),#"Removed Columns" = Table.RemoveColumns(#"Pivoted Column",{"Index"})
in #"Removed Columns"