Con la funcio de exportacion funcionando

This commit is contained in:
Miguel 2024-09-24 21:09:24 +02:00
parent f40a9ee331
commit f819f41016
3 changed files with 391 additions and 419 deletions

View File

@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V19" />
<SW.Blocks.GlobalDB ID="0">
<AttributeList>
<AutoNumber>false</AutoNumber>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="Static">
<Member Name="Alarms" Datatype="Array[0..1] of &quot;UDT SV Manager Allarm&quot;">
<AttributeList>
<BooleanAttribute Name="SetPoint" SystemDefined="true">true</BooleanAttribute>
</AttributeList>
<Sections>
<Section Name="None">
<Member Name="AlarmNum" Datatype="Int">
<Subelement Path="0">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>0</StartValue>
</Subelement>
</Member>
<Member Name="Source DB" Datatype="Int">
<Subelement Path="0">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>0</StartValue>
</Subelement>
</Member>
<Member Name="Source Byte" Datatype="Int">
<Subelement Path="0">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>0</StartValue>
</Subelement>
</Member>
<Member Name="Source Bit" Datatype="Byte">
<Subelement Path="0">
<StartValue>16#00</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>16#00</StartValue>
</Subelement>
</Member>
<Member Name="Priority" Datatype="Byte">
<Subelement Path="0">
<StartValue>16#00</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>16#00</StartValue>
</Subelement>
</Member>
<Member Name="Section" Datatype="Array[1..&quot;Numero_Sezioni&quot;] of Bool">
<Subelement Path="0,1">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="0,2">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="0,3">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="0,4">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="0,5">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1,1">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1,2">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1,3">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1,4">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1,5">
<StartValue>FALSE</StartValue>
</Subelement>
</Member>
<Member Name="Value" Datatype="Bool">
<Subelement Path="0">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>FALSE</StartValue>
</Subelement>
</Member>
<Member Name="Enable" Datatype="Bool">
<Subelement Path="0">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>FALSE</StartValue>
</Subelement>
</Member>
<Member Name="Error / Warning" Datatype="Bool">
<Subelement Path="0">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>FALSE</StartValue>
</Subelement>
</Member>
<Member Name="Ons" Datatype="Bool">
<Subelement Path="0">
<StartValue>FALSE</StartValue>
</Subelement>
<Subelement Path="1">
<StartValue>FALSE</StartValue>
</Subelement>
</Member>
</Section>
</Sections>
<Subelement Path="0">
<Comment>
<MultiLanguageText Lang="it-IT">Coment1</MultiLanguageText>
</Comment>
</Subelement>
<Subelement Path="1">
<Comment>
<MultiLanguageText Lang="it-IT">Coment2</MultiLanguageText>
</Comment>
</Subelement>
</Member>
<Member Name="SECTIONS" Datatype="Array[1..&quot;Numero_Sezioni&quot;] of &quot;SIPA XDATA_Alarm_Sect_V04&quot;">
<AttributeList>
<BooleanAttribute Name="SetPoint" SystemDefined="true">true</BooleanAttribute>
</AttributeList>
<Sections>
<Section Name="None">
<Member Name="GV_IOT_PRJ.cmm.i_wrn_nr" Datatype="Int">
<Subelement Path="1">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="2">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="3">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="4">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="5">
<StartValue>0</StartValue>
</Subelement>
</Member>
<Member Name="GV_IOT_PRJ.cmm.i_alm_stp_nr" Datatype="Int">
<Subelement Path="1">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="2">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="3">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="4">
<StartValue>0</StartValue>
</Subelement>
<Subelement Path="5">
<StartValue>0</StartValue>
</Subelement>
</Member>
</Section>
</Sections>
</Member>
</Section>
</Sections></Interface>
<MemoryLayout>Standard</MemoryLayout>
<Name>DB Supervisor Manager</Name>
<Namespace />
<Number>5100</Number>
<ProgrammingLanguage>DB</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3" CompositionName="Items">
<AttributeList>
<Culture>en-GB</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="5" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="6" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="7" CompositionName="Items">
<AttributeList>
<Culture>en-GB</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="8" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.GlobalDB>
</Document>

View File

@ -68,16 +68,16 @@ Sub ImportSiemensXML()
xmlDoc.Load (filePath)
xmlDoc.SetProperty "SelectionNamespaces", "xmlns:a='http://www.siemens.com/automation/Openness/SW/Interface/v5'"
' Buscar el nodo "Allarms"
Set alarmNode = xmlDoc.SelectSingleNode("//a:Member[@Name='Allarms']")
' Buscar el nodo "Alarms"
Set alarmNode = xmlDoc.SelectSingleNode("//a:Member[@Name='Alarms']")
' Verificar si se encontró el nodo
If alarmNode Is Nothing Then
MsgBox "No se encontró el nodo 'Allarms' en el archivo XML."
MsgBox "No se encontró el nodo 'Alarms' en el archivo XML."
Exit Sub
End If
' Obtener los miembros del array "Allarms"
' Obtener los miembros del array "Alarms"
Set alarmArray = alarmNode.SelectNodes("a:Sections/a:Section/a:Member")
' Inicializar el desplazamiento de columna
@ -129,7 +129,7 @@ Sub ImportSiemensXML()
startValue = subElement.SelectSingleNode("a:StartValue").Text
' Escribir "X" o dejar vacío según el valor booleano
ws.Cells(rowIndex, colIndex).value = TextBool(startValue)
ws.Cells(rowIndex, colIndex).value = ImportBool(startValue)
Next subElement
' Actualizar el desplazamiento de columna
@ -150,7 +150,7 @@ Sub ImportSiemensXML()
' Si el tipo de dato es Bool, escribir "X" o dejar vacío
If InStr(memberDataType, "Bool") > 0 Then
ws.Cells(rowIndex, colOffset).value = TextBool(startValue)
ws.Cells(rowIndex, colOffset).value = ImportBool(startValue)
' Byte
ElseIf InStr(memberDataType, "Byte") > 0 Then
ws.Cells(rowIndex, colOffset).value = ImportByte(startValue)
@ -168,7 +168,7 @@ Sub ImportSiemensXML()
' Añadir la columna para las descripciones
ws.Cells(primeraFila, colOffset).value = "Descripción"
' Obtener los subelementos directamente bajo "Allarms"
' Obtener los subelementos directamente bajo "Alarms"
Set subElements = alarmNode.SelectNodes("a:Subelement")
' Obtener el número de alarmas (filas)
@ -192,37 +192,32 @@ Sub ImportSiemensXML()
MsgBox "Importación completada."
End Sub
Sub ExportSiemensXML()
Dim xmlDoc As Object
Dim xmlNode As Object
Dim alarmNode As Object
Dim alarmArray As Object
Dim i As Integer, j As Integer
Dim alarmsMemberNode As Object
Dim i As Long, j As Long
Dim ws As Worksheet
Dim filePath As String
Dim primeraFila As Integer, primeraColumna As Integer
Dim subElements As Object
Dim subElement As Object
Dim pathParts() As String
Dim rowIndex As Integer
Dim rowIndex As Variant
Dim colIndex As Integer
Dim memberName As String
Dim memberDataType As String
Dim colOffset As Integer
Dim s As Integer
Dim maxSectionIndex As Integer
Dim sectionIndex As Integer
Dim cellValue As String
Dim cellValue As Variant
Dim startValueNode As Object
Dim description As String
Dim descriptionNode As Object
Dim creationDate As Date
Dim currentDate As Date
Dim fso As Object
Dim file As Object
Dim fechaBase As Integer
Dim numAlarmas As Integer
Dim sectionsNode As Object
Dim sectionNode As Object
Dim memberNode As Object
Dim subElementNode As Object
Dim visibleRows As New Collection
primeraFila = 5
primeraColumna = 2
@ -258,419 +253,166 @@ Sub ExportSiemensXML()
Set ws = ThisWorkbook.Sheets(1)
' Calcular el número de alarmas considerando solo las filas visibles
numAlarmas = 0
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, primeraColumna).End(xlUp).Row
For rowIndex = primeraFila + 1 To lastRow
If Not ws.Rows(rowIndex).Hidden Then
numAlarmas = numAlarmas + 1
visibleRows.Add rowIndex
End If
Next rowIndex
' Cargar el archivo XML
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
xmlDoc.async = False
xmlDoc.Load (filePath)
xmlDoc.SetProperty "SelectionNamespaces", "xmlns:a='http://www.siemens.com/automation/Openness/SW/Interface/v5'"
' Buscar el nodo "Allarms"
Set alarmNode = xmlDoc.SelectSingleNode("//a:Member[@Name='Allarms']")
' Buscar el nodo "Member" con Name="Alarms"
Set alarmsMemberNode = xmlDoc.SelectSingleNode("//a:Member[@Name='Alarms']")
' Verificar si se encontró el nodo
If alarmNode Is Nothing Then
MsgBox "No se encontró el nodo 'Allarms' en el archivo XML."
If alarmsMemberNode Is Nothing Then
MsgBox "No se encontró el nodo 'Member' con Name='Alarms' en el archivo XML."
Exit Sub
End If
' Obtener los miembros del array "Allarms"
Set alarmArray = alarmNode.SelectNodes("a:Sections/a:Section/a:Member")
' Actualizar el tamaño del array en el XML
' Obtener el valor actual del atributo Datatype
Dim datatypeText As String
datatypeText = alarmsMemberNode.Attributes.getNamedItem("Datatype").Text
' Inicializar el desplazamiento de columna
colOffset = primeraColumna
' Reemplazar el tamaño del array con el número de alarmas menos uno (porque empieza en 0)
Dim pattern As String
pattern = "Array\[0\.\.\d+\]"
Dim replacement As String
replacement = "Array[0.." & (numAlarmas - 1) & "]"
Dim regex As Object
Set regex = CreateObject("VBScript.RegExp")
regex.pattern = pattern
regex.Global = True
regex.IgnoreCase = False
' Iterar sobre los miembros del array para determinar el desplazamiento de columna final
For i = 0 To alarmArray.Length - 1
memberName = alarmArray.item(i).Attributes.getNamedItem("Name").Text
memberDataType = alarmArray.item(i).Attributes.getNamedItem("Datatype").Text
datatypeText = regex.Replace(datatypeText, replacement)
If memberName = "Section" Then
' Procesar el miembro "Section"
' Obtener los subelementos
Set subElements = alarmArray.item(i).SelectNodes("a:Subelement")
' Actualizar el atributo Datatype
alarmsMemberNode.Attributes.getNamedItem("Datatype").Text = datatypeText
' Determinar el número máximo de secciones
maxSectionIndex = 0
For Each subElement In subElements
' Obtener el atributo "Path"
pathParts = Split(subElement.Attributes.getNamedItem("Path").Text, ",")
If UBound(pathParts) >= 1 Then
sectionIndex = CInt(pathParts(1))
If sectionIndex > maxSectionIndex Then
maxSectionIndex = sectionIndex
End If
End If
Next subElement
' Actualizar el desplazamiento de columna
colOffset = colOffset + maxSectionIndex
Else
' Actualizar el desplazamiento de columna
colOffset = colOffset + 1
End If
' Eliminar todos los nodos "Subelement" existentes
Dim existingSubElements As Object
Set existingSubElements = alarmsMemberNode.SelectNodes(".//a:Subelement")
For i = existingSubElements.Length - 1 To 0 Step -1
existingSubElements.item(i).ParentNode.RemoveChild existingSubElements.item(i)
Next i
' Ahora colOffset está en la posición de la columna de descripciones
Dim descriptionCol As Integer
descriptionCol = colOffset
' Reiniciar colOffset para comenzar desde la primera columna de datos
colOffset = primeraColumna
' Iterar sobre los miembros del array nuevamente para exportar los datos
For i = 0 To alarmArray.Length - 1
memberName = alarmArray.item(i).Attributes.getNamedItem("Name").Text
memberDataType = alarmArray.item(i).Attributes.getNamedItem("Datatype").Text
If memberName = "Section" Then
' Procesar el miembro "Section"
' Obtener los subelementos
Set subElements = alarmArray.item(i).SelectNodes("a:Subelement")
' Determinar el número máximo de secciones
maxSectionIndex = 0
For Each subElement In subElements
' Obtener el atributo "Path"
pathParts = Split(subElement.Attributes.getNamedItem("Path").Text, ",")
If UBound(pathParts) >= 1 Then
sectionIndex = CInt(pathParts(1))
If sectionIndex > maxSectionIndex Then
maxSectionIndex = sectionIndex
End If
End If
Next subElement
' Leer los valores de Excel y actualizar el XML
For Each subElement In subElements
' Obtener el atributo "Path"
pathParts = Split(subElement.Attributes.getNamedItem("Path").Text, ",")
' Calcular el índice de fila en Excel
rowIndex = CInt(pathParts(0)) + primeraFila + 1
' Verificar si la fila está oculta
If Not ws.Rows(rowIndex).Hidden Then
' Calcular el índice de columna
sectionIndex = CInt(pathParts(1))
colIndex = colOffset + sectionIndex - 1
' Leer el valor de la celda
cellValue = ws.Cells(rowIndex, colIndex).value
' Convertir "X" a "TRUE", otros a "FALSE"
cellValue = BoolText(Trim(cellValue))
' Actualizar el valor en el XML
Set startValueNode = subElement.SelectSingleNode("a:StartValue")
startValueNode.Text = cellValue
End If
Next subElement
' Actualizar el desplazamiento de columna
colOffset = colOffset + maxSectionIndex
Else
' Procesar otros miembros normalmente
' Leer los valores de Excel y actualizar el XML
Set subElements = alarmArray.item(i).SelectNodes("a:Subelement")
For j = 0 To subElements.Length - 1
' Índice de fila en Excel
rowIndex = j + primeraFila + 1
' Verificar si la fila está oculta
If Not ws.Rows(rowIndex).Hidden Then
' Leer el valor de la celda
cellValue = ws.Cells(rowIndex, colOffset).value
' Si el tipo de dato es Bool, convertir "X" a "TRUE", otros a "FALSE"
If InStr(memberDataType, "Bool") > 0 Then
cellValue = BoolText(Trim(cellValue))
ElseIf InStr(memberDataType, "Byte") > 0 Then
cellValue = ExportByte(cellValue)
' Eliminar la sección "Sections" existente bajo "Alarms"
Dim existingSectionsNode As Object
Set existingSectionsNode = alarmsMemberNode.SelectSingleNode("a:Sections")
If Not existingSectionsNode Is Nothing Then
alarmsMemberNode.RemoveChild existingSectionsNode
End If
' Actualizar el valor en el XML
Set startValueNode = subElements.item(j).SelectSingleNode("a:StartValue")
startValueNode.Text = cellValue
End If
' Crear el nodo "Sections"
Set sectionsNode = xmlDoc.createNode(1, "Sections", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
alarmsMemberNode.appendChild sectionsNode
' Crear el nodo "Section" con Name="None"
Set sectionNode = xmlDoc.createNode(1, "Section", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
sectionNode.Attributes.setNamedItem(xmlDoc.createAttribute("Name")).Text = "None"
sectionsNode.appendChild sectionNode
' Definir los miembros y sus tipos de datos
Dim members As Variant
members = Array("AlarmNum", "Source DB", "Source Byte", "Source Bit", "Priority", "Section", "Value", "Enable", "Error / Warning", "Ons")
Dim dataTypes As Variant
dataTypes = Array("Int", "Int", "Int", "Byte", "Byte", "Array[1..""Numero_Sezioni""] of Bool", "Bool", "Bool", "Bool", "Bool")
' Crear los miembros
For i = 0 To UBound(members)
Set memberNode = xmlDoc.createNode(1, "Member", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
memberNode.Attributes.setNamedItem(xmlDoc.createAttribute("Name")).Text = members(i)
memberNode.Attributes.setNamedItem(xmlDoc.createAttribute("Datatype")).Text = dataTypes(i)
sectionNode.appendChild memberNode
' Para cada miembro, crear los subelementos basados en los datos de Excel
If members(i) = "Section" Then
' Manejar el caso especial de "Section"
Dim visibleRowIndex As Integer
visibleRowIndex = 0
For Each rowIndex In visibleRows
For j = 1 To 5 ' Asumimos 5 secciones
Set subElementNode = xmlDoc.createNode(1, "Subelement", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
subElementNode.Attributes.setNamedItem(xmlDoc.createAttribute("Path")).Text = visibleRowIndex & "," & j
Set startValueNode = xmlDoc.createNode(1, "StartValue", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
cellValue = ws.Cells(rowIndex, primeraColumna + i + j - 1).value
startValueNode.Text = IIf(UCase(Trim(cellValue)) = "X", "TRUE", "FALSE")
subElementNode.appendChild startValueNode
memberNode.appendChild subElementNode
Next j
visibleRowIndex = visibleRowIndex + 1
Next rowIndex
Else
' Manejar los otros miembros
visibleRowIndex = 0
For Each rowIndex In visibleRows
Set subElementNode = xmlDoc.createNode(1, "Subelement", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
subElementNode.Attributes.setNamedItem(xmlDoc.createAttribute("Path")).Text = CStr(visibleRowIndex)
' Actualizar el desplazamiento de columna
colOffset = colOffset + 1
Set startValueNode = xmlDoc.createNode(1, "StartValue", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
cellValue = ws.Cells(rowIndex, primeraColumna + i).value
Select Case dataTypes(i)
Case "Bool"
startValueNode.Text = IIf(UCase(Trim(cellValue)) = "X", "TRUE", "FALSE")
Case "Byte"
startValueNode.Text = ExportByte(cellValue)
Case "Int"
startValueNode.Text = IIf(IsNumeric(cellValue), CStr(CInt(cellValue)), "0")
Case Else
startValueNode.Text = CStr(cellValue)
End Select
subElementNode.appendChild startValueNode
memberNode.appendChild subElementNode
visibleRowIndex = visibleRowIndex + 1
Next rowIndex
End If
Next i
' Actualizar las descripciones en el XML
' Obtener los subelementos directamente bajo "Allarms"
Set subElements = alarmNode.SelectNodes("a:Subelement")
' Añadir los comentarios
Dim commentColumn As Integer
commentColumn = ws.Cells(primeraFila, ws.Columns.Count).End(xlToLeft).Column
' Obtener el número de alarmas (filas)
Dim numAlarmas As Integer
numAlarmas = subElements.Length
visibleRowIndex = 0
For Each rowIndex In visibleRows
Set subElementNode = xmlDoc.createNode(1, "Subelement", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
subElementNode.Attributes.setNamedItem(xmlDoc.createAttribute("Path")).Text = CStr(visibleRowIndex)
' Actualizar las descripciones en el XML
For j = 0 To numAlarmas - 1
' Índice de fila en Excel
rowIndex = primeraFila + j + 1
' Verificar si la fila está oculta
If Not ws.Rows(rowIndex).Hidden Then
' Leer la descripción de la celda en Excel
description = ws.Cells(rowIndex, descriptionCol).value
' Obtener o crear el nodo de descripción para cada alarma
Set descriptionNode = subElements.item(j).SelectSingleNode("a:Comment/a:MultiLanguageText")
If descriptionNode Is Nothing Then
' Crear el nodo de descripción si no existe
Set descriptionNode = xmlDoc.createElement("MultiLanguageText")
descriptionNode.Text = description
descriptionNode.setAttribute "Lang", "it-IT" ' Ajusta el idioma según tus necesidades
' Crear el nodo padre "Comment" si no existe
Dim commentNode As Object
Set commentNode = subElements.item(j).SelectSingleNode("a:Comment")
If commentNode Is Nothing Then
Set commentNode = xmlDoc.createElement("Comment")
subElements.item(j).appendChild commentNode
End If
Set commentNode = xmlDoc.createNode(1, "Comment", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
commentNode.appendChild descriptionNode
Else
' Actualizar el texto de la descripción
descriptionNode.Text = description
End If
End If
Next j
Dim multiLangTextNode As Object
Set multiLangTextNode = xmlDoc.createNode(1, "MultiLanguageText", "http://www.siemens.com/automation/Openness/SW/Interface/v5")
multiLangTextNode.Attributes.setNamedItem(xmlDoc.createAttribute("Lang")).Text = "it-IT"
multiLangTextNode.Text = ws.Cells(rowIndex, commentColumn).value
commentNode.appendChild multiLangTextNode
subElementNode.appendChild commentNode
alarmsMemberNode.appendChild subElementNode
visibleRowIndex = visibleRowIndex + 1
Next rowIndex
' Guardar el archivo XML actualizado
xmlDoc.Save filePath
MsgBox "Exportación completada."
MsgBox "Exportación completada. Exportadas " + Str(numAlarmas) + " Filas."
End Sub
Sub GenerateSiemensXML()
Dim xmlDoc As Object
Dim rootNode As Object
Dim documentNode As Object
Dim xmlDeclaration As Object
Dim alarmNode As Object
Dim alarmsSectionsNode As Object
Dim alarmsSectionNode As Object
Dim newMemberNode As Object
Dim subElementNode As Object
Dim startValueNode As Object
Dim commentNode As Object
Dim multiLanguageTextNode As Object
Dim attributeListNode As Object
Dim nameNode As Object
Dim i As Integer, j As Integer
Dim ws As Worksheet
Dim filePath As String
Dim primeraFila As Integer, primeraColumna As Integer
Dim numAlarmas As Integer
Dim colOffset As Integer
Dim memberName As String
Dim memberDataType As String
Dim colIndex As Integer
Dim rowIndex As Integer
Dim cellValue As String
Dim description As String
Dim decimalValue As Long
Dim hexValue As String
Dim maxSectionIndex As Integer
Dim sectionIndex As Integer
primeraFila = 5
primeraColumna = 2
' Pedir al usuario que seleccione la ubicación para guardar el archivo XML
filePath = Application.GetSaveAsFilename("NuevoArchivo.xml", "Archivos XML (*.xml), *.xml", , "Guardar archivo XML")
' Verificar si se seleccionó una ruta
If filePath = "False" Or filePath = "Falso" Then
Exit Sub
End If
Set ws = ThisWorkbook.Sheets(1)
' Crear el documento XML
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
xmlDoc.async = False
' Añadir la declaración XML
Set xmlDeclaration = xmlDoc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'")
xmlDoc.appendChild xmlDeclaration
' Crear el nodo raíz
Set rootNode = xmlDoc.createElement("Document")
xmlDoc.appendChild rootNode
' Añadir el nodo de información del documento (opcional)
Set documentNode = xmlDoc.createElement("DocumentInfo")
rootNode.appendChild documentNode
' Aquí puedes añadir más información al DocumentInfo si lo deseas
' Crear el nodo "SW.DT"
Set alarmNode = xmlDoc.createElement("SW.DT")
alarmNode.setAttribute "ID", "0"
rootNode.appendChild alarmNode
' Crear el nodo "AttributeList" dentro de "SW.DT"
Set attributeListNode = xmlDoc.createElement("AttributeList")
alarmNode.appendChild attributeListNode
' Añadir los atributos necesarios (Nombre, Comentario, etc.)
Set nameNode = xmlDoc.createElement("Name")
nameNode.Text = "AllarmsDB"
attributeListNode.appendChild nameNode
' Añadir más atributos según sea necesario
' Crear el nodo "Sections" dentro de "SW.DT"
Set sectionsNode = xmlDoc.createElement("Sections")
alarmNode.appendChild sectionsNode
' Crear la sección "Static"
Set sectionNode = xmlDoc.createElement("Section")
sectionNode.setAttribute "Name", "Static"
sectionsNode.appendChild sectionNode
' Crear el miembro "Allarms"
Set memberNode = xmlDoc.createElement("Member")
memberNode.setAttribute "Name", "Allarms"
memberNode.setAttribute "Datatype", "Array"
sectionNode.appendChild memberNode
' Crear los nodos necesarios dentro de "Allarms"
' Aquí asumiremos que tienes una estructura similar a la del XML original
' Crear "Sections" dentro de "Allarms"
Set alarmsSectionsNode = xmlDoc.createElement("Sections")
memberNode.appendChild alarmsSectionsNode
' Crear "Section" dentro de "Sections" de "Allarms"
Set alarmsSectionNode = xmlDoc.createElement("Section")
alarmsSectionNode.setAttribute "Name", "Member"
alarmsSectionsNode.appendChild alarmsSectionNode
' Ahora añadiremos los miembros (campos) de cada alarma
' Primero, obtenemos los nombres de los miembros desde las columnas en Excel
Dim columnNames As Collection
Set columnNames = New Collection
colOffset = primeraColumna
Do While ws.Cells(primeraFila, colOffset).value <> ""
columnNames.Add ws.Cells(primeraFila, colOffset).value
colOffset = colOffset + 1
Loop
' Determinar el número de alarmas (filas)
numAlarmas = ws.Cells(ws.Rows.Count, primeraColumna).End(xlUp).Row - (primeraFila + 1) + 1
' Ahora, creamos los miembros dentro de "Allarms"
Dim membersCollection As Collection
Set membersCollection = New Collection
' Colección para almacenar los tipos de datos
Dim memberDataTypes As Collection
Set memberDataTypes = New Collection
For i = 1 To columnNames.Count
memberName = columnNames(i)
' Determinar el tipo de dato basado en el nombre de la columna o alguna otra lógica
' Aquí asumiremos que tienes una manera de determinar el tipo de dato
' Por simplicidad, asumiremos que todos son Bool excepto "Descripción" y "Section.X"
If Left(memberName, 8) = "Section." Then
memberDataType = "Bool"
ElseIf memberName = "Descripción" Then
memberDataType = "String"
Else
memberDataType = "Bool"
End If
' Crear el miembro
Set newMemberNode = xmlDoc.createElement("Member")
newMemberNode.setAttribute "Name", memberName
newMemberNode.setAttribute "Datatype", memberDataType
alarmsSectionNode.appendChild newMemberNode
' Añadir a las colecciones
membersCollection.Add newMemberNode
memberDataTypes.Add memberDataType
Next i
' Ahora, añadimos los subelementos (valores) para cada alarma
For j = 1 To numAlarmas
rowIndex = primeraFila + j
' Verificar si la fila está oculta
If Not ws.Rows(rowIndex).Hidden Then
For i = 1 To membersCollection.Count
memberName = columnNames(i)
Set newMemberNode = membersCollection(i)
memberDataType = memberDataTypes(i)
' Crear el subelemento
Set subElementNode = xmlDoc.createElement("Subelement")
subElementNode.setAttribute "Path", CStr(j - 1)
newMemberNode.appendChild subElementNode
' Leer el valor de la celda
colIndex = primeraColumna + i - 1
cellValue = ws.Cells(rowIndex, colIndex).value
' Crear el nodo "StartValue"
Set startValueNode = xmlDoc.createElement("StartValue")
' Manejar los diferentes tipos de datos
If Left(memberName, 8) = "Section." Or memberDataType = "Bool" Then
' Convertir "X" a "TRUE", otros a "FALSE"
If UCase(Trim(cellValue)) = "X" Then
startValueNode.Text = "TRUE"
Else
startValueNode.Text = "FALSE"
End If
ElseIf memberDataType = "Byte" Then
' Convertir decimal a "16#xx"
If IsNumeric(cellValue) Then
decimalValue = CLng(cellValue)
hexValue = Hex(decimalValue)
If Len(hexValue) < 2 Then
hexValue = "0" & hexValue
End If
startValueNode.Text = "16#" & hexValue
Else
startValueNode.Text = "16#00"
End If
Else
' Otros tipos de datos
startValueNode.Text = CStr(cellValue)
End If
subElementNode.appendChild startValueNode
' Si es el campo "Descripción", agregar el nodo de comentario
If memberName = "Descripción" Then
Set commentNode = xmlDoc.createElement("Comment")
Set multiLanguageTextNode = xmlDoc.createElement("MultiLanguageText")
multiLanguageTextNode.setAttribute "Lang", "it-IT" ' Ajusta el idioma según sea necesario
multiLanguageTextNode.Text = CStr(cellValue)
commentNode.appendChild multiLanguageTextNode
subElementNode.appendChild commentNode
End If
Next i
End If
Next j
' Guardar el archivo XML
xmlDoc.Save filePath
MsgBox "Archivo XML generado exitosamente."
End Sub
' Función para verificar si un elemento existe en una colección
Function ExistsInCollection(col As Collection, key As Variant) As Boolean
On Error GoTo ErrHandler
@ -723,23 +465,23 @@ Sub QuickSort(arr As Variant, first As Long, last As Long)
If low < last Then QuickSort arr, low, last
End Sub
Function TextBool(startValue As String)
Function ImportBool(startValue)
' Escribir "X" o dejar vacío según el valor booleano
TextBool = " "
ImportBool = " "
If UCase(startValue) = "TRUE" Or UCase(startValue) = "1" Then
TextBool = "X"
ImportBool = "X"
End If
End Function
Function BoolText(excelValue As String)
Function ExportBool(excelValue)
' Escribir "X" o dejar vacío según el valor booleano
BoolText = "FALSE"
ExportBool = "FALSE"
If UCase(excelValue) = "X" Or UCase(excelValue) = "TRUE" Or UCase(excelValue) = "1" Then
BoolText = "TRUE"
ExportBool = "TRUE"
End If
End Function
Function ImportByte(startValue As String)
Function ImportByte(startValue)
If Left(startValue, 3) = "16#" Then
' Extraer el valor hexadecimal
hexValue = Mid(startValue, 4)
@ -751,7 +493,7 @@ Function ImportByte(startValue As String)
End If
End Function
Function ExportByte(cellValue As String)
Function ExportByte(cellValue)
' Es Byte, convertir de decimal a hexadecimal en formato "16#xx"
If IsNumeric(cellValue) Then
decimalValue = CLng(cellValue)

Binary file not shown.