首页 > 解决方案 > 通过 VBA 将 excel 行导出到单个 XML 文件

问题描述

我正在关注这个答案(将电子表格的行转换为单独的 XML 文件),但是我收到一个错误消息,告诉我未定义对象。我很抱歉,因为我是 VBA 的新手。

我的表格遵循代码中显示的顺序,例如

我产生错误的代码是:

    Sub testXLStoXML()

sTemplateXML = _
        "<xml_version>" + vbNewLine + _
        "<xml_movie>" + vbNewLine + _
        "<plot>" + vbNewLine + _
        "<xml_outline>" + vbNewLine + _
        "<xml_lockdata>" + vbNewLine + _
        "<dateadded>" + vbNewLine + _
        "<title>" + vbNewLine + _
        "<rating>" + vbNewLine + _
        "<year>" + vbNewLine + _
        "<sorttile>" + vbNewLine + _
        "<mpaa>" + vbNewLine + _
        "<premiered>" + vbNewLine + _
        "<releasedate>" + vbNewLine + _
        "<runtime>" + vbNewLine + _
        "<studio>" + vbNewLine + _
        "<1>" + vbNewLine + _
        "<2>" + vbNewLine + _
        "<3>" + vbNewLine + _
        "<folder>" + vbNewLine + _
        "</data>" + vbNewLine

 Set doc = CreateObject("MSXML2.DOMDocument")
 doc.async = False
 doc.validateOnParse = False
 doc.resolveExternals = False

 With ActiveWorkbook.Worksheets(1)
  lLastRow = .UsedRange.Rows.Count

  For lRow = 2 To lLastRow
   sFile = .Cells(lRow, 2).Value
   sXml_version = .Cells(lRow, 677).Value
   sXml_movie = .Cells(lRow, 678).Value
   sPlot = .Cells(lRow, 679).Value
   sXml_outline = .Cells(lRow, 680).Value
   sXml_lockdata = .Cells(lRow, 681).Value
   sDateadded = .Cells(lRow, 682).Value
   sTitle = .Cells(lRow, 683).Value
   sRating = .Cells(lRow, 684).Value
   sYear = .Cells(lRow, 685).Value
   sSorttile = .Cells(lRow, 686).Value
   sMpaa = .Cells(lRow, 687).Value
   sPremiered = .Cells(lRow, 688).Value
   sReleasedate = .Cells(lRow, 689).Value
   sRuntime = .Cells(lRow, 690).Value
   sStudio = .Cells(lRow, 691).Value
   s1 = .Cells(lRow, 692).Value
   s2 = .Cells(lRow, 693).Value
   s3 = .Cells(lRow, 694).Value
   sFolder = .Cells(lRow, 800).Value
   doc.LoadXML sTemplateXML
   doc.getElementsByTagName("xml_version")(0).appendChild doc.createTextNode(sXml_version)
   doc.getElementsByTagName("xml_movie")(0).appendChild doc.createTextNode(sXml_movie)
   doc.getElementsByTagName("plot")(0).appendChild doc.createTextNode(sPlot)
   doc.getElementsByTagName("xml_outline")(0).appendChild doc.createTextNode(sXml_outline)
   doc.getElementsByTagName("xml_lockdata")(0).appendChild doc.createTextNode(sXml_lockdata)
   doc.getElementsByTagName("dateadded")(0).appendChild doc.createTextNode(sDateadded)
   doc.getElementsByTagName("title")(0).appendChild doc.createTextNode(sTitle)
   doc.getElementsByTagName("rating")(0).appendChild doc.createTextNode(sRating)
   doc.getElementsByTagName("year")(0).appendChild doc.createTextNode(sYear)
   doc.getElementsByTagName("sorttile")(0).appendChild doc.createTextNode(sSorttile)
   doc.getElementsByTagName("mpaa")(0).appendChild doc.createTextNode(sMpaa)
   doc.getElementsByTagName("premiered")(0).appendChild doc.createTextNode(sPremiered)
   doc.getElementsByTagName("releasedate")(0).appendChild doc.createTextNode(sReleasedate)
   doc.getElementsByTagName("runtime")(0).appendChild doc.createTextNode(sRuntime)
   doc.getElementsByTagName("studio")(0).appendChild doc.createTextNode(sStudio)
   doc.getElementsByTagName("1")(0).appendChild doc.createTextNode(s1)
   doc.getElementsByTagName("2")(0).appendChild doc.createTextNode(s2)
   doc.getElementsByTagName("3")(0).appendChild doc.createTextNode(s3)
   doc.getElementsByTagName("folder")(0).appendChild doc.createTextNode(sFolder)
   doc.Save sFile
  Next

 End With

End Sub

突出显示的错误是“ doc.getElementsByTagName("xml_version")(0).appendChild doc.createTextNode(sXml_version)”

虽然这可能只是第一个顺序。

我想要做的 - 这是针对每一行不为空的

最后 3 个是斜体字,因为我还没有想到要这样做,因为它不在示例中。例如,我什至不知道将文件夹值放在代码中的哪个位置,它是否可以像我所做的那样与其他列一起列出。我也不知道是否需要模板中的“/data”。

澄清一下,这是为媒体系统自动生成 NFO 文件以作为元数据读取。我有很多面向家庭的视频文件,所以没有元数据网站可以从中抓取数据。

编辑:

更新的代码 - 此代码有效!

Sub Export()

sTemplateXML = _
        "<data>" + vbNewLine + _
        "   <_version/>" + vbNewLine + _
        "   <_movie/>" + vbNewLine + _
        "   <plot/>" + vbNewLine + _
        "   <_outline/>" + vbNewLine + _
        "   <_lockdata/>" + vbNewLine + _
        "   <dateadded/>" + vbNewLine + _
        "   <title/>" + vbNewLine + _
        "   <rating/>" + vbNewLine + _
        "   <year/>" + vbNewLine + _
        "   <sorttile/>" + vbNewLine + _
        "   <mpaa/>" + vbNewLine + _
        "   <premiered/>" + vbNewLine + _
        "   <releasedate/>" + vbNewLine + _
        "   <runtime/>" + vbNewLine + _
        "   <studio/>" + vbNewLine + _
        "   <_1/>" + vbNewLine + _
        "   <_2/>" + vbNewLine + _
        "   <_3/>" + vbNewLine + _
        "</data>" + vbNewLine


 Set doc = CreateObject("MSXML2.DOMDocument")
 doc.async = False
 doc.validateOnParse = False
 doc.resolveExternals = False

With Sheets("Sheet3")
  lLastRow = .UsedRange.Rows.Count

 For lRow = 3 To lLastRow
   sFile = .Cells(lRow, 2).Value
   s_version = .Cells(lRow, 677).Value
   s_movie = .Cells(lRow, 678).Value
   sPlot = .Cells(lRow, 679).Value
   s_outline = .Cells(lRow, 680).Value
   s_lockdata = .Cells(lRow, 681).Value
   sDateadded = .Cells(lRow, 682).Value
   sTitle = .Cells(lRow, 683).Value
   sRating = .Cells(lRow, 684).Value
   sYear = .Cells(lRow, 685).Value
   sSorttile = .Cells(lRow, 686).Value
   sMpaa = .Cells(lRow, 687).Value
   sPremiered = .Cells(lRow, 688).Value
   sReleasedate = .Cells(lRow, 689).Value
   sRuntime = .Cells(lRow, 690).Value
   sStudio = .Cells(lRow, 691).Value
   sFolder = .Cells(lRow, 3).Value
   s_1 = .Cells(lRow, 692).Value
   s_2 = .Cells(lRow, 693).Value
   s_3 = .Cells(lRow, 694).Value
   
   doc.LoadXML sTemplateXML
   doc.getElementsByTagName("_version")(0).appendChild doc.createTextNode(s_version)
   doc.getElementsByTagName("_movie")(0).appendChild doc.createTextNode(s_movie)
   doc.getElementsByTagName("plot")(0).appendChild doc.createTextNode(sPlot)
   doc.getElementsByTagName("_outline")(0).appendChild doc.createTextNode(s_outline)
   doc.getElementsByTagName("_lockdata")(0).appendChild doc.createTextNode(s_lockdata)
   doc.getElementsByTagName("dateadded")(0).appendChild doc.createTextNode(sDateadded)
   doc.getElementsByTagName("title")(0).appendChild doc.createTextNode(sTitle)
   doc.getElementsByTagName("rating")(0).appendChild doc.createTextNode(sRating)
   doc.getElementsByTagName("year")(0).appendChild doc.createTextNode(sYear)
   doc.getElementsByTagName("sorttile")(0).appendChild doc.createTextNode(sSorttile)
   doc.getElementsByTagName("mpaa")(0).appendChild doc.createTextNode(sMpaa)
   doc.getElementsByTagName("premiered")(0).appendChild doc.createTextNode(sPremiered)
   doc.getElementsByTagName("releasedate")(0).appendChild doc.createTextNode(sReleasedate)
   doc.getElementsByTagName("runtime")(0).appendChild doc.createTextNode(sRuntime)
   doc.getElementsByTagName("studio")(0).appendChild doc.createTextNode(sStudio)
   doc.getElementsByTagName("_1")(0).appendChild doc.createTextNode(s_1)
   doc.getElementsByTagName("_2")(0).appendChild doc.createTextNode(s_2)
   doc.getElementsByTagName("_3")(0).appendChild doc.createTextNode(s_3)
   doc.Save sFolder & sFile & ".NFO"
   Next
   
   End With
 
End Sub

我不确定最后一行,但我只收到 doc.save 并出错,我尝试了所有组合(例如“doc.save sFile”、“doc.save sFile 和“NFO”等)。我已经还尝试了“doc.Save ThisWorkbook.Path & “/” & sFolder & “/” & sFile & “.NFO”。

标签: excelxmlvba

解决方案


从技术上讲,您应该收到一个错误LoadXML(除非它返回一个空doc),因为您的模板 XML 字符串由于各种原因格式不正确:

  • 没有合适的根。你关闭</data>但从不在<data>一开始就打开它。

  • 所有节点都不会关闭。尝试添加自闭合标签,您可以稍后在其中附加文本节点。

  • 根据XML 规范规则,节点名称不能以数字开头,也不能以xml关键字开头。

    [定义:名称是具有一组受限初始字符的 Nmtoken。] 名称中不允许使用的初始字符包括数字、变音符号、句号和连字符。

    以字符串“xml”开头的名称,或任何与 (('X'|'x') ('M'|'m') ('L'|'l')) 匹配的字符串,都保留用于标准化在本规范的此版本或未来版本中。

考虑使用下划线开头的禁止节点名称进行以下调整:

sTemplateXML = _
        "<data>" + vbNewLine + _
        "   <_xml_version/>" + vbNewLine + _
        "   <_xml_movie/>" + vbNewLine + _
        "   <plot/>" + vbNewLine + _
        "   <xml_outline/>" + vbNewLine + _
        "   <xml_lockdata/>" + vbNewLine + _
        "   <dateadded/>" + vbNewLine + _
        "   <title/>" + vbNewLine + _
        "   <rating/>" + vbNewLine + _
        "   <year/>" + vbNewLine + _
        "   <sorttile/>" + vbNewLine + _
        "   <mpaa/>" + vbNewLine + _
        "   <premiered/>" + vbNewLine + _
        "   <releasedate/>" + vbNewLine + _
        "   <runtime/>" + vbNewLine + _
        "   <studio/>" + vbNewLine + _
        "   <_1/>" + vbNewLine + _
        "   <_2/>" + vbNewLine + _
        "   <_3/>" + vbNewLine + _
        "   <folder/>" + vbNewLine + _
        "</data>" + vbNewLine

对于文件名处理,只需在doc.Save调用中连接需要的部分,这将在没有警告的情况下替换文件。

doc.Save SFolder & "\" & sFile & ".NFO"

推荐阅读