【问题标题】:VBA code that reads a txt file, places specified words into columns读取 txt 文件的 VBA 代码,将指定的单词放入列中
【发布时间】:2021-10-13 03:26:17
【问题描述】:

我正在尝试编写一个 VBA 宏,该宏将读取文本文档并将特定单词放入列中。更新:这是一个文件样本,显然是 XML,所以至少我今天学到了一些新东西。所以我想我需要一个程序来摆脱 XML 部分,并将文本放入列中。

<Alarm>
<ID>1002</ID>
<Type>Fault</Type>
<Message>Bad Brake</Message>
<Tagname>error.e2</Tagname>
</Alarm>
<Alarm>
<ID>1004</ID>
<Type>Fault</Type>
<Message>No Motion</Message>
<Tagname>error.e4</Tagname>
</Alarm>
<Alarm>
<ID>1005</ID>
<Type>Fault</Type>
<Message>Upper safety door open</Message>
<Tagname>error.e5</Tagname>
</Alarm>

最终,我试图将 4 位错误代码放入 A 列(即 1002、1004...),并将错误消息放入 B 列(即刹车不良、无动作...)。我将粘贴到目前为止的内容,我尝试将其编码为仅开始一对数据。我一直试图将错误消息放入 B 列。错误消息都从每一行的相同位置开始,但我不知道如何停止复制文本,因为每个错误消息的长度不同人物。有什么想法吗?

(P.S. - 如果代码很糟糕,我深表歉意,我一直在实习电气工程师,所以我的编程已经相当生疏了。)

Private Sub CommandButton1_Click()

Dim myFile As String, textLine As String, ID As Integer, error_msg As Integer

myFile = "C:\Users\scholtmn\Documents\Projects\Borg_Warner_txt_file\BW_fault_codes.txt"

Open myFile For Input As #1
Do Until EOF(1)
Line Input #1, textLine
Text = Text & textLine
Loop
Close #1

ID = InStr(Text, "<ID>")
error_msg = InStr(Text, "<Message>")

Range("A1").Value = Mid(Text, ID + 4, 4)
Range("B1").Value = Mid(Text, error_msg + 9, (InStr(Text, " <") - 31))



End Sub

【问题讨论】:

  • 根据这里的网站规则,请不要发布文本图像,只需发布​​文本(在这种情况下作为代码)。我们不能处理图片,我们需要文字。
  • 另外,这个文本是真正的 XML,所以你需要的是 VBA 代码,它会为你“分解”XML。
  • 所以,请编辑您的问题并将文本文件作为纯文本放入其中。

标签: excel vba text


【解决方案1】:

请尝试下一个代码:

Sub ExtractErrorsDefinition()
   'it needs a reference to 'Microsoft XML, v6.0'
   Dim XMLFileName As String, oXMLFile As New MSXML2.DOMDocument60, sh As Worksheet
   Dim N As MSXML2.IXMLDOMNode, i As Long, arr
   
   Set sh = ActiveSheet 'use here the necessary sheet
   
   XMLFileName = "the full text file path" '"C:\Utile\Teste Corel\XMLtext.txt"
   oXMLFile.Load (XMLFileName)
   
   ReDim arr(1 To oXMLFile.SelectNodes("AlarmDictionary/Alarm").length, 1 To 2): i = 1
   For Each N In oXMLFile.SelectNodes("AlarmDictionary/Alarm")
        arr(i, 1) = N.SelectSingleNode("ID").Text: arr(i, 1) = N.SelectSingleNode("Message").Text: i = i + 1
  Next
  sh.Range("A2").Resize(UBound(arr), 2).value = arr
End Sub

它可以使用后期绑定,但最好有智能感知建议,尤其是在不太熟练使用 XML 时。

如果添加这样的引用看起来很复杂,我可以添加一段代码来自动添加它。

请运行下一个代码以自动添加必要的引用。保存您的工作簿并在之后运行第一个代码:

Sub addXMLRef()
  'Add a reference to 'Microsoft Scripting Runtime':
  'In case of error ('Programmatic access to Visual Basic Project not trusted'):
  'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
  '         check "Trust access to the VBA project object model"
  Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\System32\msxml6.dll"
End Sub

【讨论】:

  • AlarmDictionary 节点的友好提示,因为它没有出现在 OP 中(并假设 Alarm 节点位于下一个层次结构级别):应用 .DocumentElement oXMLFile 对象的属性,您可以引用文档的实际根节点,而不必强制通过名称显式地对其进行寻址,例如通过oXMLFile.DocumentElement.SelectNodes("Alarm")@FaneDuru
  • @T.M.谢谢,但你错过了他的第一张附加图片,AlarmDictionary 是...当他发布可编辑的,在我们坚持这样做之后,他跳过了它,可能,不理解它可能很重要...:) 我准备好了可编辑文本之前的代码。
  • 感谢各位的帮助。我使用了您所有代码中的片段,以及一些坚韧不拔的老式“查找和替换”,并得到了我的清单。我应该提到这与功能/可重用性无关,它是一次性的场景,我只需要尽快完成它。如果我能对你所有的答案投赞成票,我会的,但我的帐户太新了:(谢谢!
【解决方案2】:

看起来您使用的 txt 文件实际上是一个 xml 文件。如果您更改了格式,我从here 稍微调整的这段代码应该可以正常工作。

Sub From_XML_To_XL()
    Dim xmlWb As Workbook, xSWb As Workbook, xStrPath$, xfdial As FileDialog, _
    xFile$, lr%, first As Boolean, r As Range
    first = True
    Set xfdial = Application.FileDialog(msoFileDialogFilePicker)
    xfdial.AllowMultiSelect = False
    xfdial.Title = "Select an XML File"
    If xfdial.Show = -1 Then xStrPath = xfdial.SelectedItems(1) & ""
    If xStrPath = "" Then Exit Sub
    Set xSWb = ThisWorkbook
    lr = xSWb.ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row    ' last used row, column A
    xFile = xStrPath
    Set xmlWb = Workbooks.OpenXML(xFile)
    If first Then
        Set r = xmlWb.Sheets(1).UsedRange                         ' with header
    Else
        xmlWb.Sheets(1).Activate
        Set r = ActiveSheet.UsedRange
        Set r = Range(Cells(3, 1), Cells(r.Rows.Count, r.Columns.Count))
    End If
    r.Copy xSWb.ActiveSheet.Cells(lr + 1, 1)
    lr = xSWb.ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row
    xmlWb.Close False
    first = False
End Sub

如果您利用它是 XML 格式的事实,我认为您会发现这项任务会容易得多。您可以在 VBA here 中找到有关使用 XML 的更多信息。

【讨论】:

    【解决方案3】:

    正如 Ben Mega 所说:您有一个 XML 文件 - 为什么不使用 XML 功能。

    将“Microsoft XML, v6.0”添加到您的项目引用中 - 然后您可以使用此代码

    
    Public Sub insertTextFromXML()
    
    Dim objXML As MSXML2.DOMDocument60
    Set objXML = New MSXML2.DOMDocument60
    
    If Not objXML.Load("T:\Stackoverflow\Test.xml") Then
        Err.Raise objXML.parseError.ErrorCode, , objXML.parseError.reason
    End If
     
    Dim nAlarm As MSXML2.IXMLDOMNode
    
    'loop through all alarms and output ID plus message
    For Each nAlarm In objXML.SelectNodes("AlarmDictionary/Alarm")
        With nAlarm
            Debug.Print .SelectSingleNode("ID").Text, .SelectSingleNode("Message").Text
        End With
    Next
    
    'Filter for ID 1004
    Set nAlarm = objXML.SelectSingleNode("AlarmDictionary/Alarm[ID=1004]")
    Debug.Print nAlarm.XML
    
    End Sub
    

    您可以搜索 VBA XPath 以了解如何访问各种值。

    【讨论】:

    • 或者不加引用也可以Dim ... As ObjectSet objXML = CreateObject("MSXML2.DOMDocument.6.0")
    猜你喜欢
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 2011-10-28
    • 2020-04-01
    相关资源
    最近更新 更多