Power Query 自定义函数 |将函数应用于存储在文件夹中的每个工作簿中的每个过滤工作表(具有不同的名称)

问题描述 投票:0回答:1

我正在处理来自 3 个不同经销商的 3 个文件。每个文件至少包含 6 页: 销售、采购、库存、销售(预测)、采购(预测)、库存(预测)以及一些概述表。

销售额指的是经销商所销售的产品, 采购指的是经销商购买的产品, 库存表示经销商的产品剩余库存。

我需要合并每个文件的 SALES 和 PURCHASING 表,并合并每个文件进行进一步分析。

现在,我正在使用 6 个自定义函数来管理此任务 - 每个函数对应每种工作表类型 (fnSALES、fnPURCHASING、fnSTOCK、fnSALES(预测)、fnPURCHASING(预测)、fnSTOCK(预测)。

我正在尝试将自定义函数应用于存储在文件夹中的每个工作簿中的每个过滤工作表(销售、采购)。

每次我尝试这样做时 - 它都会崩溃或抛出循环条件错误。

这是一张纸的功能:

(**PURCHESES_GROSS_FileName**)=>
let
    Source = Excel.Workbook(**PURCHESES_GROSS_FileName**, null, true),
    #"PURCHASES, GROSS_Sheet" = Source{[Item="PURCHASES, GROSS",Kind="Sheet"]}[Data],
    #"Transposed Table" = Table.Transpose(#"PURCHASES, GROSS_Sheet"),
    #"Filled Down" = Table.FillDown(#"Transposed Table",{"Column1", "Column2"}),
    #...
    #"Inserted Multiplication2" = Table.AddColumn(#"Inserted Multiplication1", "WHSL Value 2023, Eur", each [#"WHSL Price 2023, Eur"] * [Quantity], type number)
in
    #"Inserted Multiplication2"

它适用于我需要转换和组合的所有工作表(销售、销售(预测)、采购、采购(预测)。

我可以将其应用于所有工作簿,但仅限于“采购总额”工作表。 有什么办法让这个动态起来吗?

我试过这个:

1)

缓冲器:

let
    Source = Folder.Files("D:\1_1_1_ROOTMARK\Stock Movement\data"),
    #"Filtered Rows" = Table.SelectRows(Source, each [Extension] = ".xlsx"),
    #"Sorted Rows" = Table.Sort(#"Filtered Rows",{{"Name", Order.Ascending}}),
    #"Removed Other Columns" = Table.SelectColumns(#"Sorted Rows",{"Content", "Name"}),
    #"Extracted Text Before Delimiter" = Table.TransformColumns(#"Removed Other Columns", {{"Name", each Text.BeforeDelimiter(_, " SKU Stock movement.xlsx"), type text}}),
    #"Extracted Text Before Delimiter1" = Table.TransformColumns(#"Extracted Text Before Delimiter", {{"Name", each Text.BeforeDelimiter(_, " ", {0, RelativePosition.FromEnd}), type text}}),
    #"Renamed Columns" = Table.RenameColumns(#"Extracted Text Before Delimiter1",{{"Name", "Distributor"}}),
    #"Filtered Rows1" = Table.SelectRows(#"Renamed Columns", each not Text.StartsWith([Distributor], "~")),
    #"Filtered Rows2" = Table.SelectRows(#"Filtered Rows1", each ([Distributor] <> "ELVIM Bal"))
in
    #"Filtered Rows2"
(**Index**) =>
let 
    Inside_Of_workbook = #"Removed Columns"{**Index**}[data],
    #"_Sheet" = Inside_Of_workbook{[Item=[Item],Kind="Sheet"]}[Data],
    #"Transposed Table" = Table.Transpose(#"_Sheet"),
    #"Filled Down" = Table.FillDown(#"Transposed Table",{"Column3", "Column2"}),
    ...
    #"Inserted Multiplication2" = Table.AddColumn(#"Inserted Multiplication1", "WHSL Value 2023, Eur", each [#"WHSL Price 2023, Eur"] * [Quantity], type number)
in
    #"Inserted Multiplication2"
let
    // just to clean up the code
    Buffer_Hopes_For_All_Sheet_fn = Buffer,
    // Open all files and store the content in a table that is stored in a row
    WorkbookContents = Table.AddColumn(Buffer_Hopes_For_All_Sheet_fn, "Sheets", each Excel.Workbook([Content])),
    // added index to get the "Row number"
    #"Added Index" = Table.AddIndexColumn(WorkbookContents, "Index", 0, 1, Int64.Type),
    // Used the [Index] to get all the sheets from the excel files( I don't know, maybe this is the exact same step as "WorkbookContents" - looks similar)
    Sheets = Table.AddColumn(#"Added Index", "data", each #"Added Index"{[Index]}[Sheets]),
    // removed unnecessary columns
    #"Removed Columns" = Table.RemoveColumns(Sheets,{"Content", "Sheets"}),
    // Tried invoking the custom function giving the index parameter in each row the value of [Index] column
    #"Invoked Custom Function" = Table.AddColumn(#"Removed Columns", "Clean_data", each #"fn_PURCHASES, GROSS (Foreccast)"([Index])),
    // Returned an error in each row instead of a table containing 2 tables from each file.
    Clean_data = #"Invoked Custom Function"{0}[Clean_data] // returned an error
in
    Clean_data

错误: “”查询中发生错误。 Expression.Error:求值期间遇到循环引用。

2)

我还尝试首先复制功能代码并使用以下概念:

let
    *code1*
    Table.AddColumn(previousStep, "Clean_data", each 
    let 
        (index)=>
            let
                *function code*
            in
                *function output*
    in
        *function output*)
    *code*
in
    *output*

这立即崩溃了,它无法识别函数中的某些步骤,因为它无法访问代码1中存储的信息

当然,我希望这会像魅力一样发挥作用。

任何帮助或想法表示赞赏。 :)

1 板材结构: 样本数据

购买:

2023 2024
产品 一月 二月 三月 四月 一月 二月 三月 四月
A 1000 2000 200 100 2000 3000 0 0
B 1000 2000 300 100 300 3000 0 0

销售:

2023 2024
产品 一月 二月 三月 四月 一月 二月 三月 四月
A 1000 2000 200 100 2000 2000 0 0
B 1000 2000 300 100 300 1000 0 0

库存:

2023 2024
产品 一月 二月 三月 四月 一月 二月 三月 四月
A 0 0 0 0 0 1000 0 0
B 0 0 0 0 0 2000 0 0
excel powerquery m custom-function
1个回答
0
投票

如果我正确理解您的数据设置,您可以向函数提供一个表和所需的工作表名称,该函数将清理并合并数据。

我还了解您的数据是工作表(六张工作表)的内容,而不是

Table

既然如此,从您要导入的

Workbook
开始,您可以输入函数来处理工作表,如下所示,工作表名称
STOCK
PURCHASING
SALES

导入的工作簿将显示在名为

Imported Excel Workbook
的步骤中,看起来像:

您可以通过函数调用来调用您的处理函数,例如:

    #"Imported Excel Workbook" = Excel.Workbook(#"C:full_path_of_workbook"),
    #"Sheets to Process" = fnProcessSheet(#"Imported Excel Workbook", "SALES")[Data]

通过上述调用,该函数将处理

SALES
SALES(Forecast)
工作表。

对该函数进行三次单独的调用是否有意义——对每对工作表进行一次调用,或者对所有六张工作表进行一次调用,取决于您将如何处理输出,但这个大纲应该可以帮助您开始了。

(tbl as table, sheetname as text)=>

let 
    #"Actual" = Table.SelectRows(tbl, each [Name]=sheetname)[Data],
    #"Forecast" = Table.SelectRows(tbl, each [Name]=sheetname & "(Forecast)")

//Combine and clean the data
    
© www.soinside.com 2019 - 2024. All rights reserved.