Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 宏,该宏跟随链接并将表下载到新工作表中_Vba_Excel_Web Scraping - Fatal编程技术网

Vba 宏,该宏跟随链接并将表下载到新工作表中

Vba 宏,该宏跟随链接并将表下载到新工作表中,vba,excel,web-scraping,Vba,Excel,Web Scraping,我是路易斯安那州一家小型石油公司的地质学家。我是我们技术部门的一员,不幸的是,我在编码方面的经验非常有限。我过去使用过非常基本的vba编码,但我在日常工作中没有这么多代码,所以我已经忘记了大部分内容 路易斯安那dnr保存着该州每一口钻井的惊人记录,所有这些记录都位于www.Sonris.com。这些记录的一部分是每口井的生产记录。我想创建一个宏,它遵循给定的url并下载url上的表(也称为生产记录)。下载完文件后,我想让它把表放在一张新的表中,然后根据井名给这张表命名 我已经玩弄了从web检索数

我是路易斯安那州一家小型石油公司的地质学家。我是我们技术部门的一员,不幸的是,我在编码方面的经验非常有限。我过去使用过非常基本的vba编码,但我在日常工作中没有这么多代码,所以我已经忘记了大部分内容

路易斯安那dnr保存着该州每一口钻井的惊人记录,所有这些记录都位于www.Sonris.com。这些记录的一部分是每口井的生产记录。我想创建一个宏,它遵循给定的url并下载url上的表(也称为生产记录)。下载完文件后,我想让它把表放在一张新的表中,然后根据井名给这张表命名

我已经玩弄了从web检索数据的功能,但是我无法使该功能具有足够的动态性。我需要代码来复制在单元格中找到的超链接数据。目前,代码只是跟随我在录制宏时复制和粘贴的超链接

任何帮助都将不胜感激

真诚地, 约西亚

下面是生成的代码

    Sub Macro2()
'
'     Macro2 Macro
' attempt with multiple well to look at code instead of 1 well
'

'
    Range("E27").Select
    ActiveWorkbook.Worksheets.Add
    With ActiveSheet.QueryTables.Add(Connection:= _
        "URL;http://sonlite.dnr.state.la.us/sundown/cart_prod/cart_con_wellinfo2?p_WSN=159392" _
        , Destination:=Range("$A$1"))
        .Name = "cart_con_wellinfo2?p_WSN=159392"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .WebSelectionType = xlSpecifiedTables
        .WebFormatting = xlWebFormattingNone
        .WebTables = "1,11"
        .WebPreFormattedTextToColumns = True
        .WebConsecutiveDelimitersAsOne = True
        .WebSingleBlockTextImport = False
        .WebDisableDateRecognition = False
        .WebDisableRedirections = False
        .Refresh BackgroundQuery:=False
    End With
    Sheets("Sheet1").Select
End Sub

使用所有可用于清除外部数据的方法,许多用户忘记了,您可以打开一个充满表格的网页,而只需要一个有效的URL和文件► 打开我在这里发布代码,但我还将提供一个指向工作示例工作簿的链接,该工作簿花了~2分钟从14个按顺序编号的WSN(web序列号)页面收集完整的网页数据。您自己的结果可能会有所不同

Option Explicit

Public Const csURL As String = "http://sonlite.dnr.state.la.us/sundown/cart_prod/cart_con_wellinfo2?p_WSN=×WSN×"

Sub Gather_Well_Data()
    Dim rw As Long, lr As Long, w As Long, wsn As String, wb As Workbook
    On Error GoTo Fìn
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    With ThisWorkbook.Sheets("WSNs")
        lr = .Cells(Rows.Count, 1).End(xlUp).Row
        For rw = 2 To lr
            .Cells(rw, 2) = 0
            For w = 1 To .Parent.Sheets.Count
                If .Parent.Sheets(w).Name = CStr(.Cells(rw, 1).Value) Then
                    .Parent.Sheets(w).Delete
                    Exit For
                End If
            Next w
            wsn = Replace(csURL, "×WSN×", .Cells(rw, 1).Value)
            Set wb = Workbooks.Open(Filename:=wsn, ReadOnly:=True, addtomru:=False)
            wb.Sheets(1).Range("A1:A3").Font.Size = 12
            wb.Sheets(1).Copy After:=.Parent.Sheets(.Parent.Sheets.Count)
            .Parent.Sheets(.Parent.Sheets.Count).Name = .Cells(rw, 1).Value
            wb.Close savechanges:=False
            Set wb = Nothing
            .Cells(rw, 2) = 1
            Application.ScreenUpdating = True
            Application.ScreenUpdating = False
            .Parent.Save
        Next rw
        .Activate
    End With
Fìn:
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub
WSN标识符列表位于从第2列开始的WSN工作表中。通过点击Alt+F8来运行宏,以打开“宏”对话框,然后运行“收集数据”宏。完成后,您将拥有一个工作簿,其中包含由WSN识别的工作表,如下所示

示例工作簿位于我的公共DropBox上,网址为:


为了利用@Jeeped awesome解决方案,我添加了要删除的格式,只保留了LeaseUnit/Well/Production信息。这假设套管表始终遵循生产表

Option Explicit

Public Const csURL As String = "http://sonlite.dnr.state.la.us/sundown/cart_prod/cart_con_wellinfo2?p_WSN=×WSN×"

Sub Gather_Well_Data()
    Dim rw As Long, lr As Long, w As Long, wsn As String, wb As Workbook, frow As String, lrow As String
    On Error GoTo Fìn
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False



    With ThisWorkbook.Sheets("WSNs")
        lr = .Cells(Rows.Count, 1).End(xlUp).Row
        For rw = 2 To lr
            .Cells(rw, 2) = 0
            For w = 1 To .Parent.Sheets.Count
                If .Parent.Sheets(w).Name = CStr(.Cells(rw, 1).Value) Then
                    .Parent.Sheets(w).Delete
                    Exit For
                End If
            Next w
            wsn = Replace(csURL, "×WSN×", .Cells(rw, 1).Value)
            Set wb = Workbooks.Open(Filename:=wsn, ReadOnly:=True, addtomru:=False)

            frow = Application.WorksheetFunction.Match("LEASE\UNIT\WELL PRODUCTION", Range("A:A"), 0)
            lrow = Application.WorksheetFunction.Match("Casing", Range("A:A"), 0)
            lrow = lrow - 1
            frow = "A" & frow
            lrow = "K" & lrow
            Range(frow, lrow).Cut Range("Q1")
            Columns("A:P").Select
            Selection.Delete Shift:=xlToLeft
            Cells.EntireColumn.AutoFit

            wb.Sheets(1).Range("A1:A3").Font.Size = 12
            wb.Sheets(1).Copy After:=.Parent.Sheets(.Parent.Sheets.Count)
            .Parent.Sheets(.Parent.Sheets.Count).Name = .Cells(rw, 1).Value
            wb.Close savechanges:=False
            Set wb = Nothing
            .Cells(rw, 2) = 1
            Application.ScreenUpdating = True
            Application.ScreenUpdating = False
            .Parent.Save
        Next rw
        .Activate
    End With
Fìn:
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub

吉普德的方法岩石+1

您还可以针对API发出
POST
请求,并按如下方式写出所有表

注意:我正在一个接一个地写每个井信息,但很容易就可以放一张表。在下一个API调用之前添加行,只需确保每次数据写出都使用activesheet即可

Option Explicit
Public Sub GetWellInfo()
    Dim ws As Worksheet, page As HTMLDocument, targetTable As HTMLTable, apiNumbers(), currNumber As Long
    Const PARAM1 As String = "p_apinum"
    Const BASESTRING As String = "http://sonlite.dnr.state.la.us/sundown/cart_prod/"
    apiNumbers = Array(1708300502, 1708300503)

    Application.ScreenUpdating = False
    Set ws = ThisWorkbook.Worksheets("Sheet1")

    With ws
        .Cells.ClearContents
        For currNumber = LBound(apiNumbers) To UBound(apiNumbers)
            Set page = GetPage(BASESTRING & "cart_con_wellapi2", apiNumbers(currNumber), PARAM1)
            Set page = GetPage(BASESTRING & GetNextURL(page.body.innerHTML))
            Dim allTables As Object
            Set allTables = page.getElementsByTagName("table")

            For Each targetTable In allTables
                AddHeaders targetTable, GetLastRow(ws, 1) + 2, ws
                WriteTables targetTable, GetLastRow(ws, 1), ws
            Next targetTable

        Next currNumber
    End With
    Application.ScreenUpdating = True
End Sub

Public Function GetPage(ByVal url As String, Optional ByVal apiNumber As Long, Optional ByVal paramN As String = vbNullString) As HTMLDocument
    Dim objHTTP As Object, html As New HTMLDocument

    Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")

    Dim sBody As String
    If Not paramN = vbNullString Then sBody = paramN & "=" & apiNumber
    With objHTTP
        .SetTimeouts 10000, 10000, 10000, 10000
        .Open "POST", url, False
        .setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
        .setRequestHeader "Content-type", "application/x-www-form-urlencoded"
        On Error Resume Next
        .send (sBody)
        If Err.Number = 0 Then
            If .Status = "200" Then
                html.body.innerHTML = .responseText
                Set GetPage = html
            Else
                Debug.Print "HTTP " & .Status & " " & .statusText
                Exit Function
            End If
        Else
            Debug.Print "Error " & Err.Number & " " & Err.Source & " " & Err.Description
            Exit Function
        End If
        On Error GoTo 0
    End With

End Function

Public Function GetNextURL(ByVal inputString As String)
    GetNextURL = Replace$(Replace$(Split(Split(inputString, "href=")(1), ">")(0), Chr$(34), vbNullString), "about:", vbNullString)
End Function

Public Sub AddHeaders(ByVal hTable As Object, ByVal startRow As Long, ByVal ws As Worksheet)
    Dim headers As Object, header As Object, columnCounter As Long
    Set headers = hTable.getElementsByTagName("th")
    For Each header In headers
        columnCounter = columnCounter + 1
        ws.Cells(startRow, columnCounter) = header.innerText
    Next header
End Sub

Public Sub WriteTables(ByVal hTable As HTMLTable, Optional ByVal startRow As Long = 1, Optional ByRef ws As Worksheet)
    If ws Is Nothing Then Set ws = ActiveSheet

    Dim tRow As Object, tCell As Object, tr As Object, td As Object, r As Long, c As Long
    r = startRow
    With ActiveSheet
        Set tRow = hTable.getElementsByTagName("tr")
        For Each tr In tRow
            Set tCell = tr.getElementsByTagName("td")
            For Each td In tCell
                .Cells(r, c).Value = td.innerText
                c = c + 1
            Next td
            r = r + 1:  c = 1
        Next tr
    End With
End Sub

您希望检索多少个井,WSN编号在哪里,您希望所有的表还是只是一个选择?理想情况下,我希望对整个油田进行此操作(因此在300个井的范围内)。我只想在表的选择中使用1个表。什么是无线传感器网络号?我猜无线传感器网络是井的序列号,如
。?p_WSN=159392
。啊,是的,我道歉。我以为那是一个密码。那代表井的序列号。序列号位于工作表的一列中。到目前为止,我还没有尝试在代码中使用它。您上面的代码当前运行时做什么?它是否能成功地用于特定的
WSN=159392
?非常感谢您为此所做的所有工作。我有一个后续问题。有没有办法只从网页下载一个表格而不是整个油井报告?我希望自动下载生产数据(网页上的leaseunit/well生产表),然后将其插入格式化的工作簿中,以自动计算我公司感兴趣的一些值。@JosiahHulsey-是的,这很可能与Excel中的任何一个数据一起使用► 获取外部数据► 从网页、Internet Explorer对象甚至Msxml.DOMDocument dom对象(TBH),收集300个页面并删除所有不需要的内容或将实际需要的内容整理到一个大型数据表或数据库中会更容易。