quinta-feira, 15 de junho de 2017

Gerar Tabela Dinâmica (Pivot Table) Excel com Delphi

Dentro do meu sistema existe varias rotinas onde são gerados arquivos para Excel  É algo trivial para qualquer programador nível médio. O desafio foi um cliente, (SEMPRE ELE) solicitou que fosse gerada um arquivo Excel como tabela dinâmica conforme a imagem.



Ai começou os problemas. Como gerar ? E para piorar ele queria que os dados da tabela dinâmica tivessem o formato tabela do Excel conforme imagem



Depois de muita pesquisa consegui esse código.

Ele esta escrito em Delphi XE7, mas acredito que deve funcionar em qualquer Delphi.

Na seçao uses colocar as seguintes units

System.Win.ComObj,  Vcl.OleServer, excel2000, System.Variants


E a procedure vai ficar assim


procedure TForm3.Button1Click(Sender: TObject);
const
    xlDatabase = $00000001;

  // XlPivotTableVersionList

  xlPivotTableVersion2000 = $00000000;
  xlPivotTableVersion10 = $00000001;
  xlPivotTableVersion11 = $00000002;
  xlPivotTableVersion12 = $00000003;
  xlPivotTableVersion14 = $00000004;
  xlPivotTableVersion15 = $00000005;
  xlPivotTableVersionCurrent = $FFFFFFFF;

   // XlListObjectSourceType

   xlSrcExternal = 0;
   xlSrcModel = 4;
   xlSrcQuery = 3;
   xlSrcRange = 1;
   xlSrcXml = 2;

   //XlYesNoGuess

   xlGuess = 0;
   xlNo = 2 ;
   xlYes = 1;

var

   objExcel : Variant;
   i, qtdadeLinhasExcel : integer;
   tableDestination, tableName, readData, defaultVersion : Variant;
   pastaTrabalho , planilha, planilhaPivot : Variant;
   LinkSource : Variant;

begin

   objExcel := CreateOleObject('Excel.Application');   // Criar objeto Excell
   objExcel.Visible := false;                          // Mostrar ou nao o Excel
   objExcel.Caption := 'Tabela Dinamica';              // Titulo da planilha
   objExcel.Application.EnableEvents := false;         // Desablita os eventos deixando mais rapido o carregamento
   pastaTrabalho   := objExcel.Workbooks.Add;          // Adicionando uma pasta de trabalho no Excel
   planilha        := pastaTrabalho.Sheets.Add;        // Adicionando uma planilha na pasta de trabalho, colocando o retorno em um objeto como nome de planilha

   planilha.Name := 'dados';                           // Nome da planilha

   Try
      Screen.Cursor := crSQLWait;

      //  Uma instrução SQL Qualquer

      Qry_Dados.Close;
      Qry_Dados.SQL.Text := ' SELECT S080.CODLJA AS LOJA, S019.NOMCLI AS NOME_CLIENTE, S019.MUNCLI AS MUNICIPIO, S019.UFDCLI AS ESTADO, '
                          + ' S106.NOMVND AS VENDEDOR, EXTRACT(YEAR FROM S080.DTAEMS) AS ANO, EXTRACT(MONTH FROM S080.DTAEMS) AS MES, '
                          + ' S109.NOMMRC AS NOME_MARCA, '
                          + ' S132.DCRGRP AS NOME_GRUPO, S032.DCRSGR AS NOME_SUBGRUPO, SUM(S081.QTDPRD) AS QTDADE, SUM(S081.VLRTOTPRD) AS VALOR '
                          + ' FROM SINAF080 S080 '
                          + ' LEFT JOIN SINAF019 S019 ON S019.CODCLI = S080.CODCLI '
                          + ' LEFT JOIN SINAF106 S106 ON S106.CODVND = S080.CODVND '
                          + ' LEFT JOIN SINAF081 S081 ON S081.EMPGRP = S080.EMPGRP AND S081.CODLJA = S080.CODLJA AND S081.CODSRENFS = S080.CODSRENFS AND S081.NUMNFS = S080.NUMNFS '
                          + ' LEFT JOIN SINAF034 S034 ON S034.CODPRD = S081.CODPRD '
                          + ' LEFT JOIN SINAF109 S109 ON S109.CODMRC = S034.CODMRC '
                          + ' LEFT JOIN SINAF132 S132 ON S132.CODCTG = S034.CODCTG AND S132.CODCLS = S034.CODCLS AND S132.CODGRP = S034.CODGRP '
                          + ' LEFT JOIN SINAF032 S032 ON S032.CODCTG = S034.CODCTG AND S032.CODCLS = S034.CODCLS AND S132.CODGRP = S034.CODGRP AND S032.CODSGR = S034.CODSGR '
                          + ' WHERE S080.STACFO = '+QuotedStr('V')
                          + ' AND   S080.DTAEMS >= '+QuotedStr('01.01.2016')
                          + ' GROUP BY 1,2,3,4,5,6,7,8,9,10';
      Qry_Dados.Open;


      // Gerando os nomes das colunas de acordo com o SQL

      qtdadeLinhasExcel := 1;
      for I := 0 to Qry_Dados.FieldCount -1 do
      begin
        planilha.cells[qtdadeLinhasExcel,i+1] := Qry_Dados.fields[i].DisplayLabel;
      end;

      // Gerado as linhas de detalhe do excel com as informacoes da query

      while Not Qry_Dados.Eof do
      begin
         Label1.Caption := IntToStr(qtdadeLinhasExcel);
         Label1.Update;
         Application.ProcessMessages;
         inc(qtdadeLinhasExcel);
         for I := 0 to Qry_Dados.FieldCount -1 do
         begin
            // Atribuindo valor para cada celula
            planilha.cells[qtdadeLinhasExcel,i+1] := Qry_Dados.fields[i].text;

            // Zebrando as linhas do excel

            // Pode fazer tambem atraves do range
            if odd(qtdadeLinhasExcel)  then
               planilha.cells[qtdadeLinhasExcel,i+1].Interior.Color := clMoneyGreen // Cor da Célula
            Else
               planilha.cells[qtdadeLinhasExcel,i+1].Interior.Color := clWhite;     // Cor da Célula

         end;

         Qry_Dados.Next;
      end;

      { Criar Tabela Pivot }


      // Criando a planilha onde vai ficar a tabela dinamica

      planilhaPivot := pastaTrabalho.Sheets.Add;

      // Atribuindo um nome para a planilha

      PlanilhaPivot.Name := 'pivot';
      // Atribuindo o destino da tabela dinamica
      TableDestination := 'pivot!r3c1';

      // O nome da tabela Dinamica

      tableName := 'pivotTable';

      // A Area de dados para gerar a tabela Dinamica

      // Os dados são da planilha que foi gerada através da query. Observe a variavel planilha
      // Ele utiliza o range, que especifica uma area da planilha.
      // Neste caso, ele esta pegando dados da Coluna A, Linha1 até a Coluna L da quantidade de linhas que foram geradas
      // atraves da query
      ReadData  := planilha.Range['A1:L'+IntToStr(qtdadeLinhasExcel)];

      // Aqui está especificando a versao do Excel

      // xlPivotTableVersion2000 Excel 2000
      // xlPivotTableVersion10 Excel 2002
      // xlPivotTableVersion11 Excel 2003
      // xlPivotTableVersion12 Excel 2007
      // xlPivotTableVersion14 Excel 2010
      // xlPivotTableVersion15 Excel 2013
      DefaultVersion := xlPivotTableVersion15;

      // com essa instrucao, cria a tabela dinamica

      pastaTrabalho.PivotCaches.Create(xlDatabase,ReadData, DefaultVersion).CreatePivotTable(TableDestination,TableName, defaultVersion);
      objExcel.Visible := true;                           // Mostrar ou nao o Excel

      // Transformar a planilha de dados como uma Tabela do Excel

      // O ultimo parametro é o local que começa a tabela excel
      linkSource := 0;
      planilha.listObjects.Add(xlSrcRange, ReadDAta, , xlYes,excel.WorkBooks[1].Sheets[4].Range['A1']);

   Finally
      Screen.Cursor := crDefault;
   End;
   ShowMessage('Fim do Processo');

end;



Com esse código, consegui cheqar a solução para o cliente.

PS: Sim, eu sei que o Try Finally está errado.







terça-feira, 10 de novembro de 2015

Identificar se o programa esta sendo executado dentro do Delphi

Para saber se o programa esta sendo executado dentro da IDE do Delphi, verifique se o valor da variavel DebugHook esta diferente de zero.


Ex:

Program P1;

uses
  Vcl.Forms;

begin
  Application.Initialize;
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
  Application.CreateForm(TFrm_Menu, Frm_Menu);
  Application.Run;
end.

quarta-feira, 28 de outubro de 2015

Extrair Metadata de um Banco Firebird

Hoje precisei extrair um metadata de um banco de dados firebird e não tinha o IBexpert instalado e não tinha como baixar, ai foi necessário usar o ISQL para fazer isso.

O comando para extrair o metadata de um banco firebird é o seguinte:

ISQL -extract -o [nome arquivo] [banco de dados] -user SYSDBA -password masterkey


Exemplo:
ISQL -extract -o metadata.sql 127.0.0.1:BANCO_TESTE -user SYSDBA -password masterkey



quarta-feira, 23 de setembro de 2015

Uso de Disco 100%

Para resolver o problema de uso de disco 100% no windows 8.1, execute os seguintes comandos no prompt do cmd como usuário administrador


Dism /Online /Cleanup-Image /ScanHealth

Dism /Online /Cleanup-Image /RestoreHealth



Origem: Retirado do Fórum DevMedia


sábado, 19 de setembro de 2015

Instalacao do PhoeneGap / Cordova

Procedimentos para instalação do PhoneGap/Cordova no Windows

1. Baixar o NodeJS no site https://nodejs.org/en/


2. Instalar o PhoneGap
    Entrar no prompt do dos e executar npm install -g phonegap


3. Instalar o Cordova
    Entrar no prompt do dos e executar npm install -g cordova

4.Instalar  o emulador GenyMotion atraves do site e instalar o programa
   https://www.genymotion.com/#!/download/freemium/windows/classical



sábado, 6 de junho de 2015

Gerar Guid em Delphi

Para gerar um UniqueId, ou seja um número que nunca repete, use a função abaixo. Ela foi retirada em um blog que não me recordo.

function GerarGuid: String;
Var
   G : TGuid;
begin
   CoCreateGuid(G);
   Result := IntToHex(G.D1,1) + '' + IntToHex(G.D2,1) + '' + IntToHex(G.D3,1) + '';
   Result := Result + IntToHex(G.D4[0],1)+IntToHex(G.D4[1],1)+IntToHex(G.D4[3],1)+IntToHex(G.D4[4],1)+IntToHex(G.D4[5],1)+IntToHex(G.D4[6],1)+IntToHex(G.D4[7],1);

end;


Não esquecer de definir as units  Windows, SysUtils, ComObj, Activex na seção interface.






quinta-feira, 28 de maio de 2015

Botões e Edits com bordas arredondas em Android

Para criar botões e campos de edição com bordas arredondadas no Android, devemos fazer o seguinte.
Primeiro precisamos criar o arquivo de layout do nosso exemplo que deverá chamar exemplo_tela.xml que ficará na pasta /res/layout:

‹?xml version="1.0" encoding="utf-8"? ›
‹LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" ›

‹TextView
     android:id="@+id/textView1"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Nome" / ›

‹EditText
     android:id="@+id/editText1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:ems="10" ›
   ‹requestFocus / ›
‹/EditText ›

‹Button
    android:id="@+id/button1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:text="Pesquisar" / ›

‹/LinearLayout ›


Depois vamos criar o arquivo  responsável por realizar o efeito arredondado nos componentes que desejamos. O nome dele será  borda_arredondada.xml. Este arquivo deverá ficar na pasta  /res/drawable

‹shape xmlns:android="http://schemas.android.com/apk/res/android"    android:padding="10dp"
   android:shape="rectangle" ›

   ‹solid android:color="#8B008B" / ›

   ‹corners
       android:bottomLeftRadius="10dp"
       android:bottomRightRadius="10dp"
       android:topLeftRadius="10dp"
       android:topRightRadius="10dp" / ›

‹/shape ›

A tag shape  é usada para definir a forma que se quer aplicar no componente, no nosso exemplo definimos uma forma bem simples que foi rectangle.

A tag solid  é usada para definir as propriedades do componente como a cor de fundo, cor da fonte, etc.

A tag corners  é tag que define a propriedades do cantos do componente, é essa tag que irá de fato aplicar as bordas arredondadas.

Para aplicarmos de fato o efeito arredondado nos componentes que queremos basta adicionar o atributo background no componente que queremos, como mostra a linha verde marcada.

‹Button
    android:id="@+id/button1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
   android:background="@drawable/borda_arredondada"  
    android:text="Pesquisar" / ›