VBA Excel macro para leer XML CFDI 3.3
Les comparto una macro que he adaptado para leer los XML de los CFDI versión 3.3 de forma masiva.
Para que la macro funcione hay que seguir los siguientes pasos:
1. Abrir el editor Visual Basic para Aplicaciones (VBA).
2. Insertar un módulo.
3. Agregar la referencia "Microsoft XML, v3.0" en el menú herramientas del editor VBA, dar click en referencias.
3. Pegar el siguiente código:
Para que la macro funcione hay que seguir los siguientes pasos:
1. Abrir el editor Visual Basic para Aplicaciones (VBA).
2. Insertar un módulo.
3. Agregar la referencia "Microsoft XML, v3.0" en el menú herramientas del editor VBA, dar click en referencias.
3. Pegar el siguiente código:
Sub Ruta_CFDI() 'macro para en listar los XML que va a leer 'Adapatado por Luis Reyes Dim fs, carpeta, archivo, subcarpeta As Object contador = 2 'determinar en que fila comenzará a colocar la ruta y nombre de los XML Set fs = CreateObject("Scripting.FileSystemObject") With Application.FileDialog(msoFileDialogFolderPicker) 'se obtiene la ruta la carpeta If .Show = -1 Then ruta = .SelectedItems(1) Range("V1").Value = ruta & "\" End If End With If ruta = "" Then Exit Sub End If Set carpeta = fs.GetFolder(ruta) For Each archivo In carpeta.Files If Right(archivo, 4) = ".xml" Then Range("AD" & contador).Value = ruta & "\" & archivo.Name contador = contador + 1 End If If Right(archivo, 4) = ".XML" Then Range("AD" & contador).Value = ruta & "\" & archivo.Name contador = contador + 1 End If Next If Application.WorksheetFunction.CountA(Columns(30)) <= 1 Then MsgBox "No se encontro ningún archivo *.XML" & Chr(10) & ruta, vbCritical, "Importar datos CFDI" End End If Call Lectura_CFDI 'ejecuta la macro que lee los XML End Sub Private Sub Lectura_CFDI() 'Adapatado por Luis Reyes With Application .ScreenUpdating = False .Calculation = xlCalculationManual .EnableEvents = False .DisplayStatusBar = False Dim Concepto As String Dim pctCompl As Single Set DocumentoXML = New DOMDocument Set r = Range("AD2").CurrentRegion 'determina apartir de donde comienza a contar filas = r.Rows.Count For i = 2 To filas + 6 'número de documentos que va a leer DocumentoXML.Load ("" & Cells(i, 30) & "") Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante") On Error Resume Next For Each Nodo In ListaNodo Subtotal = Val(Nodo.Attributes.getNamedItem("SubTotal").Text) Fecha = Mid(Nodo.Attributes.getNamedItem("Fecha").Text, 1, 10) Serie = Nodo.Attributes.getNamedItem("Serie").Text Folio = Serie & " - " & Nodo.Attributes.getNamedItem("Folio").Text Total = Val(Nodo.Attributes.getNamedItem("Total").Text) Descuento = Val(Nodo.Attributes.getNamedItem("Descuento").Text) Next Nodo ''''''''''''''''''''''''''''''''''''''''''''''''Nombre del emisor''''''''''''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Emisor") For Each Nodo In ListaNodo Proveedor = Nodo.Attributes.getNamedItem("Nombre").Text RFC = Nodo.Attributes.getNamedItem("Rfc").Text Next Nodo ''''''''''''''''''''''''''''''''''''''''''''''''Conceptos''''''''''''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto") For Each Nodo In ListaNodo Concepto = Concepto & Nodo.Attributes.getNamedItem("Descripcion").Text & " - " Next Nodo ''''''''''''''''''''''''''''''''''''''''''''''''Impuestos''''''''''''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/cfdi:Impuestos/cfdi:Traslados/cfdi:Traslado") For Each Nodo In ListaNodo If Nodo.Attributes.getNamedItem("Impuesto").Text = "002" Then IVA = IVA + Val(Nodo.Attributes.getNamedItem("Importe").NodeValue) End If If Nodo.Attributes.getNamedItem("Impuesto").Text = "003" Then IEPS = IEPS + Val(Nodo.Attributes.getNamedItem("Importe").NodeValue) End If Next Nodo ''''''''''''''''''''''''''''''''''''''''''''''''Retenciones''''''''''''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/cfdi:Impuestos/cfdi:Retenciones/cfdi:Retencion") For Each Nodo In ListaNodo If Nodo.Attributes.getNamedItem("Impuesto").Text = "001" Then ISRRe = IVARe + Val(Nodo.Attributes.getNamedItem("Importe").NodeValue) End If If Nodo.Attributes.getNamedItem("Impuesto").Text = "002" Then IVARe = IVARe + Val(Nodo.Attributes.getNamedItem("Importe").NodeValue) End If Next Nodo '''''''''''''''''''''''''''OTROS IMPUESTOS'''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("cfdi:Comprobante/cfdi:Complemento/implocal:ImpuestosLocales/implocal:TrasladosLocales") For Each Nodo In ListaNodo ISH = Nodo.Attributes.getNamedItem("Importe").Text Next Nodo '''''''''''''''''''''''''''AEROLINEAS'''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("cfdi:Comprobante/cfdi:Complemento/aerolineas:Aerolineas") For Each Nodo In ListaNodo TUA = Nodo.Attributes.getNamedItem("TUA").Text Next Nodo Set ListaNodo = DocumentoXML.SelectNodes("cfdi:Comprobante/cfdi:Complemento/aerolineas:Aerolineas/aerolineas:OtrosCargos/aerolineas:Cargo") 'MsgBox ListaNodo.Length For Each Nodo In ListaNodo YR = Nodo.Attributes.getNamedItem("Importe").Text Next Nodo ''''''''''''''''''''''''''''''''''''UUID'''''''''''''''''''''''''''''''''''''''''''' Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital") For Each Nodo In ListaNodo UUID = Nodo.Attributes.getNamedItem("UUID").Text Next Nodo Cells(i, 1) = Fecha Cells(i, 2) = Folio Cells(i, 3) = RFC Cells(i, 4) = Proveedor Cells(i, 5) = Concepto Cells(i, 5).ClearFormats Cells(i, 6) = Subtotal - TUA - YR - Descuento Cells(i, 7) = IVA Cells(i, 8) = ISRRe Cells(i, 9) = IVARe Cells(i, 10) = IEPS Cells(i, 11) = ISH Cells(i, 12) = TUA Cells(i, 13) = YR Cells(i, 14) = Total Cells(i, 15) = UUID Fecha = "" Folio = "" RFC = "" Proveedor = "" Concepto = "" Subtotal = 0 Descuento = 0 IVA = 0 ISRRe = 0 IVARe = 0 IEPS = 0 ISH = 0 TUA = 0 YR = 0 Total = 0 UUID = "" Next Cells(1, 1).Value = "Fecha" Cells(1, 2).Value = "Folio" Cells(1, 3).Value = "RFC" Cells(1, 4).Value = "Proveedor" Cells(1, 5).Value = "Concepto" Cells(1, 6).Value = "Subtotal" Cells(1, 7).Value = "IVA" Cells(1, 8).Value = "ISR RETENIDO" Cells(1, 9).Value = "IVA RETENIDO" Cells(1, 10).Value = "IEPS" Cells(1, 11).Value = "ISH" Cells(1, 12).Value = "TUA" Cells(1, 13).Value = "YR" Cells(1, 14).Value = "Total" Cells(1, 15).Value = "UUID" .Calculation = xlCalculationAutomatic .EnableEvents = True .DisplayStatusBar = True End With End Sub
Buenas tardes, y para extraer los Pagos de un XML en la parte de RELACIONES, Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Complemento/pago10:Pagos/pago10:Pago/pago10:DoctoRelacionado")
ResponderBorrarOn Error Resume Next
por favor me puedes enviar tu xml a zona.lerh@gmail.com
ResponderBorrarenviame el xml al correo jcintriadp@yahoo.es
ResponderBorrarjajajajajajaj
BorrarHola al pasar tu macro le adapte unos codigos para que me sume por bases de IVA los diferentes conceptos es decir cada uno de los concepos del xml tiene una base y una tasa de iva al 16 al 8 al 0 o exento puse el codigo y todo bien con las tasas pero cuando lee un xml que tiene concepto exento no suma correctamente las otras tasas poniendo en todas las tasas la misma cantidad que el exento
ResponderBorrarBuenas noches, para obtener el uuid relacionado del complemento de pago, que se tendria que modificar
ResponderBorrarjportas18@hotmail.com
Borrarte digo como resolverlo
Buenas tardes Luis, copie tu codigo, y jalo, sin embargo veo que duplica unos datos
ResponderBorrardonde puedo enviarte por email el codigo y si puedes checarlo.
Hola buenas noches, estoy adaptando el código para importar los XML en una bases de datos de Access y hasta ahorita he logrado importar todos los conceptos, pero necesito saber como hacer que un nodo de impuestos se pueda asociar al nodo padre que correspondería al de su concepto para copiar los impuestos de manera individual a una tabla independiente de los conceptos, tienes alguna idea de como podría hacerlo?
ResponderBorrarpor favor me puedes contactar por correo:
Borrarzona.lerh@gmail.com
Hola, para agregarle a este macro la opción de extraer el uso del CFDI, que es lo que se tiene que hacer ?
ResponderBorrarHola buen día
Borrartiene que buscar:
RFC = Nodo.Attributes.getNamedItem("Rfc").Text
y debajo de ese código tiene debe colocar:
UCFDI = Nodo.Attributes.getNamedItem("UsoCFDI").Text
después busque:
Cells(i, 15) = UUID
y después de eso coloque:
Cells(i, 16) = UCFDI
después busque:
Cells(1, 15).Value = "UUID"
y después de eso coloque:
Cells(1, 16).Value = "USO CFDI"
Saludos!!
Cells(1, 16).Value = "UUID"
Muy buena explicación con los campos, solo que estoy siguiendo este ejemplo (UsoCFDI="G03") y al momento de ejecutar la macro no me mostro el valor en la celda que le correspondia, siempre queda espacio en blanco, y segui las instrucciones paso a paso...
BorrarHabra alguna linea de codigo que requiera de mas?
muchas gracias.
y lo estas colocando en donde va??
Borrarpor favor me puedes enviar correo a zona.lerh@gmail.com con el codigo
Hola, si ya vi el error de mi parte, lo corregi y si funciona
BorrarExcelente!!! me da mucho gusto
BorrarEs necesario llevar un orden para extraer los datos?
ResponderBorrarEs decir, yo quiero extraer solo para los combustibles el total de Litros del XML, ejemplo:
Cells(1, 17).Value = "Cantidad" 'Litros que se cargan
Gracias por el aporte
no es necesario, los puede distribuir como guste
ResponderBorraresto si puede ser:
Cells(1, 17).Value = "Cantidad" 'Litros que se cargan
muchas gracias por el dato :)
Borrarde nada, cualquier cosa me avisa
BorrarPor si le sirve a alguien, en las facturas el UUID note que unas vienen en mayusculas y otras en minusculas, asi que agregue este codigo al final de la macro:
ResponderBorrar.DisplayStatusBar = True 'Buscar este codigo de Luis
' Voy a convertir de una vez el UUID y Concepto a Mayusculas
'rango que se convertira a mayusculas, modificar a criterio
' agregar solo esta linea de codigo
[I1:I100] = [INDEX(UPPER(I1:I100),,)]
End With
Gracias por el dato amig@
BorrarHola Amigo, corre excelente la macro, solo que tengo un dato que se encuentra en la addenda pero no corresponde a un concepto, solo es un dato que requiero extraer el cual es diferente en cada xml, ¿cómo le podría hacer para extraer datos en esos casos?
ResponderBorrarhola mi estimado, por favor me puedes enviar un ejemplo a zona.lerh@gmail.com
BorrarHola, como podría modificarla para que muestre los conceptos de los xml emitidos de nomina.
ResponderBorrarHola buen día. revisa esta entrada:
Borrarhttps://www.elblogdeluisreyes.com/2019/08/vba-excel-macro-para-leer-xml-nomina-12.html
Espero que te sea úti.
BUENAS TARDES PARA EXTRAER EL IMPORTE DE LOS COMPLEMENTOS DE PAGOS CUAL SERIA EL MACRO
ResponderBorrarHola FABIAN, buen día, aun no tengo la macro, voy a trabajar en ello y próximamente lo subiré al blog.
BorrarSaludos!!
me podrías ayudar ? que tengo que hacer para que me aparezca el método de pago y la forma de pago ?
ResponderBorrarHola, buen día, me podrías ayudar? que tengo que hacer para que me aparezcan los datos de método de pago y forma de pago ?
ResponderBorrargracias.
Hola buen día, si claro, tienes que agregar el nodo
Borraren:
Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante")
FPago = Nodo.Attributes.getNamedItem("FormaPago").text
Me pudieras ayudar, como puedo agregar el método de pago y la forma de pago ?
ResponderBorrargracias.
hola buenas tardes, yo modifique los nodos para los complementos de pago, solo que no me trae el numero de Facturas por pago (si se pagaron 10 Facturas en un pago solo me trae una) que le faltaría al código, lo comparto por correo
ResponderBorrarSaludos
gracias lo reviso!!
Borrarmi xml tiene cdata, y no se como extrar informacion q eta dentro d esa seccion
ResponderBorrarpor favor me puede enviar su XML a zona.lerh@gmail.com
BorrarSaludos, excelente sitio, gracias. Sobre esta macro la he copiado a un libro de trabajo en el que concentro mis papeles de trabajo, pero al ejecutarla obtengo el siguiente mensaje de error "Compile error: User-defined type not defined", y resalta el texto "New DOMDocument" que se detalla en la novena línea después del título "Private Sub Lectura_CFDI()", sin embargo al ejecutar la misma macro directamente de el documento que proporcionas no tengo ningún problema, ¿podrías ayudarme a resolver esto?, por favor. Gracias por tu trabajo y atención.
ResponderBorrarHola G7, al principio de la entrada describo lo que tienes que hacer para que no salga ese error.
BorrarSaludos!!
Buenas noches, me ha sido de mucha utilidad su código, sin embargo, quisiera ver si me pudiera apoyar en ver la forma de que los artículos se desglosen en cada fila, estuve probando varías cosas pero ninguna me ha funcionado, gracias de antemano
ResponderBorrarHola mi estimado, por favor me puedes contactar por whatsapp 5584553535
BorrarHola, yo hice un VB para leer solo los conceptos del XML pero al abrir el xml y extraer con GET me da caracteres especiales e4n donde hay acentos o CR. como lo puedo arreglar, creo es el conjunto de caracteres al pasarlo a texto en el excel
ResponderBorrarHola mr_alver, si gustas me puedes contactar por correo: zona.lerh@gmail.com
BorrarHola Luis, saludos de la Ciudad de México, he trabajado con tu código, me ha funcionando bien, ahora estoy atorado ya que unos xml vienen varios concepto pero al correr la macro solo me da el importe de un solo producto.
ResponderBorrarEn Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto")
For Each nodo In ListaNodo
Concepto = Concepto & nodo.Attributes.getNamedItem("Descripcion").Text & " - "
Next nodo
Aquí me aparecen todos los conceptos, si incluyo lo siguiente para que me sume todos esos concepto solo aparece uno:
En Set ListaNodo = DocumentoXML.SelectNodes("/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto")
For Each nodo In ListaNodo
Concepto = Concepto & nodo.Attributes.getNamedItem("Descripcion").Text & " - "
If nodo.Attributes.getNamedItem("importe").Text <> "" Then
Importe = nodo.Attributes.getNamedItem("importe").Text
End If
Next nodo
Como tendría que ser la instruccion para Importe?
Gracias de antemano, saludos
Si, tienes que hacer esto:
BorrarImporte = nodo.Attributes.getNamedItem("importe").Text + Importe