Max number of fields in FIREDAC select statement in runTime - delphi

I migrated my application from BDE to FIREDac.
A routine that I use to update my database does not work:
SELECT
CODIGO , NOME , ENDERECO , ENDERECO1 , COMPLEMENTO , COMPLEMENTO1 ,
PONTOREFERENCIA , BAIRRO , CIDADE , UF , PAIS , CEP , CX_POSTAL ,
FONE , FAX , EMAIL , CONTATO , CGC , INSCRICAO , DATA_FICHA , CI ,
CPF , TIT_ELEITOR , DATA_NASC , SEXO , EST_CIVIL , NATURAL , FILIACAO ,
PAI , MAE , CONJUGE , NASC_CONJ , ALUGUEL , VAL_ALUGUEL , TEMP_RESID ,
EMPRESA , FONE_EMPR , ADMISSAO , CEP_EMPR , CIDA_EMPR , UF_EMPR ,
FUNCAO , TEMP_SERV , REF_COML , REF_BANC , CONS_SPC , OBS , CREDITO ,
ATRASO , SALARIO , ENDEMPRESA , FOTO , NOMEFANTASIA , CREDITOS ,
ENDCOBRANCA , RESTRICAO , BAIRRO_EMPR , INATIVO , CONTATO1 , CONTATO2 ,
CONTATO3 , TAXABOLETO , RESTRICAOANTIGA , NUMERO , IDCIDADE ,
IDPAISES , CUF
FROM
Clientes
It gives me an internal error.
Some light ??!
Note: In Time designer, put the direct command in FdQuery and it works normally!bs: In designer Time, input direct comand in FdQuery and
Note2: BD is in Access !!!
As I tried to explain, I would select the data and inserted No target table! The abiaxo routine works for tables with few fields. but in the case of error above it!
The select was only to demonstrate the table where the error occurs!
The code:
procedure ConverteTabela(Query: TFDQuery; Alias, Tabela, Campo: string; Tipo: Integer; Senha: string);
var
Tabela1: TFDTable;
I: Integer;
STR:String;
begin
// Tipo = 0 -> Todos os registros da tabela antiga
// Tipo = 1 -> Todos os registros da tabela antiga que não estão na tabela de atualização
// Tipo = 2 -> Todos os registros da tabela antiga que possuem Campo <> 0
// Tipo = 3 -> Apaga os registro da tabela de atualização e coloca os da empresa
Tabela1 := TFDTable.Create(Application);
Tabela1.ConnectionName := Query.ConnectionName;
Tabela1.TableName := Tabela;
Str:='';
try
Tabela1.open;
for I := 0 to tabela1.Fields.Count-1 do
begin
if not (i=tabela1.Fields.Count-1) then
begin
Str:= Str + UpperCase(tabela1.Fields[i].FieldName)+ ' , '
end
else
Str:= Str + tabela1.Fields[i].FieldName;
end;
Tabela1.Close;
Tabela1.free;
except
exit;
end;
Mensagem('Convertendo : ' + Tabela + ' ...');
if Tipo = 3 then
begin
Query.SQL.Clear;
Query.SQL.Add('DELETE FROM "'+ Alias + '".'+Tabela);
Query.ExecSQL;
Tipo := 0;
end;
//test Select -
Query.SQL.Clear;
Query.SQL.Text := 'Select ' + str + 'from '+Tabela;
Query.open;
Query.SQL.Clear;
Query.SQL.Text:='INSERT INTO "'+ Alias + '".'+tabela+' ('+str+')'+ ' SELECT '+str+' FROM ' + Tabela;
if (Tipo = 1) then
begin
Query.SQL.Add('WHERE ' + Campo + ' NOT IN');
Query.SQL.Add('(SELECT ' + Campo + ' FROM "'+ Alias + '".'+tabela+')');
end
else if (Tipo = 2) then
begin
Query.SQL.Add('WHERE ' + Campo + ' <> 0');
Query.SQL.Add('AND ' + Campo + ' <> -1');
end;
// Query.Prepare;
try
Query.ExecSQL;
except
showmessage('Erro ao executar comando : ' + Query.Sql.CommaText);
exit;
end;
end;

Related

The Range.getValue method is widely used by the script an execution hint(the light bulb in the menu)

Hello I wrote a script that complets several Google Docs tables with values from different columns in a Spreadsheet.
I declared the columns variables : (8 in total)
var colonne_nom_de_projet = 3
var colonne_code_de_projet = 1
var colonne_chef_de_projet = 7
var colonne_service_pilote_de_projet = 8
var colonne_autres_services_projet = 11
var colonne_typede_projet = 10
var colonne_perimetre__projet = 12
var colonne_date_de_projet = 18
and var NUMERO_COLONNE_2019 = 2;
so the name of the project is in the third column ... and the date in 18 column and I want to create a doc only if I have yes in the second columnAfter that I started to complete my Google Doc table with this values
var sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
var data = sheet.getDataRange().getValues();
var targetFolder = DriveApp.getFolderById(FOLDER_ID);
Logger.log('targetFolder name: ' + targetFolder.getName());
var numRows=sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var nombre_projets_2019 = 0 ;
// à partir de 2 car la première ligne ne nous interesse pas
for(n=2;n<=data.length;++n) {
if (sheet.getRange(n,NUMERO_COLONNE_2019).getValue() == 'yes'){
if(child.getType()==DocumentApp.ElementType.TABLE && child.asTable().getNumRows() >= 8)
{
child.asTable().getCell(0, k).editAsText().setText( sheet.getRange(n,colonne_nom_de_projet).getValue() );
child.asTable().getCell(1, k).editAsText().setText( sheet.getRange(n,colonne_code_de_projet).getValue() ) ;
child.asTable().getCell(2, k).editAsText().setText(sheet.getRange(n,colonne_chef_de_projet).getValue()) ;
child.asTable().getCell(3, k).editAsText().setText( sheet.getRange(n,colonne_service_pilote_de_projet).getValue() ) ;
child.asTable().getCell(4, k).editAsText().setText( sheet.getRange(n,colonne_autres_services_projet).getValue() ) ;
child.asTable().getCell(5, k).editAsText().setText( sheet.getRange(n,colonne_typede_projet).getValue() ) ;
child.asTable().getCell(6, k).editAsText().setText( sheet.getRange(n,colonne_perimetre__projet).getValue() ) ;
child.asTable().getCell(7, k).editAsText().setText( sheet.getRange(n,colonne_date_de_projet).getValue() ) ;
and it works but I have a message and an execution hint(the light bulb in the menu)
"The Range.getValue method is widely used by the script.CollapseFile:
Code Line: 75The script uses a method that is considered expensive.
Each invocation generates a long-term call to a remote server. This
can have a critical impact on script execution time, especially on
large data. If the script has a performance problem, we recommend that
you use another method, such as Range.getValues ()." If you have any ideas it will be great ^^^^ because line 75 corresponds to
if (sheet.getRange(n,NUMERO_COLONNE_2019).getValue() == 'yes')
Edit edit : this is my very very slow code 4 minutes
function create_Google_Docs_2019_0() {
var sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
var numRows = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var data = sheet.getRange(1,1,numRows,lastColumn).getValues()
var targetFolder = DriveApp.getFolderById(FOLDER_ID);
Logger.log('targetFolder name: ' + targetFolder.getName());
var numRows=sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var nombre_projets_2019 = 0 ;
// à partir de 2 car la première ligne ne nous interesse pas
for(n=1;n < data.length;n++) {
//verifier si c'est une projet 2019 >>>>>>>>>>>>>>>>>>> ici on fait notre travail
if ( data[n][1] == 'o'){
nombre_projets_2019 = nombre_projets_2019 + 1;
var nom_projet = data[n][2];
//var nom_document = 'Projet ' + nom_projet ;
var nom_document = nom_projet ;
/** Recherche si dans folder il y a déjà ce fichier avec ce nom on va l'actualiser avec les données changés**/
if( checkFile_in_a_Folder(nom_document,targetFolder) == 1){
//on ajoute le fichier dans le repertoire courant targetFolder
Logger.log('On va réecrire le ficher / overwrite le ficher ');
}
else
{
Logger.log('On va le créer avec les données qu on a dans le tableau ');
//Make a copy of the template file
var documentId = DriveApp.getFileById(TEMPLATE_DOC_ID).makeCopy().getId();
//Rename the copied file
var name = DriveApp.getFileById(documentId).setName(nom_document);
var body = DocumentApp.openById(documentId).getBody();
if(body)
{
var ok = 0; //pour l'instant il n'y a pas de tableau
var numChildren=body.getNumChildren();
var i=0;
//tant qu'on n'a pas du tableau on va parcourir
while(ok ==0 && i<numChildren)
{
var child=body.getChild(i);
/** ============On est concerné par le premier tableau seulement qui a au plus 8 lignes d'information ================**/
Logger.log('Le type dans la boucle ' + child.getType());
//on a trouvé un tableau
if(child.getType()==DocumentApp.ElementType.TABLE && child.asTable().getNumRows() >= 8)
{
//on a trouve notre premier tableau
ok=1;
var numrows = child.asTable().getNumRows();
Logger.log('Le nombre de lignes dans notre Google Doc ' + numrows);
var insertion_position = n ;
Logger.log('Position pour inserer dans le spreadsheet ' + insertion_position);
var k = 1;
child.asTable().getCell(0, k).editAsText().setText( data[n][colonne_nom_de_projet-1]);
child.asTable().getCell(1, k).editAsText().setText( data[n][colonne_code_de_projet-1] ) ;
child.asTable().getCell(2, k).editAsText().setText( data[n][colonne_chef_de_projet-1]) ;
child.asTable().getCell(3, k).editAsText().setText( data[n][colonne_service_pilote_de_projet-1] ) ;
child.asTable().getCell(4, k).editAsText().setText( data[n][colonne_autres_services_projet-1] ) ;
child.asTable().getCell(5, k).editAsText().setText( data[n][colonne_typede_projet-1] ) ;
child.asTable().getCell(6, k).editAsText().setText( data[n][colonne_perimetre__projet-1] ) ;
child.asTable().getCell(7, k).editAsText().setText( data[n][colonne_date_de_projet-1] ) ;
}
i++;
}
}
}
}
Logger.log('Nombre de projets 2019 ' + nombre_projets_2019 );
}
}
it's a project so that by searching in the second column for 'o' (oui in French) means that the project will be in 2019 so i will get the information from several columns i want(name project,date,chef de project...) and then put this information in a Google Doc Table created using a Template with makecopy() with 8 rows and 2 columns so all the information will be put in the second colum.In fact my code is very slow and if you have any ideas to improuve it will be great because it does the work in about 4 min
Use range.getValues() to get the values in an array (single call to API), instead of using .getValue() multiple times (multiple calls, 'considered expensive').
Instead of:
for(n=2;n<=data.length;++n) {
child.asTable().getCell(0, k).editAsText().setText( sheet.getRange(n,colonne_nom_de_projet).getValue() );
child.asTable().getCell(2, k).editAsText().setText(sheet.getRange(n,colonne_chef_de_projet).getValue()) ;
//etc.
Use:
var values = sheet.getRange(0,0,20,20).getValues() //or whatever the range is
for(n=2;n<=data.length;++n) {
child.asTable().getCell(0, k).editAsText().setText( values[n][colonne_nom_de_projet]) );
child.asTable().getCell(2, k).editAsText().setText(values[n][colonne_chef_de_projet])) ;
//etc.
Something like that, you get the idea.

How to execute a multi row cursor as a table report

Dear friends i have done this:
FUNCTION ALL_CLIENTS_DATA
( client_in IN varchar2)
RETURN sys_refcursor
IS c1 sys_refcursor;
BEGIN
OPEN c1 FOR
Select TO_CHAR('SELECT '''||ATR_NOMBRE_ATRIBUTO||''','||ATR_VALOR_ATRIBUTO||' FROM '||ATR_VALOR_TABLA||' WHERE NRO_CLIENTE='''||client_in||''';')FROM GNT_ATRIBUTO WHERE ATR_TAB_IDENTIFICADOR = 7;
RETURN c1;
END;
And receiving this as cursor/function value:
SELECT 'Estado',TO_CHAR(DECODE(estado,0,'ACTIVO',1,'ELIMINADO',2,'RETIRADO',3,'NUEVO',4,'PROCESO DE RETIRO','No Disponible')) FROM cliente WHERE NRO_CLIENTE='253417';
SELECT 'SED-Cuadro-Llave',cadena FROM cliente WHERE NRO_CLIENTE='253417';
SELECT 'Sector',to_char(sector) FROM cliente WHERE NRO_CLIENTE='253417';
SELECT 'Zona',to_char(zona) FROM cliente WHERE NRO_CLIENTE='253417';
.
.
.
And this if I execute line for line (alone for testing):
Estado ACTIVO
SED-Cuadro-Llave 00100S / 21 / 3SP
Sector 89
Zona 291
.
.
.
I just don't know how to display my final result in a single execution. Please help.
If you want all the attributes in one row you need to assemble a query from the result set of GNT_ATRIBUTO then open the cursor for that.
FUNCTION ALL_CLIENTS_DATA
( client_in IN varchar2)
RETURN sys_refcursor
IS
stmt varchar2(32767);
c1 sys_refcursor;
l_tgt_table varchar2 (32767);
BEGIN
stmt := 'select ';
for lrec in (
Select ATR_NOMBRE_ATRIBUTO
, ATR_VALOR_ATRIBUTO
, ATR_VALOR_TABLA
, rownum as rn
from GNT_ATRIBUTO
where ATR_TAB_IDENTIFICADOR = 7
)
loop
if lrec.rn > 1 then
stmt := stmt || ',';
end if;
stmt := stmt || lrec.ATR_VALOR_ATRIBUTO
|| ' as "' || lrec.ATR_NOMBRE_ATRIBUTO || '"';
l_tgt_table := lrec.ATR_VALOR_TABLA;
end loop;
stmt := stmt || ' from ' || l_tgt_table
|| ' WHERE NRO_CLIENTE= :p1 ';
OPEN c1 FOR stmt using client_in;
RETURN c1;
END;

Delphi ADODB Create dbf table

I have to create dbf file in my Delphi application.
For this case I use ADODB.
Connection string:
const
ConnStringDBF =
'Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=%s;';
//'Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBASE III;OLE DB Services=-1;Data Source=%s;';
//'Driver={Microsoft Visual Foxpro Driver};SourceType=DBF;SourceDB=%s;';
//Driver='Microsoft.ACE.OLEDB.12.0;Data Source=%s;';
And procedure (which doesn work):
procedure InsertRecordInDBF(file_name: string; DbfRecord: TDbfRecord);
var
ADOConnDBF : TADOConnection;
ADOCommand : TADOCommand;
begin
ADOConnDBF := TADOConnection.Create(nil);
ADOConnDBF.ConnectionString := Format(ConnStringDBF, [data_dir]);
ADOCommand := TADOCommand.Create(nil);
ADOCommand.Connection := ADOConnDBF;
ADOCommand.CommandText := 'Create Table ' + file_name + ' ('
+ 'NUMBER CHAR(11)'
+ ')'
;
ADOCommand.Execute;
end;
The error is:
raised exception class EOleException with message '[Microsoft][Драйвер ODBC dBase] Ошибка синтаксиса при определении поля'.
Which means: syntax error in translation from Russian.
But this CommandText works perfectly:
ADOCommand.CommandText := 'Create Table ' + file_name + ' ('
+ 'NUMBER_ CHAR(11)'
+ ')'
;
The difference in the name of the field (Number_ instead of Number)
How can I create table with field Number?
Maybe I need different connection string?
It seems that I found solution for this problem. The right syntax is:
ADOCommand.CommandText := 'Create Table ' + file_name + ' ('
+ '[NUMBER] CHAR(11)'
+ ')'
;
I added [] to the name of the field
Use VFPOLEDB provider with the following connection string:
Provider=VFPOLEDB.1;Data Source=%s;Password="";Collating Sequence=MACHINE
In this case your CREATE TABLE clause will work fine.

CIS(Clever Internet Suite) form fieldvalue encode

Delphi XE5 + CIS 7.8 for XE5,when POST use Chinese formfield value like below
clHttpRequest.AddFormField('Status', '待处理');
itAutoStatus := '待处理' ;
mmo1.Lines.Add( ' 汉字为 : <'+ itAutoStatus +'>' ) ; // <待处理>
a2us := AnsiToUtf8(itAutoStatus) ;
mmo1.Lines.Add( ' 汉字AnsiToUtf8为 : <' + a2us +'>' ) ; // <待处理>
gbs := HTTPEncode(itAutoStatus);
mmo1.Lines.Add( ' 汉字HTTPEncode为 : <' + gbs +'>' ) ; // <%B4%FD%B4%A6%C0%ED>
utfs := HTTPEncode(AnsiToUtf8(itAutoStatus));
mmo1.Lines.Add( ' 汉字HTTPEncode(AnsiToUtf8())为 : <' + utfs +'>' ) ; // <%E5%BE%85%E5%A4%84%E7%90%86>
in IE8,right raw stream is : pageNo=1&total=&SortField=&SortType=&PromTitle=&C1=&Status=%E5%BE%85%E5%A4%84%E7%90%86
clHttpRequest.AddFormField('Status', '待处理');
CIS default raw stream is : pageNo=1&total=&SortField=&SortType=&PromTitle=&C1=&Status=%B4%FD%B4%A6%C0%ED
clHttpRequest.AddFormField('Status', HTTPEncode(AnsiToUtf8('待处理')));
Now CIS raw stream is : pageNo=1&total=&SortField=&SortType=&PromTitle=&C1=&Status=%25E5%25BE%2585%25E5%25A4%2584%25E7%2590%2586
clHttpRequest.AddFormField add string '25',so web server will no database query result.
I want to make raw stream like IE8,How to fix this? thanks!!!
solved
clHttpRequest.Header.CharSet := 'UTF-8';

"bpl" load in IntraWeb

I am setting up a module of "bpl" load in IntraWeb, Delphi2010, and I found the following problem:
I don't get to create an instance the application to not to be this is as an internal form.
.
procedure CargaDoSubModulo;
type
TIWFormClass = class of TIWForm;
var
Integra : IIntegracaoIW;
Formulario : TIWForm;
intClas : Integer;
strForm : String;
begin
strForm := srtPacotes + '_' + Copy ( IntToStr ( Rtn_Alternativa) + 10000 ), 2, 4 );
// Descrição do formulário
strDescricaoTela := Des_Tela;
// Nome da classe do formulário
vrtClasseModulo := 'p_' + strForm + '.dll';
// Nome da rotina interna a ser carregada
strForm := 'iwfrm_' + strForm;
// Nome da classe do formulário
vrtNomeFormulario := 'T' + strForm;
// Verificação se a rotina e compativel com o sistema iwfrm_hrb_0010
intClas := -1;
if WebApplication.FindComponent( strForm ) = nil then
begin
Formulario := TIWFormClass(FindClass( vrtNomeFormulario )).Create(WebApplication);
if not Supports (Formulario, IIntegracaoIW) then
begin
WebApplication.ShowMessage(CargaTexto(msnRotIncompIntgra), smAlert);
Exit;
end;
Integra := Formulario as IIntegracaoIW;
with Integra do
begin
SetServidor( ParServidor1.Servidor ); // 1
SetAreaTrabalho( ParServidor1.AreaTrabalho ); // 2
SetIdUsuario( intUsuario ); // 3
SetNomeUsuario( iwlStUsuario.Caption ); // 11
SetAcesso( intAcesso ); // 4
SetEmpresa( ParServidor1.Empresa ); // 5
SetFilial( ParServidor1.Filial ); // 6
SetIdClasse( intClas ); // 8
SetVersao( strVersaoInterna ); // 10
SetDescricao(Des_Tela ); // 7
SetEnderecoIP( strIdentificacaoPorta ); // 13
SetDataTrabalho( DateToStr(dtDataTrabalho) ); // 14
SetIdentificacaoSistema( iwlIdentificacao.Caption ); // 12
SetModuloCarga(Rtn_Busca ); // 9
end;
end;
TIWAppForm(WebApplication.FindComponent( strForm )).Show;
end;
Your question - or actually the exact problem/error - is a bit unclear to me. Locating a form via FindComponent is a bit uncommon. At least you shouldn't call FindComponent more than nessecary, as it is potentially slow.
If you create a Form with WebApplication being the owner, it will be added to WebApplication.Forms
Web Application.FormCount is the number of forms (UserSession is a form in this context). WebApplication.ActiveForm is the form that is currently shown.

Resources