【问题标题】:How to modify VBA code for Excel to use with an Access table?如何修改 Excel 的 VBA 代码以与 Access 表一起使用?
【发布时间】:2021-07-13 22:59:03
【问题描述】:

我从一位称职的用户那里得到了这个代码,不确定他是否想被命名。该代码在 HTML 内容中搜索某些标签的 innerText 并将它们传输到 Excel 表格中,在标题下很好地排序,结构为枢轴。

Public Sub GetDataFromURL()
    Const URL = "URL"
    Dim html As MSHTML.HTMLDocument, xhr As Object

    Set html = New MSHTML.HTMLDocument
    Set xhr = CreateObject("MSXML2.ServerXMLHTTP.6.0")

    With xhr
        .Open "POST", URL, False
        .setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
        .send "...parameters..."
        html.body.innerHTML = .responseText
    End With

    Dim table As MSHTML.HTMLTable, r As Long, c As Long, headers(), row As MSHTML.HTMLTableRow
    Dim results() As Variant, html2 As MSHTML.HTMLDocument

    headers = Array("HDR01", "HDR02", "HDR03", "HDR04")

    ReDim results(1 To 100, 1 To UBound(headers) + 1)

    Set table = html.querySelector("table")
    Set html2 = New MSHTML.HTMLDocument

    Dim lastRow As Boolean

    For Each row In table.Rows
        lastRow = False
        Dim header As String

        html2.body.innerHTML = row.innerHTML
        header = Trim$(row.Children(0).innerText)

        If header = "HDR01" Then
            r = r + 1
            Dim dict As Scripting.Dictionary: Set dict = GetBlankDictionary(headers)
            On Error Resume Next
            dict("HDR02") = Replace$(html2.querySelector("a").href, "about:", "https://URL")
            On Error GoTo 0
        End If

        If dict.Exists(header) Then dict(header) = Trim$(row.Children(1).innerText)

        If (header = vbNullString And html2.querySelectorAll("a").Length > 0) Then
            dict("HDR03") = Replace$(html2.querySelector("a").href, "about:blank", "URL")
            lastRow = True
        ElseIf header = "HDR04" Then
            If row.NextSibling.NodeType = 1 Then lastRow = True
        End If

        If lastRow Then
            populateArrayFromDict dict, results, r
        End If
    Next

    results = Application.Transpose(results)
    ReDim Preserve results(1 To UBound(headers) + 1, 1 To r)
    results = Application.Transpose(results)
    
    Dim re As Object
    
    Set re = CreateObject("VBScript.RegExp")
    
    With re
        .Global = False
        .MultiLine = False
        .IgnoreCase = True
        .Pattern = "\s([0-9.]+)\sm²"
    End With

    Dim ie As SHDocVw.InternetExplorer
    
    Set ie = New SHDocVw.InternetExplorer
    
    With ie
        .Visible = True
        
        For r = LBound(results, 1) To UBound(results, 1)
            
            If results(r, 7) <> vbNullString Then
                
                .Navigate2 results(r, 7), headers:="Referer: " & URL
                
                While .Busy Or .readyState <> READYSTATE_COMPLETE: DoEvents: Wend
 
                'On Error Resume Next
                results(r, 8) = re.Execute(.document.querySelector("#anz").innerHTML)(0).Submatches(0)
                'On Error GoTo 0
   
            End If
            
        Next
        
        .Quit
        
    End With
    
    With ActiveSheet
        .Cells(1, 1).Resize(1, UBound(headers) + 1) = headers
        .Cells(2, 1).Resize(UBound(results, 1), UBound(results, 2)) = results
    End With

End Sub

它在 Excel 中完美运行,但我需要它用于 Access 表。我的名为 tblTab01 的 Aceess 表包含 headers = array("...") 中的代码中存在的所有字段,并且我禁用了以下行在代码中:

results = Application.Transpose(results)

ActiveSheet.Cells(1, 1).Resize(1, UBound(headers) + 1) = headers

相反,我添加了以下几行:

Dim db As DAO.Database
Dim strInsert
Set db = CurrentDb
strInsert = "INSERT INTO tblTab01 VALUES (results);"
db.Execute strInsert

但我只会得到所有可能的错误!

如何修改代码以用于 Access 表?谢了

【问题讨论】:

  • 它们有完全不同的对象模型,需要大量重写。此外,除非您确切知道从 html 收到的内容,否则您可以使用正则表达式 cannot parse 它。
  • 虽然保存为 CSV 并导入 Access 可能会奏效,但您只会为未来制造巨大的混乱。最好退后一步,从 Access 开始(如果那里是数据所在的位置)并将其拆分为小步骤。首先获取网页,然后解析出您需要的数据,最后将其添加到 Access 表中。如果遇到问题,请发布您拥有的代码和数据,预期结果,并正确解释问题。
  • 根据结构,Access 可以导入/链接到 HTML 文档。如果您使用 VALUES 子句,则需要指定要插入的字段。但是,AFAIK 不能在 INSERT 操作中使用这样的数组对象。
  • 读取HTML和提取数据应该与Excel VBA中的基本相同(RegEx在Access VBA中可用,假设RegEx合适)。 VBA 将数据写入表可以通过以下几种方式完成:1)打开记录集并将记录添加到记录集对象或 2)插入操作 SQL。循环遍历数组对象以将其元素写入 Access 表。
  • 如果您从 Excel 写入 csv,您可以从 Access(甚至只是从 Excel)导入。而不是担心任何重写。很确定这是在 Access 中单击几下按钮。

标签: html sql excel vba ms-access


【解决方案1】:

这会产生与 Excel 代码相同的输出。我尝试了一个消除循环数组的解决方案,但这个版本实际上更快。

必须使用 Excel WorksheetFunction 才能使 Transpose 方法起作用。确保在 References 中选择了 Excel 库。

    results = Excel.WorksheetFunction.Transpose(results)
    ReDim Preserve results(1 To UBound(headers) + 1, 1 To r)
    results = Excel.WorksheetFunction.Transpose(results)

取消注释 On Error 行:

On Error Resume Next
results(r, 8) = re.Execute(.document.querySelector("#anz").innerHTML)(0).Submatches(0)
On Error GoTo 0

然后,不是With ActiveSheet 块,而是遍历数组。

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    CurrentDb.Execute "DELETE * FROM tblNetzPortDwnLd"
    Set db = CurrentDb
    Set rs = db.OpenRecordset("tblNetzPortDwnLd", dbOpenDynaset)
    For r = LBound(results, 1) To UBound(results, 1)
        With rs
            .AddNew
            .Fields("zpID") = r
            .Fields("zpAktenzeichen") = results(r, 1)
            .Fields("zpAmtsgericht") = results(r, 2)
            .Fields("zpObjekt") = results(r, 3)
            .Fields("zpVerkehrswert") = results(r, 4)
            .Fields("zpTermin") = results(r, 5)
            .Fields("zpPdfLink") = results(r, 6)
            .Fields("zpAdditLink") = results(r, 7)
            .Fields("zpm2") = results(r, 8)
            .Update
        End With
    Next

根据我们的聊天讨论,表格中的所有字段都是文本类型。

【讨论】:

  • 我对 zpID 字段使用了自动编号类型。这将自动创建一个“运行号码”。无需使用代码设置值。这就是为什么 zpID 不在 headers 数组中而不在字典中的原因。该程序有效。
  • 还有为什么它不在 populateTableFromDict 过程中。
  • 它对我有用。您是否将该字段设为自动编号类型?
  • 在文本字段中有一个“运行号码”是没有意义的。为什么不能只使用自动编号类型?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-25
  • 2017-06-01
  • 1970-01-01
  • 2015-06-24
  • 2017-05-26
  • 1970-01-01
  • 2023-04-08
相关资源
最近更新 更多