Page 1 of 3

Visor o leer XML...(Solucionado)

Posted: Tue Aug 12, 2014 9:43 pm
by ACC69
Hola buenas tardes, de antemano les envio cordial saludos.

Mis estimados, alguien ha desarrollado un visor de XML, para ver la presentacion de la factura u otro tipo de documentos normal.

Ando creando cargar todos los documentos de archivos XML, a una base de datos,aunque no logro cargar masivamente, solo de uno en uno que mas adelante veo de que otra funcion cargo masivamente los archivos xml.

Pero ahora se me presenta una gran duda, como ver la presentacion del archivo xml, no la estructura de datos que eso se puede ver en pagina web o notepad,sino un visor para ver la presentacion en pantalla de una factura normal y si es posible crear ese visor ?.

Saludos a todos.

Atte: Adrian C. C.

Re: Visor XML

Posted: Wed Aug 13, 2014 2:28 pm
by ACC69
ACC69 wrote:Hola buenas tardes, de antemano les envio cordial saludos.

Mis estimados, alguien ha desarrollado un visor de XML, para ver la presentacion de la factura u otro tipo de documentos normal.

Ando creando cargar todos los documentos de archivos XML, a una base de datos,aunque no logro cargar masivamente, solo de uno en uno que mas adelante veo de que otra funcion cargo masivamente los archivos xml.

Pero ahora se me presenta una gran duda, como ver la presentacion del archivo xml, no la estructura de datos que eso se puede ver en pagina web o notepad,sino un visor para ver la presentacion en pantalla de una factura normal y si es posible crear ese visor ?.

Saludos a todos.

Atte: Adrian C. C.
Por lo visto nadie tiene desarrollado esa herramienta de Visol XML, o no me supe explicar . :(

Saludos y buen dia .!
Atte: Adrian C. C.

Re: Visor XML

Posted: Wed Aug 13, 2014 4:28 pm
by MGA
Adrian,

c:\fwh\samples\xmlreader.prg

Re: Visor XML

Posted: Wed Aug 13, 2014 5:37 pm
by karinha

Re: Visor XML

Posted: Wed Aug 13, 2014 9:17 pm
by ACC69

Hola buenas tardes, gracias a ambos,no encuentro en el sample xmlreader , por tener mi version antigua que es la 10.06 .

Este es archivo de xml, por el quiero que me visualice el formato como una factura .

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd" version="3.2" serie="A" folio="8303" fecha="2014-05-06T16:37:03" sello="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" formaDePago="PAGO EN UNA SOLA EXHIBICIÓN" noCertificado="00001000000300959274" certificado="MIIEdTCCA12gAwIBAgIUMDAwMDEwMDAwMDAzMDA5NTkyNzQwDQYJKoZIhvcNAQEFBQAwggGKMTgwNgYDVQQDDC9BLkMuIGRlbCBTZXJ2aWNpbyBkZSBBZG1pbmlzdHJhY2nDs24gVHJpYnV0YXJpYTEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMR8wHQYJKoZIhvcNAQkBFhBhY29kc0BzYXQuZ29iLm14MSYwJAYDVQQJDB1Bdi4gSGlkYWxnbyA3NywgQ29sLiBHdWVycmVybzEOMAwGA1UEEQwFMDYzMDAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBEaXN0cml0byBGZWRlcmFsMRQwEgYDVQQHDAtDdWF1aHTDqW1vYzEVMBMGA1UELRMMU0FUOTcwNzAxTk4zMTUwMwYJKoZIhvcNAQkCDCZSZXNwb25zYWJsZTogQ2xhdWRpYSBDb3ZhcnJ1YmlhcyBPY2hvYTAeFw0xMzEwMDEyMjU5MzFaFw0xNzEwMDEyMjU5MzFaMIHBMSIwIAYDVQQDExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQpExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQKExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSUwIwYDVQQtExxFUEYxMTA0MDFMMTQgLyBDVVJINzcwNTEyS0I0MR4wHAYDVQQFExUgLyBDVVJINzcwNTEySFBMWkNDMDQxDDAKBgNVBAsTA1NBVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArBdcMufQBkuLt4HZbdhptENUS+o4vDcRybKf1qnEh52S45KS3VCg1UjICQi81aKN/3Olcch++wXXlw9d+Q+vbYScrZXXGwqCQXET5H7ymP0DbwOEQqXJKuJ8SxGbVhu/EAij7Sx1q+auV1xlQg2IWBXYMPenLU7JfGUmswUIZ4cCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwDQYJKoZIhvcNAQEFBQADggEBAFLaN3h4RbyzT6BgnaTOP4vncqXTzMIVrBbc+i23zDE8kX3UFitHGJ4Y7oK40UQSQiTZHvqSkAwOtuGvC5A6N0KYs6+lhoe0eiZos9k10s4SvJ5vorFw91JdzvstFEG82by44xxPhctUobU2QXUYPIrO9xuoAavDkcX8alMtPefy1IrQJZHw88crPilXa4uTl/bnptK/AN3g70uuqe/cCRJXDKGDUMUregJBZrkuXRNRs/bD9m8gjCxNylzpvRMAkxbEzxKyUpM1PoNtFutfoGO9goXqmfnM77BgQzSKpXAgWRD1cEhaPveeIe+r1I51p/o772NlGSo/gmEy1Ruvpb0=" condicionesDePago="UNA SOLA EXHIBICION" subTotal="2027.72" descuento="0.00" TipoCambio="1.00" Moneda="PESOS" total="2352.16" metodoDePago="CHEQUE" tipoDeComprobante="ingreso" NumCtaPago="6520" LugarExpedicion="BENITO JUAREZ,QUINTANA ROO">
  <cfdi:Emisor rfc="EPF110401L14" nombre="ESTRATEGIA PUNTO FINAL S. C.">
    <cfdi:DomicilioFiscal calle="CHIETLA" noExterior="906" colonia="LA PAZ HEROICA" municipio="PUEBLA DE ZARAGOZA" estado="PUEBLA" pais="MEXICO" codigoPostal="72160" />
    <cfdi:ExpedidoEn calle="AV TULUM, INTERIOR 10" noExterior="LT 17-19" colonia="SM 22" localidad="CANCUN" municipio="BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77500" />
    <cfdi:RegimenFiscal Regimen="General de ley Personas Morales" />
  </cfdi:Emisor>
  <cfdi:Receptor rfc="CTS070503999" nombre="COMERCIALIZADORA TIME SHARE INTERNACIONAL, S. A. DE C. V.">
    <cfdi:Domicilio calle="BLVD LUIS DONALDO COLOSIO" noExterior="KM 9" noInterior="BODEGA 44" colonia="CTRA BODEGAS CANCUN" municipio="CANCUN; BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77560" />
  </cfdi:Receptor>
  <cfdi:Conceptos>
    <cfdi:Concepto cantidad="1.00" unidad="Servicio" noIdentificacion="001" descripcion="COMISIONES MERCANTILES" valorUnitario="2027.72" importe="2027.72" />
  </cfdi:Conceptos>
  <cfdi:Impuestos totalImpuestosTrasladados="324.44">
    <cfdi:Traslados>
      <cfdi:Traslado impuesto="IVA" tasa="16.00" importe="324.44" />
    </cfdi:Traslados>
  </cfdi:Impuestos>
  <cfdi:Complemento>
    <tfd:TimbreFiscalDigital xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/TimbreFiscalDigital/TimbreFiscalDigital.xsd" version="1.0" UUID="A05C2BD0-6162-4690-BD53-9876CF51D68F" FechaTimbrado="2014-05-06T16:44:26" selloCFD="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" noCertificadoSAT="00001000000202639096" selloSAT="ez6xFxA9QqFPF2y0hix3yZvElNeX3EZaT5xOv5DlncB+bMYIps/2sTdoCjhq6U2sKyl03somlItxN/vE8F5I3VNq9P5pirBJ+LxAoBzyWa0ttisqRH3t27EAKD8NOi4Q6E/WM2HozszrRouXEW4TUMhHi5K+b8am/pEtuooWT2U=" />
  </cfdi:Complemento>
</cfdi:Comprobante>
Estuve averiguando y nada de nada que encontre en el foro.!
Adjunto la imagen, asi como se muestra en el dialogo, extraido los datos asi como al igual se podria ver en imagen antes de imprimir la factura que contiene el archivo xml, es por eso que preguntaba si alguien ya tiene esa herramienta de Visor xml.

Image
http://s1286.photobucket.com/user/ACC69 ... c.jpg.html


Saludos y buen dia.!

Atte: Adrian C. C.

Re: Visor XML

Posted: Thu Aug 14, 2014 12:52 am
by ACC69
ACC69 wrote:

Hola buenas tardes, gracias a ambos,no encuentro en el sample xmlreader , por tener mi version antigua que es la 10.06 .

Este es archivo de xml, por el quiero que me visualice el formato como una factura .

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd" version="3.2" serie="A" folio="8303" fecha="2014-05-06T16:37:03" sello="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" formaDePago="PAGO EN UNA SOLA EXHIBICIÓN" noCertificado="00001000000300959274" certificado="MIIEdTCCA12gAwIBAgIUMDAwMDEwMDAwMDAzMDA5NTkyNzQwDQYJKoZIhvcNAQEFBQAwggGKMTgwNgYDVQQDDC9BLkMuIGRlbCBTZXJ2aWNpbyBkZSBBZG1pbmlzdHJhY2nDs24gVHJpYnV0YXJpYTEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMR8wHQYJKoZIhvcNAQkBFhBhY29kc0BzYXQuZ29iLm14MSYwJAYDVQQJDB1Bdi4gSGlkYWxnbyA3NywgQ29sLiBHdWVycmVybzEOMAwGA1UEEQwFMDYzMDAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBEaXN0cml0byBGZWRlcmFsMRQwEgYDVQQHDAtDdWF1aHTDqW1vYzEVMBMGA1UELRMMU0FUOTcwNzAxTk4zMTUwMwYJKoZIhvcNAQkCDCZSZXNwb25zYWJsZTogQ2xhdWRpYSBDb3ZhcnJ1YmlhcyBPY2hvYTAeFw0xMzEwMDEyMjU5MzFaFw0xNzEwMDEyMjU5MzFaMIHBMSIwIAYDVQQDExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQpExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQKExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSUwIwYDVQQtExxFUEYxMTA0MDFMMTQgLyBDVVJINzcwNTEyS0I0MR4wHAYDVQQFExUgLyBDVVJINzcwNTEySFBMWkNDMDQxDDAKBgNVBAsTA1NBVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArBdcMufQBkuLt4HZbdhptENUS+o4vDcRybKf1qnEh52S45KS3VCg1UjICQi81aKN/3Olcch++wXXlw9d+Q+vbYScrZXXGwqCQXET5H7ymP0DbwOEQqXJKuJ8SxGbVhu/EAij7Sx1q+auV1xlQg2IWBXYMPenLU7JfGUmswUIZ4cCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwDQYJKoZIhvcNAQEFBQADggEBAFLaN3h4RbyzT6BgnaTOP4vncqXTzMIVrBbc+i23zDE8kX3UFitHGJ4Y7oK40UQSQiTZHvqSkAwOtuGvC5A6N0KYs6+lhoe0eiZos9k10s4SvJ5vorFw91JdzvstFEG82by44xxPhctUobU2QXUYPIrO9xuoAavDkcX8alMtPefy1IrQJZHw88crPilXa4uTl/bnptK/AN3g70uuqe/cCRJXDKGDUMUregJBZrkuXRNRs/bD9m8gjCxNylzpvRMAkxbEzxKyUpM1PoNtFutfoGO9goXqmfnM77BgQzSKpXAgWRD1cEhaPveeIe+r1I51p/o772NlGSo/gmEy1Ruvpb0=" condicionesDePago="UNA SOLA EXHIBICION" subTotal="2027.72" descuento="0.00" TipoCambio="1.00" Moneda="PESOS" total="2352.16" metodoDePago="CHEQUE" tipoDeComprobante="ingreso" NumCtaPago="6520" LugarExpedicion="BENITO JUAREZ,QUINTANA ROO">
  <cfdi:Emisor rfc="EPF110401L14" nombre="ESTRATEGIA PUNTO FINAL S. C.">
    <cfdi:DomicilioFiscal calle="CHIETLA" noExterior="906" colonia="LA PAZ HEROICA" municipio="PUEBLA DE ZARAGOZA" estado="PUEBLA" pais="MEXICO" codigoPostal="72160" />
    <cfdi:ExpedidoEn calle="AV TULUM, INTERIOR 10" noExterior="LT 17-19" colonia="SM 22" localidad="CANCUN" municipio="BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77500" />
    <cfdi:RegimenFiscal Regimen="General de ley Personas Morales" />
  </cfdi:Emisor>
  <cfdi:Receptor rfc="CTS070503999" nombre="COMERCIALIZADORA TIME SHARE INTERNACIONAL, S. A. DE C. V.">
    <cfdi:Domicilio calle="BLVD LUIS DONALDO COLOSIO" noExterior="KM 9" noInterior="BODEGA 44" colonia="CTRA BODEGAS CANCUN" municipio="CANCUN; BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77560" />
  </cfdi:Receptor>
  <cfdi:Conceptos>
    <cfdi:Concepto cantidad="1.00" unidad="Servicio" noIdentificacion="001" descripcion="COMISIONES MERCANTILES" valorUnitario="2027.72" importe="2027.72" />
  </cfdi:Conceptos>
  <cfdi:Impuestos totalImpuestosTrasladados="324.44">
    <cfdi:Traslados>
      <cfdi:Traslado impuesto="IVA" tasa="16.00" importe="324.44" />
    </cfdi:Traslados>
  </cfdi:Impuestos>
  <cfdi:Complemento>
    <tfd:TimbreFiscalDigital xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/TimbreFiscalDigital/TimbreFiscalDigital.xsd" version="1.0" UUID="A05C2BD0-6162-4690-BD53-9876CF51D68F" FechaTimbrado="2014-05-06T16:44:26" selloCFD="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" noCertificadoSAT="00001000000202639096" selloSAT="ez6xFxA9QqFPF2y0hix3yZvElNeX3EZaT5xOv5DlncB+bMYIps/2sTdoCjhq6U2sKyl03somlItxN/vE8F5I3VNq9P5pirBJ+LxAoBzyWa0ttisqRH3t27EAKD8NOi4Q6E/WM2HozszrRouXEW4TUMhHi5K+b8am/pEtuooWT2U=" />
  </cfdi:Complemento>
</cfdi:Comprobante>
Estuve averiguando y nada de nada que encontre en el foro.!
Adjunto la imagen, asi como se muestra en el dialogo, extraido los datos asi como al igual se podria ver en imagen antes de imprimir la factura que contiene el archivo xml, es por eso que preguntaba si alguien ya tiene esa herramienta de Visor xml.

Image
http://s1286.photobucket.com/user/ACC69 ... c.jpg.html


Saludos y buen dia.!

Atte: Adrian C. C.

Gracias Karinha por el link, si es compatible con mi version, aunque no tenga el ejemplo de xmlreader.prg

Como yo podre leer o extraer oTagActual:aAttributes de donde viene la variable cValue y como validar desde attributos mi variable Serie y Folio y asignar al get ...

Estoy tratando de entender este codigo:.

Code: Select all

local hFile    := FOpen( "test.xml" ) 
   Local oXmlDoc  := TXmlDocument():New( hFile )
   Local oXmlIter := TXmlIterator():New( oXmlDoc:oRoot ), oTagActual

   while .T.
      oTagActual = oXmlIter:Next()
      If oTagActual != nil
         *MsgInfo( oTagActual:cName, oTagActual:cData )
         HEval( oTagActual:aAttributes, { | cKey, cValue | MsgInfo( cKey, cValue ) } )
      Else
         Exit
      Endif
   End

   FClose( hFile )

return nil
y este otro :

Code: Select all

#include "FiveWin.ch"
#include "Splitter.ch"

static oSplit1, oSplit2, oLbxDatas, oLbxMethods

//----------------------------------------------------------------------------/

function Test()

   local oWnd

   DEFINE WINDOW oWnd TITLE "XML viewer" ;
      MENU BuildMenu()

   ACTIVATE WINDOW oWnd ;
      ON INIT BuildTree( oWnd ) ;
      ON RESIZE ( If( oSplit1 != nil, oSplit1:AdjLeft(),),;
                  If( oSplit2 != nil, oSplit2:AdjRight(),) )

return nil

//----------------------------------------------------------------------------/


function BuildMenu()

   local oMenu

   MENU oMenu
      MENUITEM "About" ACTION MsgAbout( "XML Viewer", "(c) FiveTech Software 2013" )
   ENDMENU

return oMenu

//----------------------------------------------------------------------------/


function BuildTree( oWnd )

   local oTree := TTreeView():New( 0, 0, oWnd )
   local oClass, cData, cMethod
   local hFile, oXmlDoc, oXmlIter, oTagActual
   local oTagLast, aRoots := {}

   oTree:nWidth = 180
   // oTree:SetImageList( oImageList )

   oTree:Expand()

   @ 0, 186 LISTBOX oLbxDatas VAR cData ITEMS {} ;
      SIZE 200, 200 PIXEL OF oWnd

   @ 0, 391 LISTBOX oLbxMethods VAR cMethod ITEMS {} ;
      SIZE 200, 200 PIXEL OF oWnd

   @ 0, 181 SPLITTER oSplit1 ;
      VERTICAL ;
      PREVIOUS CONTROLS oTree ;
      HINDS CONTROLS oLbxDatas ;
      LEFT MARGIN 150 ;
      RIGHT MARGIN oSplit2:nLast + 100 ;
      SIZE 4, 300  PIXEL ;
      OF oWnd STYLE

   @ 0, 386 SPLITTER oSplit2 ;
      VERTICAL ;
      PREVIOUS CONTROLS oLbxDatas ;
      HINDS CONTROLS oLbxMethods ;
      LEFT MARGIN oSplit1:nFirst + 120 ;
      RIGHT MARGIN 80 ;
      SIZE 4, 300 PIXEL ;
      OF oWnd STYLE

   hFile    = FOpen( "test.xml" )
   oXmlDoc  = TXmlDocument():New( hFile )
   oXmlIter = TXmlIterator():New( oXmlDoc:oRoot )

   AAdd( aRoots, oTree )

   while ( oTagActual := oXmlIter:Next() ) != nil
      if oTagLast != nil
         if oTagLast:Depth() < oTagActual:Depth()
            ASize( aRoots, Len( aRoots ) + 1 )
            aRoots[ oTagActual:Depth() + 1 ] = aRoots[ oTagActual:Depth() ]:Add( oTagActual:cName )
            aRoots[ oTagActual:Depth() + 1 ]:Cargo = oTagActual
         endif

         if oTagLast:Depth() > oTagActual:Depth()
            aRoots[ oTagActual:depth() + 1 ] = aRoots[ oTagActual:Depth() ]:Add( oTagActual:cName )
            aRoots[ oTagActual:depth() + 1 ]:Cargo = oTagActual
         endif

         if oTagLast:Depth() == oTagActual:Depth()
            aRoots[ Max( oTagLast:Depth(), 1 ) ]:Add( oTagActual:cName ):Cargo = oTagActual 
         endif
      else
         AAdd( aRoots, oTree:Add( oTagActual:cName ) )
         ATail( aRoots ):Cargo = oTagActual
      endif
      oTagLast = oTagActual
   end

   FClose( hFile )

   oTree:bChanged = { | oItem | oLbxDatas:SetItems( { oItem:GetSelected():Cargo:cData } ),;
                                oLbxMethods:Reset(),;
                                HEval( oItem:GetSelected():Cargo:aAttributes,;
                                { | cKey, cData | oLbxMethods:Add( cKey + " : " + cData ) } ) }

return nil
Como puedo extraer los datos y mostrarlos en mi pantalla del dialogo o al igual imprimir.
Que al parecer viene de aAttributes,muestra los valores de datos,pero como traerlo a mi dialogo ya sea get o PROMP var cFolio = FOLIO desde xml.

Ya busque en todos los foros y nada que se menciona de como extraer todos estos datos, como el ejemplo de la imagen que subi. Donde puedo encontrar documentacion y saber mas todo tipo de datos, nodos,etc etc . :cry: :(

Atte: Adrian C. C.

Re: Visor XML

Posted: Thu Aug 14, 2014 3:10 am
by ACC69
ACC69 wrote:
ACC69 wrote:

Hola buenas tardes, gracias a ambos,no encuentro en el sample xmlreader , por tener mi version antigua que es la 10.06 .

Este es archivo de xml, por el quiero que me visualice el formato como una factura .

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd" version="3.2" serie="A" folio="8303" fecha="2014-05-06T16:37:03" sello="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" formaDePago="PAGO EN UNA SOLA EXHIBICIÓN" noCertificado="00001000000300959274" certificado="MIIEdTCCA12gAwIBAgIUMDAwMDEwMDAwMDAzMDA5NTkyNzQwDQYJKoZIhvcNAQEFBQAwggGKMTgwNgYDVQQDDC9BLkMuIGRlbCBTZXJ2aWNpbyBkZSBBZG1pbmlzdHJhY2nDs24gVHJpYnV0YXJpYTEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMR8wHQYJKoZIhvcNAQkBFhBhY29kc0BzYXQuZ29iLm14MSYwJAYDVQQJDB1Bdi4gSGlkYWxnbyA3NywgQ29sLiBHdWVycmVybzEOMAwGA1UEEQwFMDYzMDAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBEaXN0cml0byBGZWRlcmFsMRQwEgYDVQQHDAtDdWF1aHTDqW1vYzEVMBMGA1UELRMMU0FUOTcwNzAxTk4zMTUwMwYJKoZIhvcNAQkCDCZSZXNwb25zYWJsZTogQ2xhdWRpYSBDb3ZhcnJ1YmlhcyBPY2hvYTAeFw0xMzEwMDEyMjU5MzFaFw0xNzEwMDEyMjU5MzFaMIHBMSIwIAYDVQQDExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQpExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQKExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSUwIwYDVQQtExxFUEYxMTA0MDFMMTQgLyBDVVJINzcwNTEyS0I0MR4wHAYDVQQFExUgLyBDVVJINzcwNTEySFBMWkNDMDQxDDAKBgNVBAsTA1NBVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArBdcMufQBkuLt4HZbdhptENUS+o4vDcRybKf1qnEh52S45KS3VCg1UjICQi81aKN/3Olcch++wXXlw9d+Q+vbYScrZXXGwqCQXET5H7ymP0DbwOEQqXJKuJ8SxGbVhu/EAij7Sx1q+auV1xlQg2IWBXYMPenLU7JfGUmswUIZ4cCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwDQYJKoZIhvcNAQEFBQADggEBAFLaN3h4RbyzT6BgnaTOP4vncqXTzMIVrBbc+i23zDE8kX3UFitHGJ4Y7oK40UQSQiTZHvqSkAwOtuGvC5A6N0KYs6+lhoe0eiZos9k10s4SvJ5vorFw91JdzvstFEG82by44xxPhctUobU2QXUYPIrO9xuoAavDkcX8alMtPefy1IrQJZHw88crPilXa4uTl/bnptK/AN3g70uuqe/cCRJXDKGDUMUregJBZrkuXRNRs/bD9m8gjCxNylzpvRMAkxbEzxKyUpM1PoNtFutfoGO9goXqmfnM77BgQzSKpXAgWRD1cEhaPveeIe+r1I51p/o772NlGSo/gmEy1Ruvpb0=" condicionesDePago="UNA SOLA EXHIBICION" subTotal="2027.72" descuento="0.00" TipoCambio="1.00" Moneda="PESOS" total="2352.16" metodoDePago="CHEQUE" tipoDeComprobante="ingreso" NumCtaPago="6520" LugarExpedicion="BENITO JUAREZ,QUINTANA ROO">
  <cfdi:Emisor rfc="EPF110401L14" nombre="ESTRATEGIA PUNTO FINAL S. C.">
    <cfdi:DomicilioFiscal calle="CHIETLA" noExterior="906" colonia="LA PAZ HEROICA" municipio="PUEBLA DE ZARAGOZA" estado="PUEBLA" pais="MEXICO" codigoPostal="72160" />
    <cfdi:ExpedidoEn calle="AV TULUM, INTERIOR 10" noExterior="LT 17-19" colonia="SM 22" localidad="CANCUN" municipio="BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77500" />
    <cfdi:RegimenFiscal Regimen="General de ley Personas Morales" />
  </cfdi:Emisor>
  <cfdi:Receptor rfc="CTS070503999" nombre="COMERCIALIZADORA TIME SHARE INTERNACIONAL, S. A. DE C. V.">
    <cfdi:Domicilio calle="BLVD LUIS DONALDO COLOSIO" noExterior="KM 9" noInterior="BODEGA 44" colonia="CTRA BODEGAS CANCUN" municipio="CANCUN; BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77560" />
  </cfdi:Receptor>
  <cfdi:Conceptos>
    <cfdi:Concepto cantidad="1.00" unidad="Servicio" noIdentificacion="001" descripcion="COMISIONES MERCANTILES" valorUnitario="2027.72" importe="2027.72" />
  </cfdi:Conceptos>
  <cfdi:Impuestos totalImpuestosTrasladados="324.44">
    <cfdi:Traslados>
      <cfdi:Traslado impuesto="IVA" tasa="16.00" importe="324.44" />
    </cfdi:Traslados>
  </cfdi:Impuestos>
  <cfdi:Complemento>
    <tfd:TimbreFiscalDigital xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/TimbreFiscalDigital/TimbreFiscalDigital.xsd" version="1.0" UUID="A05C2BD0-6162-4690-BD53-9876CF51D68F" FechaTimbrado="2014-05-06T16:44:26" selloCFD="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" noCertificadoSAT="00001000000202639096" selloSAT="ez6xFxA9QqFPF2y0hix3yZvElNeX3EZaT5xOv5DlncB+bMYIps/2sTdoCjhq6U2sKyl03somlItxN/vE8F5I3VNq9P5pirBJ+LxAoBzyWa0ttisqRH3t27EAKD8NOi4Q6E/WM2HozszrRouXEW4TUMhHi5K+b8am/pEtuooWT2U=" />
  </cfdi:Complemento>
</cfdi:Comprobante>
Estuve averiguando y nada de nada que encontre en el foro.!
Adjunto la imagen, asi como se muestra en el dialogo, extraido los datos asi como al igual se podria ver en imagen antes de imprimir la factura que contiene el archivo xml, es por eso que preguntaba si alguien ya tiene esa herramienta de Visor xml.

Image
http://s1286.photobucket.com/user/ACC69 ... c.jpg.html


Saludos y buen dia.!

Atte: Adrian C. C.

Gracias Karinha por el link, si es compatible con mi version, aunque no tenga el ejemplo de xmlreader.prg

Como yo podre leer o extraer oTagActual:aAttributes de donde viene la variable cValue y como validar desde attributos mi variable Serie y Folio y asignar al get ...

Estoy tratando de entender este codigo:.

Code: Select all

local hFile    := FOpen( "test.xml" ) 
   Local oXmlDoc  := TXmlDocument():New( hFile )
   Local oXmlIter := TXmlIterator():New( oXmlDoc:oRoot ), oTagActual

   while .T.
      oTagActual = oXmlIter:Next()
      If oTagActual != nil
         *MsgInfo( oTagActual:cName, oTagActual:cData )
         HEval( oTagActual:aAttributes, { | cKey, cValue | MsgInfo( cKey, cValue ) } )
      Else
         Exit
      Endif
   End

   FClose( hFile )

return nil
y este otro :

Code: Select all

#include "FiveWin.ch"
#include "Splitter.ch"

static oSplit1, oSplit2, oLbxDatas, oLbxMethods

//----------------------------------------------------------------------------/

function Test()

   local oWnd

   DEFINE WINDOW oWnd TITLE "XML viewer" ;
      MENU BuildMenu()

   ACTIVATE WINDOW oWnd ;
      ON INIT BuildTree( oWnd ) ;
      ON RESIZE ( If( oSplit1 != nil, oSplit1:AdjLeft(),),;
                  If( oSplit2 != nil, oSplit2:AdjRight(),) )

return nil

//----------------------------------------------------------------------------/


function BuildMenu()

   local oMenu

   MENU oMenu
      MENUITEM "About" ACTION MsgAbout( "XML Viewer", "(c) FiveTech Software 2013" )
   ENDMENU

return oMenu

//----------------------------------------------------------------------------/


function BuildTree( oWnd )

   local oTree := TTreeView():New( 0, 0, oWnd )
   local oClass, cData, cMethod
   local hFile, oXmlDoc, oXmlIter, oTagActual
   local oTagLast, aRoots := {}

   oTree:nWidth = 180
   // oTree:SetImageList( oImageList )

   oTree:Expand()

   @ 0, 186 LISTBOX oLbxDatas VAR cData ITEMS {} ;
      SIZE 200, 200 PIXEL OF oWnd

   @ 0, 391 LISTBOX oLbxMethods VAR cMethod ITEMS {} ;
      SIZE 200, 200 PIXEL OF oWnd

   @ 0, 181 SPLITTER oSplit1 ;
      VERTICAL ;
      PREVIOUS CONTROLS oTree ;
      HINDS CONTROLS oLbxDatas ;
      LEFT MARGIN 150 ;
      RIGHT MARGIN oSplit2:nLast + 100 ;
      SIZE 4, 300  PIXEL ;
      OF oWnd STYLE

   @ 0, 386 SPLITTER oSplit2 ;
      VERTICAL ;
      PREVIOUS CONTROLS oLbxDatas ;
      HINDS CONTROLS oLbxMethods ;
      LEFT MARGIN oSplit1:nFirst + 120 ;
      RIGHT MARGIN 80 ;
      SIZE 4, 300 PIXEL ;
      OF oWnd STYLE

   hFile    = FOpen( "test.xml" )
   oXmlDoc  = TXmlDocument():New( hFile )
   oXmlIter = TXmlIterator():New( oXmlDoc:oRoot )

   AAdd( aRoots, oTree )

   while ( oTagActual := oXmlIter:Next() ) != nil
      if oTagLast != nil
         if oTagLast:Depth() < oTagActual:Depth()
            ASize( aRoots, Len( aRoots ) + 1 )
            aRoots[ oTagActual:Depth() + 1 ] = aRoots[ oTagActual:Depth() ]:Add( oTagActual:cName )
            aRoots[ oTagActual:Depth() + 1 ]:Cargo = oTagActual
         endif

         if oTagLast:Depth() > oTagActual:Depth()
            aRoots[ oTagActual:depth() + 1 ] = aRoots[ oTagActual:Depth() ]:Add( oTagActual:cName )
            aRoots[ oTagActual:depth() + 1 ]:Cargo = oTagActual
         endif

         if oTagLast:Depth() == oTagActual:Depth()
            aRoots[ Max( oTagLast:Depth(), 1 ) ]:Add( oTagActual:cName ):Cargo = oTagActual 
         endif
      else
         AAdd( aRoots, oTree:Add( oTagActual:cName ) )
         ATail( aRoots ):Cargo = oTagActual
      endif
      oTagLast = oTagActual
   end

   FClose( hFile )

   oTree:bChanged = { | oItem | oLbxDatas:SetItems( { oItem:GetSelected():Cargo:cData } ),;
                                oLbxMethods:Reset(),;
                                HEval( oItem:GetSelected():Cargo:aAttributes,;
                                { | cKey, cData | oLbxMethods:Add( cKey + " : " + cData ) } ) }

return nil
Como puedo extraer los datos y mostrarlos en mi pantalla del dialogo o al igual imprimir.
Que al parecer viene de aAttributes,muestra los valores de datos,pero como traerlo a mi dialogo ya sea get o PROMP var cFolio = FOLIO desde xml.

Ya busque en todos los foros y nada que se menciona de como extraer todos estos datos, como el ejemplo de la imagen que subi. Donde puedo encontrar documentacion y saber mas todo tipo de datos, nodos,etc etc . :cry: :(

Atte: Adrian C. C.

Ya mas o menos le voy entendiendo, aunque me falta muchas cosas mas, he visto mas ejemplos en el foro,pero incluyen este include hbxml.ch, pero es para xharbour y no harbour .

Code: Select all

 local hFile    := FOpen( "test.xml" )
 Local oXmlDoc  := TXmlDocument():New( hFile )
 Local oXmlIter := TXmlIterator():New( oXmlDoc:oRoot ), oTagActual

   while .T.
      oTagActual = oXmlIter:Next()
      If !oTagActual = nil
         *MsgInfo( oTagActual:cName )
         *MsgInfo( oTagActual:cData )
         *HEval( oTagActual:aAttributes, { | cKey, cValue | MsgInfo( cValue ) } )

         MsgInfo( oTagActual:GetAttribute("LugarExpedicion") )
         MsgInfo( oTagActual:GetAttribute("metodoDePago") )
         MsgInfo( oTagActual:GetAttribute("tipoDeComprobante") )
         MsgInfo( oTagActual:GetAttribute("total") )
         MsgInfo( oTagActual:GetAttribute("Moneda") )
         MsgInfo( oTagActual:GetAttribute("TipoCambio") )
         MsgInfo( oTagActual:GetAttribute("subTotal") )
         MsgInfo( oTagActual:GetAttribute("certificado") )
         MsgInfo( oTagActual:GetAttribute("formaDePago") )
         MsgInfo( oTagActual:GetAttribute("sello") )
         MsgInfo( oTagActual:GetAttribute("fecha") )
         MsgInfo( oTagActual:GetAttribute("folio") )
         MsgInfo( oTagActual:GetAttribute("version") )
         MsgInfo( oTagActual:GetAttribute("schemalocation") )
         MsgInfo( oTagActual:GetAttribute("nombre") )
      Else
         Exit
      Endif
   End

   FClose( hFile )

return nil
Esta parte de GetAttribute ya me extrae los datos que necesito, segun mas o menos, pero ahora, como lo integro a mi pantalla de dialogo por ejemplo:

Serie : A Folio: 313
Lugar : Cancun Emisor: Caro Services.
Metodo de Pago: No identificado


Alguien alguna idea de como agregarlo a mi say prompt en una pantalla de dialogo?,cualquier sugerencia sera bienvenida, por el momento solo me queda investigar mas oTagActual:cName, oTagActual:cData y HEval( oTagActual:aAttributes, { | cKey, cValue | MsgInfo( cValue ) } ), para extraer como titulo cada parametro del dato de oTagActual:GetAttribute("LugarExpedicion")

Si hubiera una buena documentacion y ejemplos, seria facil entenderle mas a esta clase.

Saludos y buenas noches.!

Atte: Adrian C. C.
acc69@hotmail.com

Re: Visor XML

Posted: Thu Aug 14, 2014 7:00 pm
by ACC69
ACC69 wrote:

Hola buenas tardes, gracias a ambos,no encuentro en el sample xmlreader , por tener mi version antigua que es la 10.06 .

Este es archivo de xml, por el quiero que me visualice el formato como una factura .

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd" version="3.2" serie="A" folio="8303" fecha="2014-05-06T16:37:03" sello="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" formaDePago="PAGO EN UNA SOLA EXHIBICIÓN" noCertificado="00001000000300959274" certificado="MIIEdTCCA12gAwIBAgIUMDAwMDEwMDAwMDAzMDA5NTkyNzQwDQYJKoZIhvcNAQEFBQAwggGKMTgwNgYDVQQDDC9BLkMuIGRlbCBTZXJ2aWNpbyBkZSBBZG1pbmlzdHJhY2nDs24gVHJpYnV0YXJpYTEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMR8wHQYJKoZIhvcNAQkBFhBhY29kc0BzYXQuZ29iLm14MSYwJAYDVQQJDB1Bdi4gSGlkYWxnbyA3NywgQ29sLiBHdWVycmVybzEOMAwGA1UEEQwFMDYzMDAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBEaXN0cml0byBGZWRlcmFsMRQwEgYDVQQHDAtDdWF1aHTDqW1vYzEVMBMGA1UELRMMU0FUOTcwNzAxTk4zMTUwMwYJKoZIhvcNAQkCDCZSZXNwb25zYWJsZTogQ2xhdWRpYSBDb3ZhcnJ1YmlhcyBPY2hvYTAeFw0xMzEwMDEyMjU5MzFaFw0xNzEwMDEyMjU5MzFaMIHBMSIwIAYDVQQDExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQpExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSIwIAYDVQQKExlFU1RSQVRFR0lBIFBVTlRPIEZJTkFMIFNDMSUwIwYDVQQtExxFUEYxMTA0MDFMMTQgLyBDVVJINzcwNTEyS0I0MR4wHAYDVQQFExUgLyBDVVJINzcwNTEySFBMWkNDMDQxDDAKBgNVBAsTA1NBVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArBdcMufQBkuLt4HZbdhptENUS+o4vDcRybKf1qnEh52S45KS3VCg1UjICQi81aKN/3Olcch++wXXlw9d+Q+vbYScrZXXGwqCQXET5H7ymP0DbwOEQqXJKuJ8SxGbVhu/EAij7Sx1q+auV1xlQg2IWBXYMPenLU7JfGUmswUIZ4cCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwDQYJKoZIhvcNAQEFBQADggEBAFLaN3h4RbyzT6BgnaTOP4vncqXTzMIVrBbc+i23zDE8kX3UFitHGJ4Y7oK40UQSQiTZHvqSkAwOtuGvC5A6N0KYs6+lhoe0eiZos9k10s4SvJ5vorFw91JdzvstFEG82by44xxPhctUobU2QXUYPIrO9xuoAavDkcX8alMtPefy1IrQJZHw88crPilXa4uTl/bnptK/AN3g70uuqe/cCRJXDKGDUMUregJBZrkuXRNRs/bD9m8gjCxNylzpvRMAkxbEzxKyUpM1PoNtFutfoGO9goXqmfnM77BgQzSKpXAgWRD1cEhaPveeIe+r1I51p/o772NlGSo/gmEy1Ruvpb0=" condicionesDePago="UNA SOLA EXHIBICION" subTotal="2027.72" descuento="0.00" TipoCambio="1.00" Moneda="PESOS" total="2352.16" metodoDePago="CHEQUE" tipoDeComprobante="ingreso" NumCtaPago="6520" LugarExpedicion="BENITO JUAREZ,QUINTANA ROO">
  <cfdi:Emisor rfc="EPF110401L14" nombre="ESTRATEGIA PUNTO FINAL S. C.">
    <cfdi:DomicilioFiscal calle="CHIETLA" noExterior="906" colonia="LA PAZ HEROICA" municipio="PUEBLA DE ZARAGOZA" estado="PUEBLA" pais="MEXICO" codigoPostal="72160" />
    <cfdi:ExpedidoEn calle="AV TULUM, INTERIOR 10" noExterior="LT 17-19" colonia="SM 22" localidad="CANCUN" municipio="BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77500" />
    <cfdi:RegimenFiscal Regimen="General de ley Personas Morales" />
  </cfdi:Emisor>
  <cfdi:Receptor rfc="CTS070503999" nombre="COMERCIALIZADORA TIME SHARE INTERNACIONAL, S. A. DE C. V.">
    <cfdi:Domicilio calle="BLVD LUIS DONALDO COLOSIO" noExterior="KM 9" noInterior="BODEGA 44" colonia="CTRA BODEGAS CANCUN" municipio="CANCUN; BENITO JUAREZ" estado="QUINTANA ROO" pais="MEXICO" codigoPostal="77560" />
  </cfdi:Receptor>
  <cfdi:Conceptos>
    <cfdi:Concepto cantidad="1.00" unidad="Servicio" noIdentificacion="001" descripcion="COMISIONES MERCANTILES" valorUnitario="2027.72" importe="2027.72" />
  </cfdi:Conceptos>
  <cfdi:Impuestos totalImpuestosTrasladados="324.44">
    <cfdi:Traslados>
      <cfdi:Traslado impuesto="IVA" tasa="16.00" importe="324.44" />
    </cfdi:Traslados>
  </cfdi:Impuestos>
  <cfdi:Complemento>
    <tfd:TimbreFiscalDigital xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/TimbreFiscalDigital/TimbreFiscalDigital.xsd" version="1.0" UUID="A05C2BD0-6162-4690-BD53-9876CF51D68F" FechaTimbrado="2014-05-06T16:44:26" selloCFD="ToFyDe4el7/IRp+0w69m4a02ArMj2mWpOzvNq3KxXmIDrnF3N+hEj/YyyRuaP45Exg9e+scTQ0pEfaD5ejYz823OkryJpDdy0O7k1SizmsumOnfaY7D9uwr8W31fctv7mKISgFVb3WAOqnUezQGz6ONfnfT3zQ7gTiiA+0SwHso=" noCertificadoSAT="00001000000202639096" selloSAT="ez6xFxA9QqFPF2y0hix3yZvElNeX3EZaT5xOv5DlncB+bMYIps/2sTdoCjhq6U2sKyl03somlItxN/vE8F5I3VNq9P5pirBJ+LxAoBzyWa0ttisqRH3t27EAKD8NOi4Q6E/WM2HozszrRouXEW4TUMhHi5K+b8am/pEtuooWT2U=" />
  </cfdi:Complemento>
</cfdi:Comprobante>
Estuve averiguando y nada de nada que encontre en el foro.!
Adjunto la imagen, asi como se muestra en el dialogo, extraido los datos asi como al igual se podria ver en imagen antes de imprimir la factura que contiene el archivo xml, es por eso que preguntaba si alguien ya tiene esa herramienta de Visor xml.

Image
http://s1286.photobucket.com/user/ACC69 ... c.jpg.html


Saludos y buen dia.!

Atte: Adrian C. C.

Bueno por lo visto nadie ha hecho algo parecido , a lo que la imagen subi, y es lo que quiero hacer, y todos los ejemplos, la mayoria esta en xHarbour, ya que me cambie a Harbour...ufs volver a cambiar a xHarbour, esta como el include "hbxml.ch" que es de xharbour.

Y no logro dar con el resultado, en do while me lo extrae , me los lee bien los datos que segun yo necesito , aun me falta mas por saber de leer xml, y por lo tanto se me vino a la idea de AADD(aData, { oTagActual:GetAttribute("formaDePago") } ), usando con SCAN() y ahi la duda, como extraigo el dato del arreglo aData := ASCAN(aData,...aqui me pone nada), no muestra nada.
Alguien que haya podido leer xml extrayendo datos mostrando en una pantalla de dialogo ? asi como tambien al imprimir . Y en harbour no encontre documentacion referente de xml.

Saludos y buen dia.

Atte: Adrian C. C.

Re: Visor o leer XML

Posted: Fri Aug 15, 2014 4:05 am
by benjiben143
Hola

este pequeña funcion te puede servir

Code: Select all

Function main()
local  xfile:=memoread("filexml.xml")
local crfc, cnombre, ccalle, ccolonia
local cimporte

crfc    :=   regresa("rfc="+chr(34),chr(34), 1,xfile)
cnombre :=regresa("nombre="+chr(34),chr(34), 1,xfile)
ccalle  := regresa("calle="+chr(34),chr(34), 1,xfile)
ccolonia:=regresa("colonia="+chr(34),chr(34), 1,xfile)
cimporte:=regresa("importe="+chr(34),chr(34), 1,xfile)
? "rfc     "+crfc
? "nombre  "+cnombre
? "calle   "+ccalle
? "colonia "+ccolonia
? "importe "+cimporte

Return nil




Function regresa(textoi,textof, cpos, ctexto)
local dev:=""
local lcapta:=.f.
local i:=0
local n:=0
local lverdad:=.f.
local lerror:=.f.

ctexto:=ctexto+space(len(ctexto))
  for i:=1 to len(ctexto)
      if lverdad   // para empezar a tomar la informacion
         if substr(ctexto,i,1)=chr(34)   // esto es la terminacion de la toma de informacion
           // ? "salio y valor de "+textoi+" es de "+dev+" con tantos digitos "+str(n)
            exit   // salida del for next
         endif
         dev:=dev+substr(ctexto,i,1)
      endif
      
      if substr(ctexto,i,len(textoi))==textoi
         
         n:=0
         lverdad:=.t.   // para empezar a tomar la informacion okidoki
         n++
         i:=i+len(textoi)-1
      else
      endif
  next i

Return dev


 
pruebalo

saludos

Re: Visor o leer XML

Posted: Fri Aug 15, 2014 2:52 pm
by karinha

Re: Visor o leer XML

Posted: Fri Aug 15, 2014 3:05 pm
by benjiben143
hola

este ya trae

los datos separados de emisor receptor

y muestra el detalle de los impuestos y detalles de articulos

Code: Select all

// Pruebas
// benjamin casarrubias moreno
// 14/08/2014

#include "FiveWin.ch"
#include "xBrowse.ch"
#include "Constant.ch"

//----------------------------------------------------------------------------//
Function main()
local  xfile:=memoread("benji.xml")
local crfc, cnombre, ccalle, ccolonia
local cimporte
local receptor
local detalles
local impuestos
local crrfc, crnombre, crcalle

crfc    :=regresa("rfc="+chr(34),chr(34), 1,xfile)
cnombre :=regresa("nombre="+chr(34),chr(34), 1,xfile)
ccalle  :=regresa("calle="+chr(34),chr(34), 1,xfile)
ccolonia:=regresa("colonia="+chr(34),chr(34), 1,xfile)
cimporte:=regresa("importe="+chr(34),chr(34), 1,xfile)

? "emisor rfc     "+crfc
? "emirsor nombre  "+cnombre
? "emisor calle   "+ccalle
? "emisor colonia "+ccolonia
? "emisor importe "+cimporte

receptor:=partir("Receptor","Receptor>",xfile)
crrfc    :=regresa("rfc="+chr(34),chr(34), 1,receptor)
crnombre :=regresa("nombre="+chr(34),chr(34), 1,receptor)
crcalle  :=regresa("calle="+chr(34),chr(34), 1,receptor)

? "receptor rfc "+crrfc
? "recepcor nombre "+crnombre
? "receptor calle "+crcalle

detalles:=partir("<cfdi:Conceptos>","</cfdi:Conceptos>",xfile)
? detalles

impuestos:=partir("<cfdi:Traslados>","</cfdi:Traslados>",xfile)
? impuestos




Return nil




Function regresa(textoi,textof, cpos, ctexto)
local dev:=""
local lcapta:=.f.
local i:=0
local n:=0
local lverdad:=.f.
local lerror:=.f.

ctexto:=ctexto+space(len(ctexto))
  for i:=1 to len(ctexto)
      if lverdad   // para empezar a tomar la informacion
         if substr(ctexto,i,1)=chr(34)   // esto es la terminacion de la toma de informacion
           // ? "salio y valor de "+textoi+" es de "+dev+" con tantos digitos "+str(n)
            exit   // salida del for next
         endif
         dev:=dev+substr(ctexto,i,1)
      endif
      
      if substr(ctexto,i,len(textoi))==textoi
         
         n:=0
         lverdad:=.t.   // para empezar a tomar la informacion okidoki
         n++
         i:=i+len(textoi)-1
      else
      endif
  next i

Return dev


Function partir(textoi,textof,ctexto)
local dev:=""
local lcapta:=.f.
local i:=0
local n:=0
local lverdad:=.f.
local lerror:=.f.

ctexto:=ctexto+space(len(ctexto))
  for i:=1 to len(ctexto)
      if lverdad   // para empezar a tomar la informacion
         if substr(ctexto,i,len(textof))=textof   // esto es la terminacion de la toma de informacion
           // ? "salio y valor de "+textoi+" es de "+dev+" con tantos digitos "+str(n)
            exit   // salida del for next
         endif
         dev:=dev+substr(ctexto,i,1)
      endif
      
      if substr(ctexto,i,len(textoi))==textoi
         
         n:=0
         lverdad:=.t.   // para empezar a tomar la informacion okidoki
         n++
         i:=i+len(textoi)-1
      else
      endif
  next i

Return dev




 

Re: Visor o leer XML

Posted: Fri Aug 15, 2014 4:03 pm
by derpipu
Hola, yo resolvi esto pues de alguna forma leyendo posts del foro y de otra pos quebrandome la cabeza, les pongo mi codigo completo de mi sistema para leer xmls y sacar informacion relevante para mis necesidades...

Aclaro que leo XML generados por sistemas de Facturacion Electronica para México.

Uso TArray para acumular los registros en memoria antes de arrojarlos a un archivo de Excel

El sistema funcional esta en: http://www.csoluciones.com.mx/descargas/LeeXML.Exe

Espero les sirva el sistema

Code: Select all


/* 
DESARROLLADO POR: LUIS FERNANDO RUBIO RUBIO
CONTACTO: fernando@csoluciones.com.mx
*/

#include "fivewin.ch"
#include "directry.ch"
#include "tarray.ch"

#DEFINE PAD_LEFT        0
#DEFINE PAD_RIGHT       1
#DEFINE PAD_CENTER      2

// Line styles
#DEFINE xlContinuous    1
#DEFINE xlDash          -4115
#DEFINE xlDashDot       4
#DEFINE xlDashDotDot    5
#DEFINE xlDot           -4118
#DEFINE xlDouble        -4119
#DEFINE xlSlantDashDot  13
#DEFINE xlLineStyleNone -4142

// Border positions
#DEFINE xlEdgeLeft      7
#DEFINE xlEdgeTop       8
#DEFINE xlEdgeBottom    9
#DEFINE xlEdgeRight     10

// Alineacion Horizontal
#DEFINE xlHorRight      -4152
#DEFINE xlHorLeft       -4131
#DEFINE xlHorCenter     -4108
#DEFINE xlHorJust       -4130
#DEFINE xlHorCombCen    7

FUNCTION Main( pcDirTrabajo )
  LOCAL hFile
  LOCAL aFileXML
  LOCAL oXmlDoc, oXmlIter, oTagActual
  LOCAL lRenombrar := .F.
  DEFAULT pcDirTrabajo := cFilePath( GetModuleFileName( GetInstance( ) ) )

  IF MsgNoYes( "El directorio de trabajo actual es: " + pcDirTrabajo + ", desea seleccionar otro diferente ?", "LeeXML" )
    IF EMPTY( pcDirTrabajo := cGetDir32( "Seleccione el directorio de trabajo...", pcDirTrabajo ) )
      MsgStop( "No selecciono ningun directorio de trabajo...", "LeeXML" ); RETURN(NIL)
    ENDIF
    pcDirTrabajo += "\"
  ENDIF

  lRenombrar := MsgYesNo( "Desea renombrar los archivos con un formato mas entendible visualmente ?", "LeeXML" )

  oDatos := NIL
  DEFINE STRUCT oDatos
    STRUCT FIELD cEmiNom   INIT ""
    STRUCT FIELD cEmiRFC   INIT ""
    STRUCT FIELD cRecNom   INIT ""
    STRUCT FIELD cRecRFC   INIT ""
    STRUCT FIELD cTipoCo   INIT ""
    STRUCT FIELD cFecha    INIT ""
    STRUCT FIELD cSerie    INIT ""
    STRUCT FIELD cFolio    INIT ""

    STRUCT FIELD cMoneda   INIT ""
    STRUCT FIELD cTCambio  INIT ""
    STRUCT FIELD cfPago    INIT ""
    STRUCT FIELD cmPago    INIT ""
    STRUCT FIELD cCtaPago  INIT ""

    STRUCT FIELD nSubtot   INIT 0.0000
    STRUCT FIELD nTotIT    INIT 0.0000
    STRUCT FIELD nTotIR    INIT 0.0000
    STRUCT FIELD nTotal    INIT 0.0000

    STRUCT FIELD cOrden    INIT ""

  END STRUCT
  oDatos:Zap()

  aFileXML := Directory( pcDirTrabajo + "*.XML" )

  FOR x := 1 TO LEN( aFileXML )

    hFile    := FOpen( pcDirTrabajo + aFileXML[x, F_NAME] )
    oXmlDoc  := TXmlDocument():New( hFile )
    oXmlIter := TXmlIterator():New( oXmlDoc:oRoot )

    cTagName := ""
    cTagData := ""

    oDatos:Blank()

    DO WHILE .T.
        oTagActual = oXmlIter:Next()
        IF oTagActual != NIL

            cTagName := oTagActual:cName
            cTagData := oTagActual:cData

            HEval( oTagActual:aAttributes, { | cKey, cValue | f_Guarda_XML_Valores( oDatos, cKey, cValue, oTagActual:cName ) } )

        ELSE
            Exit
        ENDIF
    ENDDO

    oDatos:cOrden := oDatos:cEmiRFC + oDatos:cFecha
    oDatos:Add()

    FClose( hFile )

    IF lRenombrar
      FRENAME( pcDirTrabajo + cFileNoExt( aFileXML[x, F_NAME] ) + ".XML", pcDirTrabajo + SUBSTR( oDatos:cFecha, 1, 10 ) + "_" + oDatos:cEmiRFC + "_" + ALLTRIM(oDatos:cSerie) + ALLTRIM(oDatos:cFolio) + "_" + oDatos:cRecRFC + ".XML" )
      FRENAME( pcDirTrabajo + cFileNoExt( aFileXML[x, F_NAME] ) + ".PDF", pcDirTrabajo + SUBSTR( oDatos:cFecha, 1, 10 ) + "_" + oDatos:cEmiRFC + "_" + ALLTRIM(oDatos:cSerie) + ALLTRIM(oDatos:cFolio) + "_" + oDatos:cRecRFC + ".PDF" )
    ENDIF

  NEXT

  IF LEN(oDatos:aDatos) = 0
    MsgStop("No se encontraron archivos XML en el directorio, verifique...", "LeeXML")
    RETURN(NIL)
  ENDIF

  oDatos:Sort("corden")
  oDatos:GoTop()

  cTitulo := "Reporte de XML'S"
  cRango1 := pcDirTrabajo
  cRango2 := ""

  aTitulos := { cTitulo, cRango1, cRango2 }
  aDatos   := { { "emisor",        "ceminom",  .F., "IZQ", .F. },;
                { "rfc emisor",    "cemirfc",  .F., "IZQ", .F. },;
                { "receptor",      "crecnom",  .F., "IZQ", .F. },;
                { "rfc receptor",  "crecrfc",  .F., "IZQ", .F. },;
                { "tipo",          "ctipoco",  .F., "IZQ", .F. },;
                { "fecha",         "cfecha",   .F., "IZQ", .F. },;
                { "serie",         "cserie",   .F., "IZQ", .F. },;
                { "folio",         "cfolio",   .F., "IZQ", .F. },;
                { "moneda",        "cmoneda",  .F., "IZQ", .F. },;
                { "tcambio",       "ctcambio", .F., "DER", .F. },;
                { "f.pago",        "cfpago",   .F., "IZQ", .F. },;
                { "m.pago",        "cmpago",   .F., "IZQ", .F. },;
                { "cta.pago",      "cctapago", .F., "IZQ", .F. },;
                { "subtotal",      "nsubtot",  .F., "DER", .T. },;
                { "i.trasla",      "ntotit",   .F., "DER", .T. },;
                { "i.reteni",      "ntotir",   .F., "DER", .T. },;
                { "total",         "ntotal",   .F., "DER", .T. } }

  MsgMeter( { | oMeter, oText, oDlg, lEnd | _ToExcel(  oMeter, oText, oDlg, @lEnd, oDatos, aTitulos, aDatos ) },;
            "Procesando Reporte: "  + aTitulos[1] + CRLF + "Por favor sea paciente se procesaran " + ALLTRIM( TRANSFORM( LEN( oDatos:aDatos ), "999,999,999" ) ) + " registro(s)...", "LeeXML" )


RETURN(NIL)

FUNCTION f_Guarda_XML_Valores( poDatos, pcKey, pcValue, pcTagName )
   //? cTagName, cTagData, pcKey, pcValue
  //? pcTagName, pcKey, pcValue

  IF       UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="MONEDA";                    poDatos:cMoneda  := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="NUMCTAPAGO";                poDatos:cCtaPago := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="TIPOCAMBIO";                poDatos:cTCambio := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="FECHA";                     poDatos:cFecha   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="FOLIO";                     poDatos:cFolio   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="FORMADEPAGO";               poDatos:cfPago   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="METODODEPAGO";              poDatos:cmPago   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="SERIE";                     poDatos:cSerie   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="SUBTOTAL";                  poDatos:nSubtot  := VAL(pcValue)
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="TOTAL";                     poDatos:nTotal   := VAL(pcValue)
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="TIPODECOMPROBANTE";         poDatos:cTipoCo  := pcValue

    // EMISOR
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:EMISOR,EMISOR"           .AND. UPPER(ALLTRIM(pcKey))="NOMBRE";                    poDatos:cEmiNom  := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:EMISOR,EMISOR"           .AND. UPPER(ALLTRIM(pcKey))="RFC";                       poDatos:cEmiRFC  := pcValue

    // RECEPTOR
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:RECEPTOR,RECEPTOR"       .AND. UPPER(ALLTRIM(pcKey))="NOMBRE";                    poDatos:cRecNom  := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:RECEPTOR,RECEPTOR"       .AND. UPPER(ALLTRIM(pcKey))="RFC";                       poDatos:cRecRFC  := pcValue

    // IMPUESTOS
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:IMPUESTOS,IMPUESTOS"     .AND. UPPER(ALLTRIM(pcKey))="TOTALIMPUESTOSTRASLADADOS"; poDatos:nTotIT   := VAL(pcValue)
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:IMPUESTOS,IMPUESTOS"     .AND. UPPER(ALLTRIM(pcKey))="TOTALIMPUESTOSRETENIDOS";   poDatos:nTotIR   := VAL(pcValue)

  ENDIF

RETURN(NIL)

/*
 poDatos   := Objeto TArray con la informacion recopilada y que se mostrara en el libro de Excel
 paDatos   := { { "enc1", campo1, .F., "CEN", .T. }, { "enc2", campo2, .T., "IZQ", .F. }, { "enc3", campo3, .T., "DER", .T. }... }
              donde el primer parametro es:  el nombre del encabezado
                    el segundo parametro es: el campo del Tarray
                    el tercer parametro es:  la alineacion del dato en general
                    el cuarto parametro es:  si se muestra el total de la columna
                    el quinto parametro es:  si se totalizara la columna
 paTitulos := { cReporte, cRango, cRango2 }
*/

FUNCTION _ToExcel( poMeter, poText, poDlg, plEnd, poDatos, paTitulos, paDatos, pcFile )
  LOCAL oExcel := nil, oHoja := nil, nLinea := 0, oWorkBook := NIL
  LOCAL oError := NIL
  LOCAL nTotal := LEN(poDatos:aDatos)
  DEFAULT pcFile := ""

  TRY
    oExcel   := ExcelObj()//CreateObject( "Excel.Application" )
  CATCH
    MsgInfo( "Excel no esta Instalado en el equipo, verifique...", "Error de Excel" ); RETURN(nil)
  END

  TRY

      poMeter:SetTotal(nTotal)

      WITH OBJECT oExcel

          WITH OBJECT oWorkBook := oExcel:WorkBooks:Add()
              :BuiltinDocumentProperties("Author"):Value   := "CSOLUCIONES"
              :BuiltinDocumentProperties("Title"):Value    := "PROPIEDAD DE CSOLUCIONES"
              :BuiltinDocumentProperties("Comments"):Value := "PROHIBIDA SU COPIA O REPRODUCCION, DERECHOS RESERVADOS"
          END WITH

          WITH OBJECT oHoja := oExcel:Get( "ActiveSheet" )

              // Aqui definimos en general cual sera el tama;o de las fuentes en todas las celdas
              :Cells:Font:Size := 08
              :Cells:Font:Name := "Lucida Console"

              nxPosTitCen := ROUND( LEN(paDatos) / 2, 0 )
              nxPosTitDer := 1
              nxPosTitIzq := IIF( LEN(paDatos) == nxPosTitCen, LEN(paDatos) + 1, LEN(paDatos) )

              nLinea ++
              :Cells( nLinea, nxPosTitIzq ):Value := time()
              :Cells( nLinea, nxPosTitIzq ):Font:Size := 12
              :Cells( nLinea, nxPosTitIzq ):Font:Name := "Lucida Console"
              :Cells( nLinea, nxPosTitIzq ):Set( "HorizontalAlignment", xlHorJust )

              :Cells( nLinea, nxPosTitCen ):Value := "cSoluciones ®"
              :Cells( nLinea, nxPosTitCen ):Font:Size := 14
              :Cells( nLinea, nxPosTitCen ):Font:Name := "Lucida Console"
              :Cells( nLinea, nxPosTitCen ):Font:Bold := .T.
              :Cells( nLinea, nxPosTitCen ):Set( "HorizontalAlignment", xlHorCombCen )

              :Cells( nLinea, nxPosTitDer ):Value := dtoc(date())
              :Cells( nLinea, nxPosTitDer ):Font:Size := 12
              :Cells( nLinea, nxPosTitDer ):Font:Name := "Lucida Console"
              :Cells( nLinea, nxPosTitDer ):Set( "HorizontalAlignment", xlHorJust )

              FOR x := 1 TO LEN(paTitulos)

                  IF ! EMPTY(paTitulos[x])
                    nLinea ++
                    :Cells( nLinea, nxPosTitCen ):Value := paTitulos[x]
                    :Cells( nLinea, nxPosTitCen ):Font:Size := 14
                    :Cells( nLinea, nxPosTitCen ):Font:Name := "Lucida Console"
                    :Cells( nLinea, nxPosTitCen ):Font:Bold := .T.
                    :Cells( nLinea, nxPosTitCen ):Set( "HorizontalAlignment", xlHorCombCen )
                  ENDIF

              NEXT

            // ahora imprimimos el encabezado de la lista
              nLinea ++
              nLinea ++

              FOR x := 1 TO LEN(paDatos)

                // AQUI IMPRIMIMOS EL TITULO
                :Cells( nLinea, x ):Value := paDatos[x,1]
                :Cells( nLinea, x ):Font:Bold := .T.

                :Range( cXlsColToLet(x) + STRZERO( nLinea, 2 ) ):Borders( xlEdgeTop ):LineStyle := xlDouble //xlDot

                // AQUI SELECCIONAMOS LA ALINEACION HORIZONTAL DEL TITULO
                DO CASE
                  CASE UPPER(paDatos[x,4])$"CEN"; :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter )
                  CASE UPPER(paDatos[x,4])$"IZQ"; :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorLeft   )
                  CASE UPPER(paDatos[x,4])$"DER"; :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorRight  )
                  OTHERWISE;                      :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter )
                ENDCASE

              NEXT

              nRenInicia := 0
              aCamposTot := {} //{ 03,  05,  11,  13,  14  }
              aCamposLet := {} //{ "C", "E", "K", "M", "N" }
              acPosSum   := {} //{ "",  "",  "",   "",  "" }

              FOR x := 1 TO LEN(paDatos)
                IF VALTYPE( paDatos[x,5] )$"L"
                    IF paDatos[x,5]
                        //? x, cXlsColToLet(x)
                        AADD( aCamposTot, x )
                        AADD( aCamposLet, cXlsColToLet(x) )
                        AADD( acPosSum,   "" )

                    ENDIF
                ENDIF
              NEXT

              nLinea ++
              nLinea ++
              nRenInicia := nLinea

              TRY

                  poDatos:GoTop()
                  DO WHILE  ! poDatos:Eof()

                    poMeter:Set(poDatos:Recno())

                    FOR x := 1 TO LEN(paDatos)

                        :Cells( nLinea, x ):Value     := poDatos:FieldGetByName( paDatos[x,2] )
                        :Cells( nLinea, x ):Font:Bold := paDatos[x,3]

                        // aqui agregamos comentarios a las celdas si es necesario
                        //:Cells( nLinea, x ):AddComment()
                        //:Cells( nLinea, x ):Comment:Text( ALLTRIM( "pruebas" + str(x) ) )

                        // aqui definimos la mascara para que imprima los datos
                        DO CASE
                          CASE VALTYPE( poDatos:FieldGetByName( paDatos[x,2] ) )$"D"; :Cells( nLinea, x ):Set( "NumberFormat",        "dd/mm/aaaa"     )
                          CASE VALTYPE( poDatos:FieldGetByName( paDatos[x,2] ) )$"N"; :Cells( nLinea, x ):Set( "NumberFormat",        "#,###,##0.0000" )
                          CASE VALTYPE( poDatos:FieldGetByName( paDatos[x,2] ) )$"C"; :Cells( nLinea, x ):Set( "NumberFormat",        "@"              )
                        ENDCASE

                        // AQUI SELECCIONAMOS LA ALINEACION HORIZONTAL
                        DO CASE
                          CASE UPPER(paDatos[x,4])$"CEN";                             :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter      )
                          CASE UPPER(paDatos[x,4])$"IZQ";                             :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorLeft        )
                          CASE UPPER(paDatos[x,4])$"DER";                             :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorRight       )
                          OTHERWISE;                                                  :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter      )
                        ENDCASE
                    NEXT

                    nLinea ++
                    poDatos:Skip(1)

                  ENDDO

              CATCH oError
                MsgStop( "Error de datos, verifique el archivo creado..." + CRLF +;
                          "Error: "     + CHR(9) + TRANSFORM( oError:GenCode,   NIL) + CRLF +;
                          "SubC: "      + CHR(9) + TRANSFORM( oError:SubCode,   NIL) + CRLF +;
                          "OSCode: "    + CHR(9) + TRANSFORM( oError:OsCode,    NIL) + CRLF +;
                          "SubSystem: " + CHR(9) + TRANSFORM( oError:SubSystem, NIL) + CRLF +;
                          "Mensaje: "   + CHR(9) + oError:Description, "LeeXML" )
              END


              // si se selecciono que quieren totales se muestran en las columnas requeridas...
              nLinea ++
              FOR x := 1 TO LEN(aCamposTot)

                  :Range( cXlsColToLet(aCamposTot[x]) + ALLTRIM(STR( nLinea) ) ):Borders( xlEdgeTop ):LineStyle := xlDouble //xlDot
                  :Cells( nLinea, aCamposTot[x] ):Value := "=@SUMA(" + cXlsColToLet(aCamposTot[x]) + ALLTRIM( STR( nRenInicia ) ) + ":" + cXlsColToLet(aCamposTot[x]) + ALLTRIM( STR( nLinea - 2 ) ) + ")"
                  :Cells( nLinea, aCamposTot[x] ):Set( "NumberFormat", "#,###,##0.0000" )
                  //:Range( aCamposLet[x] + ALLTRIM(STR(nlinea)) + ":" + aCamposLet[x] + ALLTRIM(STR(nlinea)) ):Interior:Color := CLR_YELLOW

                  //acPosSum[x] += ( aCamposLet[x] + ALLTRIM(STR(nLinea)) + IIF( ! oDatos:Eof(), ",", "" ) )

              NEXT

              nLinea ++
              nLinea ++

              :Cells( nLinea, 1 ):Value := ALLTRIM( TRANSFORM( LEN( poDatos:aDatos ), "999,999,999" ) ) + " registro(s) procesados..."

              IF ! EMPTY(pcFile)
                oWorkBook:SaveAS( ALLTRIM( pcFile ) )
              ENDIF

          END WITH // oHoja

          poMeter:Set( nTotal )

          :Visible := .T.

      END WITH // oexcel



  CATCH oError
      MsgStop( "Error :" + oError:Description, "LeeXML" )
  END


  oHoja := nil
  oExcel := nil

RETURN(NIL)

FUNCTION cXlsColToLet(pnCol)
  LOCAL cLetra := ""

  DO CASE
    CASE pnCol = 1;  cLetra := "A"
    CASE pnCol = 2;  cLetra := "B"
    CASE pnCol = 3;  cLetra := "C"
    CASE pnCol = 4;  cLetra := "D"
    CASE pnCol = 5;  cLetra := "E"
    CASE pnCol = 6;  cLetra := "F"
    CASE pnCol = 7;  cLetra := "G"
    CASE pnCol = 8;  cLetra := "H"
    CASE pnCol = 9;  cLetra := "I"
    CASE pnCol = 10; cLetra := "J"
    CASE pnCol = 11; cLetra := "K"
    CASE pnCol = 12; cLetra := "L"
    CASE pnCol = 13; cLetra := "M"
    CASE pnCol = 14; cLetra := "N"
    CASE pnCol = 15; cLetra := "O"
    CASE pnCol = 16; cLetra := "P"
    CASE pnCol = 17; cLetra := "Q"
    CASE pnCol = 18; cLetra := "R"
    CASE pnCol = 19; cLetra := "S"
    CASE pnCol = 20; cLetra := "T"
    CASE pnCol = 21; cLetra := "U"
    CASE pnCol = 22; cLetra := "V"
    CASE pnCol = 23; cLetra := "W"
    CASE pnCol = 24; cLetra := "X"
    CASE pnCol = 25; cLetra := "Y"
    CASE pnCol = 26; cLetra := "Z"
  ENDCASE

RETURN(cLetra)

FUNCTION nXlsLetToCol( pcLet )
  LOCAL nNum := 0

  DO CASE
    CASE pcLet$"A"; nNum := 1
    CASE pcLet$"B"; nNum := 2
    CASE pcLet$"C"; nNum := 3
    CASE pcLet$"D"; nNum := 4
    CASE pcLet$"E"; nNum := 5
    CASE pcLet$"F"; nNum := 6
    CASE pcLet$"G"; nNum := 7
    CASE pcLet$"H"; nNum := 8
    CASE pcLet$"I"; nNum := 9
    CASE pcLet$"J"; nNum := 10
    CASE pcLet$"K"; nNum := 11
    CASE pcLet$"L"; nNum := 12
    CASE pcLet$"M"; nNum := 13
    CASE pcLet$"N"; nNum := 14
    CASE pcLet$"O"; nNum := 15
    CASE pcLet$"P"; nNum := 16
    CASE pcLet$"Q"; nNum := 17
    CASE pcLet$"R"; nNum := 18
    CASE pcLet$"S"; nNum := 19
    CASE pcLet$"T"; nNum := 20
    CASE pcLet$"U"; nNum := 21
    CASE pcLet$"V"; nNum := 22
    CASE pcLet$"W"; nNum := 23
    CASE pcLet$"X"; nNum := 24
    CASE pcLet$"Y"; nNum := 25
    CASE pcLet$"Z"; nNum := 26
  ENDCASE

RETURN(nNum)

Re: Visor o leer XML

Posted: Mon Aug 18, 2014 4:07 pm
by ACC69
Hola buenos dias,mil disculpas, apenas voy entrando al foro y revisando mensajes.

De antemano les envio cordial saludos.

Gracias Ing. Benji por la rutina, al igual gracias al Ing. Luis Fernando,y creo que mejor opto por la rutina del Ing. Luis Fernando.

Ing. Luis Fernando, una preguntita mas!, cual es el equivalente de TArray, ya que no cuento con esta clase de TArray, que segun funciona como temporal, que se guarda registros,a ver si lo encuentro en el foro esta clase TArray,que no sabia que existia,pero si me gustaria saber el equivalente de TArray, ya que tenia en mente crear como arreglos con la funcion de AADD(),pero ya estare trabajando en estos dias , adaptando a mi sistema tu codigo completo, gracias de nuevo Ing. Luis Fernando.

Saludos y buen dia.!

Atte: Adrian C. C.
acc69@hotmail.com

Re: Visor o leer XML

Posted: Mon Aug 18, 2014 6:06 pm
by karinha
Luis Fernando, podria poner aca un ejemplo de archivo.xml que funcione con esta function, porfa?

Code: Select all

/*
DESARROLLADO POR: LUIS FERNANDO RUBIO RUBIO
CONTACTO: fernando@csoluciones.com.mx
*/

#include "fivewin.ch"
#include "directry.ch"
#include "tarray.ch"
#include "objects.ch"

#DEFINE PAD_LEFT        0
#DEFINE PAD_RIGHT       1
#DEFINE PAD_CENTER      2

// Line styles
#DEFINE xlContinuous    1
#DEFINE xlDash          -4115
#DEFINE xlDashDot       4
#DEFINE xlDashDotDot    5
#DEFINE xlDot           -4118
#DEFINE xlDouble        -4119
#DEFINE xlSlantDashDot  13
#DEFINE xlLineStyleNone -4142

// Border positions
#DEFINE xlEdgeLeft      7
#DEFINE xlEdgeTop       8
#DEFINE xlEdgeBottom    9
#DEFINE xlEdgeRight     10

// Alineacion Horizontal
#DEFINE xlHorRight      -4152
#DEFINE xlHorLeft       -4131
#DEFINE xlHorCenter     -4108
#DEFINE xlHorJust       -4130
#DEFINE xlHorCombCen    7

STATIC oTArrayTmp := {}

FUNCTION Main( pcDirTrabajo )
  LOCAL hFile
  LOCAL aFileXML
  LOCAL oXmlDoc, oXmlIter, oTagActual
  LOCAL lRenombrar := .F.
  DEFAULT pcDirTrabajo := cFilePath( GetModuleFileName( GetInstance( ) ) )

  IF MsgNoYes( "El directorio de trabajo actual es: " + pcDirTrabajo + ", desea seleccionar otro diferente ?", "LeeXML" )
    IF EMPTY( pcDirTrabajo := cGetDir32( "Seleccione el directorio de trabajo...", pcDirTrabajo ) )
      MsgStop( "No selecciono ningun directorio de trabajo...", "LeeXML" ); RETURN(NIL)
    ENDIF
    pcDirTrabajo += "\"
  ENDIF

  lRenombrar := MsgYesNo( "Desea renombrar los archivos con un formato mas entendible visualmente ?", "LeeXML" )

  oDatos := NIL
  DEFINE STRUCT oDatos

    STRUCT FIELD cEmiNom   INIT ""
    STRUCT FIELD cEmiRFC   INIT ""
    STRUCT FIELD cRecNom   INIT ""
    STRUCT FIELD cRecRFC   INIT ""
    STRUCT FIELD cTipoCo   INIT ""
    STRUCT FIELD cFecha    INIT ""
    STRUCT FIELD cSerie    INIT ""
    STRUCT FIELD cFolio    INIT ""

    STRUCT FIELD cMoneda   INIT ""
    STRUCT FIELD cTCambio  INIT ""
    STRUCT FIELD cfPago    INIT ""
    STRUCT FIELD cmPago    INIT ""
    STRUCT FIELD cCtaPago  INIT ""

    STRUCT FIELD nSubtot   INIT 0.0000
    STRUCT FIELD nTotIT    INIT 0.0000
    STRUCT FIELD nTotIR    INIT 0.0000
    STRUCT FIELD nTotal    INIT 0.0000

    STRUCT FIELD cOrden    INIT ""

  END STRUCT
  oDatos:Zap()

  aFileXML := Directory( pcDirTrabajo + "*.XML" )

  FOR x := 1 TO LEN( aFileXML )

    hFile    := FOpen( pcDirTrabajo + aFileXML[x, F_NAME] )
    oXmlDoc  := TXmlDocument():New( hFile )
    oXmlIter := TXmlIterator():New( oXmlDoc:oRoot )

    cTagName := ""
    cTagData := ""

    oDatos:Blank()

    DO WHILE .T.
        oTagActual = oXmlIter:Next()
        IF oTagActual != NIL

            cTagName := oTagActual:cName
            cTagData := oTagActual:cData

            HEval( oTagActual:aAttributes, { | cKey, cValue | f_Guarda_XML_Valores( oDatos, cKey, cValue, oTagActual:cName ) } )

        ELSE
            Exit
        ENDIF
    ENDDO

    oDatos:cOrden := oDatos:cEmiRFC + oDatos:cFecha
    oDatos:Add()

    FClose( hFile )

    IF lRenombrar
      FRENAME( pcDirTrabajo + cFileNoExt( aFileXML[x, F_NAME] ) + ".XML", pcDirTrabajo + SUBSTR( oDatos:cFecha, 1, 10 ) + "_" + oDatos:cEmiRFC + "_" + ALLTRIM(oDatos:cSerie) + ALLTRIM(oDatos:cFolio) + "_" + oDatos:cRecRFC + ".XML" )
      FRENAME( pcDirTrabajo + cFileNoExt( aFileXML[x, F_NAME] ) + ".PDF", pcDirTrabajo + SUBSTR( oDatos:cFecha, 1, 10 ) + "_" + oDatos:cEmiRFC + "_" + ALLTRIM(oDatos:cSerie) + ALLTRIM(oDatos:cFolio) + "_" + oDatos:cRecRFC + ".PDF" )
    ENDIF

  NEXT

  IF LEN(oDatos:aDatos) = 0
    MsgStop("No se encontraron archivos XML en el directorio, verifique...", "LeeXML")
    RETURN(NIL)
  ENDIF

  oDatos:Sort("corden")
  oDatos:GoTop()

  cTitulo := "Reporte de XML'S"
  cRango1 := pcDirTrabajo
  cRango2 := ""

  aTitulos := { cTitulo, cRango1, cRango2 }
  aDatos   := { { "emisor",        "ceminom",  .F., "IZQ", .F. },;
                { "rfc emisor",    "cemirfc",  .F., "IZQ", .F. },;
                { "receptor",      "crecnom",  .F., "IZQ", .F. },;
                { "rfc receptor",  "crecrfc",  .F., "IZQ", .F. },;
                { "tipo",          "ctipoco",  .F., "IZQ", .F. },;
                { "fecha",         "cfecha",   .F., "IZQ", .F. },;
                { "serie",         "cserie",   .F., "IZQ", .F. },;
                { "folio",         "cfolio",   .F., "IZQ", .F. },;
                { "moneda",        "cmoneda",  .F., "IZQ", .F. },;
                { "tcambio",       "ctcambio", .F., "DER", .F. },;
                { "f.pago",        "cfpago",   .F., "IZQ", .F. },;
                { "m.pago",        "cmpago",   .F., "IZQ", .F. },;
                { "cta.pago",      "cctapago", .F., "IZQ", .F. },;
                { "subtotal",      "nsubtot",  .F., "DER", .T. },;
                { "i.trasla",      "ntotit",   .F., "DER", .T. },;
                { "i.reteni",      "ntotir",   .F., "DER", .T. },;
                { "total",         "ntotal",   .F., "DER", .T. } }

  MsgMeter( { | oMeter, oText, oDlg, lEnd | _ToExcel(  oMeter, oText, oDlg, @lEnd, oDatos, aTitulos, aDatos ) },;
            "Procesando Reporte: "  + aTitulos[1] + CRLF + "Por favor sea paciente se procesaran " + ALLTRIM( TRANSFORM( LEN( oDatos:aDatos ), "999,999,999" ) ) + " registro(s)...", "LeeXML" )


RETURN(NIL)

FUNCTION f_Guarda_XML_Valores( poDatos, pcKey, pcValue, pcTagName )
   //? cTagName, cTagData, pcKey, pcValue
  //? pcTagName, pcKey, pcValue

  IF       UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="MONEDA";                    poDatos:cMoneda  := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="NUMCTAPAGO";                poDatos:cCtaPago := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="TIPOCAMBIO";                poDatos:cTCambio := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="FECHA";                     poDatos:cFecha   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="FOLIO";                     poDatos:cFolio   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="FORMADEPAGO";               poDatos:cfPago   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="METODODEPAGO";              poDatos:cmPago   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="SERIE";                     poDatos:cSerie   := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="SUBTOTAL";                  poDatos:nSubtot  := VAL(pcValue)
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="TOTAL";                     poDatos:nTotal   := VAL(pcValue)
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:COMPROBANTE,COMPROBANTE" .AND. UPPER(ALLTRIM(pcKey))="TIPODECOMPROBANTE";         poDatos:cTipoCo  := pcValue

    // EMISOR
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:EMISOR,EMISOR"           .AND. UPPER(ALLTRIM(pcKey))="NOMBRE";                    poDatos:cEmiNom  := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:EMISOR,EMISOR"           .AND. UPPER(ALLTRIM(pcKey))="RFC";                       poDatos:cEmiRFC  := pcValue

    // RECEPTOR
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:RECEPTOR,RECEPTOR"       .AND. UPPER(ALLTRIM(pcKey))="NOMBRE";                    poDatos:cRecNom  := pcValue
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:RECEPTOR,RECEPTOR"       .AND. UPPER(ALLTRIM(pcKey))="RFC";                       poDatos:cRecRFC  := pcValue

    // IMPUESTOS
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:IMPUESTOS,IMPUESTOS"     .AND. UPPER(ALLTRIM(pcKey))="TOTALIMPUESTOSTRASLADADOS"; poDatos:nTotIT   := VAL(pcValue)
    ELSEIF UPPER(ALLTRIM(pcTagName))$"CFDI:IMPUESTOS,IMPUESTOS"     .AND. UPPER(ALLTRIM(pcKey))="TOTALIMPUESTOSRETENIDOS";   poDatos:nTotIR   := VAL(pcValue)

  ENDIF

RETURN(NIL)

/*
 poDatos   := Objeto TArray con la informacion recopilada y que se mostrara en el libro de Excel
 paDatos   := { { "enc1", campo1, .F., "CEN", .T. }, { "enc2", campo2, .T., "IZQ", .F. }, { "enc3", campo3, .T., "DER", .T. }... }
              donde el primer parametro es:  el nombre del encabezado
                    el segundo parametro es: el campo del Tarray
                    el tercer parametro es:  la alineacion del dato en general
                    el cuarto parametro es:  si se muestra el total de la columna
                    el quinto parametro es:  si se totalizara la columna
 paTitulos := { cReporte, cRango, cRango2 }
*/

FUNCTION _ToExcel( poMeter, poText, poDlg, plEnd, poDatos, paTitulos, paDatos, pcFile )
  LOCAL oExcel := nil, oHoja := nil, nLinea := 0, oWorkBook := NIL
  LOCAL oError := NIL
  LOCAL nTotal := LEN(poDatos:aDatos)
  DEFAULT pcFile := ""

  TRY
    oExcel   := ExcelObj()//CreateObject( "Excel.Application" )
  CATCH
    MsgInfo( "Excel no esta Instalado en el equipo, verifique...", "Error de Excel" ); RETURN(nil)
  END

  TRY

      poMeter:SetTotal(nTotal)

      WITH OBJECT oExcel

          WITH OBJECT oWorkBook := oExcel:WorkBooks:Add()
              :BuiltinDocumentProperties("Author"):Value   := "CSOLUCIONES"
              :BuiltinDocumentProperties("Title"):Value    := "PROPIEDAD DE CSOLUCIONES"
              :BuiltinDocumentProperties("Comments"):Value := "PROHIBIDA SU COPIA O REPRODUCCION, DERECHOS RESERVADOS"
          END WITH

          WITH OBJECT oHoja := oExcel:Get( "ActiveSheet" )

              // Aqui definimos en general cual sera el tama;o de las fuentes en todas las celdas
              :Cells:Font:Size := 08
              :Cells:Font:Name := "Lucida Console"

              nxPosTitCen := ROUND( LEN(paDatos) / 2, 0 )
              nxPosTitDer := 1
              nxPosTitIzq := IIF( LEN(paDatos) == nxPosTitCen, LEN(paDatos) + 1, LEN(paDatos) )

              nLinea ++
              :Cells( nLinea, nxPosTitIzq ):Value := time()
              :Cells( nLinea, nxPosTitIzq ):Font:Size := 12
              :Cells( nLinea, nxPosTitIzq ):Font:Name := "Lucida Console"
              :Cells( nLinea, nxPosTitIzq ):Set( "HorizontalAlignment", xlHorJust )

              :Cells( nLinea, nxPosTitCen ):Value := "cSoluciones ®"
              :Cells( nLinea, nxPosTitCen ):Font:Size := 14
              :Cells( nLinea, nxPosTitCen ):Font:Name := "Lucida Console"
              :Cells( nLinea, nxPosTitCen ):Font:Bold := .T.
              :Cells( nLinea, nxPosTitCen ):Set( "HorizontalAlignment", xlHorCombCen )

              :Cells( nLinea, nxPosTitDer ):Value := dtoc(date())
              :Cells( nLinea, nxPosTitDer ):Font:Size := 12
              :Cells( nLinea, nxPosTitDer ):Font:Name := "Lucida Console"
              :Cells( nLinea, nxPosTitDer ):Set( "HorizontalAlignment", xlHorJust )

              FOR x := 1 TO LEN(paTitulos)

                  IF ! EMPTY(paTitulos[x])
                    nLinea ++
                    :Cells( nLinea, nxPosTitCen ):Value := paTitulos[x]
                    :Cells( nLinea, nxPosTitCen ):Font:Size := 14
                    :Cells( nLinea, nxPosTitCen ):Font:Name := "Lucida Console"
                    :Cells( nLinea, nxPosTitCen ):Font:Bold := .T.
                    :Cells( nLinea, nxPosTitCen ):Set( "HorizontalAlignment", xlHorCombCen )
                  ENDIF

              NEXT

            // ahora imprimimos el encabezado de la lista
              nLinea ++
              nLinea ++

              FOR x := 1 TO LEN(paDatos)

                // AQUI IMPRIMIMOS EL TITULO
                :Cells( nLinea, x ):Value := paDatos[x,1]
                :Cells( nLinea, x ):Font:Bold := .T.

                :Range( cXlsColToLet(x) + STRZERO( nLinea, 2 ) ):Borders( xlEdgeTop ):LineStyle := xlDouble //xlDot

                // AQUI SELECCIONAMOS LA ALINEACION HORIZONTAL DEL TITULO
                DO CASE
                  CASE UPPER(paDatos[x,4])$"CEN"; :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter )
                  CASE UPPER(paDatos[x,4])$"IZQ"; :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorLeft   )
                  CASE UPPER(paDatos[x,4])$"DER"; :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorRight  )
                  OTHERWISE;                      :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter )
                ENDCASE

              NEXT

              nRenInicia := 0
              aCamposTot := {} //{ 03,  05,  11,  13,  14  }
              aCamposLet := {} //{ "C", "E", "K", "M", "N" }
              acPosSum   := {} //{ "",  "",  "",   "",  "" }

              FOR x := 1 TO LEN(paDatos)
                IF VALTYPE( paDatos[x,5] )$"L"
                    IF paDatos[x,5]
                        //? x, cXlsColToLet(x)
                        AADD( aCamposTot, x )
                        AADD( aCamposLet, cXlsColToLet(x) )
                        AADD( acPosSum,   "" )

                    ENDIF
                ENDIF
              NEXT

              nLinea ++
              nLinea ++
              nRenInicia := nLinea

              TRY

                  poDatos:GoTop()
                  DO WHILE  ! poDatos:Eof()

                    poMeter:Set(poDatos:Recno())

                    FOR x := 1 TO LEN(paDatos)

                        :Cells( nLinea, x ):Value     := poDatos:FieldGetByName( paDatos[x,2] )
                        :Cells( nLinea, x ):Font:Bold := paDatos[x,3]

                        // aqui agregamos comentarios a las celdas si es necesario
                        //:Cells( nLinea, x ):AddComment()
                        //:Cells( nLinea, x ):Comment:Text( ALLTRIM( "pruebas" + str(x) ) )

                        // aqui definimos la mascara para que imprima los datos
                        DO CASE
                          CASE VALTYPE( poDatos:FieldGetByName( paDatos[x,2] ) )$"D"; :Cells( nLinea, x ):Set( "NumberFormat",        "dd/mm/aaaa"     )
                          CASE VALTYPE( poDatos:FieldGetByName( paDatos[x,2] ) )$"N"; :Cells( nLinea, x ):Set( "NumberFormat",        "#,###,##0.0000" )
                          CASE VALTYPE( poDatos:FieldGetByName( paDatos[x,2] ) )$"C"; :Cells( nLinea, x ):Set( "NumberFormat",        "@"              )
                        ENDCASE

                        // AQUI SELECCIONAMOS LA ALINEACION HORIZONTAL
                        DO CASE
                          CASE UPPER(paDatos[x,4])$"CEN";                             :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter      )
                          CASE UPPER(paDatos[x,4])$"IZQ";                             :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorLeft        )
                          CASE UPPER(paDatos[x,4])$"DER";                             :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorRight       )
                          OTHERWISE;                                                  :Cells( nLinea, x ):Set( "HorizontalAlignment", xlHorCenter      )
                        ENDCASE
                    NEXT

                    nLinea ++
                    poDatos:Skip(1)

                  ENDDO

              CATCH oError
                MsgStop( "Error de datos, verifique el archivo creado..." + CRLF +;
                          "Error: "     + CHR(9) + TRANSFORM( oError:GenCode,   NIL) + CRLF +;
                          "SubC: "      + CHR(9) + TRANSFORM( oError:SubCode,   NIL) + CRLF +;
                          "OSCode: "    + CHR(9) + TRANSFORM( oError:OsCode,    NIL) + CRLF +;
                          "SubSystem: " + CHR(9) + TRANSFORM( oError:SubSystem, NIL) + CRLF +;
                          "Mensaje: "   + CHR(9) + oError:Description, "LeeXML" )
              END


              // si se selecciono que quieren totales se muestran en las columnas requeridas...
              nLinea ++
              FOR x := 1 TO LEN(aCamposTot)

                  :Range( cXlsColToLet(aCamposTot[x]) + ALLTRIM(STR( nLinea) ) ):Borders( xlEdgeTop ):LineStyle := xlDouble //xlDot
                  :Cells( nLinea, aCamposTot[x] ):Value := "=@SUMA(" + cXlsColToLet(aCamposTot[x]) + ALLTRIM( STR( nRenInicia ) ) + ":" + cXlsColToLet(aCamposTot[x]) + ALLTRIM( STR( nLinea - 2 ) ) + ")"
                  :Cells( nLinea, aCamposTot[x] ):Set( "NumberFormat", "#,###,##0.0000" )
                  //:Range( aCamposLet[x] + ALLTRIM(STR(nlinea)) + ":" + aCamposLet[x] + ALLTRIM(STR(nlinea)) ):Interior:Color := CLR_YELLOW

                  //acPosSum[x] += ( aCamposLet[x] + ALLTRIM(STR(nLinea)) + IIF( ! oDatos:Eof(), ",", "" ) )

              NEXT

              nLinea ++
              nLinea ++

              :Cells( nLinea, 1 ):Value := ALLTRIM( TRANSFORM( LEN( poDatos:aDatos ), "999,999,999" ) ) + " registro(s) procesados..."

              IF ! EMPTY(pcFile)
                oWorkBook:SaveAS( ALLTRIM( pcFile ) )
              ENDIF

          END WITH // oHoja

          poMeter:Set( nTotal )

          :Visible := .T.

      END WITH // oexcel



  CATCH oError
      MsgStop( "Error :" + oError:Description, "LeeXML" )
  END


  oHoja := nil
  oExcel := nil

RETURN(NIL)

FUNCTION cXlsColToLet(pnCol)
  LOCAL cLetra := ""

  DO CASE
    CASE pnCol = 1;  cLetra := "A"
    CASE pnCol = 2;  cLetra := "B"
    CASE pnCol = 3;  cLetra := "C"
    CASE pnCol = 4;  cLetra := "D"
    CASE pnCol = 5;  cLetra := "E"
    CASE pnCol = 6;  cLetra := "F"
    CASE pnCol = 7;  cLetra := "G"
    CASE pnCol = 8;  cLetra := "H"
    CASE pnCol = 9;  cLetra := "I"
    CASE pnCol = 10; cLetra := "J"
    CASE pnCol = 11; cLetra := "K"
    CASE pnCol = 12; cLetra := "L"
    CASE pnCol = 13; cLetra := "M"
    CASE pnCol = 14; cLetra := "N"
    CASE pnCol = 15; cLetra := "O"
    CASE pnCol = 16; cLetra := "P"
    CASE pnCol = 17; cLetra := "Q"
    CASE pnCol = 18; cLetra := "R"
    CASE pnCol = 19; cLetra := "S"
    CASE pnCol = 20; cLetra := "T"
    CASE pnCol = 21; cLetra := "U"
    CASE pnCol = 22; cLetra := "V"
    CASE pnCol = 23; cLetra := "W"
    CASE pnCol = 24; cLetra := "X"
    CASE pnCol = 25; cLetra := "Y"
    CASE pnCol = 26; cLetra := "Z"
  ENDCASE

RETURN(cLetra)

FUNCTION nXlsLetToCol( pcLet )
  LOCAL nNum := 0

  DO CASE
    CASE pcLet$"A"; nNum := 1
    CASE pcLet$"B"; nNum := 2
    CASE pcLet$"C"; nNum := 3
    CASE pcLet$"D"; nNum := 4
    CASE pcLet$"E"; nNum := 5
    CASE pcLet$"F"; nNum := 6
    CASE pcLet$"G"; nNum := 7
    CASE pcLet$"H"; nNum := 8
    CASE pcLet$"I"; nNum := 9
    CASE pcLet$"J"; nNum := 10
    CASE pcLet$"K"; nNum := 11
    CASE pcLet$"L"; nNum := 12
    CASE pcLet$"M"; nNum := 13
    CASE pcLet$"N"; nNum := 14
    CASE pcLet$"O"; nNum := 15
    CASE pcLet$"P"; nNum := 16
    CASE pcLet$"Q"; nNum := 17
    CASE pcLet$"R"; nNum := 18
    CASE pcLet$"S"; nNum := 19
    CASE pcLet$"T"; nNum := 20
    CASE pcLet$"U"; nNum := 21
    CASE pcLet$"V"; nNum := 22
    CASE pcLet$"W"; nNum := 23
    CASE pcLet$"X"; nNum := 24
    CASE pcLet$"Y"; nNum := 25
    CASE pcLet$"Z"; nNum := 26
  ENDCASE

RETURN(nNum)

// CLASSE - TARRAY.PRG
/*
#include "objects.ch"
#include "fivewin.ch"
*/


//----------------------------------------------------------------------------//
// TArray: by Hernan Diego Ceccarelli - hceccarelli@cesotech.com.ar
// Lenguaje: CA-Clipper/[x]Harbour [+ FiveWin / FiveWin for [x]Harbour]
// Fecha: 01/05/1999
// Modificaciones:
//    Agosto 2000 por Enrique Guerra (Quique) quique@quiquesoft.com
//                Permite anidar objetos TArray ( utilizar objetos TArray como si
//                   fueran campos
//                El valor lógico para vacío es .F.
//                Se agregó un método FieldPos() para que devuelva la posición del
//                   campo como los DBF
//                Se agreguó el método aEval() el cual hace un simple aEval a ::aBuffer
//                Se agreguó el método dbEval() el cual funciona parecido al dbeval en
//                   los DBF, pero en este caso es para ::aDatos
//                El comando STRUCT Field acepta nombres de campos o variables
//                   STRUCT Field nombre        => agrega el campo nombre
//                   STRUCT Field ( cNombre )   => agrega el campo con el nombre que
//                                                 contenga cNombre
//                Se modificó la función valorVacio para que por DEFAULT revise:
//                   si el valor es una matriz, vacía los elementos de la matriz
//                   si es un objeto TArray vacía el objeto (obj:zap())
//                   los valores no contemplados (nil, codeblocks, objetos) devuelven
//                      el mismo valor que tienen, no una cadena vacía (nil, codeblocks,
//                      objetos)
//                Se modificó el método append para que borre el buffer, de forma
//                   parecida a la del append de las DBF devuelven valores vacíos, para
//                   esto, también modifiqué el método add() para que siguiera
//                   funcionando igual, ya que se puede utilizar el metodo add() para
//                   agregar un registro sin borrar el buffer
//                Se agregó el método dbResize(), el cual sirve si se tiene un campo
//                   que contenga un objeto TArray o un array, y durante el transcurso
//                   del programa se aumentan o se eliminan campos o elementos en
//                   algunos registros, lo que hace es que todoslos registros tengan
//                   ese campo con el mismo tamaño (mismo número de elementos )
//                Se agregó el método SortFields() el cual ordena todos _ en
//                   orden ascendente o descendente, tomando como base los nombres de
//                   _
//                Los métodos Sort() y seek() también se puede enviar el nombre del campo
//                   en lugar del número (ojo, estos son los únicos métodos que lo permite,
//                   todos los métodos que se agregaron únicamente permiten el nombre
//                   no el número del campo, pero esto es muy fácil de solucionar en caso
//                   de que así se necesite)
//                Se puede indicar el el valor que se quiere utilizar en cada campo como
//                   valor vacio, por si no se quieren utilizar los valores por defaul,
//                   en caso de que se envíe el valor vacio y no el valor inicial,
//                   tomará el valor vacío como valor inical
//                      STRUCT Field fecha INIT date() DEFAULT ctod("01/01/2000")
//                      En este ejemplo, el campo fecha va a tener el valor de date(),
//                      pero para cada registro nuevo, va a tener ctod("01/01/2000")
//                El método load borra el buffer si se encuentra en un registro mayor
//                   al total de registros, como en el caso de eof() en los DBF
//                Si se hace un oArray:goto(0) envía a eof() como en los DBF
//    02/Nov/00 - quique@quiquesoft.com
//                Se aumentó la opción de cargar un el objeto desde un DBF desde el
//                si en el comando el valor de la clausula INIT es un álias
//                 DEFINE STRUCT oArray INIT "archivo"    // **OJO** va entre comillas
//    09/Nov/00 - quique@quiquesoft.com
//                se aumento el método SetFilter
//    10/Nov/00 - quique@quiquesoft.com
//                se aumento que los codeblocks FOR y WHILE del método dbEval()
//                recibieran como parámetro Self
//    19/Feb/01 - Por Ing. Mario González - mgonzalez@ing.unne.edu.ar
//                Se introdujo capacidad de busqueda blanda en el método
//                Seek( uClave, cnField, lSoft)
//                Por defecto lSoft es FALSO (búsqueda exacta )
//    29/Sep/04 - Hernan Diego Ceccarelli  hceccarelli@cesotech.com.ar
//                Adaptacion a motor de objetos Harbour/xHarbour
//----------------------------------------------------------------------------//

/*
STATIC oTArrayTmp := {}
*/

//----------------------------------------------------------------------------//

function __StructNew( aInit )

   local nLen:= Len( oTArrayTmp ), oArray:= TArray():New()

   aAdd(oTArrayTmp,{oArray,.F.})

   if ValType( aInit )$"NC" .and. Select(aInit) > 0
      aTail(oTArrayTmp)[2]:=.T.
      aEval((aInit)->(dbStruct()),{|x|oArray:addField(x[1])})
   endif

   if aInit != Nil
      oArray:aDatos:= aInit
   endif

   if nLen > 0
      oTArrayTmp[nLen,1]:aBuffer[Len(oTArrayTmp[nLen,1]:aBuffer)]:= oArray
   endif

return oArray

//----------------------------------------------------------------------------//

function __StructField(cName,uInit,uDefault)

   oTArrayTmp[Len(oTArrayTmp),1]:AddField(cName,uInit,uDefault)

return .T.

//----------------------------------------------------------------------------//

function __StructEnd()

   local oArray,nCampos,cAlias,aMatriz

   if aTail(oTArrayTmp)[2]
      oArray  := aTail(oTArrayTmp)[1]
      cAlias  := oArray:aDatos
      nCampos := (cAlias)->(fCount())
      oArray:aDatos := {}
      (cAlias)->(dbEval({||aMatriz:={},aAdd(oArray:aDatos,aMatriz),;
                        aEval(oArray:aBuffer,{|x,y|aAdd(aMatriz,FieldGet(y))},1,nCampos),;
                        aEval(oArray:aBuffer,{|x,y|aAdd(aMatriz,oArray:aDefault[y])},nCampos+1)}))
      oArray:goTop()
   endif

   return aSize(oTArrayTmp,len(oTArrayTmp)-1)

//----------------------------------------------------------------------------//

CLASS TArray
  DATA   aDatos                     // Matriz real de datos
  DATA   aBuffer                    // Según cantidad de Datos
  DATA   aDEFAULT                   // valores por DEFAULT para cada campo
  DATA   aFields                    // Nombres de _
  data   bSetFilter                 // Codeblock que indica el filtro para los registros
  DATA   nRecNo           INIT 1    // Número del registro
  DATA   lBof             INIT .T.  // Inicio de archivo
  DATA   lCheckMayuscula  INIT .T.
  DATA   lEof             INIT .T.  // Fin de archivo

  METHOD New() CONSTRUCTOR
  METHOD AddField( cName, uInit, uDEFAULT )                                                            // Aumenta un campo
  METHOD Eof()                                     INLINE If( Len(::aDatos) == 0 .or. ::lEof ,.T.,.F.) // Fin de archivo
  METHOD Bof()                                     INLINE If( Len(::aDatos) == 0 .or. ::lBof ,.T.,.F.) // Principio de archivo
  METHOD Load()                                                                                        // Carga el buffer
  METHOD Save()                                                                                        // Guarda el buffer
  METHOD Blank()                                                                                       // Borra el buffer
  METHOD ValorVacio( uValor, nPos )                                                                    // devuelve el valor por DEFAULT de uValor
  METHOD Skip( nRecs )                                                                                 // cambia de registro nRecs registros
  METHOD GoTop()                                   INLINE ::Goto( 1 ), if(ValType(::bSetFilter)="B" .and. !Eval(::bSetFilter,Self),::SkipFilter(1),) // va al inicio del arreglo
  METHOD GoTo(nRecGoto)                                                                                // cambia al registro nRecGoto
  METHOD GoBottom()                                INLINE ::Goto( Len(::aDatos) ),if(ValType(::bSetFilter)="B" .and. !Eval(::bSetFilter,Self),::Skip(-1),) // va al final del registro
  METHOD Append( nPosRecNo )                                                                           // aumenta un registro en nPosRecNo, si no se envía, se aumenta al final
  METHOD Add( nPos )                                                                                   // Graba los datos del buffer en nPos, si no se envía se agregan al final del arreglo
  MESSAGE Delete()                                 METHOD _Delete( nPosRecNo )                         // borra el registro nPosRecNo, si no se envía borra ::RecNo()
  METHOD RecNo()                                   INLINE ::nRecNo                                     // devuelve el registro actual
  METHOD LastRec()                                 INLINE Len(::aDatos)                                // devuelve el número total de registros
  METHOD Zap()                                     INLINE ::nRecNo:= 0,::aDatos:={}, ::Blank()         // borra todos los datos de la matriz
  METHOD Sort( cnField, lAscendente, nIni, nNro )                                                      // ordena la matriz de acuerdo al campo cnField
  METHOD Seek( uClave, cnField, lSoft )                                                                // busca un valor en un campo. lSoft=.T.para búsqueda blanda. Por defecto es falso: busqueda exacta
  MESSAGE FieldPos                                 METHOD _FieldPos( cField )                          // devuelve la posición del campo cField
  METHOD FieldName( nField )                       INLINE ::aFields[nField]                            // devuelve el nombre del camopo nField
  METHOD aEval( bBloque, nInicio, nElementos )     INLINE aEval( ::aBuffer, bBloque, nInicio, nElementos ) // realiza un aEval con el buffer
  METHOD dbResize( cField, nRecord )                                                                   // ajusta el campo cField de todos los registros a un mismo tamaño si es matriz u objeto TArray, toma el tamaño del registro nRecord o el último si este no se envia
  METHOD SortFields( lDesen )                                                                          // ordena _ del objeto
  METHOD dbSortField( cField , lDesen )                                                                // ordena _ del objeto TArray del campo cField a toda la matriz
  METHOD Field2Array(caField)                                                                          // devuelve un campo en una matriz, o una matriz donde cada elemento es una matriz de _ seleccionados
  METHOD SetFilter(bSetFilter)                     INLINE ::bSetFilter:=bSetFilter                     // define un filtro para los registros
  METHOD SkipFilter( nRecs )
  METHOD IsField( cField )                         INLINE ( aScan( ::aFields, Upper(AllTrim(cField)) ) > 0 )
  METHOD FieldPos( cField )                        INLINE aScan( ::aFields, Upper(AllTrim(cField)) )
  METHOD FieldGet( nField )                        INLINE if( ::LastRec()>0, ::aDatos[::RecNo(),nField], ::aDefault[nField] )
  METHOD FieldGetByName( cField )                  INLINE ::FieldGet( ::FieldPos( cField ) )
  METHOD FieldPut( nField, uVal )                  INLINE if( ::LastRec()>0, ::aDatos[::RecNo(), nField]:= uVal, )
  METHOD FieldPutByName( cField, uVal )            INLINE ::FieldPut( ::FieldPos( cField ), uVal )

  MESSAGE dbEval                                   METHOD _dbEval( bBloque, bFor, bWhile, nNext, nRecord, lRest )  // realiza un aEval a toda la matriz con las mismas caracteristicas que el dbEval de clipper
  ERROR HANDLER ArrayErrorHand()
ENDCLASS

//----------------------------------------------------------------------------//

METHOD New() CLASS TArray

   ::aDatos := {} /// Matriz real de datos
   ::aFields:= {} ///
   ::aBuffer:= {} /// Seg£n cantidad de Datos
   ::aDefault:={}

return Self

//----------------------------------------------------------------------------//

METHOD AddField( cName, uInit, uDEFAULT ) CLASS TArray

   Aadd( ::aFields  , Upper(cName) )
   Aadd( ::aBuffer  , if(uInit=nil,uDefault,uInit) )
   Aadd( ::aDEFAULT , uDEFAULT )

return .T.

//----------------------------------------------------------------------------//

METHOD Load() CLASS TArray

   local aDatos := ::aDatos
   local aBuffer:= ::aBuffer
   local nLen   := Len ( aDatos )
   local nRecNo := ::nRecNo

   if nLen > 0 // .or. nRecNo <= ::LastRec()
      nRecNo  := Max( Min( nRecNo, nLen ), 1 )
      ::nRecNo:= nRecNo
      nLen := len(aDatos[nRecNo])
      if nLen<len(aBuffer)
         aSize(aDatos[nRecNo],len(aBuffer))
         aEval(aBuffer,{|uValor,nPos|aDatos[nRecNo,nPos] := ::valorVacio(uValor,nPos)},nLen+1)
      endif
      ::aBuffer:= aClone( aDatos[nRecNo] )
   Else
      ::Blank()
   endif

return .T.

//----------------------------------------------------------------------------//

METHOD Blank() CLASS TArray

   local aBuffer:= ::aBuffer

   AEval( aBuffer, {|uValor,nPos| aBuffer[nPos]:= ::valorVacio(uValor,nPos) } )

return .T.

//----------------------------------------------------------------------------//

METHOD ValorVacio( uValor, nPos, aDEFAULT ) CLASS TArray

   local cType:= ValType( uValor ),uDev

   DEFAULT aDefault := ::aDefault

   do case

      case cType == 'N'

         uDev:= if(nPos=nil .or. aDefault[nPos]=nil,0,aDefault[nPos])

      case cType == 'D'

         uDev:= if(nPos=nil .or. aDefault[nPos]=nil,CtoD(''),aDefault[nPos])

      case cType == 'L'

         uDev:= if(nPos=nil .or. aDefault[nPos]=nil,.F.,aDefault[nPos])

      case cType == 'C' .or. cType == 'M'

         uDev:= if(nPos=nil .or. aDefault[nPos]=nil,Space(Len(uValor)),aDefault[nPos])

      case cType == 'A'

         uDev:= if(nPos=nil .or. aDefault[nPos]=nil,aEval(aClone(uValor),{|x,y|uDev[y]:=::valorVacio( x )}),aClone(aDefault[nPos]))

      case cType == 'O' .and. uValor:classname() == "TArray"

         if nPos=nil .or. aDefault[nPos]=nil
            uDev:= oClone(uValor)
            uDev:zap()
         else
            oClone(aDefault[nPos])
         endif

    otherwise

       uDev:= if(nPos=nil .or. aDefault[nPos]=nil,uValor,aDefault[nPos])

    endcase

return uDev

//----------------------------------------------------------------------------//
METHOD Save() CLASS TArray

   local aDatos := ::aDatos
   local aBuffer:= ::aBuffer
   local nLen   := Len ( aDatos )
   local nRecNo := ::nRecNo

   if nLen > 0
      nRecNo  := Max( Min( nRecNo, nLen ), 1 )
      ::nRecNo:= nRecNo
      ::aDatos[nRecNo] := aClone(aBuffer)
   endif

return .T.

//----------------------------------------------------------------------------//

METHOD Skip( nRecs ) CLASS TArray

   local nLen   := Len ( ::aDatos )
   local nRecNo := ::nRecNo
   local nSalto := 0

   DEFAULT nRecs:= 1

   if nLen > 0 .and. nRecs <> 0

      // SetFilter
      if ValType(::bSetFilter)="B"
         nSalto := ::SkipFilter(nRecs)
      else // sin SetFilter

         nRecNo  := Max( Min( nRecNo, nLen ), 1 )
         nSalto  := nRecs
         if nRecs > 0 // Pa' delante
            if nRecNo + nRecs > nLen
               nSalto-= nRecNo + nRecs - nLen
            endif
         Else         // Pa' tras
            if nRecNo + nRecs < 1
               nSalto+= 1 - ( nRecNo + nRecs )
            endif
         endif
      endif
      if nSalto <> 0
         nRecNo+= nSalto
         ::nRecNo:= nRecNo
         ::Load()
      endif
   endif

   if nSalto == 0
      if nRecs <> 0
         if nRecs > 0
           ::lEof:= .T.
           ::lBof:= .F.
         Else
           ::lEof:= .F.
           ::lBof:= .T.
         endif
      endif
   Else
      ::lEof:= .F.
      ::lBof:= .F.
   endif

return nSalto

//----------------------------------------------------------------------------//

METHOD Goto( nRecGoto ) CLASS TArray

   local nLen   := Len ( ::aDatos )
   local nRecNo := ::nRecNo

   if nRecGoto=0
      ::nRecNo := ::LastRec()+1
      ::lEof   := .T.
      ::lBof   := ::LastRec()=0
      ::Blank()
   else
      nRecGoto:= Min( nLen, nRecGoto )

      if nLen > 0
         ::nRecNo:= nRecGoto
         ::Load()
         ::lEof:= .F.
         ::lBof:= .F.
      Else
         ::Blank()
      endif
   endif

return .T.

//----------------------------------------------------------------------------//

METHOD Append( nPosRecNo ) CLASS TArray

   local nLen   := Len ( ::aDatos )
   local nRecNo := ::nRecNo
   local aDatos := ::aDatos

   if nLen > 0 .and. nPosRecNo != Nil .and. nPosRecNo >= 1
      nPosRecNo:= Min( nLen, nPosRecNo )
      ASize( aDatos, nLen+1 )
      AIns( aDatos, nPosRecNo )
      ::nRecNo:= nPosRecNo
      aDatos[ nPosRecNo ]:= Array( Len(::aFields) )
      AEval( ::aBuffer, {|uValor,nPos| aDatos[nPosRecNo,nPos]:= ::valorVacio(uValor,nPos) } )
   else
      Aadd( aDatos, Array( Len(::aFields) ) )
      nPosRecNo:= nLen + 1
      ::nRecNo := nPosRecNo

   endif
   AEval( ::aBuffer, {|uValor,nPos| aDatos[nPosRecNo,nPos]:= ::valorVacio(uValor,nPos) } )
   ::aBuffer := aClone( aDatos[nPosRecNo] )
   ::lEof:= .F.
   ::lBof:= .F.

return .T.

//----------------------------------------------------------------------------//
METHOD Add( nPos ) CLASS TArray

   local aBuffer:= aClone(::aBuffer)

   ::Append( nPos )
   ::aBuffer := aBuffer
   ::Save()

return .T.

//----------------------------------------------------------------------------//

METHOD _Delete( nPosRecNo ) CLASS TArray

   local nLen   := Len ( ::aDatos )
   local nRecNo := ::nRecNo
   local aDatos := ::aDatos

   DEFAULT nPosRecNo:= ::nRecNo

   if nLen > 0
      nPosRecNo:= Max( Min( nLen, nPosRecNo ), 1)
      ADel( aDatos, nPosRecNo )
      ASize( aDatos, nLen-1 )
      if nPosRecNo > nLen-1
         nPosRecNo--
      endif
      ::nRecNo:= nPosRecNo
      ::Load()
   endif

return .T.

//----------------------------------------------------------------------------//

METHOD Sort( cnField, lAscendente, nIni, nNro ) CLASS TArray

   local bBlock, uValor, nPosNueva
   local nField:=if(ValType(cnField)="N",cnField,if(ValType(cnField)="C",::FieldPos(cnField),1))

   DEFAULT nField:= 1,;
           lAscendente:= .T.

   if Len( ::aDatos ) > 0

      if lAscendente
         bBlock:= {|x,y| x[nField] < y[nField] }
      Else
         bBlock:= {|x,y| x[nField] > y[nField] }
      endif

      uValor:= ::aDatos[::nRecNo,nField]  /// Valor Donde Estaba

      ASort( ::aDatos, nIni, nNro, bBlock )

      if ( nPosNueva:= AScan( ::aDatos, {|x| x[nField] == uValor } ) ) > 0
         ::nRecNo:= nPosNueva
      endif

   endif

return .T.

//----------------------------------------------------------------------------//

METHOD Seek( uClave, cnField, lSoft ) CLASS TArray

   local lEncontro:= .F.
   local nPosNueva:=0
   local bSetFilter := if(ValType(::bSetFilter)="B",::bSetFilter,{||.T.})

   DEFAULT lSoft:= .F.

   if(ValType(cnField)="C",cnField:=::FieldPos(cnField),)

//      if ( nPosNueva:= AScan( ::aDatos, {|x| x[cnField] == uClave }, nPosNueva ) ) > 0
//         ::nRecNo:= nPosNueva
//         ::Load()
//         ::lEof:= .F.
//         ::lBof:= .F.
//         lEncontro:= .T.
//      else
//         ::lEof   := .T.
//         ::nRecNo := 0
//         ::blank()
//      endif

   if lSoft // Busqueda blanda
      do while .T.
         nPosNueva := AScan( ::aDatos, {|x| AllTrim( x[cnField] ) = uClave }, nPosNueva+1 )
         ::Goto(nPosNueva)
         if nPosNueva = 0
            exit
         elseif Eval(bSetFilter,Self)
            lEncontro := .T.
            exit
         endif
      enddo
   else
      do while .T.
         nPosNueva := AScan( ::aDatos, {|x| AllTrim( x[cnField] )== uClave }, nPosNueva+1 )
         ::Goto(nPosNueva)
         if nPosNueva = 0
            exit
         elseif Eval(bSetFilter,Self)
            lEncontro := .T.
            exit
         endif
      enddo
   end

return lEncontro

//----------------------------------------------------------------------------//

METHOD _FieldPos( cField ) CLASS TArray

   cField := if(ValType(cField)="C",upper(cField),"")

return aScan( ::aFields, {|x|x==cField} )

//----------------------------------------------------------------------------//

METHOD _dbEval( bBloque, bFor, bWhile, nNext, nRecord, lRest ) CLASS TArray

   local nCont,nSkip:=1,bSetFilter:=if(ValType(::bSetFilter)="B",::bSetFilter,{||.T.})

   DEFAULT bFor   := {||.T.}
   DEFAULT bWhile := {||.T.}
   DEFAULT nNext  := ::LastRec()

   if ValType(nRecord)="N"
      ::goto(nRecord)
      nNext := 1
      nSkip := 0
   elseif pCount()<4 .or. !Empty(lRest)
      ::GoTop()
   else
      ::Load()
   endif

   do while --nNext>=0 .and. !::eof() .and. Eval(bWhile,Self)
      if Eval(bFor,Self) .and. Eval(bSetFilter,Self)
         Eval(bBloque,Self)
      endif
      ::Skip(nSkip)
   enddo

return nil

//----------------------------------------------------------------------------//

METHOD dbResize( cField, nRecord ) CLASS TArray

   local nCampo:=::FieldPos(cField),nTamActual,nTamNuevo,aBuffer,aFields,aDefault

   DEFAULT nRecord := ::LastRec()

   ::Goto(nRecord)

   if ValType(::aBuffer[nCampo])="A"
      nTamNuevo := len(::aBuffer[nCampo])
      aEval(::aDatos,{|aReg|aBuffer:=aReg,nTamActual:=len(aReg[nCampo]),;
                            aSize(aReg[nCampo],nTamNuevo),;
                            aEval(aReg[nCampo],{|uValor,nPos|aBuffer[nPos]:= ::valorVacio(uValor,nPos)},nTamActual+1)})
   elseif ValType(::aBuffer[nCampo])="O" .and. ::aBuffer[nCampo]:classname() == "TArray"
      aFields   := aClone(::aBuffer[nCampo]:aFields)
      aDEFAULT  := aClone(::aBuffer[nCampo]:aDefault)
      aBuffer   := aClone(::aBuffer[nCampo]:aBuffer)
      nTamNuevo := len(aBuffer)
      aEval(aBuffer,{|uValor,nPos|aBuffer[nPos]:= ::valorVacio(uValor,nPos,aDefault)})
      ::dbEval({|aBuf|::aBuffer[nCampo]:aFields:=aClone(aFields),;
                      ::aBuffer[nCampo]:aDefault:=aClone(aDefault),;
                      aBuf:=::aBuffer[nCampo]:aBuffer,nTamActual:=len(aBuf),aSize(aBuf,nTamNuevo),;
                      aEval(aBuffer,{|uValor,nPos|::aBuffer[nCampo]:aBuffer[nPos]:= ::valorVacio(uValor,nPos,aDefault)},nTamActual+1),;
                      ::aBuffer[nCampo]:save()})
   endif
   ::GoTop()

return nil

//----------------------------------------------------------------------------//

METHOD SortFields( lDesen ) CLASS TArray

   local aFields := aClone(::aFields),aNuevo[len(::aFields)]

   aSort(::aFields,,,if(Empty(lDesen),{|x,y|x<y},{|x,y|x>y}))
   aEval(::aFields,{|cField,nPos|aNuevo[nPos]:=aScan(aFields,cField)})
   aEval(aNuevo,{|nField,nPos|aFields[nPos]:=aScan(aNuevo,nPos)})
   aEval(aClone(::aDefault),{|uValor,nPos|::aDefault[aFields[nPos]]:=uValor})

   if Empty(::aDatos)
      aEval(aClone(::aBuffer),{|uValor,nPos|::aBuffer[aFields[nPos]]:=uValor})
   else
      ::dbEval({||aEval(aClone(::aBuffer),{|uValor,nPos|::aBuffer[aFields[nPos]]:=uValor}),::save()})
   endif

return nil

//----------------------------------------------------------------------------//

METHOD dbSortField( cField , lDesen ) CLASS TArray

   local nField:=::FieldPos(cField)

return ::dbEval({||::aBuffer[nField]:SortFields( lDesen )})

//----------------------------------------------------------------------------//

METHOD Field2Array(caField) CLASS TArray

   local aArray:={}, nPos

   if ValType(caField)="C" .and. (nPos:=::FieldPos(caField))>0
      ::dbEval({||aAdd(aArray,::aBuffer[nPos])})
   elseif ValType(caField)="A"
      aEval(caField,{|cField,nPos| aAdd( aArray[nPos],::Field2Array(cField) ) })
   endif

return aArray

//-------------------------------------------------------------------------------------

METHOD SkipFilter(nRecs) class TArray

   local nSalto:=0,nRecNo:=::RecNo(),bSetFilter:=::bSetFilter,nSkipFilt,nSkip

   DEFAULT nRecs := 1

   ::bSetFilter := nil
   nSkipFilt    := nRecs
   nSkip        := if(nSkipFilt>0,1,-1)

   do while nSkipFilt<>0
      ::Skip(nSkip)
      if ::bof() .or. ::eof()
         ::goto(nRecNo)
         exit
      elseif Eval(bSetFilter,Self)
         nSkipFilt -= nSkip
         nRecNo    := ::nRecNo
         nSalto    += nSkip
      endif
   enddo
   ::bSetFilter := bSetFilter

return nSalto

//-------------------------------------------------------------------------------------


#ifdef __HARBOUR__
   METHOD ArrayErrorHand( uParam1 ) CLASS TArray
      local cMetodo:= __GetMessage()
      local nError := If( SubStr( cMetodo, 1, 1 ) == "_", 1005, 1004 )
#else
   METHOD ArrayErrorHand( cMetodo, nError ) CLASS TArray
      local uParam1 := GetParam( 1, 1 )
#endif
   local lAsignacion:= .F.
   local nId
   local lExact:= Set( _SET_EXACT, .T. )
   local uDev
   local bMetodo := {|x|x==cMetodo}, oError

   if SubStr( cMetodo, 1, 1 ) == '_'
      lAsignacion:= .T.
      cMetodo:= SubStr( cMetodo, 2 )
      #ifndef __HARBOUR
         bMetodo := {|x|left(x,9)==cMetodo}
      #endif
   endif

   if ::lCheckMayuscula
      AEval( ::aFields, {|cVal,nId| ::aFields[nId]:= Upper(cVal) } )
      ::lCheckMayuscula:= .F.
   endif

   if ( nId:= AScan( ::aFields, bMetodo ) ) > 0
      if lAsignacion
         uDev:= uParam1
         ::aBuffer[ nId ]:= uDev
      Else
         uDev:= ::aBuffer[ nId ]
      endif
   Else
      // uDev:= _ClsSetErr( _GenError( nError, ::ClassName, cMetodo ) )
      oError:= ErrorNew()
      oError:description:= "CLASE TArray " +   ;
                           "Campo " + cMetodo + " Inexistente."
      uDev:= Eval( ErrorBlock(), oError )
   endif

   Set( _SET_EXACT, lExact )

return uDev

//----------------------------------------------------------------------------//

// TARRAY.CH

//----------------------------------------------------------------------------//
// Creando Estructuras de Datos // Arrays orientados a objetos
//----------------------------------------------------------------------------//

/*
#command DEFINE STRUCT [<oTArray>] [INIT <aInit>] => ;
         [<oTArray>:= ]__StructNew(<aInit>)
#command STRUCT FIELD <(cName)> [INIT <uInit>] [DEFAULT <uDefault>] => ;
         __StructField(<(cName)>,<uInit>,<uDefault> )
#command END STRUCT => __StructEnd()
*/
 
Gracias, saludos.

Re: Visor o leer XML

Posted: Mon Aug 18, 2014 6:12 pm
by karinha