Ошибка 1004 при извлечении таблицы с ActiveWorkbook.Queries.Add - PullRequest
0 голосов
/ 16 февраля 2019

Я пытаюсь создать быстрый способ получить финансовые отчеты (базовую таблицу) из финансов Yahoo (например, https://finance.yahoo.com/quote/FB/financials?p=FB) с VBA. Я полный нуб, поэтому я использовал инструмент записи макросов и Getданные из Интернета и попытался (с моим несуществующим знанием VBA) адаптировать его для использования переменной (Ticker) для изменения компании.

При использовании функции получения данных из веб-таблицы таблица импортируется идеально, ноне работает с кодом VBA. Я получаю ошибку 1004 о ListObject.DisplayName или Refresh BackgroundQuery

Sub Macro5()
Dim Ticker As String
Ticker = InputBox("Ticker")
ActiveWorkbook.Queries.Add Name:="Table" & Ticker, Formula:= _
    "let" & Chr(13) & "" & Chr(10) & "    Source = Web.Page(Web.Contents(""https://finance.yahoo.com/quote/& Ticker &/financials?p=&Ticker &""))," & Chr(13) & "" & Chr(10) & "    Data2 = Source{2}[Data]," & Chr(13) & "" & Chr(10) & "    #""Type modifié"" = Table.TransformColumnTypes(Data2,{{""Column1"", type text}, {""Column2"", type text}, {""Column3"", type text}, {""Column4"", type text}, {""Column5"", type text}})" & Chr(13) & "" & Chr(10) & "in" & Chr(13) & "" & Chr(10) & "    #""Type modifié"""
ActiveWorkbook.Worksheets.Add
With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
    "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Extended Properties=""""" _
    , Destination:=Range("$A$1")).QueryTable
    .CommandType = xlCmdSql
    .CommandText = Array("SELECT * FROM [Table & Ticker")
    .RowNumbers = False
    .FillAdjacentFormulas = False
    .PreserveFormatting = True
    .RefreshOnFileOpen = False
    .BackgroundQuery = True
    .RefreshStyle = xlInsertDeleteCells
    .SavePassword = False
    .SaveData = True
    .AdjustColumnWidth = True
    .RefreshPeriod = 0
    .PreserveColumnInfo = True
    .ListObject.DisplayName = "Table" & Ticker
    .Refresh BackgroundQuery:=False
End With
End Sub

Идея состоит в том, чтобы вывести форму отчета о доходах для «Тикера» (FB в моем примере).Я использую Excel 365 на Windows

Большое спасибо

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Я пытался найти решение для вашего принятого кода.Ваша таблица интереса будет Table 2 на странице, когда мы получаем URL через вкладку данных Excel из Интернета.Мы должны решить две проблемы.

  • Ссылка на таблицу верна.При запуске программы количество раз имя таблицы запросов находится в памяти Excel и не удаляется даже после удаления листа.Поэтому я должен увеличить индекс таблицы как [Table 2 (2)], а затем в следующий раз [Table 2 (3)] в 3 местах в коде.Если мы будем увеличивать индекс таблицы каждый раз, когда программа будет работать правильно. Узнать, что такое индексный номер таблицы, поможет подпрограмма ListTables().Я не смог найти подходящий способ, чтобы Excel не запоминал индекс таблицы таблицы удаленных листов.
  • Второй необходимый момент - закрыть соединение.Я добавил подходящий код для того же.Окончательный код работает следующим образом.

     Sub Macro7()
     '
     ' Macro1 Macro
     '
    
     '
    Dim Cn As Variant
    Dim Ticker As String
    
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Ticker = InputBox("Ticker")
    
    ActiveWorkbook.Queries.Add Name:="Table 2 (18)", Formula:= _
        "let" & Chr(13) & "" & Chr(10) & "    Source = Web.Page(Web.Contents(""https://finance.yahoo.com/quote/" & Ticker & "/financials?p=" & Ticker & """))," & Chr(13) & "" & Chr(10) & "    Data2 = Source{2}[Data]," & Chr(13) & "" & Chr(10) & "    #""Changed Type"" = Table.TransformColumnTypes(Data2,{{""Column1"", type text}, {""Column2"", type text}, {""Column3"", type text}, {""Column4"", type text}, {""Column5"", type text}})" & Chr(13) & "" & Chr(10) & "in" & Chr(13) & "" & Chr(10) & "    #""Changed Type"""
    ActiveWorkbook.Worksheets.Add
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
        "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=""Table 2 (2)"";Extended Properties=""""" _
        , Destination:=Range("$A$1")).QueryTable
        .CommandType = xlCmdSql
        .CommandText = Array("SELECT * FROM [Table 2 (18)]")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .ListObject.DisplayName = "Table_2__18"
        .Refresh BackgroundQuery:=False
    End With
    'Range("A16").Select
    For Each Cn In ThisWorkbook.Connections
        Cn.Delete
     Next Cn
    For Each Cn In ActiveSheet.QueryTables
        Cn.Delete
    Next Cn
    
    Application.EnableEvents = True
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    
    
    End Sub
    

    А подпрограмма кода для индексации таблицы перечисления:

    Sub ListTables()
        Dim xTable As ListObject
        Dim xSheet As Worksheet
        Dim I As Long
        I = -1
        Sheets.Add.Name = "Table Name"
        For Each xSheet In Worksheets
        For Each xTable In xSheet.ListObjects
        I = I + 1
        Sheets("Table Name").Range("A1").Offset(I).Value = xTable.Name
        Sheets("Table Name").Range("B1").Offset(I).Value = xSheet.Name
        Next xTable
        Next
    End Sub
    
0 голосов
/ 16 февраля 2019

Простой способ - захватить все элементы таблицы на странице и зациклить те, которые используют буфер обмена для копирования вставки на лист.Вы можете настроить запись на разные листы в зависимости от значения тикера.Используйте тикеры с циклом для извлечения данных, но убедитесь, что вы создаете объект ie перед циклом, а затем поместите navigate2 в цикле, чтобы посещать каждую новую страницу тикера.

Public Sub GetTables()
    Dim clipboard As Object, ws As Worksheet, j As Long, tables As Object
    Dim ie As Object, ticker As String
    ticker = "FB"
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    ws.Cells.UnMerge
    ws.Cells.ClearContents
    Set clipboard = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")

    Application.ScreenUpdating = False
    Set ie = CreateObject("InternetExplorer.Application")
    With ie
        .Visible = True
        .Navigate2 "https://finance.yahoo.com/quote/FB/financials?p=" & ticker

        While .Busy Or .readyState < 4: DoEvents: Wend

        Set tables = .document.querySelectorAll("table")

        For j = 0 To tables.Length - 1
            clipboard.SetText tables.item(j).outerHTML
            clipboard.PutInClipboard
            ws.Cells(LastRow(ws) + 2, 1).PasteSpecial
        Next
        .Quit
    End With

    Application.ScreenUpdating = True
End Sub

'https://www.rondebruin.nl/win/s9/win005.htm

Public Function LastRow(ByVal sh As Worksheet) As Long
    On Error Resume Next
    LastRow = sh.Cells.Find(What:="*", _
                            After:=sh.Range("A1"), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlPrevious, _
                            MatchCase:=False).Row
    On Error GoTo 0
End Function

Этот второй методэто скорее скачок в знаниях для вас, но может быть полезным в будущем и для других читателей.Вы можете извлечь всю информацию на странице из тега скрипта.С помощью некоторого разбиения строки на innerHTML этого элемента скрипта вы можете получить строку, которую может обработать анализатор json.Затем вы можете проанализировать JSON для любой информации, которую вы хотите.Я добавляю схему только ниже.

Option Explicit
'VBE > Tools > References:
' Microsoft Internet Controls
' Microsoft Scripting Runtime
'Download and add in jsonconverter.bas from https://github.com/VBA-tools/VBA-JSON/blob/master/JsonConverter.bas
Public Sub GetYahooData()
    Dim IE As New InternetExplorer, ticker As String
    ticker = "FB"
    With IE
        .Visible = True
        .Navigate2 "https://finance.yahoo.com/quote/FB/financials?p=" & ticker

        While .Busy Or .readyState < 4: DoEvents: Wend

        Dim script As Object, scripts As Object, i As Long, extract As String, json As Object
        Set scripts = .document.querySelectorAll("script")

        For i = 0 To scripts.Length - 1
            If InStr(1, scripts.item(i).innerHTML, "/* -- Data -- */") Then
                Set script = scripts.item(i)
                Exit For
            End If
        Next
        If Not script Is Nothing Then
            extract = Split(Split(script.innerHTML, "root.App.main = ")(1), "(this));")(0)
            extract = Left$(extract, InStrRev(extract, ";") - 1)
            Set json = JsonConverter.ParseJson(extract)("context")("dispatcher")("stores")("QuoteSummaryStore")("cashflowStatementHistory")
        End If
        If Not json Is Nothing Then
            'parse json for data of interest
        End If
        Stop ' <== Delete me later
        .Quit
    End With
End Sub

В json просто слишком много информации, чтобы пройти через все это, но вот фрагмент снимка веб-страницы слева и json, которыйотносится к нему справа:

enter image description here


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...