Con este código podrás generar una factura en XML desde tu programa de Access y la factura ya firmada en formato XSIG de eFactura.

Copia y pega el código en un botón de tu programa de facturación.

Tendrás que cambiar tus datos de empresa y el nombre de los campos que usas en tu programa.

Serán necesarios 6 campos nuevos en tu ficha de cliente y en ellos se almacenan la información que da la institución a la que facturas (Órgano Gestor, Unidad Tramitadora y Oficina Contable). Estos campos son: GestorCode, GestorNombre, UnidadCode, UnidadNombre, OficinaCode y OficinaNombre. Todos ellos de texto.

Se abrirá automáticamente autofirma de forma oculta y te pesentará los certificados que tengas disponibles para firmar digitalmente la factura.

Se generará el fichero firmado que podrás subirlo directamente a FACE.

Tener en cuenta una cosa, las líneas de detalle de la factura no pueden contener solo texto en el concepto, si hay una línea de detalle con sólo texto hay que rellenar los campos de cantidad, precio unidad y líneatotal con ceros o unos (según el campo) porque FACE no admite líneas de detalle con datos parciales o campos sin datos.

'®Tantor Systems Creative Commons CC BY
Dim dbs As Database, tdf2 As Recordset, fld As Field, tdf3 As Recordset
Dim stDocName As String
Dim xxx, nrolineas As Integer
Dim cuantoiva As Double
Dim lineacomando as string
Dim retval

Set dbs = CurrentDb
' abro la tabla donde tengo al cliente
stDocName = "SELECT * FROM Agenda WHERE Agenda.Id_Agenda=" + Str(Me.Id_Clientes) + "; "
Set tdf2 = dbs.OpenRecordset(stDocName)
tdf2.MoveFirst

'Creo el fichero XML de destino cuyo nombre será Emit-nºfactura.xml
'Open "C:\Directorio\Borrador-" & Trim(Str(Me.NroFact)) & ".xml" For Output As #1
Open "C:\Directorio\Emit-" & Trim(Str(Me.NroFact)) & ".xml" For Output As #1
Print #1, "<?xml version=""1.0"" encoding=""UTF-8""?>"
Print #1, "<fe:Facturae xmlns:ds=""http://www.w3.org/2000/09/xmldsig#"" xmlns:fe=""http://www.facturae.es/Facturae/2014/v3.2.1/Facturae"">";
Print #1, "<FileHeader>";
    Print #1, "<SchemaVersion>3.2.1</SchemaVersion>";
    Print #1, "<Modality>I</Modality>";
    Print #1, "<InvoiceIssuerType>EM</InvoiceIssuerType>";
    Print #1, "<Batch>";
        Print #1, "<BatchIdentifier>" & Trim(tdf2!CIF) & Trim(Str(Me.NroFact)) & "Emit-</BatchIdentifier>"; ' grabo nro de factura
        Print #1, "<InvoicesCount>1</InvoicesCount>";
        Print #1, "<TotalInvoicesAmount><TotalAmount>" & Trim(Str(Me.ImporteFactura)) & "</TotalAmount></TotalInvoicesAmount>"; 	  ' grabo importe factura
        Print #1, "<TotalOutstandingAmount><TotalAmount>" & Trim(Str(Me.ImporteFactura)) & "</TotalAmount></TotalOutstandingAmount>"; ' grabo importe factura
        Print #1, "<TotalExecutableAmount><TotalAmount>" & Trim(Str(Me.ImporteFactura)) & "</TotalAmount></TotalExecutableAmount>";   ' grabo importe factura
        Print #1, "<InvoiceCurrencyCode>EUR</InvoiceCurrencyCode>";
    Print #1, "</Batch>";
Print #1, "</FileHeader>";

Print #1, "<Parties>";
    ' Vendedor
    Print #1, "<SellerParty>";
        Print #1, "<TaxIdentification><PersonTypeCode>J</PersonTypeCode><ResidenceTypeCode>U</ResidenceTypeCode><TaxIdentificationNumber>MI NIF/CIF</TaxIdentificationNumber></TaxIdentification>";
        Print #1, "<LegalEntity>";
            Print #1, "<CorporateName>NOMBRE DE MI EMPRESA</CorporateName>";
            ' CAMBIA LOS DATOS POR LOS TUYOS
            Print #1, "<RegistrationData><RegisterOfCompaniesLocation>Santander</RegisterOfCompaniesLocation><Sheet>5555</Sheet><Folio>666</Folio><Volume>777</Volume></RegistrationData>";
            Print #1, "<AddressInSpain><Address>FERNANDEZ DE ISLA 10, BAJO</Address><PostCode>39008</PostCode><Town>SANTANDER</Town><Province>CANTABRIA</Province><CountryCode>ESP</CountryCode></AddressInSpain>";
            Print #1, "<ContactDetails><Telephone>942123456</Telephone><TeleFax>942123456</TeleFax><WebAddress>www.miweb.com</WebAddress><ElectronicMail>micorreo@miempresa.com</ElectronicMail></ContactDetails>";
        Print #1, "</LegalEntity>";
    Print #1, "</SellerParty>";
    ' Comprador
    Print #1, "<BuyerParty>";
        ' grabo los datos del cliente
        Print #1, "<TaxIdentification><PersonTypeCode>J</PersonTypeCode><ResidenceTypeCode>U</ResidenceTypeCode><TaxIdentificationNumber>" & tdf2!CIF & "</TaxIdentificationNumber></TaxIdentification>";
        Print #1, "<AdministrativeCentres>";
            ' Los campos GestorCode, GestorNombre, UnidadCode, UnidadNombre, OficinaCode y OficinaNombre los tienes que tener en la tabla del cliente y estos datos
            ' los consigues de la página web o llamando a la institución a la que facturas
            'Receptor / Organo Gestor
            Print #1, "<AdministrativeCentre>";
            Print #1, "<CentreCode>" & tdf2!GestorCode & "</CentreCode><RoleTypeCode>02</RoleTypeCode><Name>" & tdf2!GestorNombre & "</Name>";
            Print #1, "<AddressInSpain><Address>" & tdf2!DIRECCION & "</Address><PostCode>" & tdf2!cp & "</PostCode><Town>" & tdf2!POBLACION & "</Town><Province>" & tdf2!PROVINCIA & "</Province><CountryCode>ESP</CountryCode></AddressInSpain>";
            Print #1, "</AdministrativeCentre>";
            'Fiscal / Unidad tramitadora
            Print #1, "<AdministrativeCentre>";
            Print #1, "<CentreCode>" & tdf2!UnidadCode & "</CentreCode><RoleTypeCode>03</RoleTypeCode><Name>" & tdf2!UnidadNombre & "</Name>";
            Print #1, "<AddressInSpain><Address>" & tdf2!DIRECCION & "</Address><PostCode>" & tdf2!cp & "</PostCode><Town>" & tdf2!POBLACION & "</Town><Province>" & tdf2!PROVINCIA & "</Province><CountryCode>ESP</CountryCode></AddressInSpain>";
            Print #1, "</AdministrativeCentre>";
            'Pagador / Oficina contable
            Print #1, "<AdministrativeCentre>";
            Print #1, "<CentreCode>" & tdf2!OficinaCode & "</CentreCode><RoleTypeCode>01</RoleTypeCode><Name>" & tdf2!OficinaNombre & "</Name>";
            Print #1, "<AddressInSpain><Address>" & tdf2!DIRECCION & "</Address><PostCode>" & tdf2!cp & "</PostCode><Town>" & tdf2!POBLACION & "</Town><Province>" & tdf2!PROVINCIA & "</Province><CountryCode>ESP</CountryCode></AddressInSpain>";
            Print #1, "</AdministrativeCentre>";
        Print #1, "</AdministrativeCentres>";
        Print #1, "<LegalEntity>";
            Print #1, "<CorporateName>" & tdf2!NOMBRE & "</CorporateName>";
            Print #1, "<TradeName>" & tdf2!RAZONSOCIA & "</TradeName>";
            Print #1, "<AddressInSpain>";
                Print #1, "<Address>" & tdf2!DIRECCION & "</Address><PostCode>" & tdf2!cp & "</PostCode><Town>" & tdf2!POBLACION & "</Town><Province>" & tdf2!PROVINCIA & "</Province><CountryCode>ESP</CountryCode>";
            Print #1, "</AddressInSpain>";
        Print #1, "</LegalEntity>";
    Print #1, "</BuyerParty>";
Print #1, "</Parties>";
' Grabo los datos de la Factura
Print #1, "<Invoices>";
    Print #1, "<Invoice>";
        Print #1, "<InvoiceHeader>";
            Print #1, "<InvoiceNumber>" & Trim(Str(Me.NroFact)) & "</InvoiceNumber>";
            Print #1, "<InvoiceSeriesCode>Borrador-</InvoiceSeriesCode>";
            Print #1, "<InvoiceDocumentType>FC</InvoiceDocumentType>";
            Print #1, "<InvoiceClass>OO</InvoiceClass>";
        Print #1, "</InvoiceHeader>";
        Print #1, "<InvoiceIssueData>";
            Print #1, "<IssueDate>" & Format(Me.FechaFactura, "yyyy-mm-dd") & "</IssueDate>";
            Print #1, "<PlaceOfIssue><PostCode>39008</PostCode><PlaceOfIssueDescription>Asiento nro 30</PlaceOfIssueDescription></PlaceOfIssue>";
            Print #1, "<InvoiceCurrencyCode>EUR</InvoiceCurrencyCode><TaxCurrencyCode>EUR</TaxCurrencyCode><LanguageName>es</LanguageName>";
        Print #1, "</InvoiceIssueData>";
        Print #1, "<TaxesOutputs>";
            Print #1, "<Tax>";
                Print #1, "<TaxTypeCode>01</TaxTypeCode><TaxRate>" & Trim(Str(Me.Iva)) & "</TaxRate>";
                Print #1, "<TaxableBase><TotalAmount>" & Trim(Str(Me.SubtotalFactura)) & "</TotalAmount></TaxableBase>";
                Print #1, "<TaxAmount><TotalAmount>" & Trim(Str(Me.ImporteIVA)) & "</TotalAmount></TaxAmount>";
            Print #1, "</Tax>";
        Print #1, "</TaxesOutputs>";
        Print #1, "<InvoiceTotals>";
            Print #1, "<TotalGrossAmount>" & Trim(Str(Me.SubtotalFactura)) & "</TotalGrossAmount>";
            Print #1, "<TotalGeneralDiscounts>0.0</TotalGeneralDiscounts>";
            Print #1, "<TotalGeneralSurcharges>0.0</TotalGeneralSurcharges>";
            Print #1, "<TotalGrossAmountBeforeTaxes>" & Trim(Str(Me.SubtotalFactura)) & "</TotalGrossAmountBeforeTaxes>";
            Print #1, "<TotalTaxOutputs>" & Trim(Str(Me.ImporteIVA)) & "</TotalTaxOutputs>";
            Print #1, "<TotalTaxesWithheld>0.0</TotalTaxesWithheld>";
            Print #1, "<InvoiceTotal>" & Trim(Str(Me.ImporteFactura)) & "</InvoiceTotal>";
            Print #1, "<TotalOutstandingAmount>" & Trim(Str(Me.ImporteFactura)) & "</TotalOutstandingAmount>";
            Print #1, "<TotalExecutableAmount>" & Trim(Str(Me.ImporteFactura)) & "</TotalExecutableAmount>";
        Print #1, "</InvoiceTotals>";
        
        ' Líneas de detalle
        stDocName = "SELECT * FROM FacturasLineas WHERE FacturasLineas.IdFactura=" + Str(Me.IdFactura) + "; "
        Set tdf3 = dbs.OpenRecordset(stDocName)
        Print #1, "<Items>";
        If tdf3.EOF = False Then
            tdf3.MoveFirst
            Do
                Print #1, "<InvoiceLine>";
                    Print #1, "<ItemDescription>" & tdf3!DENOMINACION & "</ItemDescription>";
                    If IsNull(tdf3!Cantidad) Then
                        Print #1, "<Quantity>0</Quantity>";
                    Else
                        Print #1, "<Quantity>" & Trim(Str(tdf3!Cantidad)) & "</Quantity>";
                    End If
                    Print #1, "<UnitOfMeasure>01</UnitOfMeasure>";
                    If IsNull(tdf3!PrecioUnidad) Then
                        Print #1, "<UnitPriceWithoutTax>0</UnitPriceWithoutTax>";
                    Else
                        Print #1, "<UnitPriceWithoutTax>" & Trim(Str((Int((tdf3!PrecioUnidad * 100) + 0.5)) / 100)) & "</UnitPriceWithoutTax>";
                    End If
                    If IsNull(tdf3!LíneaTotal) Then
                        Print #1, "<TotalCost>0</TotalCost>";
                        Print #1, "<GrossAmount>0</GrossAmount>";
                    Else
                        Print #1, "<TotalCost>" & Trim(Str((Int((tdf3!LíneaTotal * 100) + 0.5)) / 100)) & "</TotalCost>";
                        Print #1, "<GrossAmount>" & Trim(Str((Int((tdf3!LíneaTotal * 100) + 0.5)) / 100)) & "</GrossAmount>";
                    End If
                    Print #1, "<TaxesOutputs>";
                        Print #1, "<Tax>";
                            Print #1, "<TaxTypeCode>01</TaxTypeCode>";
                            Print #1, "<TaxRate>" & Trim(Str(Me.Iva)) & "</TaxRate>";
                            Print #1, "<TaxableBase><TotalAmount>" & Trim(Str((Int((tdf3!LíneaTotal * 100) + 0.5)) / 100)) & "</TotalAmount></TaxableBase>";
                            If IsNull(tdf3!LíneaTotal) Then
                                cuantoiva = 0
                            Else
                                cuantoiva = (Int((tdf3!LíneaTotal * 100) + 0.5)) / 100
                                cuantoiva = (cuantoiva * Me.Iva / 100)
                            End If
                            Print #1, "<TaxAmount><TotalAmount>" & Trim(Str((Int((cuantoiva * 100) + 0.5)) / 100)) & "</TotalAmount></TaxAmount>";
                        Print #1, "</Tax>";
                    Print #1, "</TaxesOutputs>";
                    If Not (IsNull(tdf3!Notas)) Then
                        Print #1, "<AdditionalLineItemInformation>" & tdf3!DENOMINACI&; "</AdditionalLineItemInformation>";
                    End If
                 Print #1, "</InvoiceLine>";
                 tdf3.MoveNext
              Loop While tdf3.EOF = False
           End If

        Print #1, "</Items>";
        
    Print #1, "</Invoice>";
Print #1, "</Invoices>";
Print #1, "</fe:Facturae>";
Close #1
tdf2.Close
tdf3.Close
Set dbs = Nothing
lineacomando = "sign -i C:\Directorio\Emit-" & Trim(Str(Me.NroFact)) & ".xml -o C:\Directorio\Emit-" & Trim(Str(Me.NroFact)) & ".xsig -certgui"
retval = Shell("C:\Program Files\AutoFirma\AutoFirma\autofirma.exe " & lineacomando)