[英]Convert Rows of Spreadsheet With Repeating Column Headings to Separate XML Files Using VBA Macro
新用戶和不常/缺乏經驗的編碼器。 我在這個站點上不久找到了一個解決方案 ,該解決方案用於VBA宏,該宏為電子表格的每一行創建一個XML文件。 我在一個檔案館工作,我們的數字存儲庫系統需要XML元數據文件,這些文件的文件名與所描述的文件名相同(帶有.metadata擴展名)。 這樣系統可以將其識別為元數據而不是離散文件。 為了實現這一點,我們在具有與我們的元數據架構元素相匹配的列標題的電子表格中記錄了元數據,並運行VBA宏為每一行數據創建XML文件。
實際上,該宏非常適合從電子表格的每一行創建單獨的XML文件。 在我們更新元數據架構以支持重復元素之后,發生了問題。 當我在具有重復列標題/元素的電子表格上運行VBA宏時,生成的XML文件僅包含來自重復元素的最后一個實例的數據。 來自最后重復元素的相同數據值也將應用於先前的實例。
這就是我在說的。 如您所見,XML文件中重復的“ RecordContributorIndividual”元素僅包含來自電子表格中該元素的最終實例(第1行,第7列)的數據:
<?xml version="1.0" encoding="UTF-8"?>
<vtcore xmlns="http://www.sec.state.vt.us/vtcore">
<RecordCreatorIndividual>Peter Shumlin</RecordCreatorIndividual>
<RecordContributorIndividual>Stuck</RecordContributorIndividual>
<RecordContributorIndividual>Stuck</RecordContributorIndividual>
<RecordContributorIndividual>Stuck</RecordContributorIndividual>
<RecordContributorIndividual>Stuck</RecordContributorIndividual>
<RecordContributorIndividual>Stuck</RecordContributorIndividual>
<RecordTitle>President Ronald Reagan Day proclamation</RecordTitle>
<RecordDesc></RecordDesc>
我要實現的是一個VBA代碼,該代碼不會將重復元素的最后一個單元格值應用於該元素的所有先前實例,而是取而代之的是將電子表格單元格中的實際內容拉到每個元素下。 我在下面粘貼了VBA代碼。 我覺得問題出在“ doc.getElementsByTagName”區域中,但我對此並不樂觀。 我感覺自己接近了,但完全被卡住了。 任何幫助是極大的贊賞!
Sub testXLSMtovtcoreXML()
sTemplateXML = _
"<?xml version='1.0' encoding='UTF-8'?>" + vbNewLine + _
"<vtcore xmlns='http://www.sec.state.vt.us/vtcore'>" + vbNewLine + _
" <RecordCreatorIndividual>" + " </RecordCreatorIndividual>" + "
<RecordContributorIndividual>" + " </RecordContributorIndividual>" +
vbNewLine + _
" <RecordContributorIndividual>" + " </RecordContributorIndividual>"
+ " <RecordContributorIndividual>" + "
</RecordContributorIndividual>" + vbNewLine + _
" <RecordContributorIndividual>" + " </RecordContributorIndividual>"
+ " <RecordContributorIndividual>" + "
</RecordContributorIndividual>" + vbNewLine + _
" <RecordTitle>" + " </RecordTitle>" + " <RecordDesc>" + "
</RecordDesc>" + " <RecordDate>" + " </RecordDate>" + "
<RecordDate>" + " </RecordDate>" + vbNewLine + _
" <RecordDate>" + " </RecordDate>" + " <RecordDate>" + "
</RecordDate>" + " <RecordDate>" + " </RecordDate>" + vbNewLine + _
" <Agency>" + " </Agency>" + " <Domain>" + " </Domain>" + "
<Activity>" + " </Activity>" + " <RecordType>" + " </RecordType>"
+ vbNewLine + _
" <ClassificationCode>" + " </ClassificationCode>" + "
<RelatedRecords>" + " </RelatedRecords>" + " <RelatedRecords>" + "
</RelatedRecords>" + vbNewLine + _
" <RelatedRecords>" + " </RelatedRecords>" + " <RelatedRecords>" +
" </RelatedRecords>" + " <RelatedRecords>" + " </RelatedRecords>"
+ vbNewLine + _
" <RecordIdentifier>" + " </RecordIdentifier>" + " <PublicAccess>"
+ " </PublicAccess>" + " <PublicAccessCitation>" + "
</PublicAccessCitation>" + vbNewLine + _
" <PublicAccessCitation>" + " </PublicAccessCitation>" + "
<PublicAccessCitation>" + " </PublicAccessCitation>" + vbNewLine + _
" <PublicAccessCitation>" + " </PublicAccessCitation>" + "
<PublicAccessCitation>" + " </PublicAccessCitation>" + vbNewLine + _
" <Subject>" + " </Subject>" + " <Subject>" + " </Subject>" + "
<Subject>" + " </Subject>" + " <Subject>" + " </Subject>" +
vbNewLine + _
" <Subject>" + " </Subject>" + vbNewLine + _
"</vtcore>" + 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
sFileName = .Cells(lRow, 1).Value
sRecordCreatorIndividual = .Cells(lRow, 2).Value
sRecordContributorIndividual = .Cells(lRow, 3).Value
sRecordContributorIndividual = .Cells(lRow, 4).Value
sRecordContributorIndividual = .Cells(lRow, 5).Value
sRecordContributorIndividual = .Cells(lRow, 6).Value
sRecordContributorIndividual = .Cells(lRow, 7).Value
sRecordTitle = .Cells(lRow, 8).Value
sRecordDesc = .Cells(lRow, 9).Value
sRecordDate = .Cells(lRow, 10).Value
sRecordDate = .Cells(lRow, 11).Value
sRecordDate = .Cells(lRow, 12).Value
sRecordDate = .Cells(lRow, 13).Value
sRecordDate = .Cells(lRow, 14).Value
sAgency = .Cells(lRow, 15).Value
sDomain = .Cells(lRow, 16).Value
sActivity = .Cells(lRow, 17).Value
sRecordType = .Cells(lRow, 18).Value
sClassificationCode = .Cells(lRow, 19).Value
sRelatedRecords = .Cells(lRow, 20).Value
sRelatedRecords = .Cells(lRow, 21).Value
sRelatedRecords = .Cells(lRow, 22).Value
sRelatedRecords = .Cells(lRow, 23).Value
sRelatedRecords = .Cells(lRow, 24).Value
sRecordIdentifier = .Cells(lRow, 25).Value
sPublicAccess = .Cells(lRow, 26).Value
sPublicAccessCitation = .Cells(lRow, 27).Value
sPublicAccessCitation = .Cells(lRow, 28).Value
sPublicAccessCitation = .Cells(lRow, 29).Value
sPublicAccessCitation = .Cells(lRow, 30).Value
sPublicAccessCitation = .Cells(lRow, 31).Value
sSubject = .Cells(lRow, 32).Value
sSubject = .Cells(lRow, 33).Value
sSubject = .Cells(lRow, 34).Value
sSubject = .Cells(lRow, 35).Value
sSubject = .Cells(lRow, 36).Value
doc.LoadXML sTemplateXML
doc.getElementsByTagName("RecordCreatorIndividual")(0).appendChild
doc.createTextNode(sRecordCreatorIndividual)
doc.getElementsByTagName("RecordContributorIndividual")(0).appendChild
doc.createTextNode(sRecordContributorIndividual)
doc.getElementsByTagName("RecordContributorIndividual")(1).appendChild
doc.createTextNode(sRecordContributorIndividual)
doc.getElementsByTagName("RecordContributorIndividual")(2).appendChild
doc.createTextNode(sRecordContributorIndividual)
doc.getElementsByTagName("RecordContributorIndividual")(3).appendChild
doc.createTextNode(sRecordContributorIndividual)
doc.getElementsByTagName("RecordContributorIndividual")(4).appendChild
doc.createTextNode(sRecordContributorIndividual)
doc.getElementsByTagName("RecordTitle")(0).appendChild
doc.createTextNode(sRecordTitle)
doc.getElementsByTagName("RecordDesc")(0).appendChild
doc.createTextNode(sRecordDesc)
doc.getElementsByTagName("RecordDate")(0).appendChild
doc.createTextNode(sRecordDate)
doc.getElementsByTagName("RecordDate")(1).appendChild
doc.createTextNode(sRecordDate)
doc.getElementsByTagName("RecordDate")(2).appendChild
doc.createTextNode(sRecordDate)
doc.getElementsByTagName("RecordDate")(3).appendChild
doc.createTextNode(sRecordDate)
doc.getElementsByTagName("RecordDate")(4).appendChild
doc.createTextNode(sRecordDate)
doc.getElementsByTagName("Agency")(0).appendChild
doc.createTextNode(sAgency)
doc.getElementsByTagName("Domain")(0).appendChild
doc.createTextNode(sDomain)
doc.getElementsByTagName("Activity")(0).appendChild
doc.createTextNode(sActivity)
doc.getElementsByTagName("RecordType")(0).appendChild
doc.createTextNode(sRecordType)
doc.getElementsByTagName("ClassificationCode")(0).appendChild
doc.createTextNode(sClassificationCode)
doc.getElementsByTagName("RelatedRecords")(0).appendChild
doc.createTextNode(sRelatedRecords)
doc.getElementsByTagName("RelatedRecords")(1).appendChild
doc.createTextNode(sRelatedRecords)
doc.getElementsByTagName("RelatedRecords")(2).appendChild
doc.createTextNode(sRelatedRecords)
doc.getElementsByTagName("RelatedRecords")(3).appendChild
doc.createTextNode(sRelatedRecords)
doc.getElementsByTagName("RelatedRecords")(4).appendChild
doc.createTextNode(sRelatedRecords)
doc.getElementsByTagName("RecordIdentifier")(0).appendChild
doc.createTextNode(sRecordIdentifier)
doc.getElementsByTagName("PublicAccess")(0).appendChild
doc.createTextNode(sPublicAccess)
doc.getElementsByTagName("PublicAccessCitation")(0).appendChild
doc.createTextNode(sPublicAccessCitation)
doc.getElementsByTagName("PublicAccessCitation")(1).appendChild
doc.createTextNode(sPublicAccessCitation)
doc.getElementsByTagName("PublicAccessCitation")(2).appendChild
doc.createTextNode(sPublicAccessCitation)
doc.getElementsByTagName("PublicAccessCitation")(3).appendChild
doc.createTextNode(sPublicAccessCitation)
doc.getElementsByTagName("PublicAccessCitation")(4).appendChild
doc.createTextNode(sPublicAccessCitation)
doc.getElementsByTagName("Subject")(0).appendChild
doc.createTextNode(sSubject)
doc.getElementsByTagName("Subject")(1).appendChild
doc.createTextNode(sSubject)
doc.getElementsByTagName("Subject")(2).appendChild
doc.createTextNode(sSubject)
doc.getElementsByTagName("Subject")(3).appendChild
doc.createTextNode(sSubject)
doc.getElementsByTagName("Subject")(4).appendChild
doc.createTextNode(sSubject)
doc.Save sFileName + ".metadata"
Next
End With
End Sub
考慮使用MSXML庫及其createElement
, createNode
和appendChild
方法動態構建XML,該方法不會硬編碼節點名稱或文本值,而是從單元格中提取它們。 然后使用Identity Transform XSLT漂亮地打印輸出。 無需構建文本模板即可在代碼中進行調整。 具體來說,使用createNode
是因為您需要在文檔xmlns="http://www.sec.state.vt.us/vtcore"
使用默認名稱空間:
Excel輸入數據
VBA (使用早期綁定與MSXML參考對象)
Option Explicit
Sub XMLExport()
On Error GoTo ErrHandle
Dim lastCol As Long, lastRow As Long
Dim xlrow As Long
' WRITE TO XML
With ThisWorkbook.Sheets(1)
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For xlrow = 2 To lastRow
Call BuildXML(xlrow)
Next xlrow
End With
MsgBox "Successfully migrated Excel data into XML files!", vbInformation
ExitHandle:
Exit Sub
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Resume ExitHandle
End Sub
Function BuildXML(i As Long)
On Error GoTo ErrHandle
' REFERENCE Microsoft XML, v6.0 UNDER TOOLS\REFERENCES
Dim doc As New MSXML2.DOMDocument, xslDoc As New MSXML2.DOMDocument, newDoc As New MSXML2.DOMDocument
Dim root As IXMLDOMNode, colNode As IXMLDOMNode
Dim xslFile As String, xml_filename As String
Dim lastCol As Long, lastRow As Long
Dim j As Long
' DECLARE XML DOC OBJECT
Set root = doc.createNode(1, "vtcore", "http://www.sec.state.vt.us/vtcore")
doc.appendChild root
' WRITE TO XML
With ThisWorkbook.Sheets(1)
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
xml_filename = Mid(.Cells(i, 1), 1, InStr(.Cells(i, 1), ".") - 1) & ".metadata"
For j = 2 To lastCol
Set colNode = doc.createNode(1, .Cells(1, j), "http://www.sec.state.vt.us/vtcore")
colNode.Text = .Cells(i, j)
root.appendChild colNode
Next j
End With
' PRETTY PRINT OUTPUT WITH INDENTATION AND LINE BREAKS
xslDoc.LoadXML "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "?>" _
& "<xsl:stylesheet version=" & Chr(34) & "1.0" & Chr(34) _
& " xmlns:xsl=" & Chr(34) & "http://www.w3.org/1999/XSL/Transform" & Chr(34) & ">" _
& " <xsl:strip-space elements=" & Chr(34) & "*" & Chr(34) & " />" _
& " <xsl:output method=" & Chr(34) & "xml" & Chr(34) & " indent=" & Chr(34) & "yes" & Chr(34) & "" _
& " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "/>" _
& " <xsl:template match=" & Chr(34) & "node() | @*" & Chr(34) & ">" _
& " <xsl:copy>" _
& " <xsl:apply-templates select=" & Chr(34) & "node() | @*" & Chr(34) & " />" _
& " </xsl:copy>" _
& " </xsl:template>" _
& "</xsl:stylesheet>"
xslDoc.async = False
doc.transformNodeToObject xslDoc, newDoc
newDoc.Save Application.ActiveWorkbook.Path & "\" & xml_filename
Debug.Print xml_filename
ExitHandle:
Set doc = Nothing: Set xslDoc = Nothing: Set newDoc = Nothing
Exit Function
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Resume ExitHandle
End Function
輸出量
<?xml version="1.0" encoding="UTF-8"?>
<vtcore xmlns="http://www.sec.state.vt.us/vtcore">
<FileName>16-001 President Ronald Reagan Day.pdf</FileName>
<RecordCreatorIndividual>Peter Shumulin</RecordCreatorIndividual>
<RecordCreatorIndividual>Help </RecordCreatorIndividual>
<RecordCreatorIndividual>I </RecordCreatorIndividual>
<RecordCreatorIndividual>Am</RecordCreatorIndividual>
<RecordCreatorIndividual>Realy</RecordCreatorIndividual>
<RecordCreatorIndividual>Stuck</RecordCreatorIndividual>
<RecordCreatorIndividual>President Ronald Reagan Day proclamation</RecordCreatorIndividual>
</vtcore>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.