Как проанализировать значения узлов XML с одинаковыми именами и списками в одной ячейке Excel - PullRequest
0 голосов
/ 25 июня 2019

У меня проблема с получением списка значений дочерних узлов XML для отображения в Excel. Я пытаюсь получить доступ к нескольким узлам с одним и тем же именем, но разными значениями, чтобы они отображались в их собственной ячейке Excel.

Мне просто нужна помощь по логике того, как получить эти несколько элементов в одной ячейке для каждого «правила» в коде ниже. Я предполагаю, что мне может понадобиться массив, но не уверен, как это сделать.

Вот код XML, по которому я зацикливаюсь:

<?xml version="1.0" encoding="utf-8"?>
<Benchmark>
    <Group id="V-26359">
        <Rule id="SV-53121r2_rule">
            <version>WN12-SO-000023</version>
            <ident system="http://cce.mitre.org">CCE-24020-0</ident>
            <ident system="http://iase.disa.mil/cci">CCI-000048</ident>
            <ident system="http://iase.disa.mil/cci">CCI-001384</ident>
            <ident system="http://iase.disa.mil/cci">CCI-001385</ident>
            <ident system="http://iase.disa.mil/cci">CCI-001386</ident>
            <ident system="http://iase.disa.mil/cci">CCI-001387</ident>
            <ident system="http://iase.disa.mil/cci">CCI-001388</ident>
        </Rule>
    </Group>
    <Group id="V-14235">
        <Rule id="SV-52947r1_rule">
            <version>WN12-SO-000078</version>
            <ident system="http://cce.mitre.org">CCE-23877-4</ident>
            <ident system="http://iase.disa.mil/cci">CCI-001084</ident>
        </Rule>
    </Group>
    <Group id="V-14236">
        <Rule id="SV-52948r1_rule">
            <version>WN12-SO-000079</version>
            <ident system="http://cce.mitre.org">CCE-24519-1</ident>
            <ident system="http://iase.disa.mil/cci">CCI-002038</ident>
        </Rule>
    </Group>
</Benchmark>

VBScript код:

On Error Resume Next

Set oShell = CreateObject("WScript.Shell")
strOutputFolder = oShell.ExpandEnvironmentStrings("%USERPROFILE%")

Set objFSO = CreateObject("Scripting.FileSystemObject")

If Not objFSO.FolderExists(strOutputFolder & "\Desktop\Output\") Then objFSO.CreateFolder(strOutputFolder & "\Desktop\Output\")

Set objExcel = CreateObject("Excel.Application")
objExcel.DisplayAlerts = False

objExcel.Workbooks.Add

Set objWorkbook = objExcel.Workbooks.Add()
Set colSheets = objWorkbook.Sheets
colSheets.Add ,,1

Sheet = 1

Set objSheet = objExcel.ActiveWorkbook.Worksheets(Sheet)
objSheet.Name = "Test"

strExcelPath = strOutputFolder & "\Desktop\Output\Test.xlsx"

objSheet.Cells(1, 1).Value = "Results" 'Row 1 Column 1 (A)

objExcel.ActiveWorkbook.SaveAs strExcelPath
objExcel.ActiveWorkbook.Close
objExcel.DisplayAlerts = True

objExcel.Application.Quit

Set objSheet = Nothing
Set objExcel = Nothing

strSheetName = "Test"

Set objExcel = CreateObject("Excel.Application")
Const xlUp = -4162
Set objWB = objExcel.Workbooks.Open(strExcelPath, False, False)
Set objWS = objWB.Sheets(strSheetName)

objExcel.Visible = False

intNextRow = objWS.Cells(65536, "A").End(xlUp).Row + 1

Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.SetProperty "SelectionLanguage", "XPath"
xmlDoc.Async = "False"
xmlDoc.Load("OutputFileForCCI.xml")

Set Rules = xmlDoc.SelectNodes("//Benchmark/Group/Rule")

For Each Rule In Rules
    Set CCIS = Rule.SelectNodes("ident[@system='http://iase.disa.mil/cci']")

    For Each CCI In CCIS
        objWS.Cells(intNextRow, "A").Value = CCI.Text
        intNextRow = intNextRow + 1
    Next
Next

objWB.Save
objWB.Close
objExcel.Quit
Set objWS = Nothing
Set objWB = Nothing
Set objExcel = Nothing

Ожидаемые результаты (каждое значение должно находиться на отдельной строке внутри ячейки):

Содержимое ячейки A1:

CCI-000048
CCI-001384
CCI-001385
CCI-001386
CCI-001387
CCI-001388

Содержимое ячейки A2:

CCI-001084

Содержимое ячейки A3:

CCI-002038

Фактический результат - вместо этого элементы помещаются в собственную ячейку.

1 Ответ

0 голосов
/ 28 июня 2019

Не увеличивайте счетчик строк во внутреннем цикле.Вместо этого соберите значения из внутреннего цикла в переменной и назначьте их ячейке после завершения внутреннего цикла.

For Each Rule In Rules
    Set CCIS = Rule.SelectNodes("ident[@system='http://iase.disa.mil/cci']")

    ReDim arr(CCIS.Length - 1)
    For i=0 To UBound(arr)
        arr(i) = CCIS(i).Text
    Next

    objWS.Cells(intNextRow, "A").Value = Join(arr, vbLf)
    intNextRow = intNextRow + 1
Next
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...