sexta-feira, 31 de julho de 2015

Função para acrescentar dias uteis a uma data

Retorna uma data acrescida de mais um certo número de dias  uteis descontando os fins de semana.

function Datafinal(dataini:tdatetime; dias_uteis:integer):tdatetime;
var dw:integer;
begin
  dw := DayOfWeek(dataini)-1;
  result := dataini+dias_uteis+((dias_uteis-1+dw) div 5)*2;
end;
  

Função para extrair o mês por extenso

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
function MesExtenso( Mes:Word ) : string;
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

function TForm1.MesExtenso( Mês:Word ) : string; const meses : array[0..11] of PChar = ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro','Outubro', 'Novembro', 'Dezembro');
begin
result := meses[mes-1];
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
label1.Caption := MesExtenso(3);
end;

end.

Como usar a cláusula UNION em um Query

O uso do componente TQuery gera muitas vantagens e economiza muitas linhas de programação. Mas muitas vezes nos deparamos com situações que parecem não ser resolvidas com sentenças SQL. Vejamos um exemplo:

Você possui 2 tabelas (VendasExternas e VendasInternas) e deseja fazer um resumo de todas as vendas de um vendedor chamado Marcos. Se você usar a sentença

SELECT Nome, Valor FROM VendasExternas, VendasInternas
WHERE Nome = 'Marcos'
você vai obter como resultado uma query com 4 campos (Nome, Valor, Nome_1 e Valor_1) e um resultado bem confuso para ser manipulado.

Para resolver o problema, você poderá usar a sentença

SELECT Nome, Valor FROM VendasExternas
WHERE Nome = 'Marcos'
UNION ALL
SELECT Nome, Valor FROM VendasInternas
WHERE Nome = 'Marcos'
A sentença acima pede para que sejam identificados as vendas de Marcos na tabela VendasExternas, as vendas de Marcos na tabela VendasInternas e que o resultado da primeira seja unido com o resultado da segunda produzindo uma query com apenas 2 colunas.

segunda-feira, 27 de julho de 2015

Enviando informações direto para a impressora

Muitas vezes torna-se necessário, ou até mesmo, imprescindível que você envie informações diretamente para a impressora, uma vez que a utilização da impressão típica do Windows é um pouco demorada e o uso do driver Genérico/Somente Texto não é muito confiável.

Uma boa solução para enviar informações diretamente para a impressora é usar o seguinte código:

Procedure TForm1.Button1Click(Sender: Object);
var
    Imp: TextFile;
begin
    AssignFile(Imp, 'LPT1');
    Rewrite(Imp);
    Write(Imp, 'Isto vai sair na impressora');
    CloseFile(Imp);
end;

COMO ARRASTAR UM FORM SEM CLICAR NO CAPTION?

Quando você pressiona o botão do mouse, o Windows identifica a posição da tela onde o cursor estava no momento do clique. Se a posição é igual a área do Caption do Form, o Windows ativa o modo de movimentação do Form permitindo que este seja arrastado. Portanto, a maneira mais fácil de solucionar esta questão é "enganar" o Windows.
Neste exemplo vamos considerar que o usuário poderá arrastar o Form ao cli-car na área cliente deste Form:

a) Crie uma nova aplicação;
b) Adicione a seguinte declaração na seção private do Form:
procedure WMNCHitTest(var M: TWMNCHitTest); message wm_NCHitTest;
c) Adicione o código deste procedimento na seção implementation do Form:

procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);
begin
inherited;                   { ativa a herança da mensagem }
if M.Result = htClient then { o clique foi na área cliente? }
            M.Result := htCaption;     { se sim, faz o Windows pensar que foi no Cap-tion. }
          end;

      Este exemplo tratou o clique na área cliente. Você pode alterar este código para suas necessidades. Eis os possíveis valores para o Result:

     VALOR - Local do clique
     HTBORDER - Borda da janela que não tem a borda de tamanho
     HTBOTTOM - Borda horizontal inferior da janela
     HTBOTTOMLEFT - Canto inferior esquerdo da janela
     HTBOTTOMRIGHT - Canto inferior direito da janela
     HTCAPTION - Barra de Título(Caption)
     HTCLIENT - Área cliente
     HTERROR - igual ao HTNOWHERE, a diferença é que produz um beep indicando erro
     HTGROWBOX - Caixa de tamanho (igual ao HTSIZE)
     HTHSCROLL - Barra de rolagem horizontal
     HTLEFT - Borda esquerda da janela
     HTMENU - Em um menu
     HTNOWHERE - Plano de fundo da janela ou linha de divisão entre janelas
     HTREDUCE - Botão minimizar
     HTRIGHT - Borda direita da janela
     HTSIZE - Caixa de tamanho (igual ao HTGROWBOX)
     HTSYSMENU - Botão de Sistema/Fechar da janela MDIChild
     HTTOP - Borda horizontal superior da janela
     HTTOPLEFT - Canto superior esquerdo da janela
     HTTOPRIGHT - Canto direito superior da janela
     HTTRANSPARENT - Janela em segundo plano
     HTVSCROLL - Barra de rolagem vertical
     HTZOOM - Botão maximizar

terça-feira, 14 de julho de 2015

Como tornar um servidor datasnap rest compatível com o cache off-line do HTML5


Por padrão, servidores DataSnap stand-alone WebBroker não permitem usar o "novo" HTML5 Aplicação manifesto de arquivo de cache.
Enquanto eu estava me preparando os conteúdos e as demonstrações do meu "HTML5 e aplicação web DataSnap desenvolvimento" eu configurei os componentes DataSnap para suportar esse recurso HTML5. Há apenas uma alteração a fazer ao "WebApplication REST" padrão gerado pelo assistente. No WebModuleUnit há o componente utilizado TWebFileDispatcher. Este componente tem as WebFileExtensions propriedade que é uma coleção de valores-chave contendo todas as extensões de arquivos permitidas relacionada com o mime-type.
A imagem abaixo mostra o que precisa ser configurado.

quarta-feira, 29 de abril de 2015

Função para gerar senhas aleatórias


Essa é uma dica simples e que para os que trabalham com redes sem fio pode ser muito útil. O que a função faz é gerar um string com caracteres hexadecimais, mas que podem ser adaptados para qualquer outro tipo. Esta função recebe como parâmetros o comprimento da senha como um integer, e outros três parametros do tipo boolean que indicam se estarão presentes letras minúsculas, maiúsculas e números.

Aqui vai o código e as explicações seguem logo abaixo.

function GeraSenhaHex(Digitos: Integer; Min: Boolean; Mai: Boolean; Num: Boolean): string;
const
   MinC = 'abcdef';
   MaiC = 'ABCDEF';
   NumC = '1234567890';
var
   p, q : Integer;
   Char, Senha: String;
begin
   Char := '';
   If Min then Char := Char + MinC;
   If Mai then Char := Char + MaiC;
   If Num then Char := Char + NumC;
   for p := 1 to Digitos do
   begin
      Randomize;
      q := Random(Length(Char)) + 1;
      Senha := Senha + Char[q];
   end;
   Result := Senha;
end;

Explicações:

Primeiro criamos as constantes que trarão os caracteres referentes a letras minúsculas, maiúsculas, e números, depois, iniciamos como vazia, só por desencargo de consciência já que o delphi faz isso por padrão, a variável "Char", que conterá todos os caracteres a serem usados para a geração da senha randômica.

Após isso, testamos os parâmetros para letras maiúsculas, minúsculas e números, acrescentando à "Char" cada um dos que forem verdadeiros segundo os parâmetros passados na chamada da função.

E depois, para finalizar, um laço com o número de repetições igual aos dígitos passados também como parâmetro na chamada, que usando a função Random do delphi gera números aleatórios dentro do limite estabelecido pelo cumprimento da variável "Char", lembrando que o fato de acrescentar o "+ 1" é por que as posições dos caracteres dentro de um string iniciam em 1, e a função Random gera números de 0 até o valor estipulado como limite. Por exemplo uma String = 'teste' temos os valores a seguir:

String[1] = 't'
String[2] = 'e'
String[3] = 's'
String[4] = 't'
String[5] = 'e'

Curso de Delphi: 7.Consultas SQL