BlackTDN Search

sexta-feira, 9 de dezembro de 2011

Protheus :: Advpl :: Duelo de Titãs :: Harbour x ADVPL (You Win!)

Nos episódios anteriores…

  1. Protheus :: Advpl :: Duelo de Titãs :: Harbour x ADVPL ; e

  2. Protheus :: Advpl :: Duelo de Titãs :: Harbour x ADVPL (Round 2, Figth!)

iniciamos o processo de compatibilização de Código Harbour com ADVPL

e…

Finalizando este “combate” tornarmos-nos vencedores!

Protheus, em detrimento a incompetência deste que vos escreve na implementação  descente de Hash (à moda Harbour e em apenas 1 dia), executou com presteza as classes para a geração dos arquivos xml compatíveis com o Microsoft Excel.

Usaremos U_hbXMLTest() para comprovar “a competência” do Protheus nesse sentido.

image[19]

image_thumb[14]

image_thumb[15]

Os exemplos gerados pelo Protheus … :

image_thumb[24]

image_thumb[23]

image_thumb[22]

… são “exatamente” iguais aos gerados pelo Harbour, exceto pela Data de Geração e, no exemplo 3, a implementação do método border (que funciona no Protheus e no Harbour Não)

image_thumb[26]

Compilando as Classes Harbour/Protheus usando hbmk2

image_thumb[68]
para a geração da libhbxlsxml.a que será utilizada pelos programas de testes

image_thumb[70]

e compilado os programas para o mesmo teste no Harbour…

image_thumb[72]

image_thumb[74]

image_thumb[76]

Obteremos os executáveis:

image_thumb[78]

sem crítica, sem erro… tudo OK. Vamos executá-los e , usando apdiff.exe ou WinMerge, vamos comparar os arquivos gerados por ambas aplicações

image_thumb[80]

image_thumb[48]

Os arquivos gerados pelo Protheus estão em %temp%

image_thumb[50]

Já os do Harbour em:

image_thumb[52]

Veremos que, para o exemplo1.xml a única diferença entre o arquivo gerado pelo Harbour e o gerado pelo Protheus é a Hora em que foram criados

image_thumb[54]

Já, para o exemplo2.xml, além da Diferença na data da Criação

image_thumb[56]

Teremos a diferença no formato da Data. No Harbour, para o Exemplo2, SET CENTURY não está ativo e o formato está como mm/dd/yy e no Protheus dd/mm/yyyy algo facilmente contornável.

image_thumb[58]

As diferenças apontadas no exemplo3.xml são um pouco maiores, teremos, além da data da geração , a tag Border.

image_thumb[60]

Desabilitando Border no Protheus teremos, para o Exemplo3.xml o mesmo resultado.

image_thumb[64]

image_thumb[66]

Às explicações e explanações do como e, depois, “vambora” tornar as classes 100% ADVPL.

[]s

иαldσ dj

14 comentários:

  1. ...será um ADEUS ao TREPORT!?

    Meus testes dirão!

    ResponderExcluir
  2. Na realidade + uma opção. Mas teríamos que implementar as "tags" para tratamento de impressão. Na versão ADVPL isso estará disponível. as Classes Harbour (baseadas na original em PHP) serão apenas referência e inspiração para as Classes em ADVPL.

    []s

    иαldσ dj

    ResponderExcluir
  3. Naldo,

    você ja tentou chamar a execucao de um TReport a partir de um webservice?

    Qual a minha ideia:
    Desenvolver um relatorio que tanto possa ser acessado por dentro do sistema, quanto de uma interface web. No caso da interface web, seria nossa intranet passando os mesmos parametros para geracao de um excel ou PDF, que seria armazenado em uma pasta dentro do siga para posterior download pelo usuario atraves do site.

    Seria viavel? Eu já tentei de várias formas fazer funcionar, mas sempre da erro.

    Mais um super desafio para o SUPER NALDO.

    ResponderExcluir
    Respostas
    1. Ismael, é possivel sim. Quais as formas que você tentou e quais os erros apresentados?

      Excluir
    2. Interessante, este item.
      Já tentei fazer algo parecido. No entanto, alguns tratamentos nos parâmetros inviabilizaram a ideia. Por exemplo, tratar os relatórios que o usuário tem acesso, restrição de campos, filiais. Mas seria bem, interessante. Até para economizar licenças.

      Por fim, fizemos um página que consulta a base direta e mostra os dados.

      Excluir
  4. Este eh o fonte que estou usando para testes

    #INCLUDE "PROTHEUS.CH"
    #INCLUDE "RWMAKE.CH"
    #INCLUDE "TBICONN.CH"
    User Function TESTE01(_xProdIni,_xProdFim)

    Private _lJob := .F.
    Private cPerg := Padr("TESTE01",10)

    If _xProdIni != Nil
    _lJob := .T.
    EndIf
    If Select("SX6") == 0
    RpcSetType(3)
    RpcSetEnv("01","01")
    EndIf

    Private oReport := ReportDef()

    If !_lJob

    Private aRegs := {}

    AADD(aRegs,{cPerg,"01","Produto de ?","","","mv_ch1","C",16,0,0,"G","","mv_par01","","","","","","","","","","","","","","","","","","","","","","","","","SB1",""})
    AADD(aRegs,{cPerg,"02","Produto ate ?","","","mv_ch2","C",16,0,0,"G","","mv_par02","","","","","","","","","","","","","","","","","","","","","","","","","SB1",""})

    U_SIDCRIAPER(cPerg,aRegs)
    pergunte(cPerg,.F.)
    oReport:PrintDialog()

    Else

    oReport:lPreview:= .f.
    oReport:lPrtParamPage:= .f.
    oReport:lXlsHeader:= .t.
    oReport:lEdit:= .f.
    oReport:nDevice:= 4
    oReport:nEnvironment:= 1
    oReport:nRemoteType:= 1
    oReport:cFile:= "\web\temp\TESTE_ISMAEL.pdf"
    oReport:cXlsFile:= "\web\temp\TESTE_ISMAEL.xml"
    oReport:cPathPdf:= "\web\temp\"
    oReport:cDir:= "\web\temp\"
    oReport:cReport:= "TESTE01"

    MV_PAR01 := _xProdIni
    MV_PAR02 := _xProdFim

    ReportPrint(oReport)

    Endif

    Return()
    Static Function ReportDef()

    Local oReport
    Local oSection1
    Local aOrdem := {}

    oReport := TReport():New("TESTE01","Produtos",cPerg,{|oReport| ReportPrint(oReport)},"Produtos")

    oReport:SetLandscape()
    oReport:SetTotalInLine(.F.)

    oSection1 := TRSection():New(oReport,"Produtos",{},aOrdem)
    oSection1:SetLineBreak(.f.)

    TRCell():New(oSection1,"CODIGO", ,"Codigo",,15,.F.,)
    TRCell():New(oSection1,"DESCRICAO", ,"Descricao",,60,.F.,)


    Return oReport
    Static Function ReportPrint(oReport)

    Local oSection1 := oReport:Section(1)

    dbSelectArea("SB1")
    SB1->(dbSetOrder(1))
    SB1->(dbSeek(xFilial("SB1")+MV_PAR01))

    While SB1->(!EOF()) .and. SB1->B1_COD >= MV_PAR01 .and. SB1->B1_COD <= MV_PAR02

    oSection1:Init()
    oSection1:Cell("CODIGO"):SetValue( { || SB1->B1_COD })
    oSection1:Cell("DESCRICAO"):SetValue( { || SB1->B1_DESC })
    oSection1:PrintLine()

    SB1->(dbSkip())
    End

    oSection1:Finish()
    Return

    Ja tentei diversas alternativas, instanciando varios atributos do TReport, mas em nenhum caso funcionou

    Para o fonte acima, o erro que me retorna eh

    THREAD ERROR (JOB_WS_0101, THIS) 28/08/2013 13:31:59
    variable is not an object on TRPAGE:PAGEWIDTH(REPORT10.PRW) 30/09/2009 18:45:46 line : 172

    [TOTVS build: 7.00.121227P-20130625]
    Called from TREPORT:PAGEWIDTH(REPORT01.PRW) 16/05/2013 14:59:18 line : 4006
    Called from TRSECTION:PAGEWIDTH(REPORT02.PRW) 26/06/2013 14:28:01 line : 2859
    Called from TRSECTION:CELLPOS(REPORT02.PRW) 26/06/2013 14:28:01 line : 1227
    Called from TRSECTION:PRINTLINE(REPORT02.PRW) 26/06/2013 14:28:01 line : 827
    Called from REPORTPRINT(TESTE01.PRW) 28/08/2013 13:31:32 line : 138
    Called from U_TESTE01(TESTE01.PRW) 28/08/2013 13:31:32 line : 73

    Terias algum exemplo funcionando?
    Lembrando que esta rotina TESTE01 eu rodo partir de um webservice.

    ResponderExcluir
  5. Então Naldo, esse desafio esta complicado, não é mesmo? Já quebrei muito a cabeça com ele e estou quase desistindo. Na verdade só não desisti ainda porque acredito no SUPER NALDO.

    Um forte abraço.

    ResponderExcluir
    Respostas
    1. Ismael, teoricamente se você criar um relatório, usando a TReport, que é impresso corretamente via client você conseguirá imprimi-lo via RPC.

      Excluir
    2. No seu exemplo, o erro está ocorrendo no momento que o sistema tenta obter informações das coordenadas das células. O erro poderá ser evitado se alterar a propriedade lCepPos de .T. para .F. na sua TRSection ou se adicionar uma TRPage ao seu relatório.

      Excluir
    3. Bom dia!

      Precisar dar um TREPORT():Init() quando a chamada for via JOB, pois o TRPAGE é criado pelo :Init do TREPORT e não da seção. Quando é executado via Smartclient o :Init do TREPORT deve ser executado automaticamente. No final do relatório deve-se executar o TREPORT():Finish(). Outra coisa, o :Printline() precisa ser chamado como :Printline(,,.T.), onde o .T. indice que trata-se da geração do relatório em planilha.

      Abraço.

      Excluir
  6. Naldo,
    seguindo o mesmo exemplo do Ismael, a geração de um relatório com Treport via client roda perfeitamente, porem via webservice ele não se comporta da mesma maneira, a princípio ele exige alguns tratamentos, e mesmo setando os obejetos TRPage e TMSPrinter durante a geração do relatorio ele não gera! Ja me deparei com varios erros tentando implementar a geracao via uma chamada webservice! O erro mais recente foi esse...

    array out of bounds on GETFONTSIZE(REPORT01.PRW) 16/05/2013 14:59:18 line : 4336

    Já verifiquei que o TReport tem uma propriedade aFontSize, mas mesmo via client essa propriedade se encontra vazia!
    Mas acredito que seja possivel realizar esta façanha! O que você acha!?

    ResponderExcluir
    Respostas
    1. Ricardo, depure o seu programa, quando da execução via WS, e verifique a propriedade nRemoteType do Objeto instanciado pela Classe TReport. Para aplicações NO_REMOTE o conteúdo desta propriedade deve estar igual a -1. Se for diferente desse valor o sistema se comportará de forma inesperada.

      Excluir
    2. Ricardo/Ismael,

      Considerando que existem vários procedimentos e tratamentos para impressão via WEB, pergunto: vocês já tentaram imprimir os seus relatórios via WPS - WebPrint & WebSpool?

      Excluir
    3. Estou tendo problemas para utilizar o TReport em schedule.

      Temos um relatório que utilizamos a anos aqui na empresa e gerou-se a necessidade de envio desta planilha automática por email.

      Então estou utilizando o mesmo relatório, porem se não utilizo o método printdialog() e utilizo o print() é gerado um erro;

      Exceção ocorrida: Invalid ReadMSInt in file c:\bamboo-agent-remote\xml-data\build-dir\totvstec-build131227atfs-windowsshell\lib_base\memstream.hpp at line 634


      Pilha de chamadas:
      GETFONTSIZE(4625)
      CHAR2PIX(4489)
      PRINTHEADER(1301)
      STARTPAGE(1565)
      PRINTTEXT(3354)
      PRINTTOT(540)
      REPORTPRINT(505)
      {|OREPORT| REPORTPRINT(OREPORT)}(168)
      eval(1914)
      PRINT(1914)
      U_FINR190B(113)
      SIGAIXB(228)
      __EXECUTE(513)
      FWPREEXECUTE(82)
      {|| FWPREEXECUTE('REL.BAIXAS ST JUDE', 'FINR190B()', 3, '06', 'XXXXXXXXXX') }(183)
      TWINDOW:ACTIVATE(0)
      ACTIVATE(621)
      SIGAADV(54)

      Alguém ja utilizou o TReport em job ?
      podem me passar um exemplo ?
      Sabem a razão do erro descrito acima ?

      Excluir