Запрос Excel с динамическим значением ячейки

#excel #powerquery #m

#excel #powerquery #m

Вопрос:

Мне нужна помощь в организации того, что нужно сделать. У меня есть список биржевых символов, и мне нужно загрузить данные для каждого из них, которые будут отображаться в таблице запросов. Вот как это будет выглядеть, даже если это сокращенная версия :

введите описание изображения здесь

Я создал URL-адрес для веб-запроса, но поскольку мой тикер меняется для каждого запроса, я не знаю, как заставить запрос просматривать ячейку тикера (C2, G2 и т. Д.) Я могу это сделать, если назову эти ячейки, но должен ли я называть каждую из них? Есть ли способ просмотреть значение ячейки на основе ссылки на ячейку? В приведенном ниже примере это должно быть в Source = Json.Документ (Web.Contents(meurl1 )), где я бы рекламировал meurl1 amp; C2 или что-то в этом роде. Есть идея?

 let
meurl1 = Excel.CurrentWorkbook(){[Name="meurl1"]}[Content]{0}[Column1],
Source = Json.Document(Web.Contents(meurl1 )),
#"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"date", "close", "high", "low", "open"}, {"Column1.date", "Column1.close", "Column1.high", "Column1.low", "Column1.open"}),
#"Changed Type" = Table.TransformColumnTypes(#"Expanded Column1",{{"Column1.date", type datetime}}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type",{{"Column1.date", "Date"}, {"Column1.close", "Close"}, {"Column1.high", "High"}, {"Column1.low", "Low"}, {"Column1.open", "Open"}}),
#"Reordered Columns" = Table.ReorderColumns(#"Renamed Columns",{"Date", "Open", "High", "Low", "Close"}),
#"Sorted Rows" = Table.Sort(#"Reordered Columns",{{"Date", Order.Descending}})
  

в

Комментарии:

1. Насколько я знаю, при использовании Excel.CurrentWorkbook вы можете ссылаться только на именованные диапазоны (включая таблицы). Это означает, что вы не можете использовать C2 (или G2 и т.д.) В своем коде запроса, поскольку Power Query не может интерпретировать произвольные ссылки на ячейки / адреса.

2. Некоторые варианты: #1 Превратите тикеры в столбце A в именованный диапазон, затем попросите Power Query захватить весь именованный диапазон сразу и перебирать его значения, чтобы получить данные каждого тикера. Однако это будет загружаться как одна таблица, содержащая данные всех тикеров (в отличие от отдельной таблицы для каждого тикера). #2 В качестве альтернативы, включите C2 G2 и т.д.) в именованные диапазоны, а затем создайте запрос для каждого тикера. Это потребует времени / усилий, чтобы сделать вручную (особенно, если вам нужно добавить / удалить тикеры позже), поэтому, возможно, используйте VBA для автоматизации создания / удаления / обновления запроса.

3. Спасибо! Я думаю, вы точно понимаете, с чем я сталкиваюсь. Вариант № 1, у меня нет знаний для этого. Будет ли это через VBA. Как вы его зацикливаете? И вариант № 2 — это именно то, чего я пытаюсь избежать. У меня более 100 тикеров. По крайней мере, теперь я знаю, какие есть варианты. Не могли бы вы привести очень простой пример того, что вы предлагаете в вариантах 1?

4. Да, мы предоставили простой пример варианта № 1. В таблице должны быть нужные вам данные, просто не в той структуре / формате, которые задал ваш вопрос.

Ответ №1:

В приведенном ниже примере данные для всех тикеров будут загружены в одну таблицу, а не в отдельную таблицу для каждого тикера.

  1. Создайте именованный диапазон, вызываемый tickers в вашем файле Excel, который содержит все тикеры (для которых вам нужно получить данные) в одном столбце.

  2. Скопируйте и вставьте приведенный ниже код в расширенный редактор в Power Query — и затем посмотрите, дает ли он ожидаемый результат.

Я включил три примера ( verticalTable , horizontalTable и anotherHorizontalTable ). Посмотрите, какой из трех вариантов лучше всего подходит для вас и ваших данных.

Я не уверен, какое значение meurl1 находится в вашем файле, поэтому я просто скопировал его из вашего вопроса.


 let
    tickers = Excel.CurrentWorkbook(){[Name="tickers"]}[Content][Column1],
    url = Excel.CurrentWorkbook(){[Name="meurl1"]}[Content]{0}[Column1],
    getTickerData = (someTicker as text) as table => 
        let
            response = Web.Contents(url amp; someTicker),
            parsed = Json.Document(response),
            toTable = Table.FromRecords(parsed, type table [
                date = datetime, open = number, high = number, low = number, close = number
            ])
        in toTable,
    // This approach should stack your ticker data vertically.
    // It's not what you asked for, but it might be a bit quicker than the approaches below.
    verticalTable = 
        let
            looped = List.Transform(tickers, each [ticker = _, data = getTickerData(ticker)]),
            toTable = Table.FromRecords(looped, type table [ticker = text, data = record]),
            expanded = Table.ExpandTableColumn(toTable, "data", {"date", "open", "high", "low", "close"}, {"Date", "Open", "High", "Low", "Close"})
        in expanded,
    // This approach will stack your ticker data horizontally, but with all tickers sharing a single
    // Date column.
    horizontalTable = 
        let
            allData = List.Transform(tickers, each [ticker = _, data = getTickerData(ticker)]),
            uniqueDates = List.Distinct(List.Combine(List.Transform(allData, each [data][date]))),
            looped = List.Accumulate(
                allData,
                Table.FromColumns({uniqueDates}, type table [Date = datetime]),
                (tableState as table, tickerData as record) as table =>
                    let
                        columnsToExpand = List.RemoveItems(Table.ColumnNames(tickerData[data]), {"date"}),
                        joined = Table.NestedJoin(tableState, "Date", tickerData[data], "date", "_toExpand"),
                        expanded = Table.ExpandTableColumn(joined, "_toExpand", columnsToExpand, List.Transform(columnsToExpand, each tickerData[ticker] amp; " (" amp; Text.Proper(_) amp; ")"))
                    in expanded
            )
        in looped,
    // This approach will stack your ticker data horizontally, but the difference here is each ticker
    // will have its own Date column.
    anotherHorizontalTable = 
        let
            looped = List.Accumulate(
                tickers,
                {},
                (tableColumns as list, ticker as text) as list =>
                    let
                        tickerTable = getTickerData(ticker),
                        renamed = Table.TransformColumnNames(tickerTable, each ticker amp; " (" amp; Text.Proper(_) amp; ")"),
                        columnNames = Table.ColumnNames(renamed),
                        columns = Table.ToColumns(renamed),
                        columnsWithMeta = List.Transform(List.Positions(columns), each columns{_} meta [columnName = columnNames{_}]),
                        combined = tableColumns amp; columnsWithMeta
                    in combined
            ),
            toTable = Table.FromColumns(looped, List.Transform(looped, each Value.Metadata(_)[columnName]))
        in toTable
in
    anotherHorizontalTable
  

Комментарии:

1. Спасибо, Чилин! Мне придется попробовать это и вернуться, если я добьюсь успеха