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, 22 de junho de 2017
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.
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']);
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.
Assinar:
Postagens (Atom)