Power Query Skewed data

时间:2017-02-09 09:32:39

标签: excel powerbi powerquery

我在电源查询中遇到问题,其中我的数据来自分成页面的报表,而某些页面将数据偏斜到不同的列。我认为可能存在基于错误的解决方案,但我希望它更加冗余,而不是依赖于文本与数字错误纠正。主要是因为有时在某些情况下可能是字母的数据在其他情况下可能是数字。我准备了一个随机生成名称和代码替换的数据集。我还必须稍微对数据进行屠宰,以提供不同变化的示例,并考虑从不同页面分割的记录。

https://drive.google.com/file/d/0B2qUbAWJXgfyNlByV2RHODJzQjA/view?usp=sharing

数据集中有12条记录,每条记录最终将包含一行。 第一页是从源文档中剥离的原始数据。这些是检查历史记录(屏蔽),需要将每个记录移动到一行,并为四个特定区域分别列:

[姓名,日期,支票号码等] [收入] [扣除] [税收]

包括姓名,日期,记录ID号和金额的记录信息是从原始数据中提取和格式化的第一件事。我在NameData和CheckData中应用的步骤将显示如何提取和格式化这些记录,本节中的一些偏斜数据也很容易与合并函数和条件列协调。

每个单独的付款项目(收入代码,扣减代码或税码)都会被格式化,然后转到它自己的列。您可以在“收入查询”中查看此操作的示例。 PayItemReference查询是我用作My Pay Items的起点的一些基本过滤器。您可以在该查询中看到代码将从列到列移位,文本和数字混合在一起。代码和它们的值之间可以有空格,或者没有空格,它也可以完全移动列。

我正在努力将代码及其值合并到常规列,然后我可以合并,取消忽略,转移等以获得最终格式。我曾尝试使用条件列和错误,但原始数据集中始终存在小问题。我只需要一些新鲜的眼睛和数据的新方法。

1 个答案:

答案 0 :(得分:2)

这是一项具有挑战性的任务。

首先将表拆分回页面是个好主意,因为每个页面的列结构可能是唯一的。因此,我形成了一个表的列表,每个表为一个页面。然后我必须处理每个页面:提取列名,添加每行的摘要信息,过滤不需要的行,以及设置列名。通过使用自定义函数ConvertTable对列表中的每个表执行此操作。之后,您只需合并结果表。

下面:

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    AddRowNum = Table.AddColumn(Table.AddIndexColumn(Source, "Index", 1, 1), "RowNum", each Number.Mod([Index]-1, 52)+1, type number),
    CountTables = {1..(Number.RoundUp(Table.RowCount(AddRowNum)/52, 0))},
    ListTables = List.Transform(CountTables, (ListItem)=>Table.SelectRows(AddRowNum, each [Index] > 52 * (ListItem - 1) and [Index] <= 52 * ListItem)),

    ConvertTable = (tbl as table) as table =>
    let
        hdr1 = Table.Transpose(Table.FillDown(Table.Transpose(Table.FromRecords({tbl{6}})), {"Column1"})),
        hdr2 = Table.FromRecords({tbl{7}}),
        ColNames = Table.Transpose(Table.SelectColumns(Table.FirstN(Table.AddColumn(Table.Transpose(Table.Combine({hdr1, hdr2})), "ColumnName", each [Column1] & ": " & [Column2]), 19), {"ColumnName"})),
        AddPayDate = Table.AddColumn(tbl, "Pay Date", each if [RowNum] > 8 and Text.Trim(tbl{[RowNum]-2}[Column9]) = "Pay Date" then [Column9] else null, type date),
        AddPeriodEndDate = Table.AddColumn(AddPayDate, "Period End Date", each if [RowNum] > 8 and Text.Trim(tbl{[RowNum]-2}[Column12]) = "Period End Date" then [Column12] else null, type date),
        AddJobCode = Table.AddColumn(AddPeriodEndDate, "Job Code", each if [RowNum] > 8 and Text.Trim(tbl{[RowNum]-2}[Column14]) = "Job Code" then [Column14] else null, Int64.Type),
        AddCheckInfo = Table.AddColumn(AddJobCode, "Check Info", each if [RowNum] > 8 and Text.Trim([Column1]) = "Check Printed:" then Table.Transpose(Table.SelectRows(Table.Transpose(Table.FromRecords({_})), each [Column1] <> null)) else null),
        ExpandedCheckInfo = Table.ExpandTableColumn(AddCheckInfo, "Check Info", {"Column4", "Column6", "Column8"}, {"Check Amount", "Direct Deposit", "Net"}),
        FillUp = Table.FillUp(ExpandedCheckInfo, {"Column3", "Check Amount", "Direct Deposit", "Net"})//Table.AddColumn(AddJobCode, "tmp2", each if [RowNum] < 9 then "" else (if Text.Trim([Column1]) = "Check Printed:" then (if [Column3] = null then -1 else [Column3]) else null), type text), {"tmp2"}),
        FillDown = Table.FillDown(FillUp, {"Column1", "Column5", "Pay Date", "Period End Date", "Job Code"}),
        AddCheckEEIDfixed = Table.AddColumn(FillDown, "Check:EEID.fixed", each Text.From([Column5]) & ":" & Text.From([Column3]), type text),
        FilteredExtraRows = Table.SelectRows(AddCheckEEIDfixed, each [RowNum] > 8 and Text.Trim([Column1]) <> "Check Printed:" and Text.Trim([Column7]) <> "PerControl" and Text.Trim(tbl{[RowNum]-2}[Column7]) <> "PerControl" and [#"Check:EEID.fixed"] <> null),
        DemotedHeaders = Table.DemoteHeaders(FilteredExtraRows),
        GetColumnNames1 = Table.Combine({Table.FromRecords({DemotedHeaders{0}}), ColNames}),
        GetColumnNames2 = Table.PromoteHeaders(Table.FillDown(GetColumnNames1, Table.ColumnNames(GetColumnNames1))),
        SetColumnNames = Table.PromoteHeaders(Table.Combine({GetColumnNames2, FilteredExtraRows}))
    in
        SetColumnNames,

    ConvertedList = List.Transform(ListTables, (t) => ConvertTable(t)),
    GetWholeTable = Table.Combine(ConvertedList)
in
    GetWholeTable