<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Abapinho</title>
	
	<link>http://abapinho.com</link>
	<description>ABAP em português</description>
	<lastBuildDate>Mon, 14 May 2012 13:02:22 +0000</lastBuildDate>
	<language>pt</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/blogabapinho" /><feedburner:info uri="blogabapinho" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Constantes gregárias</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/5OG0tZ-qb5E/</link>
		<comments>http://abapinho.com/2012/05/constantesgregarias/#comments</comments>
		<pubDate>Mon, 14 May 2012 09:00:28 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[estilo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1671</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/fernandopessoa1.png" class="attachment-thumbnail wp-post-image" alt="fernandopessoa" title="fernandopessoa" />Se és daqueles que, em vez de usarem constantes, espetam com os valores directamente no código, então pára de ler isto e vai ali para o canto de castigo durante 1 hora que é para aprenderes a não ser mandrião. Quando voltares podes continuar a ler. Se já voltaste do castigo ou se costumas usar [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/fernandopessoa1.png" class="attachment-thumbnail wp-post-image" alt="fernandopessoa" title="fernandopessoa" /><p>Se és daqueles que, em vez de usarem constantes, espetam com os valores directamente no código, então pára de ler isto e vai ali para o canto de castigo durante 1 hora que é para aprenderes a não ser mandrião. Quando voltares podes continuar a ler.</p>
<p><span id="more-1671"></span></p>
<p>Se já voltaste do castigo ou se costumas usar constantes, então faz o favor de continuar a ler.</p>
<p>Imagina o seguinte uso de constantes:</p>
<pre><code>
CONSTANTS:
  C_BUKRS_ESPANHA TYPE BUKRS VALUE '1111',
  C_BUKRS_FRANCA   TYPE BUKRS VALUE '2222',
  C_BUKRS_INDIA       TYPE BUKRS VALUE '3333',
  C_MODE_ERRO        TYPE XFELD VALUE 'E',
  C_MODE_INFO         TYPE XFELD VALUE 'I',
  C_MODE_WARN       TYPE XFELD VALUE 'W'.

START-OF-SELECTION.

  CASE l_bukrs.
    WHEN C_BUKRS_ESPANHA.
      txt = 'Hola'.
   WHEN C_BUKRS_FRANCA.
     txt = 'Bonjour'.
   WHEN C_BUKRS_INDIA.
     txt = 'Namaste'.
  ENDCASE.
  WRITE txt.
</code></pre>
<p>Como vêem há 2 grupos de constantes que idealmente estariam agrupados e não estão. Podem agrupar-se assim:</p>
<pre><code>
CONSTANTS:
  BEGIN OF C_BUKRS,
    ESPANHA TYPE BUKRS VALUE '1111',
    FRANCA TYPE BUKRS VALUE '2222',
    INDIA TYPE BUKRS VALUE '3333',
  END OF C_BUKRS,

  BEGIN OF C_MODE,
    ERRO        TYPE XFELD VALUE 'E',
    INFO         TYPE XFELD VALUE 'I',
    WARN       TYPE XFELD VALUE 'W',
  END OF C_MODE.

START-OF-SELECTION.

  CASE l_bukrs.
    WHEN C_BUKRS-ESPANHA.
      txt = 'Hola'.
   WHEN C_BUKRS-FRANCA.
     txt = 'Bonjour'.
   WHEN C_BUKRS-INDIA.
     txt = 'Namaste'.
  ENDCASE.
  WRITE txt.
</code></pre>
<p>Assim a declaração faz muito mais sentido porque as constantes ficam agrupadas logicamente. E a utilização é quase igual. Tão óbvio. E no entanto só há uns dias é que descobri que isto se pode fazer.</p>
<p>Obrigado a <a href="http://www.flickr.com/photos/vanesuki/2172430914/" target="_blank">suki suk</a> pela foto.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/5OG0tZ-qb5E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/05/constantesgregarias/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/05/constantesgregarias/</feedburner:origLink></item>
		<item>
		<title>A sua password expirou. Mude-a 5 vezes.</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/RAK_zxr8glI/</link>
		<comments>http://abapinho.com/2012/05/a-sua-password-expirou/#comments</comments>
		<pubDate>Mon, 07 May 2012 09:00:08 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1666</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/dori.png" class="attachment-thumbnail wp-post-image" alt="dori" title="dori" />Não é incomum criarmos uma relação emocional com as nossas passwords. Por isso, é sempre com alguma dor que se recebe aqueles abjectos avisos ameaçadores que dizem que &#8220;a sua password vai expirar&#8221;. Brevemente seguidos pelo duro golpe que recebemos no coração quando surge a inevitável ignóbil invectiva que diz que &#8220;a sua password expirou&#8221;. [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/dori.png" class="attachment-thumbnail wp-post-image" alt="dori" title="dori" /><p>Não é incomum criarmos uma relação emocional com as nossas passwords. Por isso, é sempre com alguma dor que se recebe aqueles abjectos avisos ameaçadores que dizem que &#8220;a sua password vai expirar&#8221;. Brevemente seguidos pelo duro golpe que recebemos no coração quando surge a inevitável ignóbil invectiva que diz que &#8220;a sua password expirou&#8221;. Nesses momentos a mágoa é tanta que todas as musas nos abandonam, temos uma cãibra na imaginação e ficamos ali, especados, esquecidos, esvaziados de qualquer ideia que nos ajude a escolher a nossa próxima palavra-chave.</p>
<p>Mas isso era dantes.</p>
<p>Para o futuro, proponho o seguinte: usa um dos <a href="http://abapinho.com/2012/03/como-sabotar-tabelas/" title="Como sabotar tabelas">maravilhosos métodos manhosos que o Abapinho te ensinou</a> para editar a tabela USR02. Vai ao registo do teu utilizador e apaga o conteúdo dos campos OCOD1, OCOD2, OCOD3, OCOD4 e OCOD5. E o SAP esqueceu. Foi um ar que lhe deu. Agora já podes tornar a usar a palavra-chave-do-teu-coração.</p>
<p>Obrigado Allan Oliveira pela dica.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/RAK_zxr8glI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/05/a-sua-password-expirou/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/05/a-sua-password-expirou/</feedburner:origLink></item>
		<item>
		<title>Mete variáveis dentro de textos standard</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/0VdTAKhgCY8/</link>
		<comments>http://abapinho.com/2012/04/mete-variaveis-dentro-de-textos-standard/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 09:00:06 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Artigos]]></category>
		<category><![CDATA[i18n]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1652</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/minuta.png" class="attachment-thumbnail wp-post-image" alt="minuta" title="minuta" />Textos standard toda a gente usa. Mas sabias que os textos standard podem ter campos dinâmicos lá pelo meio? A SAP chama-lhes &#8220;símbolos de texto&#8221;. A forma de o conseguir é igual à dos velhos formulários da nefasta SE71, ou seja, envolvendo-os com o símbolo &#038;. Assim: &#038;KNA1-NAME1&#038;. Dá um jeitão. Vou mostrar-te como se [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/minuta.png" class="attachment-thumbnail wp-post-image" alt="minuta" title="minuta" /><p>Textos standard toda a gente usa. Mas sabias que os textos standard podem ter campos dinâmicos lá pelo meio? A SAP chama-lhes &#8220;símbolos de texto&#8221;. A forma de o conseguir é igual à dos velhos formulários da nefasta SE71, ou seja, envolvendo-os com o símbolo &#038;. Assim: &#038;KNA1-NAME1&#038;. Dá um jeitão. Vou mostrar-te como se faz.</p>
<p><span id="more-1652"></span></p>
<p>Primeiro tens de definir o texto na SO10. Escolhe um ID (que representa um grupo de textos), depois um nome único para o nosso texto e finalmente a língua em que o vais definir:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/04/so10a.png" alt="" title="so10a" width="578" height="191" class="alignnone size-full wp-image-1653" /></p>
<p>A seguir define o texto:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/04/so10a.png" alt="" title="so10a" width="578" height="191" class="alignnone size-full wp-image-1653" /></p>
<p>Agora que tens o texto definido, podes obtê-lo em qualquer lado utilizado a função READ_TEXT. O resultado desta função é uma tabela interna com as linhas do texto:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/04/read_text.png" alt="" title="read_text" width="537" height="356" class="alignnone size-full wp-image-1655" /></p>
<p>Como vês, ainda lá estão os campos dinâmicos por substituir. Até aqui, tudo banal. Agora é que vem o truque. Para isto vamos usar duas funções: TEXT_SYMBOL_SETVALUE e TEXT_SYMBOL_REPLACE. A primeira deve ser invocada uma vez por cada símbolo de texto para substituir individualmente cada um deles pelo valor desejado. Esta limita-se a preparar em memória essas alterações. Para as efectivar é necessário invocar a segunda. Tudo junto fica assim:</p>
<pre><code>
DATA: w_thead TYPE thead,
           t_tline TYPE STANDARD TABLE OF tline.

    CALL FUNCTION 'READ_TEXT'
      EXPORTING
        id                      = 'ZZST'
        language                = 'P'
        name                    = 'ABAPINHO'
        object                  = 'TEXT'
      IMPORTING
        header                  = w_thead
      TABLES
        lines                   = t_tline
      EXCEPTIONS
        id                      = 1
        language                = 2
        name                    = 3
        not_found               = 4
        object                  = 5
        reference_check         = 6
        wrong_access_to_archive = 7
        OTHERS                  = 8.
   CHECK sy-subrc = 0.

*     Substitui valor da encomenda
        CALL FUNCTION 'TEXT_SYMBOL_SETVALUE'
          EXPORTING
            name  = '&#038;VBAK-NETWR&#038;'
            value = w_vbak-netwr.

*      Substitui moeda da encomenda
        CALL FUNCTION 'TEXT_SYMBOL_SETVALUE'
          EXPORTING
            name  = '&#038;VBAK-WAERK&#038;'
            value = w_vbak-waerk.

        CALL FUNCTION 'TEXT_SYMBOL_REPLACE'
          EXPORTING
            header = w_thead
          TABLES
            lines  = t_tline.
</code></pre>
<p>Se olhares agora para as linhas vais ver que os símbolos foram substituídos pelos valores desejados. </p>
<p>A carta pode seguir para fazer mais uma mãe e um filho felizes.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/0VdTAKhgCY8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/04/mete-variaveis-dentro-de-textos-standard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/04/mete-variaveis-dentro-de-textos-standard/</feedburner:origLink></item>
		<item>
		<title>Atender o cliente ou aviar o freguês?</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/6O5pE-lrJ7E/</link>
		<comments>http://abapinho.com/2012/04/cliente-ou-fregues/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 09:00:05 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[DDIC]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1625</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/vinhosepetiscos.png" class="attachment-thumbnail wp-post-image" alt="vinhosepetiscos" title="vinhosepetiscos" />Em todo o lado onde se use o elemento de dados KUNNR, a sua descrição diz &#8220;Cliente&#8221;. E se quiseres mudar a descrição deste campo de &#8220;Cliente&#8221; para &#8220;Freguês&#8221;? &#8220;Freguês&#8221; é tão mais bonito! Ou imagina que a empresa para quem trabalhas trafica droga e te diz que gostava que no LIFNR aparecesse &#8220;Dealer&#8221; em [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/vinhosepetiscos.png" class="attachment-thumbnail wp-post-image" alt="vinhosepetiscos" title="vinhosepetiscos" /><p>Em todo o lado onde se use o elemento de dados KUNNR, a sua descrição diz &#8220;Cliente&#8221;. E se quiseres mudar a descrição deste campo de &#8220;Cliente&#8221; para &#8220;Freguês&#8221;? &#8220;Freguês&#8221; é tão mais bonito! Ou imagina que a empresa para quem trabalhas trafica droga e te diz que gostava que no LIFNR aparecesse &#8220;Dealer&#8221; em vez de &#8220;Fornecedor&#8221;. Claro que nos ecrãs e relatórios Z podemos descrevê-lo como quisermos mas&#8230; e nas transacções standard?</p>
<p>Fazes isto: vai à transacção CMOD e escolhes o menu &#8220;Ir para > Ampliações Globais > Palavras-chave > Modificar&#8221;. Depois introduzes o elemento de dados cuja descrição pretendes alterar. Aparece-te então uma caixa de diálogo na qual podes redefinir todas as descrições desse elemento de dados. A seguir gravas e já está. A partir de agora, em todo o lugar onde este elemento de dados é usado aparece a tua nova descrição. Poderoso!</p>
<p>Ah, e na opção de menu mesmo ao lado (aquele que diz &#8220;exibir&#8221;)  podes ver a lista de elementos de dados que foram já alterados nesse sistema.</p>
<p>Simples? Pois, mas tem calma, não te ponhas a chamar &#8220;coisa&#8221; ao MATNR nem &#8220;amiguinho&#8221; ao UNAME e por aí adiante. O SAP é uma coisa séria. </p>
<p>Obrigado ao Miguel Freitas pela dica.</p>
<p>(E obrigado a David Rodrigues pela <a href="http:://nimages.blogspot.com">foto</a>).</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/6O5pE-lrJ7E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/04/cliente-ou-fregues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/04/cliente-ou-fregues/</feedburner:origLink></item>
		<item>
		<title>Mete botões no ecrã de selecção</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/vre8iUERH2w/</link>
		<comments>http://abapinho.com/2012/04/botoes-no-ecra-de-seleccao/#comments</comments>
		<pubDate>Mon, 16 Apr 2012 09:00:45 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1612</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/botaopanico.png" class="attachment-thumbnail wp-post-image" alt="botaopanico" title="botaopanico" />Quando num relatório é preciso criar botões para os utilizadores carregarem, normalmente recorre-se ao Screen Painter para criar um ecrã que depois é invocado pelo report com CALL SCREEN. Mas, a não ser que o ecrã a desenhar tenha já alguma complexidade, não é preciso apanhar a valente seca de fazer um ecrã que depois [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/botaopanico.png" class="attachment-thumbnail wp-post-image" alt="botaopanico" title="botaopanico" /><p>Quando num relatório é preciso criar botões para os utilizadores carregarem, normalmente recorre-se ao Screen Painter para criar um ecrã que depois é invocado pelo report com CALL SCREEN. Mas, a não ser que o ecrã a desenhar tenha já alguma complexidade, não é preciso apanhar a valente seca de fazer um ecrã que depois fica para lá. Ecrãs sempre me irritaram.</p>
<p>Mostro aquí um exemplo de utilização de botões num normalíssimo ecrã de selecção recorrendo a um botão chamado PUSHBUTTON e a um truque muito esperto chamado ONLI.</p>
<p><span id="more-1612"></span></p>
<p>Vamos então por partes, como de costume. Primeiro a declaração do ecrã:</p>
<pre><code>
REPORT zbotoes.

TABLES: sscrfields.
DATA: g_ucomm TYPE syucomm.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-200.
SELECTION-SCREEN PUSHBUTTON /1(35) p_but1 USER-COMMAND but1.
SELECTION-SCREEN PUSHBUTTON /1(35) p_but2 USER-COMMAND but2.
SELECTION-SCREEN PUSHBUTTON /1(35) p_but3 USER-COMMAND but3.
SELECTION-SCREEN END OF BLOCK b1.
</code></pre>
<p>Usamos os botões tipo PUSHBUTTON e definimos o USER-COMMAND por forma a que ao serem carregados invoquem imediatamente o PAI do ecrã (vulgo AT SELECTION-SCREEN) sem ter de se carregar em ENTER nem em F8.</p>
<p>Nota a declaração da tabela SSCRFIELDS. Esta será necessária mais tarde no PAI para obter o código do botão carregado.</p>
<p>Os nomes dos botões P_BUT1, P_BUT2 e P_BUT3 são na verdade variáveis que deverão conter o texto que aparece no botão. Isto é no mínimo bizarro e só revela que os gajos que inventaram o ABAP deviam estar bêbedos. Mas enfim, definamos então os textos:</p>
<pre><code>
INITIALIZATION.
  p_but1 = 'Carrega aqui'(001).
  p_but2 = 'Ou aqui'(002).
  p_but3 = 'Ou então aqui'(003).
</code></pre>
<p>Assim definimos o texto dos botões de forma a que possa ser traduzido <a href="http://abapinho.com/2011/11/programas-poliglotas/" target="_blank">conforme já se explicou aqui</a>. A seguir implementa-se o PAI:</p>
<pre><code>
AT SELECTION-SCREEN.
* Se se carregou num dos botões, guarda o seu código e continua
  IF sscrfields-ucomm EQ 'BUT1' OR
      sscrfields-ucomm EQ 'BUT2' OR
      sscrfields-ucomm EQ 'BUT3'.
    g_ucomm = sscrfields-ucomm.
    sscrfields-ucomm = 'ONLI'. " Finge que carregou em F8. Belo truque ;)
  ENDIF.
</code></pre>
<p>Ao redefinir o UCOMM com &#8216;ONLI&#8217; fingimos que se carregou no F8 o que faz com que o programa avance para o START-OF-SELECTION. Aí continuamos a vidinha:</p>
<pre><code>
START-OF-SELECTION.
  CASE g_ucomm.
    WHEN 'BUT1'.
      WRITE 'Carregaste no botão de cima'.
    WHEN 'BUT2'.
      WRITE 'Carregaste no botão do meio'.
    WHEN 'BUT3'.
      WRITE 'Carregaste no botão de baixo'.
ENDCASE.
</code></pre>
<p>E o resultado é este:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/04/botoes-ecra-seleccao.png" alt="" title="Botões no ecrã de selecção" width="468" height="363" class="alignnone size-full wp-image-1621" /></p>
<p>Percebeste? É invulgar e requer uns truques meio manhosos, mas não é nada de especial. Faz bom proveito.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/vre8iUERH2w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/04/botoes-no-ecra-de-seleccao/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/04/botoes-no-ecra-de-seleccao/</feedburner:origLink></item>
		<item>
		<title>Atafulha o ecrã de selecção de bonecada</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/VZoUhsM1CE4/</link>
		<comments>http://abapinho.com/2012/04/bonecada-no-ecra-seleccao/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 09:00:58 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1596</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/icones.png" class="attachment-thumbnail wp-post-image" alt="icones" title="icones" />Foi o SAP que nasceu tristonho ou são os SAPeiros que não o alegram? É verdade que o SAPGui não é nenhum arco-íris nem inspira felicidade ao olhar para ele. Mas ainda assim põe uma catrefada de bonequinhos ao nosso dispôr que podemos usar para o tornar nem que seja um pouquinho mais animado. E [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/04/icones.png" class="attachment-thumbnail wp-post-image" alt="icones" title="icones" /><p>Foi o SAP que nasceu tristonho ou são os SAPeiros que não o alegram? </p>
<p>É verdade que o SAPGui não é nenhum arco-íris nem inspira felicidade ao olhar para ele. Mas ainda assim põe uma catrefada de bonequinhos ao nosso dispôr que podemos usar para o tornar nem que seja um pouquinho mais animado.</p>
<p>E vê como é tão fácil.</p>
<p><span id="more-1596"></span></p>
<p>Imagina que escreves o seguinte programa:</p>
<pre><code>
REPORT  Z_ICONES_NO_ECRA_DE_SELECCAO

PARAMETERS: p_coiso TYPE char20.

START-OF-SELECTION.
  WRITE p_coiso.
</code></pre>
<p>O próximo passo é ir aos textos de selecção definir o texto do parâmetro P_COISO. Antes de lá ires experimenta correr o report SHOWICON para veres a bonecada toda. Quando te fartares de olhar para eles escolhes um e guardas o seu nome. Eu escolhi o ICON_COLOR. Guardas o código alfa-numérico de dois caracteres que aparece lá na antepenúltima coluna chamada &#8220;interno&#8221;. Por exemplo, o código do ícone chamado ICON_COLOR é o G3:</p>
<p><a href="http://abapinho.com/wp-content/uploads/2012/03/icones1.png" rel="lightbox[1596]" title="icones1"><img src="http://abapinho.com/wp-content/uploads/2012/03/icones1.png" alt="" title="icones1" width="472" height="178" class="alignnone size-full wp-image-1597" /></a></p>
<p>Agora sim vais aos textos de selecção e onde quiseres que apareça o ícone escreves o código ladeado por arrobas:</p>
<p><a href="http://abapinho.com/wp-content/uploads/2012/03/icones2.png" rel="lightbox[1596]" title="icones2"><img src="http://abapinho.com/wp-content/uploads/2012/03/icones2.png" alt="" title="icones2" width="483" height="161" class="alignnone size-full wp-image-1598" /></a></p>
<p>E o resultado é, como seria de esperar, animador:</p>
<p><a href="http://abapinho.com/wp-content/uploads/2012/03/icones3.png" rel="lightbox[1596]" title="icones3"><img src="http://abapinho.com/wp-content/uploads/2012/03/icones3.png" alt="" title="icones3" width="527" height="213" class="alignnone size-full wp-image-1599" /></a></p>
<p>Ficas já agora a saber que os bonecos têm de estar no início da linha e que só dá para meter um (que isto não é o msn, pá!).</p>
<p>Obrigado a Luís Rocha pela dica.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/VZoUhsM1CE4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/04/bonecada-no-ecra-seleccao/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/04/bonecada-no-ecra-seleccao/</feedburner:origLink></item>
		<item>
		<title>Ó Tempo Volta Para Trás</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/BFNs33fDKiw/</link>
		<comments>http://abapinho.com/2012/04/o-tempo-volta-para-tras/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 09:00:08 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[segredo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1583</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/delorean1.png" class="attachment-thumbnail wp-post-image" alt="delorean" title="delorean" />&#8220;Ó tempo volta para trás Dá-me tudo o que eu perdi Tem pena e dá-me a vida A vida que eu já vivi Ò tempo volta p&#8217;ra trás Mata as minhas esperanças vãs Vê que até o próprio sol Volta todas as manhãs&#8221; &#8211; António Mourão Ó Tony, é para já. Vou mostrar-te como podes [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/delorean1.png" class="attachment-thumbnail wp-post-image" alt="delorean" title="delorean" /><p>&#8220;Ó tempo volta para trás<br />
Dá-me tudo o que eu perdi<br />
Tem pena e dá-me a vida<br />
A vida que eu já vivi<br />
Ò tempo volta p&#8217;ra trás<br />
Mata as minhas esperanças vãs<br />
Vê que até o próprio sol<br />
Volta todas as manhãs&#8221; &#8211; António Mourão</p>
<p>Ó <a href="http://www.youtube.com/watch?v=LOtAfLvhSZo" target="_blank">Tony</a>, é para já. Vou mostrar-te como podes voltar atrás no tempo. </p>
<p><span id="more-1583"></span></p>
<p>Estás tu muito bem a fazer debug e, sem querer, avanças demais. Querias ter mudado um parâmetro antes de chamar uma função, por exemplo. Mas distraíste-te. Sem o poder de viajar no tempo a única hipótese seria recomeçar o debug do início, o que pode ser doloroso.</p>
<p>Aqui está o cenário trágico. Passaste por cima da função e não alteraste a variável:</p>
<p><a href="http://abapinho.com/wp-content/uploads/2012/03/otempovoltaparatras11.png" rel="lightbox[1583]" title="Debug demasiado à frente"><img src="http://abapinho.com/wp-content/uploads/2012/03/otempovoltaparatras11.png" alt="" title="Debug demasiado à frente" width="616" height="319" class="alignnone size-full wp-image-1589" /></a></p>
<p>Para salvares a situação fazes clique com o botão direito na linha acima para a qual desejas regressar e no menu escolhes &#8220;Ir para a instrução&#8221;:</p>
<p><a href="http://abapinho.com/wp-content/uploads/2012/03/otempovoltaparatras2.png" rel="lightbox[1583]" title="Pedir para viajar no tempo"><img src="http://abapinho.com/wp-content/uploads/2012/03/otempovoltaparatras2.png" alt="" title="Pedir para viajar no tempo" width="415" height="277" class="alignnone size-full wp-image-1588" /></a></p>
<p>Feito isto, depurador regressa ao passado sem refilar:</p>
<p><a href="http://abapinho.com/wp-content/uploads/2012/03/otempovoltaparatras3.png" rel="lightbox[1583]" title="Voltámos atrás no tempo"><img src="http://abapinho.com/wp-content/uploads/2012/03/otempovoltaparatras3.png" alt="" title="Voltámos atrás no tempo" width="622" height="324" class="alignnone size-full wp-image-1587" /></a></p>
<p>E tu podes continuar a trabalhar e já não precisas de cantar o fado até ao fim.</p>
<p>Obrigado Sérgio Fraga pela óptima dica.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/BFNs33fDKiw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/04/o-tempo-volta-para-tras/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/04/o-tempo-volta-para-tras/</feedburner:origLink></item>
		<item>
		<title>Pesquisar por atributos de objectos em tabelas internas</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/0tHWFCPHh2E/</link>
		<comments>http://abapinho.com/2012/03/atributos-de-objectos-em-tabelas-internas/#comments</comments>
		<pubDate>Mon, 26 Mar 2012 09:00:17 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Artigos]]></category>
		<category><![CDATA[estilo]]></category>
		<category><![CDATA[OO]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1551</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/casabonecas.png" class="attachment-thumbnail wp-post-image" alt="casabonecas" title="casabonecas" />Há cada vez mais objectos em ABAP, cada vez menos medo deles e, vê só!, cada vez mais gente a escrevê-los e a usá-los. Ora, se começam a aparecer objectos por todo o lado, é normal e desejável que comecem a enfiá-los também dentro de tabelas internas. Também eu guardei há uns tempos um monte [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/casabonecas.png" class="attachment-thumbnail wp-post-image" alt="casabonecas" title="casabonecas" /><p>Há cada vez mais objectos em ABAP, cada vez menos medo deles e, vê só!, cada vez mais gente a escrevê-los e a usá-los. Ora, se começam a aparecer objectos por todo o lado, é normal e desejável que comecem a enfiá-los também dentro de tabelas internas. Também eu guardei há uns tempos um monte de objectos dentro de tabelas mas infelizmente na altura não sabia disto que vou ensinar aqui. Tinha-me dado jeito.</p>
<p>Mas afinal o que vou eu ensinar aqui?</p>
<p><span id="more-1551"></span></p>
<p>Eu, aqui, vou ensinar que se pode fazer pesquisas numa tabela interna usando como critérios atributos públicos de objectos guardados dentro dessa tabela interna. Compreendeste? Agora que já ensinei que se pode fazê-lo, vou ensinar como se faz. </p>
<p>Vamos por partes. Primeiro a classe. A classe é muito simples e permite apenas guardar uma chave e um valor:</p>
<pre><code>
CLASS my_class DEFINITION.
  PUBLIC SECTION.
    DATA: chave TYPE string,
          valor TYPE string.
ENDCLASS.                    "my_class DEFINITION

CLASS my_class IMPLEMENTATION.
  METHOD constructor.
    chave = i_chave.
    valor = i_valor.
  ENDMETHOD.                    "constructor
</code></pre>
<p>Agora declaramos uma tabela interna que contenha objectos desta classe e preenchemo-la com dois registos:</p>
<pre><code>
START-OF-SELECTION.

  TYPES: BEGIN OF ty_data,
           idx TYPE i,
           obj TYPE REF TO my_class,
         END OF ty_data.

  DATA: t_data TYPE STANDARD TABLE OF ty_data,
        w_data LIKE LINE OF t_data,
        o_obj TYPE REF TO my_class.

  CREATE OBJECT o_obj
    EXPORTING
      i_chave = 'S'
      i_valor = 'Sim'.
  w_data-idx = 1.
  w_data-obj = o_obj.
  APPEND w_data TO t_data.

  CREATE OBJECT o_obj
    EXPORTING
      i_chave = 'N'
      i_valor = 'Não'.
  w_data-idx = 2.
  w_data-obj = o_obj.
  APPEND w_data TO t_data.
</code></pre>
<p>E agora, nada nas mangas,&#8230; o truque:</p>
<pre><code>
  READ TABLE t_data INTO w_data WITH KEY obj->chave = 'S'.
  IF sy-subrc = 0.
    WRITE w_data-obj->valor.
  ENDIF.
</code></pre>
<p>E o resultado é&#8230; &#8220;Sim&#8221;, é possível fazer pesquisas a tabelas internas, usando directamente como critérios os atributos de objectos.</p>
<p>Levando a coisa um pouco mais longe e misturando-a com o recente <a href="http://abapinho.com/2012/02/tabela-interna-nao-estruturada/">artigo sobre tabelas não estruturadas </a>, vamos alterar agora o exemplo para o caso de uma tabela interna não estruturada, ou seja, que contém apenas instâncias do objecto. A classe é exactamente a mesma, por isso não a repito. Partamos da declaração e preenchimento da tabela. Notem em particular a declaração da tabela interna:</p>
<pre><code>
START-OF-SELECTION.

  DATA: t_obj TYPE TABLE OF REF TO my_class,
        o_obj TYPE REF TO my_class.

  CREATE OBJECT o_obj
    EXPORTING
      i_chave = 'S'
      i_valor = 'Sim'.
  APPEND o_obj TO t_obj.

  CREATE OBJECT o_obj
    EXPORTING
      i_chave = 'N'
      i_valor = 'Não'.
  APPEND o_obj TO t_obj.
</code></pre>
<p>E agora utilizamos a palavra especial TABLE_LINE para aceder aos atributos da classe:</p>
<pre><code>
  READ TABLE t_obj INTO o_obj WITH KEY table_line->chave = 'S'.
  IF sy-subrc = 0.
    WRITE o_obj->valor.
  ENDIF.
</code></pre>
<p>Obrigado a Custodio Oliveira que deixou esta dica no comentário sobre o <a href="http://abapinho.com/2012/02/tabela-interna-nao-estruturada/">table_line</a>.</p>
<p>(E obrigado a <a href="http://www.flickr.com/photos/diepuppenstubensammlerin/6451375637/in/photostream/">diepuppenstubensammlerin</a> pela foto)</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/0tHWFCPHh2E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/03/atributos-de-objectos-em-tabelas-internas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/03/atributos-de-objectos-em-tabelas-internas/</feedburner:origLink></item>
		<item>
		<title>Implementar métodos privados em BADIs</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/gPRMyCI6FWk/</link>
		<comments>http://abapinho.com/2012/03/metodos-privados-em-badis/#comments</comments>
		<pubDate>Mon, 19 Mar 2012 10:00:09 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Artigos]]></category>
		<category><![CDATA[enhancements]]></category>
		<category><![CDATA[OO]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1487</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/02/gavetas.png" class="attachment-thumbnail wp-post-image" alt="gavetas" title="gavetas" />Há uns tempos tive uma ideia meio estrambólica meio fantástica que hoje decidi partilhar aqui: criar métodos privados nas classes das BADIs. Passo a explicar. Como parêntesis introdutório: há dois anos atrás, escrevi um artigo chamado Melhorar os melhoramentos a sugerir uma forma organizada de implementar enhancements que consiste em nunca colocar código directamente nos [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/02/gavetas.png" class="attachment-thumbnail wp-post-image" alt="gavetas" title="gavetas" /><p>Há uns tempos tive uma ideia meio estrambólica meio fantástica que hoje decidi partilhar aqui: criar métodos privados nas classes das BADIs.</p>
<p>Passo a explicar.</p>
<p><span id="more-1487"></span></p>
<p>Como parêntesis introdutório: há dois anos atrás, escrevi um artigo chamado <a href="http://abapinho.com/2009/03/melhorar-os-melhoramentos/" title="Melhorar os melhoramentos">Melhorar os melhoramentos</a> a sugerir uma forma organizada de implementar <em>enhancements</em> que consiste em nunca colocar código directamente nos <em>enhancements</em> (sejam eles <em>user-exits</em>, <em>mods</em>, <em>BADIs</em> ou <em>enhancements</em>) mas antes encapsular cada coisa distinta que lá se tem de fazer dentro de uma função. Lê o artigo para entenderes as vantagens desta abordagem. Na altura ainda não usava objectos e por isso sugeri a criação de um grupo de funções com um conjunto de módulos de função. Entretanto, 2 anos depois, acho que não faz sentido nenhum usar funções a não ser quando o SAP a isso nos obriga (RFCs por exemplo). Por isso o artigo mereceria ser actualizado para usar uma classe com métodos estáticos.</p>
<p>Ora estava eu a implementar uma BADI seguindo essa mesma lógica de encapsular sempre a lógica que se adiciona aos enhancements e comecei por criar uma classe, à qual acrescentei um método, o qual invoquei a partir do método da BADI.</p>
<p>Mas depois, <em>fiat lux</em>, e pensei: mas a BADI já é ela própria uma classe. Porque é que hei-de eu então estar a criar uma classe nova? Pois.</p>
<p>Então surgiu a ideia de implementar métodos privados na própria classe que implementa a BADI e depois invocá-los a partir dos métodos oficiais da BADI. Desta forma, fica tudo arrumadinho à mesma sem ser necessário criar outra classe.</p>
<p>Passo a explicar o processo detalhadamente.</p>
<p>Imagina então que tens de implementar um método de uma BADI. Fazes assim:</p>
<ol>
<li>Na SE19 crias a implementação da BADI com base na BADI desejada. Dás-lhe um nome, etc, etc;</li>
<li>Em vez de entrares no método que queres implementar, entras antes na classe que lá diz conter a implementação:
<p><img src="http://abapinho.com/wp-content/uploads/2012/02/2012-02-07-08.10.30-pm.png" alt="" title="2012-02-07 08.10.30 pm" width="604" height="352" class="alignnone size-full wp-image-1490" style="border:1px solid grey" />
</li>
<li>(Agora estás na SE24) Cria um método privado com um nome que descreva o que pretendes fazer (eu criei 2):
<p><img src="http://abapinho.com/wp-content/uploads/2012/02/2012-02-07-08.12.27-pm.png" alt="" title="2012-02-07 08.12.27 pm" width="578" height="274" class="alignnone size-full wp-image-1491" style="border:1px solid grey"  />
</li>
<li>Define os parâmetros desse método copiando do método da BADI apenas os parâmetros de que vais necessitar:
<p><img src="http://abapinho.com/wp-content/uploads/2012/02/2012-02-07-08.13.52-pm.png" alt="" title="2012-02-07 08.13.52 pm" width="582" height="237" class="alignnone size-full wp-image-1492" style="border:1px solid grey" />
</li>
<li>Define excepções se tal fizer sentido;</li>
<li>Implementa a tua lógica dentro do novo método privado:
<p><img src="http://abapinho.com/wp-content/uploads/2012/02/2012-02-07-08.46.50-pm.png" alt="" title="2012-02-07 08.46.50 pm" width="550" height="277" class="alignnone size-full wp-image-1501" style="border:1px solid grey" />
</li>
<li>Vai, agora sim, para o o método público da BADI que queres implementar (podes ir directamente pela SE24 ou fazê-lo a partir da SE19);</li>
<li>Nesse método invoca o teu novo método privado (neste caso invoco logo os 2):
<p><img src="http://abapinho.com/wp-content/uploads/2012/02/2012-02-07-08.09.03-pm.png" alt="" title="2012-02-07 08.09.03 pm" width="566" height="394" class="alignnone size-full wp-image-1489" style="border:1px solid grey" />
</li>
</ol>
<p>Já está. Agora é só activares a BADI (na SE19) caso ainda não esteja activa.</p>
<p>Vantagem: Tudo arrumadinho sem ter de recorrer a classes externas</p>
<p>Desvantagem: Os métodos privados não são visíveis na transacção de BADIs tradicionais SE19 (que mostra apenas o interface da BADI) o que pode levantar alguma confusão para quem não esteja familiarizado com classes. Mas já aparecem no caso dos novos enhancements.</p>
<p>Eu acho que a vantagem ultrapassa a desvantagem. E tu? O que achas? Vês mais vantagens ou mais desvantagens?</p>
<p>Parece que a SAP também gosta desta abordagem porque entretanto descobri uma BADI standard (BNK_BADI_ORIG_PAYMT_CHG) que a usa na implementação &#8220;fallback&#8221; (CL_BNK_BADI_ORIG_PAYMT_CHG). Temos, portanto, a benção da SAP.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/gPRMyCI6FWk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/03/metodos-privados-em-badis/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/03/metodos-privados-em-badis/</feedburner:origLink></item>
		<item>
		<title>Como sabotar tabelas</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/3NQPyQ_OHQk/</link>
		<comments>http://abapinho.com/2012/03/como-sabotar-tabelas/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 13:30:24 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Artigos]]></category>
		<category><![CDATA[segredo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1520</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/02/anonymous.png" class="attachment-thumbnail wp-post-image" alt="anonymous" title="anonymous" />Mais um artigo em auxílio dos que buscam a subversão subreptícia. Espiões, reparem como editar uma tabela que não pode (e provavelmente não deve) ser editada. Apresento-vos 3 técnicas. A primeira já caducou há anos, a segunda está em vias de caducar e a terceira vamos ver quando caducará. 1. SE16 /H OK_CODE EDIT O [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/02/anonymous.png" class="attachment-thumbnail wp-post-image" alt="anonymous" title="anonymous" /><p>Mais um artigo em auxílio dos que buscam a subversão subreptícia. Espiões, reparem como editar uma tabela que não pode (e provavelmente não deve) ser editada. Apresento-vos 3 técnicas. A primeira já caducou há anos, a segunda está em vias de caducar e a terceira vamos ver quando caducará.</p>
<p><span id="more-1520"></span></p>
<p><strong>1. SE16 /H OK_CODE EDIT</strong><br />
O primeiro sistema é já do século XX e usar a velha transacção SE16.</p>
<ul>
<li>na transacção SE16 escolhe a tabela a editar</li>
<li>selecciona os dados e vai para o detalhe de um dos registos</li>
<li>/H para debug</li>
<li>muda o valor da variável OK_CODE para &#8220;EDIT&#8221;</li>
<li>F8 para continuar</li>
</ul>
<p>Se tudo tiver corrido bem agora o registo está editável. Depois é só gravar.</p>
<p><strong>2. SE16N &#038;sap_edit</strong></p>
<ul>
<li>na transacção SE16N escolhe a tabela a editar</li>
<li>selecciona os dados se quiseres filtrar registos</li>
<li>no campo da transacção escreve &#038;sap_edit e enter</li>
<li>F8 para ires para a lista de dados</li>
</ul>
<p>Um Service Pack recente da SAP inibe esta técnica. Se, com um bocado de sorte, o teu sistema estiver desactualizado, agora o registo está editável. Depois é só gravar. Se não der, experimenta a mesma coisa mas com a transacção UASE16N ao invés.</p>
<p><strong>3. Função SE16N_INTERFACE</strong></p>
<ul>
<li>transacção SE37, função SE16N_INTERFACE</li>
<li>F8 para testar</li>
<li>parâmetros:</li>
<ul>
<li>I_TAB = KNA1 :-)</li>
<li>I_EDIT = X</li>
<li>I_SAPEDIT = X</li>
<li>IT_SELFIELDS preenchido opcionalmente para restringir os registos a editar</li>
</ul>
<li>novamente F8 para executar</li>
</ul>
<p>Se tudo tiver corrido bem agora aparece uma lista de registos editável. Depois é só gravar.</p>
<p>Vá, agora não comeces para aí a sabotar tabelas como se não houvesse amanhã!</p>
<p>Obrigado a Renato Oliveira pelo material secreto.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/3NQPyQ_OHQk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/03/como-sabotar-tabelas/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/03/como-sabotar-tabelas/</feedburner:origLink></item>
		<item>
		<title>F1 + F9 = Informações técnicas</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/EdsBXPu6DXI/</link>
		<comments>http://abapinho.com/2012/03/f1-f9-informacoes-tecnicas/#comments</comments>
		<pubDate>Mon, 05 Mar 2012 16:18:59 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[SAPgui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1510</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/boia.png" class="attachment-thumbnail wp-post-image" alt="boia" title="boia" />Amiúde sinto necessidade de, num ecrã funcional, ver as informações técnicas de um determinado campo. Coloco o cursor sobre o campo desejado, depois carrego em F1 e aparece um ecrã de diálogo com ajuda sobre esse campo. A seguir carrego no botão que diz &#8220;informações técnicas&#8221;. Mas há uma forma rápida de fazer o mesmo [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/03/boia.png" class="attachment-thumbnail wp-post-image" alt="boia" title="boia" /><p>Amiúde sinto necessidade de, num ecrã funcional, ver as informações técnicas de um determinado campo. Coloco o cursor sobre o campo desejado, depois carrego em F1 e aparece um ecrã de diálogo com ajuda sobre esse campo. A seguir carrego no botão que diz &#8220;informações técnicas&#8221;. Mas há uma forma rápida de fazer o mesmo recorrendo apenas ao teclado.</p>
<p>É que há dois modos possíveis para o F1 mostrar ajuda de um campo:</p>
<ul>
<li>no assistente de performance</li>
<li>em janela modal</li>
</ul>
<p>Por defeito o modo escolhido é o &#8220;no assistente de performance&#8221;. Mas o modo &#8220;em janela modal&#8221; tem uma grande vantagem: o botão &#8220;informações técnicas&#8221; está associado à tecla F9. Uma vez definido o modo &#8220;em janela modal&#8221;, basta fazer F1 seguido de F9 em cima de qualquer campo para obter as informações técnicas.</p>
<p>Este modo pode ser configurado no menu Ajuda | Opções | Ajuda F1. E tem de ser feito em cada sistema.</p>
<p>F1+F9!</p>
<p>Obrigado a Ana Pinto pela dica.</p>
<p><em>E obrigado a <a href="http://www.flickr.com/photos/the_okapi/2663109009/">the okapi</a> pela foto.</em></p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/EdsBXPu6DXI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/03/f1-f9-informacoes-tecnicas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/03/f1-f9-informacoes-tecnicas/</feedburner:origLink></item>
		<item>
		<title>Quando a tabela interna não é estruturada</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/8Yw8o85epww/</link>
		<comments>http://abapinho.com/2012/02/tabela-interna-nao-estruturada/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 10:00:06 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[segredo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1477</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/arranha-ceus.png" class="attachment-thumbnail wp-post-image" alt="arranha-ceus" title="arranha-ceus" />Quando queres seleccionar linhas numa tabela interna normalmente fazes algo assim: DATA: BEGIN OF itbl, campo1 TYPE c, campo2 TYPE c, END OF itbl. READ TABLE itbl WITH KEY campo1 = 'X' campo2 = 'Y'. LOOP AT itbl WHERE campo1 = 'X' and campo2 = 'Y'. COISO. ENDLOOP. Mas, e se a tabela não for [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/arranha-ceus.png" class="attachment-thumbnail wp-post-image" alt="arranha-ceus" title="arranha-ceus" /><p>Quando queres seleccionar linhas numa tabela interna normalmente fazes algo assim:</p>
<pre><code>
DATA: BEGIN OF itbl,
            campo1 TYPE c,
            campo2 TYPE c,
          END OF itbl.

READ TABLE itbl WITH KEY campo1 = 'X' campo2 = 'Y'.

LOOP AT itbl WHERE campo1 = 'X' and campo2 = 'Y'.
  COISO.
ENDLOOP.
</code></pre>
<p>Mas, e se a tabela não for estruturada e quiseres pesquisar na linha como um todo? Bem, nesse caso, fica aqui a dica: usas a palavra especial <i>TABLE_LINE</i>:</p>
<pre><code>
DATA: itbl TYPE STANDARD TABLE OF string,
            wa LIKE LINE OF itbl.

READ TABLE itbl WITH KEY table_line = 'X'.

LOOP AT itbl INTO wa WHERE table_line = 'X'.
  COISO.
ENDLOOP.
</code></pre>
<p>(Obrigado a  <a href="http://www.flickr.com/photos/aaronescobar/2179228774/" target="_blank">Aaron Escobar</a> pela foto.)</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/8Yw8o85epww" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/02/tabela-interna-nao-estruturada/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/02/tabela-interna-nao-estruturada/</feedburner:origLink></item>
		<item>
		<title>Cria variantes de teste em funções a partir do debugger</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/juoX1CTCQJY/</link>
		<comments>http://abapinho.com/2012/02/variantes-de-teste-em-debug/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 10:00:42 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[segredo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1447</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/02/maquina_lavar_roupa.gif" class="attachment-thumbnail wp-post-image" alt="maquina_lavar_roupa" title="maquina_lavar_roupa" />Imagina que estás a fazer debug de uma transacção e entras numa função e encontras algo interessante. Tão interessante que tens de lhe fazer debug várias vezes. A via convencional é tornar a iniciar o debug da transacção desde o início. Que seca. Mas há uma via mais directa. Quando estás a fazer debug de [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/02/maquina_lavar_roupa.gif" class="attachment-thumbnail wp-post-image" alt="maquina_lavar_roupa" title="maquina_lavar_roupa" /><p>Imagina que estás a fazer debug de uma transacção e entras numa função e encontras algo interessante. Tão interessante que tens de lhe fazer debug várias vezes. A via convencional é tornar a iniciar o debug da transacção desde o início. Que seca. </p>
<p>Mas há uma via mais directa. Quando estás a fazer debug de uma função podes, directamente a partir do debugger, criar dados de teste para essa função com os valores com que a função tiver sido chamada nessa instância. É assim:</p>
<p><span id="more-1447"></span></p>
<p>1. Faz debug e entra dentro de uma função. Neste caso entrámos na DD_SHLP_CALL_FROM_DYNP:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/01/debugger_grava_variante_fm.png" alt="" title="Grava variante de módulo de função 1" width="439" height="314" class="alignnone size-full wp-image-1448" /></p>
<p>2. Depois carregas no ícone das ferramentas assinalado a vermelho na imagem anterior. Aparece-te uma árvore de opções:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/01/debugger_grava_variante_fm2.png" alt="" title="Grava variante de módulo de função 2" width="454" height="338" class="alignnone size-full wp-image-1449" /></p>
<p>3. Escolhe &#8220;Gravar parâmetros como dados de teste(SE37). Aparece-te a caixa de diálogo seguinte pedindo o nome da variante de dados de teste:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/01/debugger_grava_variante_fm3.png" alt="" title="Grava variante de módulo de função 3" width="438" height="118" class="alignnone size-full wp-image-1450" /></p>
<p>Agora é só ires à SE37, fazeres F8 para testar a função, carregares lá em cima no botão &#8220;Diretório de dados de teste&#8221; e constatares com alegria que a nova variante que acabaste de criar no debugger está lá à tua espera.</p>
<p>Já podes fazer debug à função directamente sem teres de fazer debug à transacção toda. Muito mais prático, não te parece?</p>
<p>Nota que isto não funcionará com funções que dependam de estado, ou seja, que dependam de dados criados por outras funções do mesmo grupo de funções. Um exemplo disto é a função WRITE_FORM que só pode ser invocada depois da função OPEN_FORM.</p>
<p>Obrigado Sérgio Fraga pela valiosa dica.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/juoX1CTCQJY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/02/variantes-de-teste-em-debug/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/02/variantes-de-teste-em-debug/</feedburner:origLink></item>
		<item>
		<title>Enviar relatório ou ordem de spool por e-mail</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/e40XbYEZI2w/</link>
		<comments>http://abapinho.com/2012/02/relatorio-por-email/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 10:00:35 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Código]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1430</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/mac_mail_icon.png" class="attachment-thumbnail wp-post-image" alt="mac_mail_icon" title="mac_mail_icon" />Este post inaugura uma nova categoria no Abapinho: Código. Os posts desta categoria apresentarão programas úteis prontos a correr. Este serve para enviar por e-mail o resultado de qualquer relatório ou ordem de spool. O programa apresentado faz uso da nova BCS (Business Communication Services) através da classe CL_BCS em vez do velho e cansado [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/mac_mail_icon.png" class="attachment-thumbnail wp-post-image" alt="mac_mail_icon" title="mac_mail_icon" /><p>Este post inaugura uma nova categoria no Abapinho: Código. Os posts desta categoria apresentarão programas úteis prontos a correr. </p>
<p>Este serve para enviar por e-mail o resultado de qualquer relatório ou ordem de spool. O programa apresentado faz uso da nova BCS (Business Communication Services) através da classe CL_BCS em vez do velho e cansado SO_DOCUMENT_SEND_API1, paz à sua alma. </p>
<p>O conteúdo pode ser enviado no corpo do email, como um anexo TXT ou como um anexo HTML, sendo que este último até vai com as cores todas certinhas e tudo. Disfruta-o. Copia-o cegamente e usa-o ou disseca-o e aprende como usar a CL_BCS. Pelo meio, se te apetecer, ainda podes aprender como usar classes locais e como usar classes de excepção.</p>
<p><span id="more-1430"></span></p>
<p>Uma classe local é mais simples de apresentar aqui no Abapinho mas se quiseres transforma numa classe global através da SE24 conforme o Abapinho já <a href="http://abapinho.com/2011/10/importar-classes-locais/">explicou há uns tempos atrás</a> para a poderes usar a partir de qualquer lado.</p>
<pre><code>
*&#038;---------------------------------------------------------------------*
*&#038; Report ZZZ_NFG_SEND_REPORT_BY_EMAIL
*&#038;
*&#038;---------------------------------------------------------------------*
*&#038; Author: Nuno Godinho
*&#038; Date:   03 January 2012
*&#038; Description: Sends an abap list (generated by a submitted program or
*&#038;              read from an existing spool) by email. The list can be
*&#038;              sent either in the email body, as a text attachment or
*&#038;              as an HTML attachment.
*&#038;---------------------------------------------------------------------*
REPORT zzz_nfg_send_list_by_mail MESSAGE-ID so.

***************************************************************************

* Exception classes
CLASS zcx_zs_no_receivers
  DEFINITION FINAL INHERITING FROM cx_static_check.
ENDCLASS.
CLASS zcx_zs_spool_error
  DEFINITION FINAL INHERITING FROM cx_static_check.
ENDCLASS.
CLASS zcx_zs_invalid_parameters
  DEFINITION FINAL INHERITING FROM cx_static_check.
ENDCLASS.
CLASS zcx_zs_objectlist_error
  DEFINITION FINAL INHERITING FROM cx_static_check.
ENDCLASS.

*----------------------------------------------------------------------*
*       CLASS cl_send_list_by_mail DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS cl_send_list_by_mail DEFINITION.
  PUBLIC SECTION.
    TYPES: ty_send_mode TYPE char4,
           ty_source    TYPE char6.

    CONSTANTS:
      k_send_mode_text        TYPE ty_send_mode VALUE 'TEXT',
      k_send_mode_text_attach TYPE ty_send_mode VALUE 'TXTA',
      k_send_mode_html_attach TYPE ty_send_mode VALUE 'HTMA',
      k_send_mode_attachment  TYPE ty_send_mode VALUE space,

      k_source_submit         TYPE ty_source    VALUE 'SUBMIT',
      k_source_spool          TYPE ty_source    VALUE 'SPOOL'.

    METHODS:
      constructor
        RAISING
          cx_send_req_bcs,

      add_recipient
        IMPORTING
          i_smtp_address TYPE ad_smtpadr
        RAISING
          cx_send_req_bcs
          cx_address_bcs,

      submit_and_send_mail
        IMPORTING
          i_report       TYPE program
          i_variant      TYPE raldb_vari
          i_send_mode    TYPE ty_send_mode
          i_subject      TYPE so_obj_des
          i_smtp_address TYPE ad_smtpadr OPTIONAL
        RAISING
          zcx_zs_no_receivers
          cx_bcs
          zcx_zs_invalid_parameters
          zcx_zs_objectlist_error
          zcx_zs_spool_error,

      read_spool_and_send_mail
        IMPORTING
          i_spool_number TYPE rspoid
          i_send_mode    TYPE ty_send_mode
          i_subject      TYPE so_obj_des
          i_smtp_address TYPE ad_smtpadr OPTIONAL
        RAISING
          zcx_zs_no_receivers
          zcx_zs_invalid_parameters
          zcx_zs_objectlist_error
          cx_send_req_bcs
          cx_bcs
          zcx_zs_spool_error.

  PRIVATE SECTION.
    DATA: go_send_request       TYPE REF TO cl_bcs.

    METHODS:
      get_objectlist_and_send_mail
        IMPORTING
          i_source       TYPE ty_source
          i_report       TYPE program OPTIONAL
          i_variant      TYPE raldb_vari OPTIONAL
          i_spool_number TYPE rspoid OPTIONAL
          i_send_mode    TYPE ty_send_mode
          i_subject      TYPE so_obj_des
          i_smtp_address TYPE ad_smtpadr OPTIONAL
        RAISING
          zcx_zs_no_receivers
          zcx_zs_invalid_parameters
          zcx_zs_objectlist_error
          cx_bcs
          zcx_zs_spool_error,

      submit_report_to_memory
        IMPORTING
          value(i_report)     TYPE program
          value(i_variant)    TYPE raldb_vari
        RETURNING
          value(ot_listobject) TYPE table_abaplist
        RAISING
          zcx_zs_objectlist_error,

      read_spool_to_memory
        IMPORTING
          i_spool_number     TYPE rspoid
        RETURNING
          value(ot_listobject) TYPE table_abaplist
        RAISING
          zcx_zs_spool_error,

       get_objectlist
        IMPORTING
          i_source       TYPE ty_source
          value(i_report)     TYPE program
          value(i_variant)    TYPE raldb_vari
          i_spool_number     TYPE rspoid
        RETURNING
          value(ot_listobject) TYPE table_abaplist
        RAISING
          zcx_zs_spool_error
          zcx_zs_objectlist_error,

       create_text_document
         IMPORTING
           i_report       TYPE program
           i_variant      TYPE raldb_vari
           i_spool_number TYPE rspoid
           i_subject      TYPE so_obj_des
           it_listobject  TYPE table_abaplist OPTIONAL
         RETURNING
           value(o_document)    TYPE REF TO cl_document_bcs
         RAISING
           zcx_zs_objectlist_error
           cx_document_bcs,

       add_header_to_body
         IMPORTING
           i_report       TYPE program
           i_variant      TYPE raldb_vari
           i_spool_number TYPE rspoid
         CHANGING
           xt_soli TYPE soli_tab,

      add_abaplist_text_attach
        IMPORTING
          it_listobject   TYPE table_abaplist
          i_name          TYPE so_obj_des
        CHANGING
          x_document      TYPE REF TO cl_document_bcs
        RAISING
          zcx_zs_objectlist_error
          cx_document_bcs,

      add_abaplist_html_attach
        IMPORTING
          it_listobject   TYPE table_abaplist
          i_name          TYPE so_obj_des
        CHANGING
          x_document      TYPE REF TO cl_document_bcs
        RAISING
          cx_document_bcs,

      send_mail
        IMPORTING
          value(it_listobject) TYPE table_abaplist
          i_report      TYPE program OPTIONAL
          i_variant     TYPE raldb_vari OPTIONAL
          i_spool_number TYPE rspoid OPTIONAL
          i_send_mode   TYPE ty_send_mode
          i_subject     TYPE so_obj_des
        RAISING
          zcx_zs_objectlist_error
          zcx_zs_invalid_parameters
          cx_bcs,

      build_attach_name
        IMPORTING
          i_report    TYPE program
          i_variant   TYPE raldb_vari
          i_spool_number TYPE rspoid
          i_extension TYPE so_obj_des OPTIONAL
        RETURNING value(o_name) TYPE so_obj_des.

ENDCLASS.                    "cl_send_list_by_mail DEFINITION

*----------------------------------------------------------------------*
*       CLASS cl_send_list_by_mail IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS cl_send_list_by_mail IMPLEMENTATION.

  METHOD constructor.
*   Create the send request
    go_send_request = cl_bcs=>create_persistent( ).
    go_send_request->set_send_immediately( 'X' ).
  ENDMETHOD.                    "constructor

  METHOD add_recipient.
    DATA: recipient TYPE REF TO if_recipient_bcs.
    recipient = cl_cam_address_bcs=>create_internet_address( i_smtp_address ).
    go_send_request->add_recipient( recipient ).
  ENDMETHOD.                    "add_receiver

  METHOD submit_and_send_mail.
    get_objectlist_and_send_mail(
              i_source       = k_source_submit
              i_send_mode    = i_send_mode
              i_report       = i_report
              i_variant      = i_variant
              i_subject      = i_subject ).
  ENDMETHOD.                    "submit_report_and_sendmail

  METHOD read_spool_and_send_mail.
    get_objectlist_and_send_mail(
              i_source       = k_source_spool
              i_send_mode    = i_send_mode
              i_spool_number = i_spool_number
              i_subject      = i_subject ).
  ENDMETHOD.                    "read_spool_and_send_mail

  METHOD get_objectlist_and_send_mail.
    DATA: t_recipients TYPE bcsy_re,
          t_listobject TYPE table_abaplist.

*   Check parameters
    IF ( i_source = k_source_spool AND i_spool_number IS INITIAL ) OR
       ( i_source = k_source_submit AND i_report IS INITIAL ).
      RAISE EXCEPTION TYPE zcx_zs_invalid_parameters.
    ENDIF.

*   Add recipient if supplied
    IF i_smtp_address IS SUPPLIED.
      add_recipient( i_smtp_address ).
    ENDIF.

*   It should only run if there is at least one recipient
    t_recipients = go_send_request->recipients( ).
    IF t_recipients[] IS INITIAL.
      RAISE EXCEPTION TYPE zcx_zs_no_receivers.
    ENDIF.

*   Get objectlist either from submit or from spool
    t_listobject = get_objectlist(
      i_source       = i_source
      i_report       = i_report
      i_variant      = i_variant
      i_spool_number = i_spool_number ).

*   Send email
    CALL METHOD send_mail
      EXPORTING
        it_listobject  = t_listobject
        i_report       = i_report
        i_variant      = i_variant
        i_spool_number = i_spool_number
        i_send_mode    = i_send_mode
        i_subject      = i_subject.
  ENDMETHOD.                    "get_objectlist_and_send_mail

  METHOD get_objectlist.
*   Get abap list into memory (either from spool or submit)
    IF i_source = k_source_submit.
      submit_report_to_memory( i_report  = i_report i_variant = i_variant ).
    ELSE.
      read_spool_to_memory( i_spool_number = i_spool_number ).
    ENDIF.

*   Import the list from memory and store it in table listobject
    REFRESH : ot_listobject.
    CALL FUNCTION 'LIST_FROM_MEMORY'
      TABLES
        listobject = ot_listobject
      EXCEPTIONS
        not_found  = 1
        OTHERS     = 2.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE zcx_zs_objectlist_error.
    ENDIF.

*   Free memory
    CALL FUNCTION 'LIST_FREE_MEMORY'
      TABLES
        listobject = ot_listobject
      EXCEPTIONS
        OTHERS     = 1.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE zcx_zs_objectlist_error.
    ENDIF.

  ENDMETHOD.                    "get_objectlist

  METHOD submit_report_to_memory.
    TRANSLATE: i_report  TO UPPER CASE,
               i_variant TO UPPER CASE.
*   Submit report
    SUBMIT (i_report) USING SELECTION-SET i_variant EXPORTING LIST TO MEMORY AND RETURN.
  ENDMETHOD.                    "submit_report

  METHOD read_spool_to_memory.
*   Adapted from FM RSPO_RETURN_ABAP_SPOOLJOB. This FM converts the list to ASCII
*   and I needed it as an ABAPLIST so I just copied the code and adapted it
    DATA: data_is_otf TYPE c.

    CALL FUNCTION 'RSPO_CHECK_JOB_ID_PERMISSION'
      EXPORTING
        rqident       = i_spool_number
        access        = 'DISP'
      EXCEPTIONS
        no_such_job   = 1
        no_permission = 2.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE zcx_zs_spool_error.
    ENDIF.

    CALL FUNCTION 'RSPO_GET_TYPE_SPOOLJOB'
      EXPORTING
        rqident        = i_spool_number
      IMPORTING
        is_otf         = data_is_otf
      EXCEPTIONS
        can_not_access = 1.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE zcx_zs_spool_error.
    ENDIF.

    IF data_is_otf = 'X'.
      RAISE EXCEPTION TYPE zcx_zs_spool_error.
    ELSE.
      SUBMIT rspolist EXPORTING LIST TO MEMORY AND RETURN
                      WITH rqident = i_spool_number
                      WITH first = 1
                      WITH last = 0
                      WITH pages = space.
    ENDIF.
  ENDMETHOD.                    "read_spool

  METHOD send_mail.

    DATA: document       TYPE REF TO cl_document_bcs,
          sent_to_all    TYPE os_boolean,
          bcs_exception  TYPE REF TO cx_bcs,
          name           TYPE so_obj_des.

    IF i_send_mode = k_send_mode_text.
      document = create_text_document(
        i_report       = i_report
        i_variant      = i_variant
        i_spool_number = i_spool_number
        it_listobject  = it_listobject
        i_subject      = i_subject ).
    ELSE.
*     Create text document without adding listobject to the body (it will be attached)
      document = create_text_document(
        i_report       = i_report
        i_variant      = i_variant
        i_spool_number = i_spool_number
        i_subject      = i_subject ).
*     Add attachment to document
      IF i_send_mode = k_send_mode_text_attach.
        name = build_attach_name(
          i_report       = i_report
          i_variant      = i_variant
          i_spool_number = i_spool_number
          i_extension    = 'TXT' ).
        add_abaplist_text_attach(
           EXPORTING
             it_listobject = it_listobject
             i_name        = name
          CHANGING
            x_document = document ).
      ELSEIF i_send_mode = k_send_mode_html_attach.
        name = build_attach_name(
          i_report       = i_report
          i_variant      = i_variant
          i_spool_number = i_spool_number ).
        add_abaplist_html_attach(
           EXPORTING
             it_listobject = it_listobject
             i_name        = name
          CHANGING
            x_document = document ).
      ENDIF.
    ENDIF.

*   Add document to send request
    go_send_request->set_document( document ).

*   Send
    sent_to_all = go_send_request->send( i_with_error_screen = 'X' ).
*    IF sent_to_all NE 'X'.
*      RAISE EXCEPTION TYPE zcx_zs_mail_not_sent.
*    ENDIF.

  ENDMETHOD.                    "send_mail

  METHOD create_text_document.
    DATA: t_listasci   TYPE STANDARD TABLE OF solisti1,
          t_listobject LIKE it_listobject,
          t_soli       TYPE soli_tab,
          w_soli       LIKE LINE OF t_soli.

*   Add header
    add_header_to_body(
      EXPORTING
        i_report       = i_report
        i_variant      = i_variant
        i_spool_number = i_spool_number
      CHANGING
        xt_soli = t_soli ).

*   Add abap list
    IF it_listobject IS SUPPLIED.

      CLEAR w_soli.
      APPEND w_soli TO t_soli.
      w_soli = '------------------------------------------------------'.
      APPEND w_soli TO t_soli.
      CLEAR w_soli.
      APPEND w_soli TO t_soli.

      t_listobject[] = it_listobject[].
      CALL FUNCTION 'LIST_TO_ASCI'
        TABLES
          listasci           = t_listasci
          listobject         = t_listobject
        EXCEPTIONS
          empty_list         = 1
          list_index_invalid = 2
          OTHERS             = 3.
      IF sy-subrc <> 0.
        RAISE EXCEPTION TYPE zcx_zs_objectlist_error.
      ENDIF.
      APPEND LINES OF t_listasci TO t_soli.
    ENDIF.

*   Create text document
    o_document = cl_document_bcs=>create_document(
                            i_type    = 'RAW'
                            i_text    = t_soli
                            i_subject = i_subject ).
  ENDMETHOD.                    "create_text_document

  METHOD add_header_to_body.
    DATA: w_soli LIKE LINE OF xt_soli.

    IF i_report IS NOT INITIAL.
      CONCATENATE 'Report:' i_report INTO w_soli SEPARATED BY space.
      APPEND w_soli TO xt_soli.
    ENDIF.

    IF i_variant IS NOT INITIAL.
      CONCATENATE 'Variant:' i_variant INTO w_soli SEPARATED BY space.
      APPEND w_soli TO xt_soli.
    ENDIF.

    IF i_spool_number IS NOT INITIAL.
      MOVE i_spool_number TO w_soli.
      CONCATENATE 'Spool number:' w_soli INTO w_soli SEPARATED BY space.
      APPEND w_soli TO xt_soli.
    ENDIF.

    CONCATENATE 'Date:' sy-datum sy-uzeit INTO w_soli SEPARATED BY space.
    APPEND w_soli TO xt_soli.

    CONCATENATE 'User:' sy-uname INTO w_soli SEPARATED BY space.
    APPEND w_soli TO xt_soli.

  ENDMETHOD.                    "build_header

  METHOD add_abaplist_text_attach.
    DATA: t_solix TYPE solix_tab.

*   It's always necessary to compress the table. SAPconnect will decompress it
    CALL FUNCTION 'TABLE_COMPRESS'                          "#EC *
      TABLES
        in             = it_listobject
        out            = t_solix
      EXCEPTIONS
        compress_error = 1
        OTHERS         = 2.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE zcx_zs_objectlist_error.
    ENDIF.

    x_document->add_attachment(
      i_attachment_type    = 'ALI'
      i_attachment_subject = i_name
      i_att_content_hex    = t_solix ).

  ENDMETHOD.                    "add_abaplist_text_attach

  METHOD add_abaplist_html_attach.
    DATA: t_soli       TYPE soli_tab,
          t_listobject LIKE it_listobject.

    t_listobject[] = it_listobject[].

    CALL FUNCTION 'WWW_HTML_FROM_LISTOBJECT'
      TABLES
        html       = t_soli
        listobject = t_listobject.

    x_document->add_attachment(
      i_attachment_type    = 'HTM'
      i_attachment_subject = i_name
      i_att_content_text   = t_soli ).

  ENDMETHOD.                    "add_abaplist_html_attach

  METHOD build_attach_name.
    IF i_report IS NOT INITIAL.
      o_name = i_report.
      IF i_variant IS NOT INITIAL.
        CONCATENATE o_name '-' i_variant INTO o_name.
      ENDIF.
    ELSE.
      MOVE i_spool_number TO o_name.
      SHIFT o_name LEFT DELETING LEADING space.
    ENDIF.
    CONCATENATE o_name '-' sy-datum '-' sy-uzeit INTO o_name.
    IF i_extension IS NOT INITIAL.
      CONCATENATE o_name '.' i_extension INTO o_name.
    ENDIF.
  ENDMETHOD.                    "build_attach_name

ENDCLASS.                    "cl_send_list_by_mail IMPLEMENTATION

***************************************************************************
TABLES: adr6.

*------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_subj TYPE so_obj_des OBLIGATORY.
SELECT-OPTIONS: s_rec  FOR adr6-smtp_addr NO INTERVALS LOWER CASE OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-002.
PARAMETERS: p_submit RADIOBUTTON GROUP typ USER-COMMAND typ.
SELECTION-SCREEN BEGIN OF BLOCK b2a WITH FRAME.
PARAMETERS:     p_rep  TYPE program MODIF ID ty1,
              p_var  TYPE raldb_vari MODIF ID ty1.
SELECTION-SCREEN END OF BLOCK b2a.
PARAMETERS: p_spool RADIOBUTTON GROUP typ.
SELECTION-SCREEN BEGIN OF BLOCK b2b WITH FRAME.
PARAMETERS:   p_rspoid TYPE rspoid MODIF ID ty2.
SELECTION-SCREEN END OF BLOCK b2b.
SELECTION-SCREEN END OF BLOCK b2.

SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME TITLE text-003.
PARAMETERS: p_text  RADIOBUTTON GROUP opt,
            p_texta RADIOBUTTON GROUP opt,
            p_htmla RADIOBUTTON GROUP opt DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b3.

AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    IF screen-group1 = 'TY1'.
      IF p_submit IS NOT INITIAL.
        screen-input = 1.
      ELSE.
        screen-input = 0.
      ENDIF.
      MODIFY SCREEN.
    ENDIF.
    IF screen-group1 = 'TY2'.
      IF p_spool IS NOT INITIAL.
        screen-input = 1.
      ELSE.
        screen-input = 0.
      ENDIF.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

START-OF-SELECTION.

  DATA: go_sender TYPE REF TO cl_send_list_by_mail,
        send_mode TYPE cl_send_list_by_mail=>ty_send_mode,
        exc_ref   TYPE REF TO cx_root,
        text      TYPE string.

  IF ( p_submit IS NOT INITIAL AND p_rep IS INITIAL ) OR
     ( p_spool IS NOT INITIAL AND p_rspoid IS INITIAL ).
    MESSAGE s622 DISPLAY LIKE 'E'.
    EXIT.
  ENDIF.

  CREATE OBJECT go_sender.

* Determine send mode
  CASE 'X'.
    WHEN p_texta.
      send_mode = cl_send_list_by_mail=>k_send_mode_text_attach.
    WHEN p_htmla.
      send_mode = cl_send_list_by_mail=>k_send_mode_html_attach.
    WHEN OTHERS.
      send_mode = cl_send_list_by_mail=>k_send_mode_text.
  ENDCASE.

* Add recipients
  LOOP AT s_rec.
    CALL METHOD go_sender->add_recipient
      EXPORTING
        i_smtp_address = s_rec-low.
  ENDLOOP.

  TRY.
      CASE 'X'.
        WHEN p_submit.
          CALL METHOD go_sender->submit_and_send_mail
            EXPORTING
              i_send_mode = send_mode
              i_report    = p_rep
              i_variant   = p_var
              i_subject   = p_subj.
        WHEN p_spool.
          CALL METHOD go_sender->read_spool_and_send_mail
            EXPORTING
              i_send_mode    = send_mode
              i_spool_number = p_rspoid
              i_subject      = p_subj.
      ENDCASE.
      WRITE: / 'Mail message sent'.
    CATCH cx_root INTO exc_ref.
      text = exc_ref->get_text( ).
      WRITE: / text.
  ENDTRY.

* It will not work without this commit
  COMMIT WORK.
</code></pre>
<p>Textos do ecrã de selecção:</p>
<table>
<tr>
<td>P_SUBJ</td>
<td>Assunto</td>
</tr>
<tr>
<td>S_REC</td>
<td>Recipientes</td>
</tr>
<tr>
<td>P_SUBMIT</td>
<td>Enviar relatório</td>
</tr>
<tr>
<td>P_REP</td>
<td>Relatório</td>
</tr>
<tr>
<td>P_VAR</td>
<td>Variante</td>
</tr>
<tr>
<td>P_SPOOL</td>
<td>Enviar ordem de spool</td>
</tr>
<tr>
<td>P_RSPOID</td>
<td>ID da ordem de spool</td>
</tr>
<tr>
<td>P_TEXT</td>
<td>No corpo do e-mail</td>
</tr>
<tr>
<td>P_TEXTA</td>
<td>Anexo TXT</td>
</tr>
<tr>
<td>P_HTMLA</td>
<td>Anexo HTML</td>
</tr>
</table>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/e40XbYEZI2w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/02/relatorio-por-email/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/02/relatorio-por-email/</feedburner:origLink></item>
		<item>
		<title>O histórico do SAPGui não funciona ainda que activo?</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/2HiHRQ3mhg4/</link>
		<comments>http://abapinho.com/2012/02/sapgui-historico/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 10:00:01 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[SAPgui]]></category>
		<category><![CDATA[segredo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1325</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/torre-belem.png" class="attachment-thumbnail wp-post-image" alt="torre-belem" title="torre-belem" />Já te aconteceu o SAPGui não guardar um histórico dos valores que vais introduzindo nos vários campos ainda que, nas configurações, a opção de Histórico esteja activa? Este aparente paradoxo pode dever-se ao facto de, no SAP Logon, a tua ligação a este servidor SAP estar configurada como &#8220;conexão lenta (tráfego de rede reduzido)&#8221; em [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/torre-belem.png" class="attachment-thumbnail wp-post-image" alt="torre-belem" title="torre-belem" /><p>Já te aconteceu o SAPGui não guardar um histórico dos valores que vais introduzindo nos vários campos ainda que, nas configurações, a opção de Histórico esteja activa?</p>
<p><span id="more-1325"></span></p>
<p><img src="http://abapinho.com/wp-content/uploads/2011/12/sapgui-opcoes-historico.png" alt="SAPGui - Opções - Histórico" title="SAPGui - Opções - Histórico" width="451" height="363" class="alignnone size-full wp-image-1328" /></p>
<p>Este aparente paradoxo pode dever-se ao facto de, no <i>SAP Logon</i>, a tua ligação a este servidor SAP estar configurada como &#8220;conexão lenta (tráfego de rede reduzido)&#8221; em vez de &#8220;conexão rápida (LAN)&#8221;. Nesse caso o histórico é automaticamente desactivado.</p>
<p><img src="http://abapinho.com/wp-content/uploads/2011/12/saplogon-coneccao-rede.png" alt="SAP Logon - Conexão - Rede" title="SAP Logon - Conexão - Rede" width="530" height="546" class="alignnone size-full wp-image-1329" /></p>
<p>Obscuro.</p>
<p>(Obrigado a <a href="http://www.flickr.com/photos/unaluzazul/2484113976/">unaluzazul</a> pela foto)</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/2HiHRQ3mhg4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/02/sapgui-historico/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/02/sapgui-historico/</feedburner:origLink></item>
		<item>
		<title>A SE80 tem favoritos</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/bgd-7eCj5Kc/</link>
		<comments>http://abapinho.com/2012/01/favoritos-se80/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 10:00:39 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[SAPgui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1420</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/marcador.png" class="attachment-thumbnail wp-post-image" alt="Marcador" title="Marcador" />Na transacção SE80 há de tudo. Parece aquelas mercearias de aldeia atafulhadas de tralha onde se compra pasta de dentes, pão, sandálias, perfume e arroz a granel. Eu gosto dessas mercearias. Mas para lá ir é preciso saber ao que se vai, senão anda-se ao tio ao tio. Mas isso é nesses mercearias, porque na [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/marcador.png" class="attachment-thumbnail wp-post-image" alt="Marcador" title="Marcador" /><p>Na transacção SE80 há de tudo. Parece aquelas mercearias de aldeia atafulhadas de tralha onde se compra pasta de dentes, pão, sandálias, perfume e arroz a granel. Eu gosto dessas mercearias. Mas para lá ir é preciso saber ao que se vai, senão anda-se ao tio ao tio.</p>
<p>Mas isso é nesses mercearias, porque na SE80&#8230; há favoritos.</p>
<p>Pois é. Só soube há uns dias que a transacção SE80 tem a capacidade de guardar favoritos. É um botãozinho logo ali à mão. Vejam a foto:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/01/se80-favoritos.png" alt="Favoritos na SE80" title="se80-favoritos" width="488" height="493" class="alignnone size-full wp-image-1422" /></p>
<p>De cada vez que se visita um objecto que se acredita vir a visitar mais vezes no futuro, é só inseri-lo na lista de favoritos e assim nunca mais se tem de andar à procura dele.</p>
<p>Obrigado Nuno Morais pela dica.</p>
<p><i>E obrigado a <a href="http://www.flickr.com/photos/chitrasudar/2756691008/">~suchitra~</a> pela foto.</i></p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/bgd-7eCj5Kc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/01/favoritos-se80/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/01/favoritos-se80/</feedburner:origLink></item>
		<item>
		<title>Se um desconhecido te oferecer valores, isso é Input</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/dBgTP4Ze6k4/</link>
		<comments>http://abapinho.com/2012/01/call-selection-screen/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 10:00:08 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1356</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/interrogacao.png" class="attachment-thumbnail wp-post-image" alt="Interrogação" title="Interrogação" />Num relatório, os valores são normalmente pedidos ao utilizador no ecrã de selecção inicial, antes da execução do programa. Mas e se quiseres pedir-lhe mais alguns valores, interactivamente, a meio da execução do programa? Uma forma de o fazer é criar um ecrã com os campos desejados e depois invocá-lo com CALL SCREEN. Mas desenhar [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2012/01/interrogacao.png" class="attachment-thumbnail wp-post-image" alt="Interrogação" title="Interrogação" /><p>Num relatório, os valores são normalmente pedidos ao utilizador no ecrã de selecção inicial, antes da execução do programa. Mas e se quiseres pedir-lhe mais alguns valores, interactivamente, a meio da execução do programa?</p>
<p>Uma forma de o fazer é criar um ecrã com os campos desejados e depois invocá-lo com CALL SCREEN. Mas desenhar o ecrã e definir o PAI e o PBO é uma valente maçada. </p>
<p>Outra solução é recorrer às funções POPUP_GET_VALUES ou POPUP_GET_VALUES_DB_CHECKED. São bastante versáteis mas ainda assim algo chatas de utilizar e com algumas limitações. </p>
<p>Mas há uma forma mais simples de o fazer. É através do CALL SELECTION-SCREEN. Passo a explicar:</p>
<p>Primeiro há que definir o ecrã de selecção. A sua definição é praticamente igual à do ecrã de selecção inicial de um relatório:</p>
<pre><code>
TABLES: t001.

SELECTION-SCREEN BEGIN OF <b>SCREEN 3000</b>.
PARAMETERS: p_uname TYPE syuname.
SELECT-OPTIONS: p_bukrs FOR t001-bukrs.
SELECTION-SCREEN END OF <b>SCREEN 3000</b>.
</code></pre>
<p>Depois, onde quer que te apeteça invocar o ecrã é só&#8230; invocares o ecrã:</p>
<pre><code>
START-OF-SELECTION.

* faz não sei quê antes

  <b>CALL SELECTION-SCREEN 3000 STARTING AT 5 5.</b>

* e mais não sei quê depois
</code></pre>
<p>E dá nisto:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/01/call-selection-screen.png" alt="CALL SELECTION-SCREEN" title="CALL SELECTION-SCREEN" width="493" height="116" class="alignnone size-full wp-image-1373" /></p>
<p>Se meteres o STARTING AT ele vai criar uma janela de diálogo modal. Se não meteres nada, o ecrã ocupará a janela toda. O ecrã de selecção pode ser tão complicado quanto quiseres, podendo incluir abas e tudo o mais. Além disso, porque para o SAP ele não passa de um ecrã de selecção como os outros, poderás gravar variantes e tudo.</p>
<p>Nota que esta abordagem pode também ser usada em transacções, sendo a única desvantagem o facto de exigir F8 em vez de ENTER para submeter os valores.</p>
<p><i>Obrigado a <a href="http://www.flickr.com/photos/cristinacosta/4304968451/">cristinacosta</a> pela foto.</i></p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/dBgTP4Ze6k4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/01/call-selection-screen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/01/call-selection-screen/</feedburner:origLink></item>
		<item>
		<title>Ecrãs de selecção com abas</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/WUtfZ5eM4lw/</link>
		<comments>http://abapinho.com/2012/01/ecra-seleccao-abas/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 10:00:23 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1335</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/abas.png" class="attachment-thumbnail wp-post-image" alt="abas" title="abas" />Os ecrãs de selecção dos programas ABAP têm várias funcionalidades que, embora sofisticadas e simples de usar, são geralmente ignoradas. Aqui mostrar-te-ei quão simples é criar abas para melhor organizar os parâmetros de um programa. Desta vez, excepcionalmente, vou poupar-te à verborreia. É uma aula prática. Vamos lá. O nosso ecrã de selecção terá 3 [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/abas.png" class="attachment-thumbnail wp-post-image" alt="abas" title="abas" /><p>Os ecrãs de selecção dos programas ABAP têm várias funcionalidades que, embora sofisticadas e simples de usar, são geralmente ignoradas. Aqui mostrar-te-ei quão simples é criar abas para melhor organizar os parâmetros de um programa. Desta vez, excepcionalmente, vou poupar-te à verborreia. É uma aula prática.<br />
<span id="more-1335"></span></p>
<p>Vamos lá. O nosso ecrã de selecção terá 3 abas que representam 3 grupos distintos de parâmetros. </p>
<p>Como o que tem que ser tem muita força, comecemos pela declaração de dados:</p>
<pre><code>
REPORT  zzz_nfg_selscreen_tabs2.

TABLES: kna1.

DATA: ucomm1 LIKE sy-ucomm,
      ucomm2 LIKE sy-ucomm,
      ucomm3 LIKE sy-ucomm.
</code></pre>
<p>A tabela KNA1 é declarada porque vai ser usada em SELECT-OPTIONS e as outras 3 variáveis são declaradas porque, embora como irão constatar, não sejam usadas para nada, é preciso declará-las senão o programa não compila.</p>
<p>Agora declaramos os 3 sub-ecrãs:</p>
<pre><code>
* Sub-ecrã: Filtros KNA1
SELECTION-SCREEN BEGIN OF SCREEN 3010 AS SUBSCREEN.
SELECT-OPTIONS: s_kunnr FOR kna1-kunnr,
                s_land1 FOR kna1-land1,
                s_ktokd FOR kna1-ktokd.
SELECTION-SCREEN END OF SCREEN 3010.

* Sub-ecrã: Opções
SELECTION-SCREEN BEGIN OF SCREEN 3020 AS SUBSCREEN.
PARAMETERS: p_opt1 AS CHECKBOX,
            p_opt2 AS CHECKBOX,
            p_opt3 AS CHECKBOX.
SELECTION-SCREEN END OF SCREEN 3020.

* Sub-ecrã: Ficheiro
SELECTION-SCREEN BEGIN OF SCREEN 3030 AS SUBSCREEN.
PARAMETERS: p_file TYPE rlgrap-filename DEFAULT '/ficheiro.txt'.
SELECTION-SCREEN END OF SCREEN 3030.
</code></pre>
<p>Agora que temos os sub-ecrãs definidos é só aplicá-los num TABBED BLOCK:</p>
<pre><code>
* Bloco normalíssimo só porque sim
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-b01.
PARAMETERS: p_uname TYPE uname OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.

* Tabbed strip
SELECTION-SCREEN BEGIN OF TABBED BLOCK tabs FOR 3 LINES.
SELECTION-SCREEN TAB (15) tab1 USER-COMMAND ucomm1 DEFAULT SCREEN 3010.
SELECTION-SCREEN TAB (30) tab2 USER-COMMAND ucomm2 DEFAULT SCREEN 3020.
SELECTION-SCREEN TAB (15) tab3 USER-COMMAND ucomm3 DEFAULT SCREEN 3030.
SELECTION-SCREEN END OF BLOCK tabs.
</code></pre>
<p>Como vês, é simples. As variáveis TAB1, TAB2 e TAB3 são declaradas implicitamente e deverão conter os títulos das abas. Já as variáveis UCOMM1, UCOMM2 e UCOMM3 têm de ser declaradas explicitamente e definem o comando que poderá ser usado no SELECTION-SCREEN OUTPUT (equivalente ao PAI dos ecrãs) para controlar qualquer coisa adicional, mas neste caso não as vamos usar para mais nada.</p>
<p>O primeiro bloco com o P_UNAME está ali só para mostrar que os TABBED BLOCKS podem conviver com outros blocos normais.</p>
<p>Só falta definirmos os títulos das abas:</p>
<pre><code>
INITIALIZATION.
  tab1 = 'Filtros KNA1'(t01).
  tab2 = 'Opções'(t02).
  tab3 = 'Ficheiro'(t03).
</code></pre>
<p>Já está. E o resultado é este:</p>
<p><img src="http://abapinho.com/wp-content/uploads/2012/01/ecra-seleccao-abas.png" alt="Ecrã de selecção com abas" title="Ecrã de selecção com abas" width="503" height="401" class="alignnone size-full wp-image-1351" /></p>
<p>A partir daqui é o START-OF-SELECTION e o resto do programa é igual ao que seria sem as abas. </p>
<p>Ainda está a milhas do Adobe Flex, mas é melhor do que nada.</p>
<p><i>Obrigado a <a href="http://www.flickr.com/photos/ensee/3092607303/">ensee_89</a> pela foto.</i></p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/WUtfZ5eM4lw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/01/ecra-seleccao-abas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/01/ecra-seleccao-abas/</feedburner:origLink></item>
		<item>
		<title>Debug em janelas de diálogo modais</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/LNW3kwhsKWQ/</link>
		<comments>http://abapinho.com/2012/01/debug-em-popups/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 10:00:29 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[segredo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1307</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/atirar-para-cima.png" class="attachment-thumbnail wp-post-image" alt="atirar-para-cima" title="atirar-para-cima" />Há determinados momentos em que não é possível fazer /H para iniciar o debugger. O caso mais comum é durante uma janela de diálogo modal (aquilo que os estrangeiros chamam de popup). Mas há uma forma simples, ainda que rocambolesca, para o conseguires: 1. Cria um ficheiro de texto com o seguinte conteúdo: [FUNCTION] Command=/H [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/atirar-para-cima.png" class="attachment-thumbnail wp-post-image" alt="atirar-para-cima" title="atirar-para-cima" /><p>Há determinados momentos em que não é possível fazer /H para iniciar o <i>debugger</i>. O caso mais comum é durante uma janela de diálogo modal (aquilo que os estrangeiros chamam de <i>popup</i>). Mas há uma forma simples, ainda que rocambolesca, para o conseguires:</p>
<p><span id="more-1307"></span></p>
<p>1. Cria um ficheiro de texto com o seguinte conteúdo:<br />
[FUNCTION]<br />
Command=/H<br />
Title=Debugger<br />
Type=SystemCommand</p>
<p>2. Grava o ficheiro numa pasta ou no ambiente de trabalho;</p>
<p>3. Arrasta (aquilo que os estrangeiros chamam de <i>drag and drop</i>) o ficheiro de onde o gravaste para cima da janela de diálogo ao mesmo tempo que gritas ABRACADABRA.</p>
<p>E assim, desta forma estrambólica, como que por magia, se tiveres gritado, o modo de <i>debug</i> será activado para teu regozijo.</p>
<p>É verdade que provavelmente já toda a gente conhece esta dica, mas é tão fundamental que me pareceu ser obrigação do Abapinho ensiná-la.</p>
<p>(Obrigado a <a href="http://www.flickr.com/photos/14617207@N00/4609793276/">alandberning</a> pela foto)</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/LNW3kwhsKWQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/01/debug-em-popups/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/01/debug-em-popups/</feedburner:origLink></item>
		<item>
		<title>O que diz uma mensagem?</title>
		<link>http://feedproxy.google.com/~r/blogabapinho/~3/RR_Uwufrnww/</link>
		<comments>http://abapinho.com/2012/01/texto-mensagem/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 10:00:15 +0000</pubDate>
		<dc:creator>Nuno Godinho</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[estilo]]></category>

		<guid isPermaLink="false">http://abapinho.com/?p=1298</guid>
		<description><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/postit.png" class="attachment-thumbnail wp-post-image" alt="postit" title="postit" />Queres obter o texto de uma mensagem da qual só sabes o ID e o número e não sabes como? Aprende aqui: DATA texto TYPE string. MESSAGE ID '00' TYPE 'E' NUMBER '163' WITH '123' INTO texto. É só isto. Agora do lado de dentro da variável texto encontras o seguinte texto: &#8220;O mandante 123 [...]]]></description>
			<content:encoded><![CDATA[<img width="150" height="150" src="http://abapinho.com/wp-content/uploads/2011/12/postit.png" class="attachment-thumbnail wp-post-image" alt="postit" title="postit" /><p>Queres obter o texto de uma mensagem da qual só sabes o ID e o número e não sabes como? Aprende aqui:</p>
<pre><code>
DATA texto TYPE string.
MESSAGE ID '00' TYPE 'E' NUMBER '163' WITH '123' INTO texto.
</code></pre>
<p>É só isto. Agora do lado de dentro da variável <i>texto</i> encontras o seguinte texto:</p>
<p>&#8220;O mandante 123 não existe no sistema&#8221;</p>
<p>Obrigado a <a href="http://www.flickr.com/photos/flatcat/3555774083/">Peteris B</a> pela foto.</p>
<p>O Abapinho saúda-vos.</p>
<img src="http://feeds.feedburner.com/~r/blogabapinho/~4/RR_Uwufrnww" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://abapinho.com/2012/01/texto-mensagem/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://abapinho.com/2012/01/texto-mensagem/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 3.727 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-20 09:34:01 -->

