EECVIEW

Exemplo de utilização da função EECVIEW ela sempre espera receber uma string neste caso sempre tratar se necessário.

No exemplo a seguir estou exibindo a descrição da TES de devolução da TES original de entrada 161

#INCLUDE "TOTVS.ch"
/*/{Protheus.doc} xprepAmb
	Preparando ambiente
	@type  Function user
	@author Cleiton Genuino da Silva
	@since 10/09/2021
	@version 12.1.23
	@param xEmpresa , CHARACTER , Empresa
	@param cRpcFil  , CHARACTER , Filial
	@return LOGICAL , Sempre verdadeiro
/*/
user function xprepAmb( aRpc )
	Local aTables  := {}
	Local cRpcEmp  := "04"
	Local cRpcFil  := "04 0039   "
	Default aRpc   := {}

	If len(aRpc) > 0
		cRpcEmp  := aRpc[1]
		cRpcFil  := aRpc[2]
	EndIf

	xautoMsg( "Preparando ambiente" , .T. , cRpcEmp , cRpcFil )

	While !RpcSetEnv(cRpcEmp,cRpcFil,/*cEnvUser*/,/*cEnvPass*/,/*cEnvMod*/,/*cFunName*/,aTables,.T.,.T.,.T.,.T.)
		xautoMsg( "Sem licenca para executar a rotina" , .T. , cRpcEmp , cRpcFil )
	End
	//PREPARE ENVIRONMENT EMPRESA cEmpresa FILIAL cFilial MODULO "FAT" //TABLES "ZIF","ZIG","ZIH"

	xautoMsg( "Ambiente preparado" )

	EECVIEW("TES:" + Posicione("SF4",1,xFilial("SF4")+'161',"F4_TESDV") )

return .T.
/*/{Protheus.doc} xautoMsg
	Funcao que executa conout
	@type  Function
	@author user Cleiton Genuino da Silva
	@since date 18/10/2018
	@version 12.1.17
	@param cMessage  , CHARACTER , Mensagem que sera apresentada no conout
	@param lCompleto , LOGICAL	 , Mensagem que sera apresentada no conout
	@param cRpcEmp  , CHARACTER , Empresa
	@param xFilial   , CHARACTER , Filial
	@return LOGICAL  , Se completo o log retorna verdadeiro senão falso
/*/
static function xautoMsg( cMessage , lCompleto , cRpcEmp , cRpcFil )

	default lCompleto	:= .F.

	if ( getSrvProfString( "SET_DEBUG" , "1" ) == "1" )

		if ( lCompleto )
			conout( "[SET LOG " + DtoC( date() ) + " - " + time() +  " Empresa: " + allTrim(cRpcEmp) + " Filial: " + allTrim(cRpcFil) + " ) ] " + allTrim(cMessage)+CRLF )
		else
			conout( "[SET LOG " + DtoC( date() ) + " - " + time() + " ] " + allTrim(cMessage)+CRLF )
		endif

	endif

return lCompleto

Tutorial: Como usar a classe PDO do PHP

Gabriel Martins

Um amigo meu e eu estávamos escrevendo códigos para um site que utilizava PHP para criar as API’s e o MySQL para fazer a conexão com o Banco de Dados. O meu amigo não utilizava o PDO por que não sabia como usar, e por isso estou criando esse tutorial, para ajudar as pessoas que como ele, não sabem utilizar a tão conhecida classe PDO presente no PHP.

● Habilitando o PDO

Se você está usando algum programa que crie um servidor web local, provalvelmente o PDO já estará habilitado nele, mas é sempre bom ter certeza. Para habilitar o PDO na sua máquina, é necessário que você encontre o caminho do arquivo php.ini e retire os comentários (;) das linhas a seguir.

  • Habilitando PDO no Windows
extension=php_pdo.dll
extension=php_pdo_mysql.dll
  • Habilitando PDO no Linux
extension=pdo.so
extension=pdo_mysql.so

● Instanciando e configurando a classe PDO

Primeiramente vamos criar a nossa estrutura de pastas para ficar um trabalho organizado:

+ php-pdo-tutorial/
• index.php
+ classes/
+ models/
• db.php

Após criar o nosso diretório, tudo relacionado ao banco de dados, iremos escrever no arquivo db.php.https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl2JHQzrwFCOw98rMA%2Ftwitter%2Fiframe&display_name=Giphy&url=https%3A%2F%2Fgiphy.com%2Fgifs%2Fgrease-live-grease-live-tell-me-more-l2JHQzrwFCOw98rMA&image=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2Fl2JHQzrwFCOw98rMA%2Fgiphy.gif&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=giphy

No arquivo db.php, vamos criar a nossa classe Models e criar uma instância da classe PDO:

Viu como é simples? Primeiro nós criamos uma variável pública chamada $pdo, depois iniciamos o nosso método construtor (Aquele método que é chamado assim que instanciamos uma classe), depois indicamos que a váriavel $pdo irá conter a instância da classe PDO.

Ao instanciarmos o PDO, é obrigatório passarmos 3 parâmetros para que ocorra tudo certo.

  • 1° Parâmetro: Nele você indica qual o seu host, se for um servidor local, o padrão é localhost, mas pode variar. E dbname que é o nome do seu banco de dados.
  • 2° Parâmetro: O segundo parâmetro é basicamente o nome de usuário que você usa para acessar o seu banco de dados. O padrão de nome de usuário para programas que criam um servidor local é root.
  • 3° Parâmetro: Assim como o segundo, o terceiro parâmetro também é bem simples, é a senha que você usa para acessar o seu banco de dados. Diferente do nome de usuário, por padrão o seu banco de dados local não usa nenhuma senha, ou seja a senha é uma string vazia (duas aspas simples ou duplas sem nenhum conteúdo dentro.

Observação: Você pode usar bancos de dados externos, alterando o host para o host que seu banco de dados está hospedado.

● Criando a nossa base de dados

Nesse tutorial irei usar o phpMyAdmin para criar a base de dados, mas você pode usar o que preferir, inclusive um terminal.

Primeiro clicamos em New (se encontra na barra lateral) para criarmos uma nova base de dados. Depois você coloca o nome da sua BD (base de dados) eu coloquei “meu_banco_de_dados” e escolhe o formato que preferir, o mais usado é o utf8-bin. E por último, clicamos em “Create” para criar a nossa BD.

Agora nós iremos criar uma tabela para a nossa BD, eu coloquei o nome “usuarios” observe que não utilizei nenhum acento e nem espaços, é uma boa prática para não ter problemas futuros, ao invés de espaço, utilize o _ (underline) para separar as palavras. Selecionamos o número de colunas, eu optei por escolher 4 colunas, para armazenar 4 dados de cada usuário.

  • 1° Coluna id: Para o id o tipo padrão é INT, pois será sempre um número inteiro de 1 ao infinito e além! id será incrementado automaticamente quando fizermos uma inserção no nosso banco de dados, ele é único para cada usuário, mais para frente você verá o quão útil ele é. Para o id ser incrementado automaticamente, devemos marcar a opção A_I (Auto Increment) na linha em que ele se encontra. Não é preciso colocarmos um tamanho para limitar ele, pois ele é uma row (linha) muito importante na nossa BD.
  • 2° Coluna nome: Para a coluna nome irei colocar o tipo VARCHAR que é basicamente o tipo “string” no MySQL, e o tamanho eu coloquei 255 que também é uma boa prática, e é mais que necessário 255 letras para o nome de alguém.
  • 3° Coluna email: A coluna email segue o mesmo raciocínio que a coluna nome, usei o tipo VARCHAR com um tamanho de 255 Chars (Caracteres).
  • 4° Coluna senha: A coluna senha será a responsável por armazenar a senha do usuário, ela será do tipo VARCHAR e assim como as outras colunas, essa também terá um valor de 255 Chars.

Depois clicamos em “Save” para salvar a nossa tabela.

● Inserindo valores na base de dados usando o PDO

Agora chegou a parte boa, a parte em que colocamos a mão no código.https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F29rsFlMw8wLlxOCPH1%2Ftwitter%2Fiframe&display_name=Giphy&url=https%3A%2F%2Fgiphy.com%2Fgifs%2Fpbskids-yes-excited-29rsFlMw8wLlxOCPH1&image=https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2F29rsFlMw8wLlxOCPH1%2Fgiphy.gif&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=giphy

No código acima eu criei uma função chamada insert_values (Insere valores), como o próprio nome diz, ela será usada para inserirmos valores na nossa BD.

$sql = "INSERT INTO usuarios (nome, email, senha) VALUES (?, ?, ?)";

Na linha acima, nós criamos uma variável que irá conter um código SQL, o código SQL sempre terá que estar entre aspas simples ou duplas.

  • INSERT: Esse comando indica que estamos querendo inserir algo na nossa base de dados.
  • INTO: Esse comando é um complemento para o comando INSERT, ele indica a tabela e as linhas que receberam os novos valores. INSERT INTO (Insira dentro de).
  • VALUES: Esse comando indica quais valores serão inseridos. Ah, mas por que os pontos de interrogação? O ponto de interrogação é uma prática utilizada para protegermos nossa base de dados de um ataque SqlInjection (Injeção de código Sql), depois nós usamos a função bindParam() para indicarmos o valor de cada ponto de interrogação.
$senha = md5($senha);

Aqui eu usei a função md5(), nativa do PHP, para criptografarmos a senha do usuário, para que ninguém tenha acesso à senha do usuário caso consiga de alguma forma, acesso ao banco de dados ou aos dados do mesmo. E também é necessário para evitar problemas no futuro com leis, por exemplo, a LGPD (Lei Geral de Proteção de Dados).

$bd = $this->pdo->prepare($sql);

Lembra daquela variável chamada $pdo que criamos lá no começo? Então agora nós iremos usar ela para utilizar as funções do PDO, criamos uma variável chamada $bd que recebe $this->pdo->prepare($sql).

  • $this: é uma Pseudo-variável do PHP, que usamos para referenciar uma função ou variável presente na nossa classe. $this->pdo faz referência a variável $pdo que guarda a instância do PDO.
  • $this->pdo->prepare(): O $this faz referência a variável $pdo, que chama a função prepare() do PDO.
$bd->bindParam(1, $nome);$bd->bindParam(2, $email);$bd->bindParam(3, $senha);

Agora que a variável $bd faz referência a função prepare() do PDO, nós podemos usá-la para chamar algumas funções referentes à função prepare(). Por exemplo a função bindParam que por padrão recebe 2 parâmetros.

  • 1° Parâmetro: A posição do valor, cada ponto de interrogação do VALUES (?, ?, ?) ocupa uma posição, cada posição faz referência à um valor do usuarios (nome, email, senha). O primeiro ponto de interrogação é para o nome, o segundo ponto de interrogação para o email, e segue essa regra para todos os valores.
  • 2° Parâmetro: O valor que será substituído pelo ponto de interrogação.
$bd->execute();

Na linha acima nós fazemos a chamada da função que executa todo o código SQL que fizemos.

● Inserindo na Base de Dados

Agora nós iremos voltar lá no arquivo index.php, que criamos anteriormente, e vamos criar uma instância da classe Models que fizemos.

No código acima, nós incluimos o arquivo db.php que contém a nossa classe Models, e depois criamos uma variável chamada $bd e atribuímos a instância da classe Models.

echo $bd->insert_values("Gabriel", "gabrielmrts@yahoo.com", "123123");

Depois disso, nós invocamos a função insert_values() que está presente na nossa classe Models, por padrão ela recebe 3 parâmetros, que são nomeemail e senha.

Ao acessar o arquivo index.php no nosso servidor local, todo o código é executado, e se tudo ocorrer certo, teremos esse retorno:

E quando vamos verificar na nossa Base de Dados:

https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FxT77XWum9yH7zNkFW0%2Ftwitter%2Fiframe&display_name=Giphy&url=https%3A%2F%2Fgiphy.com%2Fgifs%2F9jumpin-wow-nice-well-done-xT77XWum9yH7zNkFW0&image=https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2FxT77XWum9yH7zNkFW0%2Fgiphy.gif&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=giphy

Viu como é simples e prático utilizar o PDO?

● Fazendo consultas na base de dados

Para podermos consultar dados de usuários na nossa base de dados, usamos a função SELECT (Selecione).

As regras do PDO são basicamente as mesmas, primeiro usa prepare(), depois o execute() e depois é só tratar os dados, mas vamos linha por linha.

$sql = "SELECT * FROM usuarios";
  • SELECT: Indica que estamos querendo selecionar dados na base de dados para consumirmos eles.
  • FROM: Indica a tabela que queremos selecionar.
  • *: SELECT *, Selecione Tudo.

Traduzindo, SELECT * FROM usuarios significa SELECIONE TUDO DE usuarios.

E também podemos pegar apenas os dados que queremos:

SELECT nome, email FROM usuarios

Voltando ao código, agora temos algo de diferente, um laço de repetição.

while ($row = $bd->fetch(PDO::FETCH_OBJ))

Aqui nós atribuímos a variável $row à uma função do PDO, a fetch().
A função fetch recebe um parâmetro obrigatório, que é o método que você vai utilizar para receber os dados. No nosso caso o PDO::FETCH_OBJ que retorna para nós um objeto contendo o resultado da consulta, juntamente com os dados. O laço de repetição no nosso caso é usado para, enquanto houver dados, armazene-os dentro da variável $row.

if ($row){    return $row;}

Se existir $row ou seja, dados, retorne os dados :).

Veja que agora estamos usando o print_r() para mostrar na tela, isso por que o echo é feito apenas para mostrar strings e nós estamos recebendo um array da nossa função get_all() e o print_r() e var_dump() são feitos para mostrar não só strings mas também arrays.https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl4FAPaGGeB7D1LfIA%2Ftwitter%2Fiframe&display_name=Giphy&url=https%3A%2F%2Fgiphy.com%2Fgifs%2Ffilmeditor-the-end-airplane-movie-l4FAPaGGeB7D1LfIA&image=https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fl4FAPaGGeB7D1LfIA%2Fgiphy.gif&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=giphy

Se você leu até aqui é por que gostou do tutorial, né? Se quiser dar uma olhada no código, clica aqui.

Espero de coração, que esse tutorial tenha te ajudado de alguma forma, pois a intenção é ajudar o próximo.

Mas é isso galera, até a próxima ️❤️.

Renovar certificado no Xampp Server

Certificado está vencido conforme imagem acima

Retire o ; do inicio da chave extension=openssl e salve o arquivo

Criar o arquivo v3.ext na pasta C:\xampp\apache

Edite o arquivo com o notepad++ informando o texto a seguir

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost

Salve o arquivo

Edite o arquivo C:\xampp\apache\makecert.bat colocando a informação a seguir neste ponto 500 -sha256 -extfile v3.ext

Agora execute como administrador

Navegue pelo wizard informando os dados do seu ceritifcado

Renovado

Entre no executar digite certmgr.msc e vamos importar o certificado

Agora vou equalizar os nomes pois eu não sou dono deste dominio vou criar o certificado com CN= localhost

Considerações finais, sempre que utilizar um domínio lembrar de gerar o certificado no seu servidor com o CN= Comum Nome igual ao da url do domínio

Ex: https://www.g1.com o CN=g1 no certificado.

O exemplo acima usa o https://localhost CN=localhost

Como ainda não tenho um domínio não sei dizer se o www. deve ser integrado no CN quem quiser comentar no post fique a vontade.

Como faço para enviar um HTTP/2 POST pedido em PHP

Como habilitar o suporte HTTP / 2 no XAMPP

Como habilitar o suporte HTTP / 2 no XAMPP

HTTP / 2 é muito rápido em comparação com HTTP / 1.1 que é o protocolo que muitas pessoas ainda usam em 2021. Por exemplo, em nosso ambiente de desenvolvimento de XAMPP no Windows, você verá que o protocolo que ele usa é HTTP / 1.1 por exemplo, PHPMyAdmin:

PHPMyAdmin XAMPP HTTP / 1.1

Você pode ver facilmente o protocolo no Chrome Devtools clicando com o botão direito do mouse nos cabeçalhos da tabela e marcando a opção Protocolo. Embora estejamos trabalhando localmente com o XAMPP, se você quiser um desempenho ainda melhor, pode mudar para a versão 2 do protocolo.

Neste artigo, explicarei como habilitar facilmente o suporte HTTP / 2 localmente na instalação do XAMPP.

1. Crie um Virtualhost para o seu projeto com suporte HTTPS

HTTP / 2 não funciona sem HTTPS (protocolo seguro), tenha isso em mente . Portanto, para fornecer suporte para HTTP / 2, você precisa ter um VirtualHost que escuta na porta 443. Por exemplo, usando o certificado HTTPS padrão de XAMPP (que é inválido, você receberá um aviso no navegador, no entanto, você pode pular e funciona), você pode construir um VirtualHost que aponta para uma página HTML simples como esta:

# 1. Support for HTTP on http://127.0.0.40/
<VirtualHost 127.0.0.40:80>
    DocumentRoot "C:/xampp/htdocs/mywebsite"
    DirectoryIndex index.html

    <Directory "C:/xampp/htdocs/mywebsite">
        AllowOverride None
        Order Allow,Deny
        Allow from All
    </Directory>
</VirtualHost>
# 2. Support for HTTPS on https://127.0.0.40/
<VirtualHost 127.0.0.40:443>
    DocumentRoot "C:/xampp/htdocs/mywebsite"
    ServerName mywebsite
    SSLEngine on
    SSLCertificateFile "conf/ssl.crt/server.crt"
    SSLCertificateKeyFile "conf/ssl.key/server.key"
    <Directory "C:/xampp/htdocs/mywebsite">
        Options All
    	AllowOverride All
    	Require all granted
    </Directory>
</VirtualHost>

COPIAR TRECHO

Teoricamente, com um index.htmlarquivo no diretório especificado, o site deve estar acessível em https://127.0.0.40/ (para HTTPS, necessário para usar HTTP / 2) e http://127.0.0.40/ (para HTTP, o que obriga para HTTP / 1.1). Não cobriremos muito o suporte para HTTPS, pois você pode implementar isso com um certificado diferente, talvez um confiável e, portanto, o importante aqui é que o host precisa rodar sobre HTTPS para funcionar com a versão HTTP / 2.

2. Habilite mod_http2.so

Agora, a parte mais importante deste tutorial é habilitar HTTP / 2 no apache. Esta versão do HTTP é um módulo que você pode ativar facilmente, modificando o C:\xampp\apache\conf\httpd.confarquivo e procurando pela mod_http2.solinha e descomente (remova o # no início da linha):

# Uncomment the line that loads the http2 module to apache
LoadModule http2_module modules/mod_http2.so

COPIAR TRECHO

Isso habilitará o suporte para HTTP / 2 no Apache. Agora, por padrão, o apache ainda usará HTTP / 1.1 para VirtualHosts que rodam na porta 80 (HTTP) e para aqueles VirtualHosts que rodam na porta 443 sem a diretiva que indica que ele deve usar HTTP / 2. 

3. Habilite HTTP / 2

Existem 2 opções para habilitar HTTP / 2 para seus projetos, você pode aplicar aquela que melhor se adapta às suas necessidades:

A. Habilite HTTP / 2 globalmente

Se você deseja habilitar este protocolo globalmente, para que funcione com qualquer VirtualHost que você tenha com HTTPS e PHPMyAdmin no XAMPP, você só precisa adicionar a seguinte diretiva no final do  C:\xampp\apache\conf\httpd.confarquivo:

Protocols h2 h2c http/1.1

COPIAR TRECHO

E é isso, no entanto, se você precisar habilitá-lo para um host virtual específico, você também pode fazer isso.

B. Habilite HTTP / 2 apenas para um VirtualHost específico

Se você só precisa usar HTTP / 2 em um VirtualHost específico, também é viável. A única coisa que você precisa fazer é adicionar a diretiva:

Protocols h2 h2c http/1.1

COPIAR TRECHO

No início do VirtualHost que escuta na porta 443:

# Somewhere at your virtualhost
# C:\xampp\apache\conf\extra\httpd-vhosts.conf
<VirtualHost 127.0.0.40:80>
    DocumentRoot "C:/xampp7413/htdocs/mywebsite"
    DirectoryIndex index.html

    <Directory "C:/xampp7413/htdocs/mywebsite">
        AllowOverride None
        Order Allow,Deny
        Allow from All
    </Directory>
</VirtualHost>
<VirtualHost 127.0.0.40:443>
    # Enable HTTP/2 on this Vhost
    Protocols h2 h2c http/1.1
    # Rest of the configuration ...
    DocumentRoot "C:/xampp7413/htdocs/mywebsite"
    ServerName myproject
    SSLEngine on
    SSLCertificateFile "conf/ssl.crt/server.crt"
    SSLCertificateKeyFile "conf/ssl.key/server.key"
    <Directory "C:/xampp7413/htdocs/mywebsite">
        Options All
    	AllowOverride All
    	Require all granted
    </Directory>
</VirtualHost>

COPIAR TRECHO

Vou enfatizar mais uma vez, que este VirtualHost é apenas um exemplo que utiliza o certificado autoassinado do XAMPP. Você pode criar seu próprio certificado que seja confiável para o navegador e o sistema operacional.

4. Reinicie o Apache 

Finalmente, apenas reinicie o apache e o MySQL (apenas no caso) com o painel de controle do XAMPP:

Reinicie o Painel de Controle do Apache XAMPP

E depois tente acessar seu site no navegador e verifique seu protocolo! Por exemplo, se você habilitou o protocolo globalmente, deverá ser capaz de acessá-lo em https: // localhost / phpmyadmin /  (observe o HTTPS):

Chrome Skip SSL Verification Localhost

Em nosso caso, receberemos um aviso porque o certificado SSL do XAMPP é autoassinado, mas você pode pular o aviso e acessar o PHPMyAdmin localmente de qualquer maneira. Nas ferramentas de desenvolvimento do Google Chrome, você poderá verificar o protocolo de qualquer solicitação para que possamos verificar agora se nosso XAMPP está usando HTTP / 2:

PHPMyAdmin HTTP / 2 XAMPP Localhost

Boa codificação ❤️!

PHP – Sessão destrói depois de fechar o navegador

Embora essa questão tenha várias soluções, não consegui encontrar uma solução adequada para mim. Precisa de ajuda.

Eu usei ini_set('session.cookie_lifetime', 0); no meu arquivo de configuração.

Mas isso não está me ajudando a destruir a sessão no fechamento do navegador. 

Fluxo de corrente da aplicação:

1) Na página de autenticação, se o usuário for válido, gere um novo identificador de sessão usando 

session_regenerate_id(true);

2) O controle vai para welcome.php onde inicio uma nova sessão usando session_start();

3) no código da página de logout é 

      $_SESSION = array();
      if (ini_get("session.use_cookies")) {
        $params = session_get_cookie_params();
        setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
      );
     }
    // Finally, destroy the session.
    session_destroy();

A melhor maneira de fechar a sessão é: se não houver resposta para essa sessão após determinado intervalo de tempo. então feche. Por favor, veja este post e espero que isso resolva o problema. ” Como alterar o timeout da sessão em PHP? “ AnkitThe most convenient and reliable file storage serviceReceive your personal cloud storage with 2Gb of space for free

Use um keep alive.

No login:

session_start();
$_SESSION['last_action'] = time();

Uma chamada de ajax a cada poucos (ex .: 20) segundos:

windows.setInterval(keepAliveCall, 20000);

Lado do servidor keepalive.php:

session_start();
$_SESSION['last_action'] = time();

Em todas as outras ações:

session_start();
if ($_SESSION['last_action'] < time() - 30 /* be a little tolerant here */) {
  // destroy the session and quit
}

Existem diferentes maneiras de fazer isso, mas o servidor não pode detectar quando o navegador é fechado, então é difícil destruí-lo.

  • sessão de tempo limite.

Crie uma nova sessão com a hora atual ou adicione uma variável de hora à sessão atual. e, em seguida, verifique-o quando você iniciar ou executar uma ação para ver se a sessão deve ser removida.

session_start();
$_SESSION["timeout"] = time();
//if 100 seconds have passed since creating session delete it.
if(time() - $_SESSION["timeout"] > 100){ 
    unset($_SESSION["timeout"];
}

  • ajax

Faça o javascript executar uma chamada de ajax que excluirá a sessão, com onbeforeunload() uma função de javascript que chama uma ação final quando o usuário sai da página. Por alguma razão, isso nem sempre funciona.

  • excluí-lo na inicialização.

Se você quiser sempre que o usuário veja a página de login na inicialização após a página ser fechada, basta excluir a sessão na inicialização.

<? php
session_start();
unset($_SESSION["session"]);

Isso pode te ajudar

session_set_cookie_params(0);
session_start();

Seu cookie de sessão será destruído … então sua sessão será boa até que o navegador esteja aberto. por favor,

Há mais um “hack” usando o HTTP Referer (supomos que a janela do navegador foi fechada e o nome do domínio do referer atual e o nome do domínio da página atual não coincidem):

session_start();
$_SESSION['somevariable'] = 'somevalue';

if(parse_url($_SERVER["HTTP_REFERER"], PHP_URL_Host) != $_SERVER["SERVER_NAME"]){
    session_destroy();
}

Você pode fazer isso usando JavaScript acionando uma solicitação de ajax para o servidor para destruir a sessão no evento onbeforeunload acionado quando fechamos a guia, janela ou navegador.

Use o seguinte código para destruir a sessão: 

 <?php
    session_start();
    unset($_SESSION['sessionvariable']);
    header("Location:index.php");
    ?>

10 maiores clientes de cada mês nos últimos 2 anos

WITH TMP AS
(
    SELECT
        LEFT(D2_EMISSAO, 6) PERIODO,
        SUM(D2_TOTAL) D2_TOTAL,
        D2_CLIENTE,
        D2_LOJA,
        A1_NREDUZ
    FROM SD2990 D2
    JOIN SA1990 A1 
        ON D2_FILIAL = A1_FILIAL
        AND D2_CLIENTE = A1_COD
        AND D2_LOJA = A1_LOJA
        AND D2_TIPO = 'N'
        AND D2.D_E_L_E_T_ = ''
        AND A1.D_E_L_E_T_ = '' 
    JOIN SF4990 F4 
        ON F4_FILIAL = D2_FILIAL
        AND F4_CODIGO = D2_TES
        AND F4_DUPLIC = 'S'
        AND F4.D_E_L_E_T_ = ''
	GROUP BY LEFT(D2_EMISSAO, 6), D2_CLIENTE, D2_LOJA, A1_NREDUZ
),
AUX AS (
SELECT 
    *,
	ROW_NUMBER() OVER (PARTITION BY PERIODO ORDER BY D2_TOTAL DESC) TOPMES
FROM TMP
)
SELECT 
	*
FROM AUX
WHERE TOPMES <= 10
ORDER BY PERIODO, TOPMES

Programação Impressoras Térmicas

Considerações Iniciais

Este documento não tem o objetivo de ensinar ao leitor a programação “ADVPL”, nem a lógica de programação, pois neste caso presumimos que o leitor já tenha este conhecimento.

impressora_termica_zebra_rz400_leitor_codificador_de_rfid_uhf_integrado_6178_1_20140828162550

Neste documento serão apresentadas todas as funções necessárias para a geração e impressão de etiquetas com ou sem código de barras para impressoras térmicas.

Atualmente as funções para impressão térmica englobam as linguagem DPL, EPL, IPL  e ZPL, sendo estas linguagens totalmente transparentes para o programador. Sendo assim o programador em questão não precisa ser um conhecedor das linguagem de programação para impressoras térmicas descritas acima, desenvolvidas por seus fabricantes.

Onde:

  • DPL    é a linguagem de programação datamax;
  • EPL    é a linguagem de programação eltron;
  • IPL    é a linguagem de programação intermec;
  • ZPL    é a linguagem de programação zebra.

Sentido da Impressão

O sentido de impressão não é o mesmo para todas impressoras térmicas. Alguns fabricantes de impressoras diferem  o sentido de impressão um do outro, tendo suas próprias justificativas, podendo elas ser desempenho, qualidade ou até facilidade para o desenvolvedor.

Quando falamos em sentido de impressão, também é importante falarmos do ponto de origem (0,0) no posicionamento do desenho de imagens, linhas e textos, pois isto também é definido pelo fabricante tendo as mesmas regra justificadas por ele.

Abaixo são apresentadas os sentidos de impressão e ponto de origem para os padrões de programação e impressoras homologadas.

Padrão Zebra e Eltron (Programação ZPL e EPL)

ZPL

A figura 01 ilustra o eixo cartesiano de trabalho, o ponto de origem do eixo cartesiano e principalmente o ponto de origem para inicio do texto ou figura, a qual fica no canto superior esquerdo ( de cima para baixo) conforme figura 01.

OBS: Alguns modelos de impressoras ELTRON, possuem o alinhamento da folha de etiqueta centralizado, por isso deve-se considerar o ponto de impressão da posição+a margem.

2.2. Padrão Datamax (Programação DPL )

DPL

Note na figura 02 que o quadrante do eixo cartesiano do padrão datamax é diferente do quadrante do eixo cartesiano da intermec e zebra. Também é importante observar que o ponto de origem para o desenho do texto ou figura inicia no canto inferior esquerdo do texto ou figura (ou seja, de baixo para cima do texto ou figura), diferentemente do padrão zebra e intermec.

Figura 02 – Apresentação do sentido de impressão da imagem na etiqueta padrão datamax.

2.3. Padrão Intermec (Programação IPL)

IPL

Note que o quadrante do eixo cartesiano do padrão intermec é diferente do quadrante do eixo cartesiano da datamax e da zebra. Porém é importante observar que o ponto de origem para o desenho do texto ou figura inicia no canto superior esquerdo do texto ou figura ( ou seja, a impressão do texto ou figura se dá de cima para baixo, a partir de sua origem), igual o padrão zebra e diferente do padrão datamax.

Figura 03 – Apresentação do sentido de impressão da imagem na etiqueta padrão Intermec.

3. Funções

 Nesta sessão serão descritos as funções necessárias para desenvolver imagens de etiqueta para impressoras térmicas.

Os parâmetros que estiverem entre [], significa que não são OBRIGATÓRIOS, os parâmetros que estiverem com (*), significa que é uso exclusivo ZPL.

3.1. MSCBPrinter

Objetivo:

            Permite realizar as configurções da impressora, as quais permitirão ao programador determinar as caracteristicas de impressão, definidas pelos parâmetros abaixo.

Sintaxe:

MSCBPRINTER(cModelPrt, cPorta, nDensidade, nTamanho, lSrv, nPorta, cServer, cEnv, nMemoria, cFila, lDrvWin, cPathSpool)

ParâmetrosDescrição
[cModelPrt]  String com o modelo de impressora:FabricanteImpressorasDatamaxALLEGRO, ALLEGRO 2, PRODIGY, DMX, DESTINY, URANO, DATAMAX, OS 214, OS 314, PRESTIGE, ARGOXEltronELTRON, TLP 2722, TLP 2742, TLP 2844, TLP 3742, C4-8IntermecINTERMEC, 3400-8, 3400-16, 3600-8, 4440-16, 7421C-8ZebraS300, S400, S500-6, S500-8, Z105S-6, Z105S-8, Z160S-6, Z160S-8, Z140XI, S600, Z4M, Z90XI, Z170XI, ZEBRA.
[cPorta]String com a porta
[nDensidade]Número com a densidade referente a quantidade de pixel por  mm. Este parâmetro só deve ser informado quando o parâmetro cModelPrt não for informado, pois cModelPrt o atualizará automaticamente. A utilização deste parâmetro deverá ser usado quando não souber o modelo da impressora, a aplicação entendera que se trata de uma impressora Zebra.  O tamanho da etiqueta será necessário quando a mesma não for continua.
[nTamanho]  Tamanho da etiqueta em Milímetros. Lembrando que este tamanho só deve ser passado se a etiqueta for continua.
[lSrv]           Se .t. imprime no server,.f. no client. O seu valor padrão é .f.
[nPorta]      Número da porta de outro server
[cServer]   endereço IP de outro server
[cEnv]   environment do outro server
[nMemoria]  Número com bloco de memória da impressora térmica. Caso seja enviada muita informação para a impressora, a fim que esta venha imprimir (sobrecarregando a memória), pode ocorrer perda de dados. Por outro lado, se for informado blocos muito pequenos de memória, implicará na diminuição da performance da impressora. Sendo assim o programador deverá fazer uma avaliação para ver o que melhor se adequa a sua situação.
[cFila]Diretório onde será gravada as filas
[lDrvWin]Indica se será utilizando os drivers do windows para impressão
[cPathSpool]Caminho do diretório onde serão geradas as filas de impressão

Exemplo usando o padrão de programação Zebra (família ZPL)

Local nXLocal cPorta/*configuracoes mais utilizadas de portacPorta := “COM2:9600,n,8,1”cPorta := “COM2:9600,n,8,2”cPorta := “COM2:9600,n,7,1”cPorta := “COM2:9600,n,7,2”cPorta := “COM2:9600,e,8,1”cPorta := “COM2:9600,e,8,2”cPorta := “COM2:9600,e,7,1”cPorta := “COM2:9600,e,7,2”cPorta := “LPT1”*/cPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)For nx:=1 to 3MSCBBEGIN(1,6)MSCBSAY(10,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBEND()NextMSCBCLOSEPRINTER()

3.2. MSCBClosePrinter

Objetivo:

Finaliza a conexão com a impressora.

Sintaxe:

MSCBClosePrinter()

Exemplo usando o padrão de programação Zebra (família ZPL):

Local cPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8″,cPorta,          , 40   ,.f.)For nx:=1 to 3MSCBBEGIN(1,6)MSCBSAY(10,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBEND()NextMSCBCLOSEPRINTER() 

3.3. MSCBBegin

Objetivo:

Inicializa a montagem da imagem para cada etiqueta.

Sintaxe:

 MSCBBEGIN(nxQtde,nVeloc,nTamanho,lSalva)

ParâmetrosDescrição                                                                                                           
[nQtde]  Quantidade de cópias
[nVeloc] Velocidade (1,2,3,4,5,6) polegadas por segundo
[nTamanho]Tamanho da etiqueta em Milímetros.
[lSalva]Variável utilizada somente para definição de form´s. O valor default da variável é .f.

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)For nx:=1 to 3MSCBBEGIN(1,6)         MSCBSAY(10,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBEND()NextMSCBCLOSEPRINTER() 

3.4. MSCBEnd

Objetivo:

Finaliza a montagem da imagem, que foi inicializada por um “MSCBBegin( )”.

Sintaxe:

MSCBEND()

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8″,cPorta,          , 40   ,.f.)For nx:=1 to 3MSCBBEGIN(1,6)MSCBSAY(10,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBEND()              NextMSCBCLOSEPRINTER() 

3.5. MSCBSay

Objetivo:

Imprime uma string.

Sintaxe:

MSCBSAY(nXmm, nYmm, cTexto, cRotacao, cFonte, cTam, lReverso, lSerial, cIncr, lZerosL, lNoAlltrim)

ParâmetroDescrição
nXmmPosição X em Milímetros
nYmmPosição Y em Milímetros
cTextoString a ser impresso ou itens especificando uma variável “@”.(Ex: “@2”).Obs: quando for especificado uma variável, o seu conteúdo deverá ser apenas o caractere “@” seguido de um número, “@1” ou “@2” e assim por diante. Vide item 3.15. 
cRotaçãoString com o tipo de Rotação (N,R,I,B):InstruçãoDescriçãoNNormalRCima para baixoIInvertidoBBaixo para cima
cFonteString com os tipos de Fonte:PadrãoTiposZebra(A,B,C,D,E,F,G,H,0) 0(zero)- fonte escalarDatamax(0,1,2,3,4,5,6,7,8,9) 9 – fonte escalarEltron(0,1,2,3,4,5)Intermec(0,1,7,20,21,22,27)
cTamString com o tamanho da Fonte
*[lReverso]Imprime  em reverso quando tiver sobre um box preto
[lSerial]Serializa o código
[cIncr]  Incrementa quando for serial positivo ou negativo
*[lZerosL]Coloca zeros a esquerda no numero serial
[lNoAlltrim]Permite brancos a esquerda e direita

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)For nx:=1 to 3MSCBBEGIN(1,6)MSCBSAY(10,06,”CODIGO”,”N”,”A”,”015,008″)   MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)   MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBEND()NextMSCBCLOSEPRINTER() 

3.6. MSCBSayBar

Objetivo:

Imprime código de barras.

Sintaxe:

MSCBSAYBAR(nXmm, nYmm, cConteudo, cRotacao, cTypePrt, nAltura, lDigVer, lLinha, lLinBaixo, cSubSetIni, nLargura, nRelacao, lCompacta, lSerial, cIncr, lZerosL)

ParâmetroDescrição
nXmmPosição X em Milímetros
nYmmPosição Y em Milímetros
cConteudoString a ser impressa especificando uma variável “@” ou array somente quando o parâmetro cTypePrt for igual á MB07.Definição do Array:cConteudo :={{“01″,”07893316010411”},;{“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;{“37″,”0004”},;{“21″,”000494”}}A possição 1 do array (ex: “01”) informa o AI utilizadado (que será visto no item 3.6.1. “Utilização do código de barras  128”).Já a possição 2 do array (ex: “07893316010411”) é o conteúdo do AI. 
cRotaçãoString com o tipo de Rotação:InstruçãoDescriçãoNNormalRCima para baixoIInvertidoBBaixo para cima
cTypePrtString com o Modelo de Código de Barras:InstruçãoModelo de Código de BarrasMB01Interleaved 2 of 5MB02Code 39MB03EAN 8MB04EAN 13MB05UPC AMB06UPC EMB07CODE 128Obs: Caso o leitor queira utilizar o modelo do padrão de programação da impressora, o mesmo deverá consultar documentação do fabricante. 
[nAltura]Altura do código de Barras em Milímetros
*[ lDigver]Imprime dígito de verificação
[lLinha]   Imprime a linha de código
*[lLinBaixo]Imprime a linha de código acima das barras
[cSubSetIni]Utilizado no code128
[nLargura] Largura da barra mais fina em pontos default 3
[nRelacao]Relação entre as barras finas e grossas em pontos default 2
[lCompacta]Parâmetro fora de uso.
[lSerial]Serializa o código
[cIncr]  Incrementa quando for serial positivo ou negativo
[lZerosL]Coloca Zeros a esquerda do conteúdo. Este parâmetro só é valido quando lSerial estiver ativado (.t.).

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “LPT1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBLOADGRF(“SIGA.GRF”)For nx:=1 to 3MSCBINFOETI(“Exemplo 1″,”MODELO 1″)MSCBBEGIN(1,6)MSCBBOX(02,01,76,35)MSCBLineH(30,05,76,3)MSCBLineH(02,13,76,3,”B”)MSCBLineH(02,20,76,3,”B”)MSCBLineV(30,01,13)MSCBGRAFIC(2,3,”SIGA”)MSCBSAY(33,02,’PRODUTO’,”N”,”0″,”025,035″)MSCBSAY(33,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBSAYBAR(23,22,Strzero(nX,10),”MB07″,”C”,8.36,.F.,.T.,.F.,,2,1)MSCBEND()NextMSCBCLOSEPRINTER() 

3.6.1. Utilização do código 128

O código 128, permite a impressão de todos os 128 caracteres ASCII, incluindo caracteres alfanuméricos maiúsculos e minúsculos, bem como os caracteres de controle. Além disso existem alguns caracteres especiais que são de uso instrínseco ao código 128.

O código 128 está dividio em três subconjuntos: A, B e C dos quais apenas um está ativo de cada vez. Cada um dos códigos tem um sentido diferente dependendo do subconjunto ativo.

No protheus os subconjuntos A, B e C, são representados pelas funções MSCB128A( )MSCB128B( ) e MSCB128C( ) respectivamente.

subconjunto A possibilita a impressão de todos os caracteres alfanuméricos maiúsculos, caracteres de controle e caracteres especiais.

subconjunto B possibilita a impressão de todos os caracteres alfanuméricos maiúsculos, caracteres minúsculos, e caracteres especiais. Este subconjunto não possibilita a compactação, porém aceita quase todos os caracteres contidos na tabela ASCII.

subconjunto C é utilizado para duplicar a densidade de códigos com conteúdo apenas NUMÉRICO e número PAR de dígitos. Este aumento de densidade é obtido pela impressão de um conjunto de 100 pares de dígitos de 00 a 99 inclusive. Além disto permite a impressão de caracteres especiais. Ou seja o subconjunto C é utilizado para compactar o código de barras.

Sendo assim as funções MSCB128A( )MSCB128B( ) e MSCB128C( ) permitem efetuar uma mudança no conjunto dentro do símbolo (código de barras). Todos os caracteres que seguem o caractere de código (subconjuto A, B ou C) são codificados de acordo com o conjunto de caracteres correspondente, salvo quando se encontra um outro caracter do código do caracter shift, que é semelhante à tecla “shift lock” no teclado de uma máquina de escrever, porém isso é tratado internamente nas funções de geração de código de barras.

A função MSCB128A( ) modifica a codificação para o conjunto de caracteres A.

A função MSCB128B( ) modifica a codificação para o conjunto de caracteres B.

A função MSCB128C( ) modifica a codificação para o conjunto de caracteres C.

O caractere de mudança (shift) permite uma alterção no conjunto de caracteres para o caracter que o segue imediatamente no símbolo. Os caracteres subsequentes revertem para o conjunto de caracteres ativo anterior ao caracter de mudança. O carctere shift opera somente entre os subconjuntos A e B. Não é possível mudar para o subconjunto C, nem mudar a partir dele. O caractere shift é semelhante à tecla “shift” no teclado de uma máquina de escrever. A função no protheus para utilização do caractere de “shift” é MSCB128Shift( ).

Existe também, o caractere FNC 1, usado como separador quando estão concatenados vários AIs e seus campos de dados quando os AI´s são variáveis, é transmitido como caractere GS. O GS no protheus é representado pela função MsCB128GS( ). Os AI´s serão discutidos no item 3.6.2.

Lembrando ao leitor que o mesmo não deverá se preocupara com a função MSCB128Shift() e MSCB128GS(), pois as mesmas são tratadas internamente na geração do código de barras. O leitor deverá somente se preocupar em seguir alguns critérios apresentados no exemplo 02 do item 3.6.

3.6.2. IDENTIFICAÇÃO DE APLICAÇÃO (Ais)

O símbolo UCC/EAN-128 é uma simbologia extremamente flexível. Permite a representação de dados de comprimento variável e possibilita codificar várias informações em um símbolo do código de barras. Isso se denomina concatenação. Este tipo de código de barras é iniciado por um caractere “START” indicando a tabela – code “A”, “B” ou “C” vistos anteriormente e que permite a identificação de 128 caracteres ASCII, seguido do caractere “FNC1”, ex: “START” (Code C) “FNC1”. Este caractere duplo inicial não é visível para as pessoas, mas deve estar no início das barras para que seja possível o reconhecimento e tratamento da estrutura da simbologia: os Indicadores de Aplicação, caractere separador, Dígito Verificador e Stop.

Os Als são códigos que anunciam com exclusividade os dados que os sucedem, seu significado e seu comprimento. Os dados que aparecem após um AI podem abranger caracteres alfabéticos e/ou numéricos de qualquer comprimento, chegando em alguns formatos até trinta caracteres. Os campos de dados têm comprimento fixo ou variável, dependendo do AI.

Os atributos de dados relacionam-se com um item: um item comercial ou de transporte, e não possuem significado caso sejam isolados. Podem ser representados no UCC/EAN-128 usando-se AIs. Existe uma faixa de AIs para medidas de itens comerciais, nos quais o peso descrito é o peso líquido, e uma faixa de AIs para medidas de unidades de transportes, denominadas unidades logísticas, nas quais o peso descrito é o peso bruto.

A tabela a seguir foi extraída da lista completa como exemplo dos AIs. Observe que um deles representa um significado – “conteúdo” , uma senha – “título de dados” para sua identificação na aplicação; e um formato” para a representação dos dados n (numéricos) ou em an (alfanuméricos), fixos ou variáveis.

A representação de AIs numa mesma linha do código de barras é possível desde que respeitadas as regras de concatenação:

  •  Máximo de 48 caracteres numa mesma seqüência de dados (incluindo os AIs e caracter(es) separador(es) se tiver(em), mas excluindo os caracteres auxiliares e o dígito verificador);
  • Máximo de 165mm do símbolo, incluindo as margens de silêncio (para uma mesma linha de código de barras);
  • Uso do caractere separador “FNC1” depois de um AI de dado variável, quando concatenado com outro AI. A tabela a seguir identifica todos os Ais reconhecidos como tendo formato de dados fixos.

Os Identificadores de Aplicação que não aparecem nesta tabela deverão receber caractere separador (FNC1), quando anteceder qualquer outro AI numa concatenação. O caractere separador de dados FNC1 não aparece na representação humano-legível, mas deverá estar contido nas barras, a menos que o AI variável for o ultimo representado no código, pois neste caso o caractere “STOP” determina o final de representação.

Tabela de AI´s disponibilizada pela EAN:

AITítulo CompletoFormato
00Código de Série de Unidade Logístican2 +n18
01Número Global de item Comercialn2+n14
02GTIN de itens comerciais contidos em uma unidade logístican2+n14
10Número de Batch ou de loten2 + an..20
11¹Data de Produção (AAMMDD)n2+n6
12¹Data de Vencimento/ Pagamento (AAMMDD)n2+n6
13¹Data de Embalagem (AAMMDD)n2+n6
15¹Data de Durabilidade Mínima (AAMMDD)n2+n6
17¹Data de Durabilidade Máxima (AAMMDD)n2+n6
20Variante do Produton2+n2
21Número de Sérien2+an20
22Dados Secundários para Produtos Específicos do Setor de Saúden2+an..29
23²Número de lote (Uso Transitório)n3+n..19
240Identificação Adicional do Produto Atribuída pelo Fabricanten3+an..30
241Número de Clienten3+an..30
2504Número de Série Secundárion3+an..30
AITítulo CompletoFormato
2514Referência da Entidade de Origemn3+an..30
30Contagem Variáveln2+n..8
31-36³Medidas Comerciais e Logícasn4+n6
337³Quilos por metro quadradon4+n6
37Contagem de itens Comerciais Contidos numa Unidade Logístican2+n..8
390³Valor a Pagar – área monetária isoladan4+n..15
391³Valor a Pagar – com o código ISO de moedan4+n3+n..15
392nValor a Pagar por um item de medida variável – área monetária isoladan4+n..15
393nValor a Pagar por um item de medida variável – com o código ISO de moedan4+n3+n..15
400Número de Ordem de Compra do Clienten3+an..30
401Número de Consignaçãon3+an..30
402Número de Identificação do Despachon3+n17
403Código de Rotan3+an..30
410Número de Localização Global EAN/UCC “Despachar para – Entregar para”– destino imediaton3+n13
411Número Global de Localização EAN/UCC “Faturar para” “ Cobrar de”n3+n13
412Número Global de Localização EAN/UCC “ Comprado de”n3+n13
413Número Global de Localização EAN/UCC “Despachar para – Entregar para “– destino finaln3+n13
414Identificação de Local Físico Número Global EAN/UCC de Localizaçãon3+n13
415Número Global de Localização EAN/UCC da Parte que faturan3 + n13
420Código Postal dentro de uma única Autoridade Postal“Despachar para – Entregar para”n3+an20
421Código Postal com Código isso de País com 3 Dígitos“ Despachar” para – Entregar para “n3+n3+an9
422País de Origem de um Item Comercial – Padrão ISO 3166n3+n3
8001Produtos em Rolo – Largura, Comprimento, Diâmetro doCentro, Direção e Junçõesn4+n14
8002Identificador Eletrônico em Série para Telefones Celulares Móveisn4+an..20
8003Identificador Global de Ativo Retornáveln4+n14+an..16
8004Identificador Global de Ativo Individualn4+an..30
8005Preço por Unidade de Medidan4+n6
8006Identificação do Componente de um Item Comercialn4+n14+n2+n2
8007Número de Conta de Banco Internacionaln4+an..30
8018Número de Relação de Serviço Globaln4+n..18
8020Número de Referência de Boleto de Pagamenton4+an..25
8100Código Estendido de Cupom – NSC+ Código de oferta (USA/Canadá)n4+n1+n5
8101Código Estendido de Cupom – NSC+ Código de oferta + final do código de oferta (USA/Canadá)n4+n1+n5+n4
8102Código Estendido de Cupom – NSC (USA/Canadá)n4+n1+ n1
90***Informação Combinada Mutuamente entre Parceiros Comerciais (Incluindo FACT DIs)n2 +na..30
91-99Informação interna de Empresan2+na..30

Tabela 01 – Tabela de AI´s

Onde:

  1. Quando forem necessários apenas ano e mês, DD deve ser preenchido com “00”.
  2. Mais um dígito para a indicação de comprimento.
  3. Estes Als compreendem 4 dígitos. Os três primeiros dígitos identificam o objetivo do AI, e o quarto dígito indica a posição do

ponto decimal.

***. O título do dado “vigente “ deve ser especificado pelo emissor da informação.

Exemplo do código 128 usando o padrão de programação ZPL:

Local cPorta := “COM1:9600,N,8,1” MSCBPRINTER(“S500-8”,cPorta,,35)MSCBBEGIN(1,6)MSCBBOX(02,01,76,34,1)aConteudo :={{“01″,”07893316010411”},;{“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;{“37″,”0004”},;{“21″,”000494”}}MSCBSAYBAR(08,10,aConteudo,”N”,”MB07″,10,.F.,.T.,.F.,”C”,2,1,.F.)MSCBEND()MSCBCLOSEPRINTER() 

Note: O conteúdo é do tipo array.

3.7. MSCBBox

Objetivo:

Imprime um box.

Sintaxe:

MSCBBOX(nX1mm, nY1mm, nX2mm, nY2mm, nExpessura, cCor)

ParâmetroDescrição
nX1mmPosição X1 em Milímetros
nY1mmPosição Y1 em Milímetros
nX2mmPosição X2 em Milímetros
nY2mmPosição Y2 em Milímetros
[nEspessura]Numero com a espessura em pixel
*[cCor]    String com a Cor Branca ou Preta  (“W” ou “B”)

Exemplo usando o padrão de programação Zebra (família ZPL):

Local cPorta := “LPT1”MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBBEGIN(1,6)MSCBBOX(02,01,76,35)MSCBEND()MSCBCLOSEPRINTER() 

3.8. MSCBLineH

Objetivo:

Imprime uma linha horizontal.

Sintaxe:

MSCBLineH(nX1mm, nY1mm, nX2mm, nExpessura, cCor)

ParâmetroDescrição
nX1mmPosição X1 em Milímetros
nY1mmPosição Y1 em Milímetros
nX2mmPosição X2 em Milímetros
[nEspessura]Numero com a espessura em pixel
*[cCor]    String com a Cor Branca ou Preta  (“W” ou “B”)

Exemplo usando o padrão de programação Zebra (família ZPL):

Local cPorta := “LPT1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBBEGIN(1,6)MSCBLineH(30,05,76,3)MSCBLineH(02,13,76,3,”B”)MSCBEND()MSCBCLOSEPRINTER() 

3.9. MSCBLineV

Objetivo:

Imprime uma linha vertical.

Sintaxe:

MSCBLineV(nX1mm, nY1mm, nY2mm, nExpessura, cCor)

ParâmetroDescrição
nX1mmPosição X1 em Milímetros
nY1mmPosição Y1 em Milímetros
nY2mmPosição X2 em Milímetros
[nEspessura]Numero com a espessura em pixel
*[cCor]      String com a Cor Branca ou Preta  (“W” ou “B”)

Exemplo usando o padrão de programação Zebra (família ZPL):

Local cPorta := “LPT1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBBEGIN(1,6)MSCBLineV(30,01,13)MSCBEND()MSCBCLOSEPRINTER() 

3.10. MSCBLoadGraf

Objetivo:

Carrega uma imagem para memória da impressora.

Sintaxe:

MSCBLOADGRF(cImagem)

ParâmetroDescrição
cImagemNome do arquivo que será carregado, inclusive o path + nome completo + extensão

Observações:

Para o padrão Zebra, o arquivo do gráfico (cImagem) tem que ser do tipo GRF, gerado através de um PCX ou TIF no software fornecido pelo fabricante da zebra.

Para o padrão Intermec, o arquivo do gráfico (cImagem) tem que ser do tipo UDC, gerado através de um BMP ou TIF(não compactado) no software fornecido pelo fabricante da intermec.

Para o padrão Datamax, o arquivo do gráfico pode ser do tipo BMP, PCX, não sendo necessário ser convertido.

Para o padrão Eltron, o arquivo do gráfico tem que ser do tipo PCX, não sendo necessário ser convertido.

Exemplo do código 128 usando o padrão de programação ZPL:

Local cPorta := “LPT1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBLOADGRF(“SIGA.GRF”)MSCBBEGIN(1,6)MSCBGRAFIC(2,3,”SIGA”)MSCBEND()MSCBCLOSEPRINTER() 

3.11. MSCBGraphic

Objetivo:

Imprime gráfico que está armazenado na memória da impressora.

Sintaxe:

MSCBGRAFIC(nXmm, nYmm, cArquivo, lReverso)

ParâmetroDescrição
NXmmPosição X em Milímetros
NYmmPosição Y em Milímetros
cArquivoNome do gráfico que foi carregado na memória da impressora (não colocar a extensão do arquivo)
*[lReverso]Imprime  em reverso quando tiver  sobre um box preto

Exemplo usando o padrão de programação ZPL:

Local cPorta := “LPT1”MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBLOADGRF(“SIGA.GRF”)MSCBBEGIN(1,6)MSCBGRAFIC(2,3,”SIGA”)                  MSCBEND()MSCBCLOSEPRINTER() 

3.12. MSCBChkStatus

Objetivo:

Seta ou visualiza o controle de status do sistema com a impressora.

Sintaxe:

MSCBCHKStatus(lStatus)

ParâmetroDescrição
[lStatus]  Lógica ativa/desativa  o controle. Seu valor default é .t.

Observações:

Com o status ativado, sempre que a aplicação enviar qualquer informação para a impressora, será analisado o status, caso esteja com o buffer cheio, sem papel ou sem ribbon, o sistema aguardara até que os itens anteriores estejam solucionados. Caso haja uma incompatibilidade com o sistema operacional ou uma configuração inadequada, o mesmo poderá travar por não conseguir efetuar uma comunicação correta, caso isto ocorra, desative esta opção.

Exemplo usando o padrão de programação Zebra (família ZPL):

Local cPorta := “LPT1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBCHKSTATUS(.t.)MSCBBEGIN(1,6)MSCBLineV(30,01,13)MSCBEND()MSCBCLOSEPRINTER() 

3.13. MSCBInfoEti

Objetivo:

Grava informações para gerenciamento do MSCBSpool.

Sintaxe:

MSCBInfoEti(cDescr,cFiltro)

ParâmetroDescrição
cDescrDescrição que gerará informação no MSCBSpool para identificar a etiqueta.
cFiltroÉ utilizado para realizar filtros no MSCBSpool. Vide documentação MSCBSpool.

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “LPT1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)For nx:=1 to 3MSCBINFOETI(“Exemplo 1″,”MODELO 1”)MSCBBEGIN(1,6)MSCBSAY(05,05,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBEND()NextMSCBCLOSEPRINTER() 

3.14. MSCBWrite

Objetivo:

Permite enviar para porta uma linha de programação nativa da Impressora.

Sintaxe:

MSCBWrite(cConteudo)

ParâmetroDescrição
cConteudoLinha de programação nativa da impressora.

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “COM1:9600,N,8,1” MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBBEGIN(1,6)MSCBWrite(“^FXPARAMETROS GERAIS ^FS”)MSCBWrite(“^LL120”)MSCBWrite(“^LH30,30”)MSCBWrite(“^PRA”)MSCBWrite(“^PQ10,2,,N”)MSCBWrite(“^FXCONTEUDO DA ETIQUETA^FS”)MSCBWrite(“^F01,1^GB250,90,10^FS”)MSCBWrite(“^F035,40^ADN,18,10^FDMicrosiga Software S/A^FS”)MSCBEND()MSCBCLOSEPRINTER() 

3.15. MSCBVar

Objetivo:

Cria variáveis para serem utilizadas nos form´s (imagem) da etiqueta. Sendo assim podemos criar para cada um dos campos (código de barras e textos) uma variável correspondente. Normalmente este recurso é utilizado somente em layout´s variáveis, ou seja, em campos que são alterados constatemente.

O uso de variáveis permite ao programador criar um layout padrão (form) o qual será enviado para a impressora térmica, e depois o mesmo somente enviará as alterações das variáveis, diminuindo a quantidade de dados que serão carregados na impressora. Isto fará com que a impressora use uma quantidade menor de memória, podendo com isto ter uma diminuição de erros provenientes do buffer de impressão e um aumento de performance (velocidade) na impressão.

Sintaxe:

MSCBVar(cVar,cDados)

ParâmetroDescrição
cVarNome da variável. Lembrando que o mesmo deverá ser incremental e sempre inicializar com “@”.( Exemplo: “@1”)
cdadosConteúdo da variável

Exemplo usando o padrão de programação Zebra (família ZPL):

Local nXLocal cPorta := “COM1:9600,N,8,1” MSCBPRINTER(“S500-8”,cPorta,          ,        ,.f. )MSCBLOADGRF(“SIGA.GRF”)MSCBBEGIN(2,6,nil,.T.)MSCBBOX(02,01,76,35)MSCBLineH(30,05,76,3)MSCBLineH(02,13,76,3,”B”)MSCBLineH(02,20,76,3,”B”)MSCBLineV(30,01,13)MSCBGRAFIC(2,3,”SIGA”)MSCBSAY(33,02,’PRODUTO’,”N”,”0″,”025,035″)MSCBSAY(33,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, “@1”, “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBSAYBAR(23,20,”@2″     ,”N”     ,”C”     ,8.36   ,.F.    ,.T.  ,.F.      ,          ,2       ,1       ,.F.,.f.,”1″,.T.)MSCBEND() For nx:=1 to 3MSCBINFOETI(“PRODUTO”,”MODELO 1″)MSCBBEGIN(10,,,.F.)MSCBVAR(“@1”,StrZero(nX,10))MSCBVAR(“@2”,StrZero(nX,10))MSCBEND()Next MSCBCLOSEPRINTER() 

Observação: Note no exemplo acima, que o primeiro bloco inicializado com MSCBBEGIN e finalizado com MSCBEND constroi o layout da etiqueta (form). Já o loop “For” imprime 3 etiquetas utilizando as variáveis que atualizam o código do produto e o código de barras, devinido com a variável “@1” e “@2” respectivamente.

4. Exemplos

4.1. Padrão Datamax

4.1.1. Exemplo 01

User Function ExDPL1()Local nXLocal cPorta := “COM1:9600,n,8,2” MSCBPRINTER(“ALLEGRO”,cPorta,          ,        ,.f. )MSCBLOADGRF(“SIGA.BMP”)For nx:=1 to 3MSCBINFOETI(“Exemplo 1″,”MODELO 1″)MSCBBEGIN(1,4)MSCBBOX(02,01,76,34,1)MSCBLineH(30,30,76,1)MSCBLineH(02,23,76,1)MSCBLineH(02,15,76,1)MSCBLineV(30,23,34,1)MSCBGRAFIC(2,26,”SIGA”)MSCBSAY(33,31,’PRODUTO’,”N”,”2″,”01,01″)MSCBSAY(33,27,”CODIGO”,”N”,”2″,”01,01″)MSCBSAY(33,24, Strzero(nX,10), “N”, “2”, “01,01”)MSCBSAY(05,20,”DESCRICAO”,”N”,”2″,”01,01″)MSCBSAY(05,16,”IMPRESSORA ALLEGRO 2 BR”,”N”, “2”, “01,01”)MSCBSAYBAR(22,03,Strzero(nX,10), , ,8.36,.F.,.T.,.F.,,3,2)MSCBEND()NextMSCBCLOSEPRINTER()Return

4.1.2. Exemplo 02

User Function EXDPL2()Local cPortacPorta := “COM1:9600,N,8,2”MSCBPRINTER(“ALLEGRO”,cPorta,          ,35      ,.f.)MSCBBEGIN()MSCBBOX(02,01,100,30)aConteudo :={{“01″,”07893316010411”},;{“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;{“37″,”0004”},;{“21″,”000494″}}MSCBSAYBAR(08,10,aConteudo,”N”,”MB07″,10,.F.,.T.,nil,’C’,3,2,.f.)MSCBEND()MSCBCLOSEPRINTER()Return

4.1.3. Exemplo 03

User Function ExDPL3()Local nXLocal cPorta := “COM1:9600,n,8,2”MSCBPRINTER(“ALLEGRO”,cPorta,          ,        ,.f. )MSCBLOADGRF(“SIGA.BMP”)MSCBBEGIN(1,4,,.t.)MSCBBOX(02,01,76,34,1)MSCBLineH(30,30,76,1)MSCBLineH(02,23,76,1)MSCBLineH(02,15,76,1)MSCBLineV(30,23,34,1)MSCBGRAFIC(2,26,”SIGA”)MSCBSAY(33,31,’PRODUTO’,”N”,”2″,”01,01″)MSCBSAY(33,27,”CODIGO”,”N”,”2″,”01,01″)MSCBSAY(33,24, “@1”, “N”, “2”, “01,01”)MSCBSAY(05,20,”DESCRICAO”,”N”,”2″,”01,01″)MSCBSAY(05,16,”IMPRESSORA ALLEGRO 2 BR”,”N”, “2”, “01,01”)MSCBSAYBAR(22,03,”@2″,”N”,”MB07″,8.36,.F.,.T.,.F.,,3,2,.F.)MSCBEND() For nx:=1 to 10MSCBINFOETI(“PRODUTO”,”MODELO 1″)MSCBBEGIN(10,,,.F.)MSCBVAR(“@1”,StrZero(nX,10))MSCBVAR(“@2″,StrZero(nX,10))MSCBEND()Next MSCBBEGIN(1,4,NIL,NIL)MSCBBOX(02,01,76,34,1)MSCBLineH(30,30,76,1)MSCBLineH(02,23,76,1)MSCBLineH(02,15,76,1)MSCBLineV(30,23,34,1)MSCBGRAFIC(2,26,”SIGA”)MSCBSAY(33,31,’TESTE FINAL’,”N”,”2″,”01,01″)MSCBSAY(33,27,”CODIGO”,”N”,”2″,”01,01″)MSCBSAY(33,24, “000001”, “N”, “2”, “01,01”)MSCBSAY(05,20,”DESCRICAO”,”N”,”2″,”01,01″)MSCBSAY(05,16,”IMPRESSORA ALLEGRO 2 BR”,”N”, “2”, “01,01”)MSCBSAYBAR(22,03,”000001″,”N”,”MB07″,8.36,.F.,.T.,.F.,,3,2,.F.)MSCBEND() MSCBCLOSEPRINTER()Return

4.2. Padrão Eltron

4.2.1. Exemplo 01

User Function EXEPL1()Local nXLocal cPorta:=”LPT1″MSCBPRINTER(“ELTRON”,cPorta,,,.F.)MSCBLOADGRF(“SIGA.PCX”)For nx:=1 to 3MSCBINFOETI(“Exemplo 1″,”MODELO 1″)MSCBBEGIN(1,6)MSCBGRAFIC(04,02,”SIGA”)MSCBBOX(05,01,76,30,2)MSCBLineH(30,06,71,2)MSCBLineH(05,12,71,2)MSCBLineH(05,18,71,2)MSCBLineV(30,1,12,2)MSCBSAY(33,02,’PRODUTO’,”N”,”2″,”1,2″)MSCBSAY(33,07,”CODIGO”, “N”, “1”, “1,1”)MSCBSAY(33,09,Strzero(nX,10), “N”,”1″,”1,2″)MSCBSAY(07,13,”DESCRICAO”,”N”,”1″,”1,1″)MSCBSAY(07,15,”IMPRESSORA ELTRON”,”N”,”1″,”1,2″)MSCBSAYBAR(28,19,Strzero(nX,10),’N’,’MB07′,06,.f.,.t.,,,2,2)MSCBEND()NextMSCBCLOSEPRINTER()Return

4.2.2. Exemplo 02

User Function EXEPL2()Local cPorta := “LPT1”MSCBPRINTER(“ELTRON”,cPorta,,,.F.)MSCBBEGIN(1,6)MSCBBOX(05,03,105,30,2)aConteudo :={{“01″,”07893316010411”},;{“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;{“37″,”0004”},;{“21″,”000494″}}MSCBSAYBAR(08,08,aConteudo,’N’,’MB07′,08,,.T.,NIL,”C”,2,2,,,,)MSCBEND()MSCBCLOSEPRINTER()Return

4.2.3. Exemplo 03

User Function EXEPL3()Local cPorta := “LPT1”Local nX MSCBPRINTER(“ELTRON”,cPorta,,,.F.)MSCBLOADGRF(“SIGA.PCX”)For nx:=1 to 1MSCBINFOETI(“ETI TESTE”,”PEQ”)MSCBBEGIN(3,6,,.t.)MSCBGRAFIC(04,02,”SIGA”)MSCBBOX(05,01,76,30,2)MSCBLineH(30,06,71,2)MSCBLineH(05,12,71,2)MSCBLineH(05,18,71,2)MSCBLineV(30,1,12,2) //Monta Linha VerticalMSCBSAY(33,02,’PRODUTO’,”N”,”2″,”1,2″)MSCBSAY(33,07,”CODIGO”, “N”, “1”, “1,1”)MSCBSAY(33  ,09  ,”0000001″, “N”   , “1”  , “1,2”,.T.    ,.t.    ,’+4′)MSCBSAY(07,13,”@1″,”N”,”1″,”1,1″)MSCBSAY(07,15,”IMPRESSORA ELTRON TLP2742″,”N”    ,”1″   , “1,2”)MSCBSAYBAR(28,19,”@2″     ,’N’     ,’MB07′  ,06     ,.f.    ,.t.  ,        ,      ,2   ,2)MSCBEND()NextFor nx:=1 to 4MSCBINFOETI(“ETI TESTE”,”PEQ”)MSCBBEGIN(10,,,.F.)MSCBVAR(“@1”,StrZero(nX,10))MSCBVAR(“@2”,StrZero(nX,10))MSCBEND()Next MSCBINFOETI(“ETI TESTE”,”PEQ”)MSCBBEGIN(3,6)MSCBGRAFIC(04,02,”SIGA”)MSCBBOX(05,01,76,30,2)MSCBLineH(30,06,71,2)MSCBLineH(05,12,71,2)MSCBLineH(05,18,71,2)MSCBLineV(30,1,12,2) //Monta Linha VerticalMSCBSAY(33,02,’PRODUTO’,”N”,”2″,”1,2″)MSCBSAY(33,07,”CODIGO”, “N”, “1”, “1,1”)MSCBSAY(33,09,”0000001″, “N”   , “1”  , “1,2”,.T.    ,.F.    ,’+4′)MSCBSAY(07,13,”teste da folha de rosto”,”N”,”1″,”1,1″)MSCBSAY(07,15,”IMPRESSORA ELTRON TLP2742″,”N”    ,”1″   , “1,2”)MSCBSAYBAR(28,19,”0000001″ ,’N’ ,’MB07′,06 ,.f. ,.t.  ,   ,”C”  ,2  ,2  ,.t. )MSCBEND() MSCBCLOSEPRINTER()Return

4.3. Padrão Intermec

4.3.1. Exemplo 01

User Function ExIPL1()Local nXLocal cPorta := “COM1:19200,E,7,1” MSCBPRINTER(“3600-8”,cPorta,,40,.f. )MSCBLOADGRF(“SIGA.UDC”)For nx:=1 to 3MSCBINFOETI(“Exemplo 1″,”MODELO 1″)MSCBBEGIN(1,5,,NIL)MSCBBOX(01,02,34,76,1)MSCBLineV(30,30,76,1)MSCBLineV(23,02,76,1)MSCBLineV(15,02,76,1)MSCBLineH(23,30,34,1)MSCBGRAFIC(34,02,”SIGA”,.T.)MSCBSAY(32,33,’PRODUTO’,”R”,”2″,”01,01″)MSCBSAY(29,33,”CODIGO”,”R”,”2″,”01,01″)MSCBSAY(26 ,33,StrZero(nX,10), “R”, “2”  ,”01,01″)MSCBSAY(22,05,”DESCRICAO”,”R”,”2″,”01,01″)MSCBSAY(19,05,”IMPRESSORA INTERMEC”,”R”, “2”, “01,01”)MSCBSAYBAR(12,22,StrZero(nX,10),”R”,”MB07″,8.36,.F.,.T.,.F.,,2,2)MSCBEND()NextMSCBCLOSEPRINTER()Return

4.3.2. Exemplo 02

User Function EXIPL2()Local cPorta := “COM1:19200,N,8,1”MSCBPRINTER(“3600-8”,cPorta,          ,35      ,.f.)MSCBBEGIN()MSCBBOX(02,01,30,100,3)aConteudo :={{“01″,”07893316010411”},;{“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;{“37″,”0004”},;{“21″,”000494″}}MSCBSAYBAR(20,08,aConteudo,”R”,”MB07″,10,.F.,.T.,nil,’C’,2,1,.f.)MSCBEND()MSCBCLOSEPRINTER()Return

4.3.3. Exemplo 03

User Function ExIPL3()Local nXLocal cPorta cPorta := “COM1:19200,E,7,1”MSCBPRINTER(“I3600”,cPorta,NIL       ,40       ,.f. )MSCBLOADGRF(“SIGA.UDC”) MSCBBEGIN(1,5,,.T.)MSCBINFOETI(“PRODUTO”,”MODELO 1″)MSCBBOX(01,02,34,76,1)MSCBLineV(30,30,76,1)MSCBLineV(23,02,76,1)MSCBLineV(15,02,76,1)MSCBLineH(23,30,34,1)MSCBGRAFIC(34,02,”SIGA”)MSCBSAY(32,33,’PRODUTO’,”R”,”2″,”01,01″)MSCBSAY(29,33,”CODIGO”,”R”,”2″,”01,01″)MSCBSAY(26,33,”@1″, “R”, “2”, “01,01”)MSCBSAY(22,05,”DESCRICAO”,”R”,”2″,”01,01″)MSCBSAY(19,05,”PARAFUSO 1/4 POLEGADAS”,”R”, “2”, “01,01”)MSCBSAYBAR(12,22,”@2″,”R”,”MB07″,8.36,.F.,.T.,.F.,,2,2)MSCBEND() For nx:=1 to 10MSCBBEGIN(,,,.F.)MSCBINFOETI(“PRODUTO”,”MODELO 1″)MSCBVAR(“@1”,StrZero(nX,10))MSCBVAR(“@2”,”999″+StrZero(nX,7))MSCBEND()Next MSCBINFOETI(“PRODUTO”,”MODELO 1″)MSCBBEGIN(2,6,,NIL)MSCBBOX(01,02,34,76,1)MSCBLineV(30,30,76,1)MSCBLineV(23,02,76,1)MSCBLineV(15,02,76,1)MSCBLineH(23,30,34,1)MSCBGRAFIC(2,26,”SIGA”,.T.)MSCBSAY(32,33,’PRODUTO’,”R”,”2″,”01,01″)MSCBSAY(29,33,”CODIGO”,”R”,”2″,”01,01″)MSCBSAY(26,33,”000010″, “R”   , “2”  , “01,01”,,.t.,”2″)MSCBSAY(22,05,”DESCRICAO”,”R”,”2″,”01,01″)MSCBSAY(19,05,”PARAFUSO 1/4 POLEGADAS”,”R”, “2”, “01,01”)MSCBSAYBAR(12,22,”000010″,”R”,”MB07″,8.36,.F.,.T.,.F.,,2,2,.F.)MSCBEND()MSCBCLOSEPRINTER()Return

4.4. Padrão Zebra

4.4.1. Exemplo 01

User Function EXZPL1()Local nXLocal cPortacPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8”,cPorta,          , 40   ,.f.)MSCBLOADGRF(“SIGA.GRF”)For nx:=1 to 3MSCBINFOETI(“Exemplo 1″,”MODELO 1″)MSCBBEGIN(1,6)MSCBBOX(02,01,76,35)MSCBLineH(30,05,76,3)MSCBLineH(02,13,76,3,”B”)MSCBLineH(02,20,76,3,”B”)MSCBLineV(30,01,13)MSCBGRAFIC(2,3,”SIGA”)MSCBSAY(33,02,’PRODUTO’,”N”,”0″,”025,035″)MSCBSAY(33,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, Strzero(nX,10), “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBSAYBAR(23,22,Strzero(nX,10),”MB07″,”C”,8.36,.F.,.T.,.F.,,2,1)MSCBEND()NextMSCBCLOSEPRINTER()Return

4.4.2. Exemplo 02

User Function EXZPL2()Local cPortacPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8”,cPorta,,35)MSCBBEGIN(1,6)MSCBBOX(02,01,76,34,1)aConteudo :={{“01″,”07893316010411”},;{“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;{“37″,”0004”},;{“21″,”000494″}}MSCBSAYBAR(08,10,aConteudo,”N”,”MB07″,10,.F.,.T.,.F.,”C”,2,1,.F.)MSCBEND()MSCBCLOSEPRINTER()Return

4.4.3. Exemplo 03

User Function EXZPL3()Local cPorta := “COM1:9600,N,8,1”MSCBPRINTER(“S500-8”,cPorta,          ,        ,.f. )MSCBLOADGRF(“SIGA.GRF”)MSCBBEGIN(2,6,nil,.T.)MSCBBOX(02,01,76,35)MSCBLineH(30,05,76,3)MSCBLineH(02,13,76,3,”B”)MSCBLineH(02,20,76,3,”B”)MSCBLineV(30,01,13)MSCBGRAFIC(2,3,”SIGA”)MSCBSAY(33,02,’PRODUTO’,”N”,”0″,”025,035″)MSCBSAY(33,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, “@1”, “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBSAYBAR(23,20,”@2″     ,”N”     ,”C”     ,8.36   ,.F.    ,.T.  ,.F.      ,          ,2       ,1)MSCBEND() For nx:=1 to 3MSCBINFOETI(“PRODUTO”,”MODELO 1″)MSCBBEGIN(10,,,.F.)MSCBVAR(“@1”,StrZero(nX,10))MSCBVAR(“@2″,StrZero(nX,10))MSCBEND()Next MSCBBEGIN(2,6,nil,nil)MSCBBOX(02,01,76,35)MSCBLineH(30,05,76,3)MSCBLineH(02,13,76,3,”B”)MSCBLineH(02,20,76,3,”B”)MSCBLineV(30,01,13)MSCBGRAFIC(2,3,”SIGA”)MSCBSAY(33,02,’PRODUTO’,”N”,”0″,”025,035″)MSCBSAY(33,06,”CODIGO”,”N”,”A”,”015,008″)MSCBSAY(33,09, “1”, “N”, “0”, “032,035”)MSCBSAY(05,17,”IMPRESSORA ZEBRA S500-8″,”N”, “0”, “020,030”)MSCBSAYBAR(23,20,”00000000002″ ,”N” ,”C” ,8.36 ,.F. ,.T.  ,.F. ,   ,2 ,1 )MSCBEND() MSCBCLOSEPRINTER()Return

KB2716442 Security Update for SQL Server 2012 Fails

Computador\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\110\ConfigurationState\SQL_DReplay_Controller de 2 para 1

Se necessário crie a chave de registro SQL_DReplay_Controller.reg e coloque o conteúdo a seguir.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\110\ConfigurationState]
“SQL_DQ_CLIENT_Full”=dword:00000001
“SQL_SNAC_CORE”=dword:00000001
“SQL_SNAC_SDK”=dword:00000001
“SQL_WRITER”=dword:00000001
“SQL_BOL_Components”=dword:00000001
“CommonFiles”=dword:00000001
“SQL_DTS_Full”=dword:00000001
“SQL_DReplay_Controller”=dword:00000001
“SQL_DReplay_Client”=dword:00000001
“CommonFiles_Loc”=dword:00000001
“MDSCoreFeature”=dword:00000001
“SQL_PowerShell_Engine_CNS”=dword:00000001
“SQL_BIDS_Full”=dword:00000001
“SQL_PowerShell_Tools_ANS”=dword:00000001
“SQL_SSMS_Adv”=dword:00000001
“Connectivity_Full”=dword:00000001
“SQL_SSMS_Full”=dword:00000001
“SDK_Full”=dword:00000001
“Tools_Legacy_Full”=dword:00000001
“RS_SHP_SharedService_Adv”=dword:00000001

Debug PHP 8 no Visual Code 1.53.0

Crie um arquivo phpinfo.php e salve na pasta C:\xampp\htdocs

Conteúdo do arquivo phpinfo.php :

<?php

phpinfo();

?>

Verifique se o serviço está no ar do seu servidor xampp acessando a sua pagina através do endereço local

No meu caso eu alterei a porta do meu servidor para 90 porém é fácil verificar em que porta o seu está olhe no monitor do xampp

Agora baixaremos o Xdebug no meu caso como utilizo o windows usaremos uma DLL o site é este para download https://xdebug.org/docs/install

O link de wizard ajuda a descobrir qual DLL você deve usar

https://xdebug.org/wizard

Como ele funciona você deve copiar o conteúdo todo da pagina do phpinfo e cola na caixa de texto e clicar em analise

Após a analise baixe a DLL indicada pelo wizard e salve na pasta de extensões do xampp

Agora renomei a DLL para php_xdebug.dll não se esqueça de liberar permissoes ao arquivo pois o sistema operacional windows 10 e outros vão bloquear

Clique como botão direito do mouse e desbloquei a DLL

Pronto agora ela esta desbloqueada e renomeada para php_xdebug.dll

Agora abra o seu php.ini

[XDebug]
zend_extension=php_xdebug.dll
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.client_host=127.0.0.1
xdebug.client_port=9000

Acrescente as linha citadas no fim do arquivo e salva as alterações.

Reinicie o serviço do seu servidor Apache Web

Acesse novamente a pagina do phpinfo.php role o arquivo e veja que agora a extensão está ativa

Pronto agora toda a configuração é no Visual Code

Baixe o vscode https://code.visualstudio.com/

Instale e ao termino ele abrirá automaticamente

Você terá que baixar algumas extensões do vscode

Eu utilizo essas para PHP e controle de fonte, no bloco digite o nome da extensão e depois instalar

Abra a pasta htdocs no vscode

Agora selecione o seu arquivo com dois cliques infophp.php, de dois cliques na linha phpinfo e ela ficara marcada com um ponto de parada para debug

Agora só falta o lançador do debug

{
    // Use o IntelliSense para saber mais sobre os atributos possíveis.
    // Focalizar para exibir as descrições dos atributos existentes.
    // Para obter mais informações, acesse: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "runtimeExecutable": "C:/xampp/php/php.exe",
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000,
        },
        {   "runtimeExecutable": "C:/xampp/php/php.exe",
	    "name": "Listen for XDebug",
	    "type": "php",
	    "request": "launch",
	    "port": 9000
	}

    ]
}

Após salvar e clicar em debugar o ponto de parada é respeitado no debug

Links uteis: https://github.com/felixfbecker/vscode-php-debug/issues/411

Links uteis: https://code.visualstudio.com/

Links uteis:https://xdebug.org/wizard

Links uteis: https://www.apachefriends.org/pt_br/index.html

VTKeyBoard teclas

 Inkey Codes
------------------------------------------------------------------------------

 Cursor Movement Keys                        | Editing Keys
---------------------------------------------+--------------------------------
 Uparrow, Ctrl-E             5  K_UP         | Del, Ctrl-G        7  K_DEL
 Dnarrow, Ctrl-X            24  K_DOWN       | Tab, Ctrl-I        9  K_TAB
 Leftarrow, Ctrl-S          19  K_LEFT       | Shift-Tab        271  K_SH_TAB
 Rightarrow, Ctrl-D          4  K_RIGHT      | Ins, Ctrl-V       22  K_INS
 Home, Ctrl-A                1  K_HOME       | Backspace, Ctrl-H  8  K_BS
 End,  Ctrl-F                6  K_END        | Ctrl-Backspace   127  K_CTRL_BS
 PgUp, Ctrl-R               18  K_PGUP       |-----------------------------------
 PgDn, Ctrl-C                3  K_PGDN       | Function Keys
 Ctrl-Leftarrow, Ctrl-Z     26  K_CTRL_LEFT  |----------------------------------
 Ctrl-Rightarrow, Ctrl-B     2  K_CTRL_RIGHT | F1, Ctrl-\        28  K_F1
 Ctrl-Home, Ctrl-]          29  K_CTRL_HOME  | F2                -1  K_F2
 Ctrl-End, Ctrl-W           23  K_CTRL_END   | F3                -2  K_F3
 Ctrl-PgUp, Ctrl-Hyphen     31  K_CTRL_PGUP  | F4                -3  K_F4
 Ctrl-PgDn, Ctrl-^          30  K_CTRL_PGDN  | F5                -4  K_F5
 Ctrl-Return                10  K_CTRL_RET   | F6                -5  K_F6
 Ctrl-ScrollLock             3  K_CTRL_C     | F7                -6  K_F7
 Esc, Ctrl-[                27  K_ESC        | F8                -7  K_F8
 Return, Ctrl-M             13  K_RETURN     | F9                -8  K_F9
 Enter, Ctrl-M              13  K_ENTER      | F10               -9  K_F10
-------------------------------------------------------------------------------
 Alt and Ctrl Keys
-------------------------------------------------------------------------------
 Alt-A  286 K_ALT_A| Alt-N 305 K_ALT_N| Ctrl-A  1 K_CTRL_A| Ctrl-N 14 K_CTRL_N
 Alt-B  304 K_ALT_B| Alt-O 280 K_ALT_O| Ctrl-B  2 K_CTRL_B| Ctrl-O 15 K_CTRL_O
 Alt-C  302 K_ALT_C| Alt-P 281 K_ALT_P| Ctrl-C  3 K_CTRL_C| Ctrl-P 16 K_CTRL_P
 Alt-D  288 K_ALT_D| Alt-Q 272 K_ALT_Q| Ctrl-D  4 K_CTRL_D| Ctrl-Q 17 K_CTRL_Q
 Alt-E  274 K_ALT_E| Alt-R 275 K_ALT_R| Ctrl-E  5 K_CTRL_E| Ctrl-R 18 K_CTRL_R
 Alt-F  289 K_ALT_F| Alt-S 287 K_ALT_S| Ctrl-F  6 K_CTRL_F| Ctrl-S 19 K_CTRL_S
 Alt-G  290 K_ALT_G| Alt-T 276 K_ALT_T| Ctrl-G  7 K_CTRL_G| Ctrl-T 20 K_CTRL_T
 Alt-H  291 K_ALT_H| Alt-U 278 K_ALT_U| Ctrl-H  8 K_CTRL_H| Ctrl-U 21 K_CTRL_U
 Alt-I  279 K_ALT_I| Alt-V 303 K_ALT_V| Ctrl-I  9 K_CTRL_I| Ctrl-V 22 K_CTRL_V
 Alt-J  292 K_ALT_J| Alt-W 273 K_ALT_W| Ctrl-J 10 K_CTRL_J| Ctrl-W 23 K_CTRL_W
 Alt-K  293 K_ALT_K| Alt-X 301 K_ALT_X| Ctrl-K 11 K_CTRL_K| Ctrl-X 24 K_Ctrl_X
 Alt-L  294 K_ALT_L| Alt-Y 277 K_ALT_Y| Ctrl-L 12 K_CTRL_L| Ctrl-Y 25 K_Ctrl_Y
 Alt-M  306 K_ALT_M| Alt-Z 300 K_ALT_Z| Ctrl-M 13 K_CTRL_M| Ctrl-Z 26 K_CTRL_Z
-------------------------------------------------------------------------------
 Shift, Alt, and Ctrl-Function Keys
-------------------------------------------------------------------------------
 Shift-F1   -10  K_SH_F1  | Ctrl-F1   -20  K_CTRL_F1  | Alt-F1   -30 K_ALT_F1
 Shift-F2   -11  K_SH_F2  | Ctrl-F2   -21  K_CTRL_F2  | Alt-F2   -31 K_ALT_F2
 Shift-F3   -12  K_SH_F3  | Ctrl-F3   -22  K_CTRL_F3  | Alt-F3   -32 K_ALT_F3
 Shift-F4   -13  K_SH_F4  | Ctrl-F4   -23  K_CTRL_F4  | Alt-F4   -33 K_ALT_F4
 Shift-F5   -14  K_SH_F5  | Ctrl-F5   -24  K_CTRL_F5  | Alt-F5   -34 K_ALT_F5
 Shift-F6   -15  K_SH_F6  | Ctrl-F6   -25  K_CTRL_F6  | Alt-F6   -35 K_ALT_F6
 Shift-F7   -16  K_SH_F7  | Ctrl-F7   -26  K_CTRL_F7  | Alt-F7   -36 K_ALT_F7
 Shift-F8   -17  K_SH_F8  | Ctrl-F8   -27  K_CTRL_F8  | Alt-F8   -37 K_ALT_F8
 Shift-F9   -18  K_SH_F9  | Ctrl-F9   -28  K_CTRL_F9  | Alt-F9   -38 K_ALT_F9
 Shift-F10  -19  K_SH_F10 | Ctrl-F10  -29  K_CTRL_F10 | Alt-F10  -39 K_ALT_F10

programArguments [“2″,”1”]

{
	"version": "0.2.0",
	"configurations": [
		{
			"type": "totvs_language_debug",
			"request": "launch",
			"name": "U_xFunDebug",
			"program": "U_xFunDebug",
			"smartclientBin": "C:/TOTVS/smartclient12/smartclient.exe",
			"isMultiSession": true,
			"enableTableSync": true,
			"programArguments": ["2","1"],
			"enableMultiThread": true,
			"enableProfile": false,
			"isAccessibilityMode": false,
			"doNotShowSplash": false,
			"language": "",
			"ignoreFiles": true
		}
	],
	"lastProgramExecuted": "U_xFunDebug"
}

SX3_VIRADA.dtc

Quando se grava alterações de campos no configurador o Protheus salva os dados na pasta “cfglog” dentro da protheus_data.

Copie o arquivo gerado no momento da edição e salve na pasta “system”.

Agora renomei o arquivo para SX3_VIRADA.dtc.

Para criar o campo no dicionario oficial acesse ativo/cadastro/lancamento padrao/ inclusao/entidades e rode o u_rel011()

MARS=1 Multiple Active Result Sets

Adicionar à TAG
[MSSQL]
MARS=1

O suporte ao MARS (Multiple Active Result Sets) está disponível a partir do SQL Native Client.
Esse recurso é necessário para a redução da quantidade de novas conexões abertas a cada nova query submetida pela aplicação.
Diante do exposto não utilize o SQL Server ODBC Driver.
Utilize o SQL Native Client ao criar uma fonte de dados ODBC para acesso ao Microsoft SQL Server.

Lembrando que deve-se comparar a DBapi.DLL do Appserver / DBacess e replicar o mais atualizado e copiá-lo nas duas pastas.

Meu IP público html

Crie um arquivo com o nome meuip.html abra no notepad++ ou notepad copie e cole o código abaixo e salve.

Agora basta abrir em qualquer navegador

<HTML>
	<HEAD>
		<TITLE>Cleiton Genuino da Silva</TITLE>
		<script language="javascript">
				function Informacao()
				{
				/* Informações do Cliente - Copyleft (2009) - Cleiton Genuino da Silva

				tubas007@gmail.com

				Você pode distribuir, utilizar e alterar livremente estas rotinas desde
				que mantenha este comentário que identifica o autor original.
				*/
				var so;
				var plataforma = navigator.platform;
				var browser=navigator.appName
				var b_version=navigator.appVersion;
				var version=parseFloat(b_version);
				if(navigator.userAgent.indexOf('Linux') != -1)
				so = "Linux";
				else if((navigator.userAgent.indexOf('Win')!= -1)&&(navigator.userAgent.indexOf('95')!= -1))
				so = "Windows 95";
				else if((navigator.userAgent.indexOf('Win')!= -1)&&(navigator.userAgent.indexOf('98')!= -1))
				so = "Windows 98";
				else if((navigator.userAgent.indexOf('Win')!= -1)&&(navigator.userAgent.indexOf('NT')!= -1))
				so = "Windows NT/XP";
				else if((navigator.userAgent.indexOf('Win')!=-1)&&(navigator.userAgent.indexOf('2000')!=-1))
				so = "Windows 2000";
				else if(navigator.userAgent.indexOf('Mac') != -1)
				so = "Macintosh";
				else if(navigator.userAgent.toLowerCase().indexOf('unix') != -1)
				so = "Unix";
				else
				{ so = "Outro";}
				alert('So = '+so+'\nPlataforma = '+plataforma+'\n Browser = '+browser+'\nVersão = '+version)
				}
		</script>
	</HEAD>
	<BODY OnLoad="Informacao()">
	</BODY>
</HTML> 

Como postar código fonte no wordpress

Este é o meu primeiro post neste blog que tem como objetivo auxiliar os desenvolvedores menos experientes a resolver coisas simples, que por muitas vezes de tão simples, tornam-se complicadas… Se você está aqui, é porque sabe bem do que eu estou falando hehehe.

Bom, vamos lá.

O primeiro assunto deste blog será sobre uma pequena dúvida que tive ao criar o blog (sim, é meu primeiro blog ‘-‘ ): como eu posto o meu código fonte no wordpress?! Pode ser uma informação fácil de achar, até mesmo no próprio suporte do wordpress, de onde pesquisei sobre o assunto. Mas estou disponibilizando isso aqui para vocês, pois não encontrei a versão em português deste artigo do suporte.

Ao ver que a toolbar de edição de conteúdo não continha alguma marcação do tipo “code”, eu pensei em postar imagens dos códigos. Seria uma boa opção, pois forçaria os leitores a digitarem o código na mão caso desejassem usá-lo como exemplo. Mas eu também já precisei muito de exemplos, e sei como é chato as vezes ter de re-escrever o código todo ><”

Toolbar wordpress

Toolbar de edição de conteúdo do wordpress

Então fui atrás disso, e aqui está:

wordpress não permite que você faça upload do seu código fonte, pois isso pode apresentar perigo de várias formas (posteriormente posso escrever sobre isso, mas recomendo uma pesquisa sobre script injection), então a maneira que encontraram foi permitir que você escreva o seu código fonte dentro de um marcador sourcecode. Assim, o conteúdo que está entre o marcador é tratado de uma forma que não apresente perigo, pois o user agent (Interface com o usuário, um browser por exemplo.) não irá interpretá-lo como um código fonte.

Veja como é muito fácil, basta colocar seu código entre os seguintes marcadores:

[sourcecode language=”<a linguagem que você quer>“]

O seu código fonte aqui

[/sourcecode]

Um exemplo de código em java:

1public static void main(String[] args){}

Caso você não defina a linguagem a ser utilizada, o conteúdo entre os marcadores será exibido em forma de texto simples sem formatação.

Agora alguns parâmetros opcionais para utilizar dentro do marcador:

autolinks: Pode assumir os valores true e false. Quando true, torna todos os links que estiverem no seu código fonte, clicáveis. (Como default, essa opção já vem como true.)

collapse: Pode assumir os valores true e false. Quando true, faz com que a caixa que contém o seu código fonte seja carregada “compactada”, exibindo somente parte de todo o código. Quando o visitante clica na caixa, ela se expande, e todo o código fonte é exibido. (Como default, essa opção já vem como false.)

firstline: Recebe um valor numérico. Define qual será o número da primeira linha de código. (O valor padrão é 1)

gutter: Pode assumir os valores true e false. Quando true, o número da linha do código fonte é exibido. (Como default, essa opção já vem como true.)

highlight: Recebe uma lista de números separados por vírgulas, ex. “2,10,50,30”. Destaca linhas de código.

htmlscript: Pode assumir os valores true e false e só funciona com certas linguagensQuando true, todo o código html/xml ficarão destacados. É muito útil quando temos HTML misturado com scriptlets de java, php ou qualquer outra linguagem.

light: Pode assumir os valores true e false. Caso true, a toolbar e o número da linha serão ocultadas. Bom para quando o seu código fonte possui poucas linhas de código, deixando a caixa de código fonte mais limpa.

padlinenumbers: Pode assumir os valores truefalse e integer. Permite controlar o número de dígitos do número da linha de código. Caso true, o controle será automático, ex. 01, 02, 03. Caso false, o controle será desabilitado, ex. 1,2,3. Caso um número seja utilizado, serão utilizados os números de dígitos correspondentes. Ex. número 4, resultará em algo como isso: 0001.

toolbar: Pode assumir os valores true e false. Caso true, exibe opções (copiar, imprimir, etc.) quando o visitante posiciona o ponteiro do mouse em cima da caixa onde está o código fonte. (Como default, essa opção já vem como true.)

wraplines: Pode assumir os valores true e false. Caso false, a quebra de linha automática será desabilitada, fazendo com que apareça a barra de rolagem horizontal nas linhas de conteúdo muito extenso.

Essa marcação possui estilos de código para as seguintes linguagens:

  • ActionScript3
  • clojure
  • coldfusion
  • cpp
  • csharp
  • css
  • delphi
  • erlang
  • fsharp
  • diff
  • groovy
  • html
  • javascript
  • java
  • javafx
  • matlab (keywords only)
  • objc
  • perl
  • php
  • text
  • powershell
  • python
  • r
  • ruby
  • scala
  • sql
  • vb
  • xml

Bom, agora que você já sabe como adicionar código fonte formatado ao seu post, faça bom proveito!

Degubar SIGAACD Protheus – debug coletor de dados

Simulador de Coletor de Dados para módulo SIGAACD – Protheus

AVTMONITOR Totvs disponibiliza programas para que a implementação seja feita sem a necessidade de um Coletor de Dados fisicamente falando.

VTDEBUG – Programa para Simular/Debugar Rotinas para Coletor de Dados(ACD)

*Basta executar o comando VTDEBUG nos parâmetros iniciais do protheus:

Após isso abrirá a tela com o Simulador do Coletor de Dados:

VTMONITOR – Programa para monitorar os Usuários/Rotinas que estão conectados via Coletor de Dados.

Podemos simular um coletor de dados ativando a seção [Telnet] no arquivo appserver.ini.

[Telnet]
Enable=1
Main=u_coletaloja
Port=23
Environment=Environment

Entrar no prompt do S.O. e digitar o comando: Telnet ipdoserver e irá acessar o módulo SIGAACD.

Obs: Isso é possivel pois a comunicação entre o ERP e o Coletor é feita através do protocolo VT100 que por sua vez é o protocolo do Telnet.

Exemplo de um fonte:
#INCLUDE “sigaacd.ch”
#include “protheus.ch”
#include “apvt100.ch”

User Function ColetaLoja()
Local aUser
Local dGetData := MsDate()
Local tRealIni := Time()
Local aEmprx := {}
Local aEmpChoice := Array(2)
Local cTmp
Local nPos
Local cArqMenu
Local nMaxRow := Val(GetPvProfString( “TELNET”, “MAXROW” , “8” , GetADV97()))
Local nMaxCol := Val(GetPvProfString( “TELNET”, “MAXCOL” , “20”, GetADV97()))

MsApp():New(‘ColetaLoja’,.T.)
oApp:cInternet := NIL
oApp:lIsBlind := .T.
oApp:CreateEnv()

//seta tamanho da tela (linha X coluna)
VTSetSize(nMaxRow,nMaxCol)
TerProtocolo(“VT100”)
SetsDefault()
VTAlert(“Coleta de”+chr(13)+chr(10)+; //’Automacao de’
“Produtos”+chr(13)+chr(10)+; //’Coleta de Dados’
chr(13)+chr(10)+;
STR0004,’ColetaLoja’,.T.) //’Pressione <ENTER>’

//verifica se o arquivo de empresas existe
If !File(cArqEmp)
Final(STR0005,STR0006) //”Instale”###”Configurador”
EndIf

//verifica se o arquivo senhas exite
If !File(“SIGAADV.PSS”)
Final(STR0005,STR0006) //”Instale”###”Configurador”
EndIf

PtInternal(1,STR0008) //”Coletor RF”

//login
aUser := VTGetSenha(@dGetData,tRealIni)
aEmprx := Aclone(aUser[2][6])

//lista empresas
aEmpChoice := VTNewEmpr(@aEmprx)

dDataBase := dGetData

//acerta variaveis globais com informacoes do usuario
aEmpresas := Aclone(aUser[2][6])
__RELDIR := Trim(aUser[2][3])
__DRIVER := AllTrim(aUser[2][4])
__IDIOMA := aUser[2][2]
__GRPUSER := “”
__VLDUSER := aUser[1][6]
__ALTPSW := aUser[1][8]
__CUSERID := aUser[1][1]
__NUSERACS := aUser[1][15]
__AIMPRESS := {aUser[2][8],aUser[2][9],aUser[2][10],aUser[2][12]}
__LDIRACS := aUser[2][13]
cAcesso := Subs(cUsuario,22,512)
If __CUSERID #”000000″
nPos := Ascan(aUser[3],{|x| Left(x,2)==”46″})
If Empty(nPos)
Final(STR0009,STR0010) //”Acesso”###”Modulo nao encontrado”
EndIf
If Subs(aUser[3,nPos],3,1) ==”X”
Final(STR0009,STR0011) //”Acesso”###”Modulo nao autorizado”
EndIf
cArqMenu := Alltrim(Subs(aUser[3,nPos],4))
cArqMenu := Left(cArqMenu,len(cArqMenu)-4)
cArqMnu := cArqMenu+RetExtMnu()
VTAlert(cArqMnu,”Peonto”,.T.)
VTAlert(Left(cArqMenu,len(cArqMenu)-4),”Alert”,.T.)

Else
cArqMnu := “SIGAACD”+RetExtMnu()
VTAlert(cArqMnu,”Pronto”,.T.)
Endif
//cNivel := aUsuario[2]

VTCLEAR
PtInternal(1,STR0012+cEmpAnt+”/”+cFIlAnt+STR0013+Subs(cUsuario,7,15)+STR0014) //”Emp :”###” Logged :”###” Equip:Coletor RF”

//gerenciamento do menu
VTDefKey()
VTMontaMenu(cArqMnu)

Final(STR0007) //”Termino Normal”
Return

VTDEBUG

VT100_ATIVAR

VT100_LOGIN

OBS: Cuidado com caráter especial na senha, tente utilizar somente números.

Ponto de entrada – CBRETEAN – SIGAACD Protheus

P.E. CBRETEAN executado após o Enter na tela de conferencia física no coletor (ACDV120).

Entrada tipo: EAN via coletor
Retorno tipo: Array PARAMIXB

aRet “{código do produto,quantidade,lote,data de validade, numero de série}”

Para pegar os dados digitados e efetuar uma busca via Dbseek na SD1 e verificar se o produto tem lote e preencher o array de retorno, ele trás um array PARAMIXB

Consumindo APIs em ADVPL

#include "PROTHEUS.ch"
/*/{Protheus.doc} API0001
(Consome api de testes via ADVPL httpget)
@type user Function
@author Cleiton Genuino da Silva
@since date 13-08-2018
@version version 12-1-17
@param cUrl , Caracter , Url que contém o serviço da ser consumido
@param cGetParms , Caracter , Parametros da aplicação
@param nTimeOut , Numerico , Timeout da requisição http com a API a ser consumida
@param aHeadStr , Array , Array de dados a passado no cabeçalho da requisição
@param cHeaderGet , Caracter , Cabeçalho da requisição
@return cRetorno , Caracter , Retorno em caracter da api consumida
@example
(examples)
@see (http://tdn.totvs.com/display/tec/HTTPGet)
@see (http://tdn.totvs.com/display/tec/ProtheusDOC)
@see (http://tdn.totvs.com/display/PROT/FWJsonDeserialize+-+Deserializa+uma+string+no+formato+JSON)
/*/
User Function API0001()
local cUrl := "http://numbersapi.com/random/trivia"
local cGetParms := ""
local nTimeOut := 200
local aHeadStr := {"Content-Type: application/json"}
local cHeaderGet := ""
local cRetorno := ""
local oObjJson := nil
cRetorno := HttpGet( cUrl , cGetParms, nTimeOut, aHeadStr, @cHeaderGet )
If !FWJsonDeserialize(cRetorno,@oObjJson)
MsgStop("Ocorreu erro no processamento do Json")
Returnnil
endif
Msginfo( "O valor " + oObjJson:type + " para o numero " + Alltrim(Str(oObjJson:number)) + " equivale: " + oObjJson:text )
Return nil

startdebug

#INCLUDE “PROTHEUS.CH”

user function startdebug()

Local cIdEnt := ‘000003’
Local nIDJob := 4 //4 – e-Mail
Local cWFModelo :=’55’ //’ALL’
local cLock := “_debug_job”
local aLock := {}
local aEntSkip := {}

aadd( aLock, { cIdent, cLock, 0 } )
aEntSkip := StrTokArr(GetSrvProfString(“NFESPED_WFENT_SKIPRANGE”,””),”-“)

//GetURLCol(cAmbiente,cTipoWS)
//SPEDWF()
SpedWfNfe(cIdent,nIDJob,cWFModelo,aLock,aEntSkip)

Return()

Base de dados fica Status de Restaurando

Base de dados fica Status de Restaurando
SQL Server > Gerenciamento, Configuração, Instalação, e Segurança

Restore de base de dados;

Criei o arquivo .bak de uma base que usamos como modelo para ser restaurada na base de teste. Selecionei a base de teste, dei um restaurar> Banco de dados e selecionei o arquivo .bak que criei da base modelo. Agora a minha base de dados teste esta como single user e nao abre para eu poder mudar, e a base modelo esta com status (Restaurando…). Isso já vai fazer umas 12 horas.

Se você selecionou a opção NORECOVERY durante o seu restore FULL, basta executar o comando abaixo para mudar o status de restoring para online.

restore database NOME_BASE with RECOVERY

Treinamento DBA ONLINE:

http://www.fabriciolima.net/blog/cursos-online/treinamento-tarefas-do-dia-a-dia-de-um-dba-online/

Faz assim….

restore database [Nomedobanco]

from disk = ‘c:\backup\backup.bak’

with replace, recovery.

Para voce entender a diferença entre recovery e norecovery segue um link.

http://blog.sqlauthority.com/2009/07/15/sql-server-restore-sequence-and-understanding-norecovery-and-recovery/

SQL Server 2008 Keygen

Enterprise : JD8Y6-HQG69-P9H84-XDTPG-34MBB

Developer : PTTFM-X467G-P7RH2-3Q6CG-4DMYB

Standard : FXHQY-JQF42-68VVV-PYVVR-RY3BB

Web : T4CTV-PVXVP-JH7GV-FB8DV-YMH3Y

Workgroup : QGRPG-DPHXX-Q69PJ-BBG4T-CMBYB

Microsoft SQL Server 2008 Enterprise

JD8Y6-HQG69-P9H84-XDTPG-34MBB

Microsoft SQL Server 2008 Developer

PTTFM-X467G-P7RH2-3Q6CG-4DMYB

Microsoft SQL Server 2008 Standard

FXHQY-JQF42-68VVV-PYVVR-RY3BB

Microsoft SQL Server 2008 Web

T4CTV-PVXVP-JH7GV-FB8DV-YMH3Y

Microsoft SQL Server 2008 Workgroup

QGRPG-DPHXX-Q69PJ-BBG4T-CMBYB

Microsoft SQL Server 2012

748RB-X4T6B-MRM7V-RTVFF-CHC8H

Liberação do java no Browser

Caso alguém pegue o problema tanto no acesso do portal de Download quanto no momento de fazer o Download segue a dica:

1º Entre em Painel de controle -> Programas -> Java
 Aba “Avançado”
 Definições de Segurança Avançadas
Marque as opções:
• Usar formato ClientHello compatível com SSL 2.0
• Usar TLS 1.1
• Usar TLS 1.2

2ºAltere a permissão de Alta para Médio e Aplique.

3º Reinicie o Navegador e pode usar novamente!

Por que / Por quê / Porque ou Porquê?

O uso dos porquês é um assunto muito discutido e traz muitas dúvidas. Com a análise a seguir, pretendemos esclarecer o emprego dos porquês para que não haja mais imprecisão a respeito desse assunto.

Por que

O por que tem dois empregos diferenciados:

Quando for a junção da preposição por + pronome interrogativo ou indefinido que, possuirá o significado de “por qual razão” ou “por qual motivo”:

Exemplos: Por que você não vai ao cinema? (por qual razão)
Não sei por que não quero ir. (por qual motivo)

Quando for a junção da preposição por + pronome relativo que, possuirá o significado de “pelo qual” e poderá ter as flexões: pela qual, pelos quais, pelas quais.

Exemplo: Sei bem por que motivo permaneci neste lugar. (pelo qual)

Por quê

Quando vier antes de um ponto, seja final, interrogativo, exclamação, o por quê deverá vir acentuado e continuará com o significado de “por qual motivo”, “por qual razão”.

Exemplos: Vocês não comeram tudo? Por quê?
Andar cinco quilômetros, por quê? Vamos de carro.

Porque

É conjunção causal ou explicativa, com valor aproximado de “pois”, “uma vez que”, “para que”.

Exemplos: Não fui ao cinema porque tenho que estudar para a prova. (pois)
Não vá fazer intrigas porque prejudicará você mesmo. (uma vez que)

Porquê

É substantivo e tem significado de “o motivo”, “a razão”. Vem acompanhado de artigo, pronome, adjetivo ou numeral.

Exemplos: O porquê de não estar conversando é porque quero estar concentrada. (motivo)
Diga-me um porquê para não fazer o que devo. (uma razão)

Corretor ortográfico em Português no Eclipse

Fonte do post :http://www.actjava.com.br/2012/03/corretor-ortografico-em-portugues-no.html

Parabéns pelo post !!! A Microsan da todos os créditos ao criador do post

Eclipse, por padrão, disponibiliza dois dicionários em seu corretor ortográfico do editor de código: o dicionário em inglês padrão e o inglês do Reino Unido. Mas como isso não será de grande ajuda para nós brasileiros, que iremos documentar e comentar o nosso programa, no nosso idioma, vamos adicionar um dicionário personalizado em Português do Brasil no corretor ortográfico do Eclipse.
Abrindo o arquivo PrimeiroPrograma.java, verificamos que as palavras dos comentários estão sublinhadas em vermelho ondulado. Isso ocorre porque o corretor ortográfico do Eclipse está configurado para o idioma em inglês. Vamos configurar o corretor ortográfico com um dicionário personalizado para o nosso idioma.

Primeiro clique aqui para fazer o download do arquivo com o dicionário de palavras no nosso idioma.
Descompacte o arquivo na mesma pasta onde está instalado o Eclipse (no meu caso é: C:\Program Files (x86)\eclipse\indigo).
Entre no Eclipse e clique em Window >> Preferences.

Na janela a seguir selecione as opções:  General >> Editors >> Text Editors >> Spelling.

Em Platform dictionary selecione a opção none e clique em Browse…

Selecione o arquivo eclipse-pt_Br.dic e clique em abrir.

Voltando a janela anterior, verifique se o caminho do dicionário está correto no campo User defined dictionary e clique em OK para finalizar.

Feito o procedimento de forma correta, feche e abra novamente a arquivo PrimeiroPrograma.java, note que agora as palavras em nosso idioma não estão mais marcadas como incorretas.

Pronto, o dicionário personalizado foi configurado com sucesso, no nosso próximo encontro continuaremos com os fundamentos da linguagem Java. Até a próxima.

Ponto de Função

#INCLUDE “rwmake.ch”
////////////////////////////////////////////////////
/* PONTO DE ENTRADA RECLOCK(“SB5”,.T.)
//INCLLUSÃO RECLOCK(“SB5”,.F.)
//EXCLUSÃO/ALTERAÇÃO
*/ ////////////////////////////////////////////////////
User function MT010INC()
LOCAL aArea := GETAREA()
RECLOCK(“SB5”,.T.) //INCLLUSÃO
SB5->B5_FILIAL:= XFilial(“SB5”)
SB5->B5_COD:= SB1->B1_COD
SB5->B5_CEME:= SB1->B1_DESC msginfo(“Voce acabou de incluir um produto”) MSUNLOCK()
RestArea(aArea)
Return

Primeira aula ADVPL – EXEC01

//User Function usado para criar funções similres a sub Programas

User Function Exerc01()

Local aArray := {{“Maria”,10,7,15,31},;
{“Gisele”,26,26,26,26},;
{“Cleiton”,9,9,9,9},;
{“Jose”,15,16,21,33}}

Local nX := 0
Local cString:=””
for nX := 1 To  Len (aArray)

Msginfo(Calcula (aArray[nX]))

Next
Static Function Calcula (aArray)
Local nMedia:=0
Local cStatus:=””
Local cString:=””
nMedia := (aArray[2]+aArray[3]+aArray[4]+aArray[5])/4
Do case
Case nMedia >=25
cStatus :=”Aprovado”
case nMedia <10
cStatus :=”Reprovado”
case nMedia>=10 .And. nMedia <25
cStatus:=”Exame”

EndCase

Return cString:= aArray[1]+” – Media: “+cValToChar(nMedia)+” – “+cStatus

Return

Relatório de entrada e saída por tipo de produtos

#INCLUDE “rwmake.ch”
#INCLUDE “topconn.ch”
/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºPrograma ³NOVO2 º Autor ³ AP6 IDE º Data ³ 03/03/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescricao ³ Codigo gerado pelo AP6 IDE. º±±
±±º ³ º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ AP6 IDE º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/

User Function RELPROQ

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Declaracao de Variaveis ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Local cDesc1 := “Este programa tem como objetivo imprimir relatorio ”
Local cDesc2 := “de acordo com os parametros informados pelo usuario.”
Local cDesc3 := “RELATORIO DE PRODUTO x QUANTIDADE”
Local cPict := “”
Local titulo := “RELATORIO DE PRODUTO x QUANTIDADE”
Local nLin := 80

Local Cabec1 := “PRODUTO: QTDE. SAIDA: QTDE. ENTRADA:”
Local Cabec2 := “”
Local imprime := .T.
Local aOrd := {}
Private lEnd := .F.
Private lAbortPrint := .F.
Private CbTxt := “”
Private limite := 80
Private tamanho := “P”
Private nomeprog := “NOME” // Coloque aqui o nome do programa para impressao no cabecalho
Private nTipo := 18
Private aReturn := { “Zebrado”, 1, “Administracao”, 2, 2, 1, “”, 1}
Private nLastKey := 0
Private cbtxt := Space(10)
Private cbcont := 00
Private CONTFL := 01
Private m_pag := 01
Private wnrel := “NOME” // Coloque aqui o nome do arquivo usado para impressao em disco

Private cString := “SB1”

dbSelectArea(“SB1″)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Monta a interface padrao com o usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

wnrel := SetPrint(cString,NomeProg,””,@titulo,cDesc1,cDesc2,cDesc3,.T.,aOrd,.T.,Tamanho,,.T.)

If nLastKey == 27
Return
Endif

SetDefault(aReturn,cString)

If nLastKey == 27
Return
Endif

nTipo := If(aReturn[4]==1,15,18)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Processamento. RPTSTATUS monta janela com a regua de processamento. ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

RptStatus({|| RunReport(Cabec1,Cabec2,Titulo,nLin) },Titulo)
Return

/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºFun‡„o ³RUNREPORT º Autor ³ AP6 IDE º Data ³ 03/03/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescri‡„o ³ Funcao auxiliar chamada pela RPTSTATUS. A funcao RPTSTATUS º±±
±±º ³ monta a janela com a regua de processamento. º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ Programa principal º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/

Static Function RunReport(Cabec1,Cabec2,Titulo,nLin)

Local nOrdem
Local nTotal :=0
Local cEst := “”
Local cQuery := “”
Local nSubTotal :=0

dbSelectArea(cString)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ SETREGUA -> Indica quantos registros serao processados para a regua ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SetRegua(RecCount())

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Posicionamento do primeiro registro e loop principal. Pode-se criar ³
//³ a logica da seguinte maneira: Posiciona-se na filial corrente e pro ³
//³ cessa enquanto a filial do registro for a filial corrente. Por exem ³
//³ plo, substitua o dbGoTop() e o While !EOF() abaixo pela sintaxe: ³
//³ ³
//³ dbSeek(xFilial()) ³
//³ While !EOF() .And. xFilial() == A1_FILIAL ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
//Cria um indice temporario para o estado ao cria o indice ele é ordenado automaticamente
//IndRegua (“SA2″, cArqTemp,”A2_FILIAL+A2_EST”)
//FERASE (cArqTemp+OrdBagExt())
//=========================================================================
//==========================================================================
//QUERY
/*
cAlias := GetNextAlias()
cQuery := ‘ SELECT B1_COD,B1_DESC,SUM(D1_QUANT) ENTRADA, SUM(D2_QUANT) SAIDA ‘
cQuery += ” FROM SB1990 SB1, SD1990 SD1, SD2990 SD2 ”
cQuery += ” WHERE B1_COD = D1_COD AND B1_COD = D2_COD AND ”
cQuery += ” SB1.D_E_L_E_T_=” AND SD1.D_E_L_E_T_=” SD2.AND D_E_L_E_T_=” ”
cQuery += ” GROUP BY B1_COD,B1_DESC ”
cQuery += ” ORDER BY B1_COD ”
TCQUERY cQuery NEW ALIAS (cAlias)
*/
//=============================================================================
dbSelectArea(“SB1”)
dbGoTop()
cEst := B1_COD // Inicia a variavel que acumula o com o 1° estado vindo da tabela SA2
cCodProd := B1_COD
While !EOF()

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Verifica o cancelamento pelo usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If lAbortPrint
@nLin,00 PSAY “*** CANCELADO PELO OPERADOR ***”
Exit
Endif

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Impressao do cabecalho do relatorio. . . ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If nLin > 55 // Salto de Página. Neste caso o formulario tem 55 linhas…
Cabec(Titulo,Cabec1,Cabec2,NomeProg,Tamanho,nTipo)
nLin := 8
Endif

// Coloque aqui a logica da impressao do seu programa…
// Se o primeiro estado igual ao proximo imprime se não inicia contador de subtotal
/*
IF cEst B1_COD
nLin := nLin + 3
@ nLin, 00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
nLin := nLin + 2
nSubTotal := 0
cEst := B1_COD
ENDIF
*/
// Utilize PSAY para saida na impressora. Por exemplo:
// @nLin,00 PSAY SA1->A1_COD
nLin := nLin + 1 // Avanca a linha de impressao
// nTotal := nTotal + 1 //Totalizador de registros
// nSubTotal := nSubTotal + 1 //Totalizador de subtotais de registros

// @nLin,00 PSAY (cAlias)->B1_COD // @ para imprimir
// @nLin,10 PSAY (cAlias)->D2_QUANT
// @nLin,20 PSAY (cAlias)->D1_QUANT

aSaldo := MySaldo(B1_Cod)

@nLin, 00 PSAY SB1->B1_Cod+” – “+SB1->B1_Desc
@nLin,pcol ()+2 PSAY TRANSFORM (aSaldo [1], “@E 999,999”)
@nLin,pcol ()+2 PSAY TRANSFORM (aSaldo [2], “@E 999,999”)

dbSelectArea(“SB1”)
dbSkip() // Avanca o ponteiro do registro no arquivo
EndDo
@ nLin+3,00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
@ nLin+4,00 PSAY “TOTAL GERAL : “+ cValToChar(nTotal)
//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Finaliza a execucao do relatorio… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SET DEVICE TO SCREEN

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Se impressao em disco, chama o gerenciador de impressao… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If aReturn[5]==1
dbCommitAll()
SET PRINTER TO
OurSpool(wnrel)
Endif

MS_FLUSH()

Return

Static FUNCTION MySaldo(cCodProd)

Local cQuery := “”
Local aRetorno := {0,0}
Local cAliasD1 := GetNextAlias()
Local cAliasD2 := GetNextAlias()

cQuery := ” SELECT SUM(D1_QUANT) ENTRADA ”
cQuery += ” FROM “+RetSqlName(“SD1″) + ” ”
cQuery += ” WHERE D1_COD = ‘”+cCodProd+”‘ AND D_E_L_E_T_ = ” ”
TCQUERY cQuery NEW ALIAS (cAliasD1)

If !(cAliasD1)->(Eof())
aRetorno[1] := (cAliasD1)->Entrada
Endif
(cAliasD1)->(dbCloseArea())

cQuery := ” SELECT SUM(D2_QUANT) SAIDA ”
cQuery += ” FROM “+RetSqlName(“SD2″) + ” ”
cQuery += ” WHERE D2_COD = ‘”+cCodProd+”‘ AND D_E_L_E_T_ = ” ”
TCQUERY cQuery NEW ALIAS (cAliasD2)

If !(cAliasD2)->(Eof())
aRetorno[2] := (cAliasD2)->SAIDA
Endif
(cAliasD2)->(dbCloseArea())

Return ( aRetorno )

Ponto de Função

#INCLUDE “rwmake.ch”

////////////////////////////////////////////////////
/*
PONTO DE ENTRADA
RECLOCK(“SB5”,.T.) //INCLLUSÃO
RECLOCK(“SB5”,.F.) //EXCLUSÃO/ALTERAÇÃO
*/
////////////////////////////////////////////////////
user function MT010INC()
LOCAL aArea := GETAREA()
RECLOCK(“SB5”,.T.) //INCLLUSÃO
SB5->B5_FILIAL:= XFilial(“SB5”)
SB5->B5_COD:= SB1->B1_COD
SB5->B5_CEME:= SB1->B1_DESC
msginfo(“Voce acabou de incluir um produto”)
MSUNLOCK()
RestArea(aArea)
Return

Relatório de NFS com total por cliente

#INCLUDE “rwmake.ch”
#INCLUDE “topconn.ch”
/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºPrograma ³NOVO3 º Autor ³ AP6 IDE º Data ³ 03/03/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescricao ³ Codigo gerado pelo AP6 IDE. º±±
±±º ³ º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ AP6 IDE º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/

User Function RELFISCAL

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Declaracao de Variaveis ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Local cDesc1 := “Este programa tem como objetivo imprimir relatorio ”
Local cDesc2 := “de acordo com os parametros informados pelo usuario.”
Local cDesc3 := “RELETORIO DE NOTAS FISCAIS”
Local cPict := “”
Local titulo := “RELETORIO DE NOTAS FISCAIS”
Local nLin := 80
Local Cabec1 := “NF/SERIE: DT.EMISSAO: CLIENTE:”
Local Cabec2 := “ITEM PRODUTO QTDE. P.UNIT. P.TOTAL”
Local imprime := .T.
Local imprime := .T.
Local aOrd := {}
Private lEnd := .F.
Private lAbortPrint := .F.
Private CbTxt := “”
Private limite := 80
Private tamanho := “P”
Private nomeprog := “NOME” // Coloque aqui o nome do programa para impressao no cabecalho
Private nTipo := 18
Private aReturn := { “Zebrado”, 1, “Administracao”, 2, 2, 1, “”, 1}
Private nLastKey := 0
Private cbtxt := Space(10)
Private cbcont := 00
Private CONTFL := 01
Private m_pag := 01
Private wnrel := “NOME” // Coloque aqui o nome do arquivo usado para impressao em disco

Private cString := “SD2”

dbSelectArea(“SD2”)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Monta a interface padrao com o usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
//PERGUNTE (“RELSD2″,.F.) // PERGUNTE
wnrel := SetPrint(cString,NomeProg,””,@titulo,cDesc1,cDesc2,cDesc3,.T.,aOrd,.T.,Tamanho,,.T.)

If nLastKey == 27
Return
Endif

SetDefault(aReturn,cString)

If nLastKey == 27
Return
Endif

nTipo := If(aReturn[4]==1,15,18)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Processamento. RPTSTATUS monta janela com a regua de processamento. ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

RptStatus({|| RunReport(Cabec1,Cabec2,Titulo,nLin) },Titulo)
Return

/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºFun‡„o ³RUNREPORT º Autor ³ AP6 IDE º Data ³ 03/03/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescri‡„o ³ Funcao auxiliar chamada pela RPTSTATUS. A funcao RPTSTATUS º±±
±±º ³ monta a janela com a regua de processamento. º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ Programa principal º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/

Static Function RunReport(Cabec1,Cabec2,Titulo,nLin)

Local nOrdem
Local nSubTotal :=0
Local nTotal :=0
Local cEst := “”
Local cQuery := “”

dbSelectArea(cString)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ SETREGUA -> Indica quantos registros serao processados para a regua ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SetRegua(RecCount())

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Posicionamento do primeiro registro e loop principal. Pode-se criar ³
//³ a logica da seguinte maneira: Posiciona-se na filial corrente e pro ³
//³ cessa enquanto a filial do registro for a filial corrente. Por exem ³
//³ plo, substitua o dbGoTop() e o While !EOF() abaixo pela sintaxe: ³
//³ ³
//³ dbSeek(xFilial()) ³
//³ While !EOF() .And. xFilial() == A1_FILIAL ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
//Cria um indice temporario para o estado ao cria o indice ele é ordenado automaticamente
cArqTemp := CriaTrab(Nil,.F.)
//IndRegua (“SA2″, cArqTemp,”A2_FILIAL+A2_EST”)
//FERASE (cArqTemp+OrdBagExt())
//==========================================================================
//QUERY

cAlias := GetNextAlias() // Tabela temporaria para fazer o query
cQuery :=’ SELECT D2_ITEM,D2_DOC,D2_SERIE,D2_EMISSAO,D2_CLIENTE,D2_COD,D2_QUANT,D2_PRCVEN,D2_TOTAL,A1_NOME,B1_DESC ‘
cQuery +=” FROM ” + RetSqlName(“SD2″) + ” SD2, “+RetSqlName(“SA1″)+” SA1,”+RetSqlName(“SB1″)+” SB1″
cQuery +=” WHERE D2_CLIENTE = A1_COD AND D2_COD = B1_COD AND SD2.D_E_L_E_T_ = ” ”
TCQUERY cQuery NEW ALIAS (cAlias)

//=============================================================================
dbGoTop()
cEst := D2_CLIENTE // Inicia a variavel que acumula o com o 1° estado vindo da tabela SA2
While !EOF()

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Verifica o cancelamento pelo usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If lAbortPrint
@nLin,00 PSAY “*** CANCELADO PELO OPERADOR ***”
Exit
Endif

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Impressao do cabecalho do relatorio. . . ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If nLin > 55 // Salto de Página. Neste caso o formulario tem 55 linhas…
Cabec(Titulo,Cabec1,Cabec2,NomeProg,Tamanho,nTipo)
nLin := 8
Endif

// Coloque aqui a logica da impressao do seu programa…
// Se o primeiro estado igual ao proximo imprime se não inicia contador de subtotal
IF cEst D2_CLIENTE
nLin := nLin + 3
@ nLin, 00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
nLin := nLin + 2
nSubTotal := 0
cEst := D2_CLIENTE
ENDIF
// Utilize PSAY para saida na impressora. Por exemplo:
// @nLin,00 PSAY SA1->A1_COD
nLin := nLin + 1 // Avanca a linha de impressao
nTotal := nTotal + 1 //Totalizador de registros
nSubTotal := nSubTotal + 1 //Totalizador de subtotais de registros

@nLin,00 PSAY (cAlias)->D2_DOC // @ para imprimir
@nLin,05 PSAY (cAlias)->D2_SERIE
@nLin,10 PSAY (cAlias)->D2_EMISSAO
@nLin,20 PSAY (cAlias)->D2_CLIENTE
@nLin,25 PSAY (cAlias)->D2_ITEM // @ para imprimir
@nLin,30 PSAY (cAlias)->B1_DESC
@nLin,40 PSAY (cAlias)->D2_QUANT
@nLin,50 PSAY (cAlias)->D2_PRCVEN
@nLin,60 PSAY (cAlias)->D2_TOTAL

dbSkip() // Avanca o ponteiro do registro no arquivo
EndDo
@ nLin+3,00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
@ nLin+4,00 PSAY “TOTAL GERAL : “+ cValToChar(nTotal)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Finaliza a execucao do relatorio… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SET DEVICE TO SCREEN

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Se impressao em disco, chama o gerenciador de impressao… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If aReturn[5]==1
dbCommitAll()
SET PRINTER TO
OurSpool(wnrel)
Endif

MS_FLUSH()

Return

Relatório com totalizador individual por estado

#INCLUDE “protheus.ch”
#INCLUDE “topconn.ch”

/*
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºPrograma ³NOVO2 º Autor ³ AP6 IDE º Data ³ 25/02/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescricao ³ Codigo gerado pelo AP6 IDE. º±±
±±º ³ º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ AP6 IDE º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
*/

User Function RELF

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Declaracao de Variaveis ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Local cDesc1 := “Este programa tem como objetivo imprimir relatorio ”
Local cDesc2 := “de acordo com os parametros informados pelo usuario.”
Local cDesc3 := “CADASTRO DE FORNECEDORES”
Local cPict := “”
Local titulo := “CADASTRO DE FORNECEDORES”
Local nLin := 80

Local Cabec1 := “CODIGO NOME UF”
Local Cabec2 := “”
Local imprime := .T.
Local aOrd := {}
Private lEnd := .F.
Private lAbortPrint := .F.
Private CbTxt := “”
Private limite := 80
Private tamanho := “P”
Private nomeprog := “NOME” // Coloque aqui o nome do programa para impressao no cabecalho
Private nTipo := 18
Private aReturn := { “Zebrado”, 1, “Administracao”, 2, 2, 1, “”, 1}
Private nLastKey := 0
Private cbtxt := Space(10)
Private cbcont := 00
Private CONTFL := 01
Private m_pag := 01
Private wnrel := “NOME” // Coloque aqui o nome do arquivo usado para impressao em disco

Private cString := “SA2”

dbSelectArea(“SA2”)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Monta a interface padrao com o usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

PERGUNTE (“RELSA2″,.F.)
wnrel := SetPrint(cString,NomeProg,”RELSA2”,@titulo,cDesc1,cDesc2,cDesc3,.T.,aOrd,.T.,Tamanho,,.T.)

If nLastKey == 27
Return
Endif

SetDefault(aReturn,cString)

If nLastKey == 27
Return
Endif

nTipo := If(aReturn[4]==1,15,18)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Processamento. RPTSTATUS monta janela com a regua de processamento. ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

RptStatus({|| RunReport(Cabec1,Cabec2,Titulo,nLin) },Titulo)
Return

/*
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºFun‡„o ³RUNREPORT º Autor ³ AP6 IDE º Data ³ 25/02/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescri‡„o ³ Funcao auxiliar chamada pela RPTSTATUS. A funcao RPTSTATUS º±±
±±º ³ monta a janela com a regua de processamento. º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ Programa principal º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
*/

Static Function RunReport(Cabec1,Cabec2,Titulo,nLin)

Local nOrdem
Local nSubTotal :=0
Local nTotal :=0
Local cEst := “”
Local cQuery := “”

dbSelectArea(cString)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ SETREGUA -> Indica quantos registros serao processados para a regua ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SetRegua(RecCount())

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Posicionamento do primeiro registro e loop principal. Pode-se criar ³
//³ a logica da seguinte maneira: Posiciona-se na filial corrente e pro ³
//³ cessa enquanto a filial do registro for a filial corrente. Por exem ³
//³ plo, substitua o dbGoTop() e o While !EOF() abaixo pela sintaxe: ³
//³ ³
//³ dbSeek(xFilial()) ³
//³ While !EOF() .And. xFilial() == A1_FILIAL ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
//=========================================================================
//Cria um indice temporario para o estado ao cria o indice ele é ordenado automaticamente
cArqTemp := CriaTrab(Nil,.F.)
//IndRegua (“SA2″, cArqTemp,”A2_FILIAL+A2_EST”)

//FERASE (cArqTemp+OrdBagExt())
//==========================================================================
/*
cAlias := GetNextAlias() // Tabela temporaria para fazer o query

cQuery := ” SELECT * FROM “+RetSqlName(“SA2″) // Seleciona qual empresa da query da tabela
cQuery += ” WHERE D_E_L_E_T_ = ” ”
cQuery += ” ORDER BY A2_FILIAL, A2_EST”
*/
cAlias := GetNextAlias() // Tabela temporaria para fazer o query

cQuery := ” SELECT * FROM “+RetSqlName(“SA2″) // Seleciona qual empresa da query da tabela
cQuery += ” WHERE A2_COD between ‘”+MV_PAR01+”‘ AND ‘”+MV_PAR02+”‘”
cQuery += ” ORDER BY A2_FILIAL, A2_COD”

TCQUERY cQuery NEW ALIAS (cAlias)

dbGoTop()
cEst := A2_EST // Inicia a variavel que acumula o estado com o 1° estado vindo da tabela SA2
While !EOF()

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Verifica o cancelamento pelo usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If lAbortPrint
@nLin,00 PSAY “*** CANCELADO PELO OPERADOR ***”
Exit
Endif

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Impressao do cabecalho do relatorio. . . ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If nLin > 55 // Salto de Página. Neste caso o formulario tem 55 linhas…
Cabec(Titulo,Cabec1,Cabec2,NomeProg,Tamanho,nTipo)
nLin := 8
Endif

// Coloque aqui a logica da impressao do seu programa…
// Se o primeiro estado igual ao proximo imprime se não inicia contador de subtotal
IF cEst A2_EST
nLin := nLin + 3
@ nLin, 00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
nLin := nLin + 2
nSubTotal := 0
cEst := A2_EST
ENDIF

// Utilize PSAY para saida na impressora. Por exemplo:
// @nLin,00 PSAY SA1->A1_COD
nLin := nLin + 1 // Avanca a linha de impressao
nTotal := nTotal + 1 //Totalizador de registros
nSubTotal := nSubTotal + 1 //Totalizador de subtotais de registros

@nLin,00 PSAY (cAlias)->A2_COD // @ para imprimir
@nLin,10 PSAY (cAlias)->A2_NOME
@nLin,50 PSAY (cAlias)->A2_EST

dbSkip() // Avanca o ponteiro do registro no arquivo
EndDo
@ nLin+3,00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
@ nLin+4,00 PSAY “TOTAL GERAL : “+ cValToChar(nTotal)

//dbclosearea

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Finaliza a execucao do relatorio… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SET DEVICE TO SCREEN

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Se impressao em disco, chama o gerenciador de impressao… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If aReturn[5]==1
dbCommitAll()
SET PRINTER TO
OurSpool(wnrel)
Endif

MS_FLUSH()

Return

Relatório com totalizador individual por tipo de produto

#INCLUDE “rwmake.ch”
#INCLUDE “topconn.ch”

/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºPrograma ³NOVO3 º Autor ³ AP6 IDE º Data ³ 25/02/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescricao ³ Codigo gerado pelo AP6 IDE. º±±
±±º ³ º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ AP6 IDE º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/

User Function RELP

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Declaracao de Variaveis ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Local cDesc1 := “Este programa tem como objetivo imprimir relatorio ”
Local cDesc2 := “de acordo com os parametros informados pelo usuario.”
Local cDesc3 := “CADASTRO DE PRODUTOS”
Local cPict := “”
Local titulo := “CADASTRO DE PRODUTOS”
Local nLin := 80

Local Cabec1 := “CODIGO NOME TIPO”
Local Cabec2 := “”
Local imprime := .T.
Local aOrd := {}
Private lEnd := .F.
Private lAbortPrint := .F.
Private CbTxt := “”
Private limite := 80
Private tamanho := “P”
Private nomeprog := “NOME” // Coloque aqui o nome do programa para impressao no cabecalho
Private nTipo := 18
Private aReturn := { “Zebrado”, 1, “Administracao”, 2, 2, 1, “”, 1}
Private nLastKey := 0
Private cbtxt := Space(10)
Private cbcont := 00
Private CONTFL := 01
Private m_pag := 01
Private wnrel := “NOME” // Coloque aqui o nome do arquivo usado para impressao em disco

Private cString := “SB1”

dbSelectArea(“SB1”)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Monta a interface padrao com o usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

PERGUNTE (“RELSB1″,.F.)
wnrel := SetPrint(cString,NomeProg,”RELSB1”,@titulo,cDesc1,cDesc2,cDesc3,.T.,aOrd,.T.,Tamanho,,.T.)

If nLastKey == 27
Return
Endif

SetDefault(aReturn,cString)

If nLastKey == 27
Return
Endif

nTipo := If(aReturn[4]==1,15,18)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Processamento. RPTSTATUS monta janela com a regua de processamento. ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

RptStatus({|| RunReport(Cabec1,Cabec2,Titulo,nLin) },Titulo)
Return

/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±±
±±ºFun‡„o ³RUNREPORT º Autor ³ AP6 IDE º Data ³ 25/02/12 º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºDescri‡„o ³ Funcao auxiliar chamada pela RPTSTATUS. A funcao RPTSTATUS º±±
±±º ³ monta a janela com a regua de processamento. º±±
±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±±
±±ºUso ³ Programa principal º±±
±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/

Static Function RunReport(Cabec1,Cabec2,Titulo,nLin)

Local nOrdem
Local nSubTotal :=0
Local nTotal :=0
Local cEst := “”
Local cQuery := “”

dbSelectArea(cString)
dbSetOrder(1)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ SETREGUA -> Indica quantos registros serao processados para a regua ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SetRegua(RecCount())

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Posicionamento do primeiro registro e loop principal. Pode-se criar ³
//³ a logica da seguinte maneira: Posiciona-se na filial corrente e pro ³
//³ cessa enquanto a filial do registro for a filial corrente. Por exem ³
//³ plo, substitua o dbGoTop() e o While !EOF() abaixo pela sintaxe: ³
//³ ³
//³ dbSeek(xFilial()) ³
//³ While !EOF() .And. xFilial() == A1_FILIAL ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
//=========================================================================
//Cria um indice temporario para o estado ao cria o indice ele é ordenado automaticamente
cArqTemp := CriaTrab(Nil,.F.)
//IndRegua (“SA2″, cArqTemp,”A2_FILIAL+A2_EST”)

//FERASE (cArqTemp+OrdBagExt())
//==========================================================================
/*
cAlias := GetNextAlias() // Tabela temporaria para fazer o query

cQuery := ” SELECT * FROM “+RetSqlName(“SA2″) // Seleciona qual empresa da query da tabela
cQuery += ” WHERE D_E_L_E_T_ = ” ”
cQuery += ” ORDER BY A2_FILIAL, A2_EST”
*/
cAlias := GetNextAlias() // Tabela temporaria para fazer o query

cQuery := ” SELECT * FROM “+RetSqlName(“SB1″) // Seleciona qual empresa da query da tabela
cQuery += ” WHERE B1_COD between ‘”+MV_PAR01+”‘ AND ‘”+MV_PAR02+”‘”
cQuery += ” ORDER BY B1_FILIAL, B1_COD”

TCQUERY cQuery NEW ALIAS (cAlias)

dbGoTop()
cEst := B1_TIPO // Inicia a variavel que acumula o estado com o 1° estado vindo da tabela SA2
While !EOF()

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Verifica o cancelamento pelo usuario… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If lAbortPrint
@nLin,00 PSAY “*** CANCELADO PELO OPERADOR ***”
Exit
Endif

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Impressao do cabecalho do relatorio. . . ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If nLin > 55 // Salto de Página. Neste caso o formulario tem 55 linhas…
Cabec(Titulo,Cabec1,Cabec2,NomeProg,Tamanho,nTipo)
nLin := 8
Endif

// Coloque aqui a logica da impressao do seu programa…
// Se o primeiro estado igual ao proximo imprime se não inicia contador de subtotal
IF cEst B1_TIPO
nLin := nLin + 3
@ nLin, 00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
nLin := nLin + 2
nSubTotal := 0
cEst := B1_TIPO
ENDIF
// Utilize PSAY para saida na impressora. Por exemplo:
// @nLin,00 PSAY SA1->A1_COD
nLin := nLin + 1 // Avanca a linha de impressao
nTotal := nTotal + 1 //Totalizador de registros
nSubTotal := nSubTotal + 1 //Totalizador de subtotais de registros

@nLin,00 PSAY (cAlias)->B1_COD // @ para imprimir
@nLin,10 PSAY (cAlias)->B1_DESC
@nLin,50 PSAY (cAlias)->B1_TIPO

dbSkip() // Avanca o ponteiro do registro no arquivo
EndDo
@ nLin+3,00 PSAY “TOTAL : “+ cValToChar(nSubTotal)
@ nLin+4,00 PSAY “TOTAL GERAL : “+ cValToChar(nTotal)

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Finaliza a execucao do relatorio… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

SET DEVICE TO SCREEN

//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
//³ Se impressao em disco, chama o gerenciador de impressao… ³
//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

If aReturn[5]==1
dbCommitAll()
SET PRINTER TO
OurSpool(wnrel)
Endif

MS_FLUSH()

Return

Primeiro relatório com Acumulador – Total

#INCLUDE “protheus.ch” /*/ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºPrograma ³NOVO3 º Autor ³ AP6 IDE º Data ³ 11/02/12 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDescricao ³ Codigo gerado pelo AP6 IDE. º±± ±±º ³ º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ AP6 IDE º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß /*/ User Function RELCLIENTES //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Declaracao de Variaveis ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local cDesc1 := “Este programa tem como objetivo imprimir relatorio ” Local cDesc2 := “de acordo com os parametros informados pelo usuario.” Local cDesc3 := “CADASTRO DE CLIENTES” Local cPict := “” Local titulo := “CADASTRO DE CLIENTES” Local nLin := 80 Local Cabec1 := “CODIGO NOME UF” Local Cabec2 := “” Local imprime := .T. Local aOrd := {} Private lEnd := .F. Private lAbortPrint := .F. Private CbTxt := “” Private limite := 80 Private tamanho := “P” Private nomeprog := “NOME” // Coloque aqui o nome do programa para impressao no cabecalho Private nTipo := 18 Private aReturn := { “Zebrado”, 1, “Administracao”, 2, 2, 1, “”, 1} Private nLastKey := 0 Private cbtxt := Space(10) Private cbcont := 00 Private CONTFL := 01 Private m_pag := 01 Private wnrel := “NOME” // Coloque aqui o nome do arquivo usado para impressao em disco Private cString := “SA1” dbSelectArea(“SA1″) dbSetOrder(1) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Monta a interface padrao com o usuario… ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ wnrel := SetPrint(cString,NomeProg,””,@titulo,cDesc1,cDesc2,cDesc3,.T.,aOrd,.T.,Tamanho,,.T.) If nLastKey == 27 Return Endif SetDefault(aReturn,cString) If nLastKey == 27 Return Endif nTipo := If(aReturn[4]==1,15,18) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Processamento. RPTSTATUS monta janela com a regua de processamento. ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ RptStatus({|| RunReport(Cabec1,Cabec2,Titulo,nLin) },Titulo) Return /*/ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºFun‡„o ³RUNREPORT º Autor ³ AP6 IDE º Data ³ 11/02/12 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDescri‡„o ³ Funcao auxiliar chamada pela RPTSTATUS. A funcao RPTSTATUS º±± ±±º ³ monta a janela com a regua de processamento. º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ Programa principal º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß /*/ Static Function RunReport(Cabec1,Cabec2,Titulo,nLin) Local nOrdem Local nTReg :=0 dbSelectArea(cString) dbSetOrder(1) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ SETREGUA -> Indica quantos registros serao processados para a regua ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ SetRegua(RecCount()) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Posicionamento do primeiro registro e loop principal. Pode-se criar ³ //³ a logica da seguinte maneira: Posiciona-se na filial corrente e pro ³ //³ cessa enquanto a filial do registro for a filial corrente. Por exem ³ //³ plo, substitua o dbGoTop() e o While !EOF() abaixo pela sintaxe: ³ //³ ³ //³ dbSeek(xFilial()) ³ //³ While !EOF() .And. xFilial() == A1_FILIAL ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ dbGoTop() While !EOF() //end of file //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Verifica o cancelamento pelo usuario… ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If lAbortPrint @nLin,00 PSAY “*** CANCELADO PELO OPERADOR ***” Exit Endif //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Impressao do cabecalho do relatorio. . . ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If nLin > 55 // Salto de Página. Neste caso o formulario tem 55 linhas… Cabec(Titulo,Cabec1,Cabec2,NomeProg,Tamanho,nTipo) nLin := 8 Endif // Coloque aqui a logica da impressao do seu programa… // Utilize PSAY para saida na impressora. Por exemplo: @nLin,00 PSAY SA1->A1_COD // @ para imprimir @nLin,10 PSAY SA1->A1_NOME nLin := nLin + 1 // Avanca a linha de impressao nTReg := nTreg + 1 dbSkip() // Avanca o ponteiro do registro no arquivo EndDo @ nLin+3,00 PSAY “TOTAL “+ cValToChar(nTReg) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Finaliza a execucao do relatorio… ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ SET DEVICE TO SCREEN //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³ Se impressao em disco, chama o gerenciador de impressao… ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If aReturn[5]==1 dbCommitAll() SET PRINTER TO OurSpool(wnrel) Endif MS_FLUSH() Return

User function para calculo de percentual de Faturamento

User Function Exerc03()
Local nX := 0
Local aArray := {{“Joao”    ,1000.00,  1},;
{“Maria”   , 620.00,  7},;
{“Jose”    ,1100.00,  2},;
{“Pedro”   ,3500.00, 15},;
{“Marcia”  , 720.00,  9},;
{“Patricia”, 400.00,  1},;
{“Antonio” , 900.00,  3}}

aArray := Asort (aArray ,,, { |x,y| x[1] < y[1]})// Colocar em ordema alfabetica

For nX := 1 To  Len (aArray)
Msginfo(CalculaReajusteSalarial (aArray[nX]))    //Passando a linha do Array para a função calcula data (aArray[nX]))
Next
Return
//====================================================================================================================================================================
Static Function CalculaReajusteSalarial (aArray)
Local cStatus   :=”
Local cString   :=”
Local nReajuste :=0
Local nSalario  :=aArray[2]
Local nTempoCasa:=aArray[3]

Do Case
//——————————ate 660
Case nSalario < 660
nReajuste:= nSalario * 1.15
If nTempoCasa > 2
nReajuste:= nReajuste * 1.08
cStatus:=”C/ Bonus”
else
cStatus:=”S/ Bonus”
Endif
//——————————-ate 1.000
Case nSalario < 1000
nReajuste:= nSalario * 1.10
If nTempoCasa > 2
nReajuste:= nReajuste * 1.08
cStatus:=”C/ Bonus”
else
cStatus:=”S/ Bonus”
Endif
//——————————-mais de 1.000
Otherwise
nReajuste:= nSalario * 1.06
If nTempoCasa > 2
nReajuste:= nReajuste * 1.08
cStatus:=”C/ Bonus”
else
cStatus:=”S/ Bonus”
Endif
endcase

Return cString:= cValToChar(aArray[1])+” – Salario – “+cValToChar(aArray[2])+” – Reajuste – “+cValToChar(nReajuste)+cStatus

Exerc Data verificar se a pessoa é maior de 18 e ordena por nome

User Function Exerc02()
Local nX := 0
Local aArray := {{“Maria” ,”21/04/74″},;
{ “Joao”  ,”18/01/91″},;
{ “Pedro” ,”03/01/69″},;
{ “Joana” ,”06/09/93″},;
{ “Karina”,”27/12/90″},;
{ “Manoel”,”21/06/77″},;
{ “Silvio”,”07/07/95″}}
SET DATE BRITISH

aArray := Asort (aArray ,,, { |x,y| x[1] < y[1]})// Colocar em ordema alfabetica

For nX := 1 To  Len (aArray)
Msginfo(CalculaData (aArray[nX]))    //Passando a linha do Array para a função calcula data (aArray[nX]))
Next
Return
//====================================================================================================================================================================
Static Function CalculaData (aArray)

Local dData := ctod(“11/02/94″)
Local cStatus:=””

If dData >= ctod (aArray[2])
cStatus:=”Maior”
else
cstatus:=”Menor”
Endif
Return cString:= cValToChar(aArray[1])+” – “+cValToChar(aArray[2])+” – “+cStatus

Verificar se a multiplicação de dois números resultam em PAR ou IMPAR

// Como verificar se o Array possui uma multiplicação de numeros igual a Par ou Impar
User Function Exerc01()

Local aArray := {{2,5},{1,7},{3,3},{9,2}}

Local nX := 0
for nX := 1 To  Len (aArray)
Msginfo(CalculaPar (aArray[nX]))    // (aArray[nX]))
Next
Return
//====================================================================================================================================================================
Static Function CalculaPar (aArray)
Local nSoma:=0
Local nX:=0
Local cStatus:=””
Local cString:=””
nSoma := (aArray[1]*aArray[2])
If mod(nSoma,2)==0
cStatus:=”Par”
else
cstatus:=”Impar”
Endif

Return cString:= cValToChar(aArray[1])+”X”+cValToChar(aArray[2])+”=”+cValToChar(nSoma)+” – “+cStatus

Primeira aula ADVPL – EXEC01

//User Function usado para criar funções similres a sub Programas
User Function Exerc01()

Local aArray := {{“Maria”,10,7,15,31},;
{“Gisele”,26,26,26,26},;
{“Cleiton”,9,9,9,9},;
{“Jose”,15,16,21,33}}

Local nX := 0
for nX := 1 To  Len (aArray)
Msginfo(Calcula (aArray[nX]))
Next
Return
//====================================================================================================================================================================
Static Function Calcula (aArray)
Local nMedia:=0
Local cStatus:=””
Local cString:=””
nMedia := (aArray[2]+aArray[3]+aArray[4]+aArray[5])/4
Do case
Case nMedia >=25
cStatus :=”Aprovado”
case nMedia <10
cStatus :=”Reprovado”
case nMedia>=10 .And. nMedia <25
cStatus:=”Exame”

EndCase

Return cString:= aArray[1]+” – Media: “+cValToChar(nMedia)+” – “+cStatus

MySQL usando Java

Aprenda a manipular bases de dados MySQL usando Java :: Baixando, instalando e testando o driver para a conexão Java + MySQL

1. Baixe o Compilador Java Eclipse
2. Baixe o Banco de Dados MySql
3.Baixar o driver MySQL Connector/J que conecta o Java com o MySQL

Após baixar o driver, é hora de configurá-lo em seu sistema. A configuração é bem simples e em alguns casos envolve apenas descompactar e mover o arquivo para um determinado diretório. As instruções a seguir se aplicam ao Windows, porém, pouca coisa muda na instalação em Linux.

  • Baixe o driver e descompacte-o em um diretório de sua preferência;
  • Se for usar o driver em aplicativos Java (e não em aplicações web), adicione o jar “mysql-connector-java-3.1.12-bin.jar” no CLASSPATH de seu sistema.
  • Se você colocou o arquivo em C:\java, a entrada seguinte deverá ser adicionada à variável CLASSPATH do sistema:

C:\java\mysql-connector-java-3.1.12-bin.jar

Teste se o driver pode ser carregado com sucesso a partir de um aplicativo. Veja o código que pode ser usado para esta finalidade:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class CarregarDriver{
public static void main(String[] args) {
try {
Class.forName(“com.mysql.jdbc.Driver”).newInstance();
System.out.println(“Driver carregado com sucesso!”);
}
catch (Exception ex) {
System.out.println(“Driver nao pode ser carregado!”);
}
}
}

Dica:
Se o driver não puder ser carregado através do CLASSPATH experimente copiar o arquivo mysql-connector-java-3.1.12-bin.jar para o diretório C:\java\jre\lib\ext (o seu deve ser bem parecido). Em nossos testes esta foi a forma mais adequada de carregar o driver.A exceção ClassNotFoundExceptionUm dos problemas mais comuns encontrados por usuários menos experientes, é o tratamento da exceção:java.lang.ClassNotFoundException: com.mysql.jdbc.DriverEsta exceção ocorre quando o driver não pode ser localizado. Revise as dicas sobre como disponibilizá-lo.


Para aplicação Web:

Se o driver for usado em aplicações web, você tem duas opções:

a) Deixar o driver no CLASSPATH ou diretório lib\ext do jre;
b) Copiar o driver para o diretório C:\Tomcat5\common\lib (se estiver usando Tomcat, é claro). Em outros containeres e servidores o procedimento é o mesmo. Caso você queira aprender mais sobre o Tomcat, basta clicar aqui.

  •  Teste se o driver pode ser acessado a partir de uma página JSP. Veja um exemplo:

<%@ page language=”java” import=”java.sql.*” errorPage=”” %>
<html>
<head><title>Teste de Carregamento do Driver MySQL</title>
</head>
<body>

<%
try{
Class.forName(“com.mysql.jdbc.Driver”).newInstance();
out.write(“Driver Carregado com Sucesso!”);
}
catch( Exception ex ){
out.write(“Não foi possível carregar o driver: ” +
ex.toString());
}
%>

</body>
</html>Este tutorial contém as seguintes seções:

Referências:

  1. Apresentação
  2. Entendendo como programas Java se conectam a uma base de dados
  3. Obtendo uma conexão com o banco de dados MySQL