quinta-feira, 22 de junho de 2017

Unable to create process Acesso Negado

De uma hora para outro os novos programas compilados no Delphi XE7 pararam de funcionar, apresentando a mensagem Unable to create process - acesso negado.

Geralmente a remoção do antivírus e reinstalação resolve esse problema.

Se não resolver, remova o programa de proteção do banco (GAS Tecnologia). Esse programa é bom para dar pau, não permitindo a execução de outros programas. Ele pensa que é virus.

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.