Power Query - 区域设置

Power Query - regional settings

我为我的部门制定了一个最佳实践 sheet,它在我自己的计算机上完美运行(en-US 区域设置),但是当我将它发送给同事时,一切都崩溃了(da -DK区域设置).

一半的部门使用 en-US,另一半使用 da-DK。不是每个人都可以使用相同的选项,所以我想创建一个可以自动处理两者的 sheet。

在 en-US 中创建的 csv 文件使用“,”分隔符和一个“.”对于十进制,而 da-DK 设置使用“;”作为分隔符和“,”用于小数。

我该如何最好地解决这个问题?

我有以下两个相同的数据查询

Data1.csv:

    Panel/Node/Case,    MXX (kNm/m),    MYY (kNm/m)
    1/ 1/ 1,            145.46,         145.46  
    1/ 1/ 2,            98.83,          98.83   
    1/ 1/ 3 (C),        244.30,         244.30  
    1/ 2/ 1,            19.80,          19.80   
    1/ 2/ 2,            13.46,          13.46   
    1/ 2/ 3 (C),        33.26,          33.26   
    1/ 3/ 1,            19.80,          19.80   
    1/ 3/ 2,            13.46,          13.46   
    1/ 3/ 3 (C),        33.26,          33.26   
    1/ 4/ 1,            145.46,         145.46  
    1/ 4/ 2,            98.83,          98.83   
    1/ 4/ 3 (C),        244.30,         244.30

Data2.csv:

    Panel/Node/Case;    MXX (kNm/m);    MYY (kNm/m)
    1/ 1/ 1;            145,46;         145,46
    1/ 1/ 2;            98,83;          98,83
    1/ 1/ 3 (C);        244,30;         244,30
    1/ 2/ 1;            19,80;          19,80
    1/ 2/ 2;            13,46;          13,46
    1/ 2/ 3 (C);        33,26;          33,26
    1/ 3/ 1;            19,80;          19,80
    1/ 3/ 2;            13,46;          13,46
    1/ 3/ 3 (C);        33,26;          33,26
    1/ 4/ 1;            145,46;         145,46
    1/ 4/ 2;            98,83;          98,83
    1/ 4/ 3 (C);        244,30;         244,30

我正在考虑使用替换值函数来替换我需要的字符,但由于两个查询都包含一个“,”,所以很难。

也许有一些 dynamic/built-in 方法可以检测文件内容的区域设置和分隔符。我还没有找到一个。在有人出现并指出更好的方法之前,也许以下可以作为临时解决方案。

  • 下面代码中的 parseCsv 函数尝试推断分隔符(它假定分隔符将始终出现在 CSV 的第一行中,紧跟在 Panel/Node/Case 之后)。
  • 它还尝试将最后两列的值从文本转换为数字(通过将 , 替换为 .)。如果你不想要这种行为,你可以从代码中删除它。此外,此转换仅适用于使用 . 作为小数点分隔符的语言环境。 (如果您需要支持其他 cultures/locales,尝试推断 culture/locale 并将其作为第二个参数传递给 Number.FromText 可能更有意义。)

let
    data1 = Text.ToBinary(
    "Panel/Node/Case,    MXX (kNm/m),    MYY (kNm/m)
    1/ 1/ 1,            145.46,         145.46  
    1/ 1/ 2,            98.83,          98.83   
    1/ 1/ 3 (C),        244.30,         244.30  
    1/ 2/ 1,            19.80,          19.80   
    1/ 2/ 2,            13.46,          13.46   
    1/ 2/ 3 (C),        33.26,          33.26   
    1/ 3/ 1,            19.80,          19.80   
    1/ 3/ 2,            13.46,          13.46   
    1/ 3/ 3 (C),        33.26,          33.26   
    1/ 4/ 1,            145.46,         145.46  
    1/ 4/ 2,            98.83,          98.83   
    1/ 4/ 3 (C),        244.30,         244.30", TextEncoding.Utf8),

    data2 = Text.ToBinary(
    "Panel/Node/Case;    MXX (kNm/m);    MYY (kNm/m)
    1/ 1/ 1;            145,46;         145,46
    1/ 1/ 2;            98,83;          98,83
    1/ 1/ 3 (C);        244,30;         244,30
    1/ 2/ 1;            19,80;          19,80
    1/ 2/ 2;            13,46;          13,46
    1/ 2/ 3 (C);        33,26;          33,26
    1/ 3/ 1;            19,80;          19,80
    1/ 3/ 2;            13,46;          13,46
    1/ 3/ 3 (C);        33,26;          33,26
    1/ 4/ 1;            145,46;         145,46
    1/ 4/ 2;            98,83;          98,83
    1/ 4/ 3 (C);        244,30;         244,30", TextEncoding.Utf8),

    parseCsv = (someFile as binary) =>
        let
            lines = Lines.FromBinary(someFile, QuoteStyle.Csv, false, TextEncoding.Utf8),
            firstLine = List.First(lines),
            expectedDelimiterPosition = Text.Length("Panel/Node/Case"), 
            delimiterInferred = Text.At(firstLine, expectedDelimiterPosition),
            csv = Csv.Document(someFile, [Delimiter = delimiterInferred, Encoding = TextEncoding.Utf8, QuoteStyle = QuoteStyle.Csv]),
            promoted = Table.PromoteHeaders(csv, [PromoteAllScalars=true]),
            lastTwoColumnsAsNumbers = 
                let
                    lastTwoHeaders = List.LastN(Table.ColumnNames(promoted), 2),
                    replaceAndConvertToNumber = (someText as text) as number => Number.From(Text.Replace(someText, ",", ".")),
                    transformers = List.Transform(lastTwoHeaders, each {_, replaceAndConvertToNumber, type number}),
                    transformed = Table.TransformColumns(promoted, transformers)
                in transformed
        in lastTwoColumnsAsNumbers,
    parsed1 = parseCsv(data1),
    parsed2 = parseCsv(data2),
    parsed3 = parseCsv(File.Contents("C:\Users\MRCH\Desktop\Data1.csv"))
in
    parsed3

  • 要实现这一点,您可以复制上面的代码,创建一个空白查询(在我的 Excel 版本中,我通过以下方式执行此操作:数据 > 获取数据 > 来自其他来源 > 来自空白查询),单击高级编辑器(靠近左上角),删除任何现有代码,粘贴您复制的内容,然后单击 "Done"。
  • 要使 parseCsv 函数使用文件路径,您可以将 parsed1 = parseCsv(data1) 更改为 parsed1 = parseCsv(File.Contents("SOME_FILE_PATH")),其中 SOME_FILE_PATH 是 [=21] 的文件路径=] 在你的机器上(保留双引号)。
  • 在查询编辑器中,您可以单击并查看 expressions/steps parsed1parsed2(这基本上是 parseCsv 函数 returns 的用途Data1.csvData2.csv)。 data1data2 仅用于演示目的,您可以将它们替换为 CSV 的实际二进制内容。

如果这没有帮助,让我知道我可以在哪里改进我的解释。