FAQ DelphiConsultez toutes les FAQ

Nombre d'auteurs : 123, nombre de questions : 919, dernière mise à jour : 14 juin 2019  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).

Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.

L'équipe Delphi de Developpez.com.

Commentez


SommaireBases de donnéesBases de données - Divers (15)
précédent sommaire suivant
 

Les grilles non connectées (par opposition aux DBGrid) disposent souvent de plus de possibilités de manipulation : tris, dimensionnements des lignes, colorations, etc. Cette méthode peut donc vous être utile quand vous n'avez besoin que d'un accès en lecture au contenu d'une table ou d'une requête. De plus, une fois la grille remplie, vous pouvez réutiliser votre requête, par exemple pour réaliser d'autres actions.

Deux propriétés importantes des ensembles de données (TDataSet) sont utilisées dans le code ci-dessous :

  • la propriété FieldCount, qui donne le nombre de colonnes nécessaires ;
  • la propriété Fields, qui contient les données de l'enregistrement en cours.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
procedure TMyForm.Remplir; 
var 
  ligne, colonne: Integer; 
begin 
  with DataSet do 
  begin 
    Open; 
  
    { Dimensionnement de la grille } 
    MyStringGrid.RowCount := 2; 
    MyStringGrid.ColCount := FieldCount; 
  
    { Remplissage des entêtes } 
    for colonne := 0 to MyStringGrid.ColCount - 1 do 
      MyStringGrid.Cells[colonne, 0] := Fields[colonne].DisplayName; 
  
    { Données } 
    First; 
    ligne := 1; 
    while not Eof do 
    begin 
      for colonne := 0 to StringGrid1.ColCount-1 do 
MyStringGrid.Cells[colonne, ligne] := Fields[colonne].AsString; 
      Next; 
      Inc(ligne); 
      if not Eof then 
MyStringGrid.RowCount := MyStringGrid.RowCount + 1; 
    end; 
    Close; 
  end; 
end;

Mis à jour le 19 octobre 2013 DidiLogic

Cette procédure prend en paramètre un dataset à exporter, le nom du fichier, le caractère séparant les zones et le caractère délimiteur des zones texte.

Les fichiers CSV ont ";" pour séparateur, les fichiers TSV ont la tabulation.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
procedure datasetToTextFile(ds : TDataSet; nomFichier : string; 
separateur : string = ';'; delimiteur : char = #0); 
var  
  i : integer; 
  fichier : TextFile;  
  bm : TBookmark;  
  sCursor : TCursor; 
  valeur : string; 
  openDS : boolean; 
  
begin 
  try 
    { Création du fichier de sortie } 
    AssignFile(fichier,nomFichier); 
    Rewrite(fichier); 
  except 
    on e: exception do 
      raise Exception.Create('Erreur pendant la création du fichier [' + nomfichier + '] : ' + 
    sLineBreak + e.message); 
  end; 
  
  sCursor := Screen.Cursor; 
  Screen.Cursor := crHourGlass; 
  try 
    ds.DisableControls; 
    openDS := not ds.Active; 
    bm := nil; 
    try 
      with ds do 
      begin 
if openDS then 
  Open 
else 
begin 
  { on sauvegarde la position de l'enregistrement courant dans } 
  { le dataset afin de la restituer en fin de traitement } 
  bm := ds.GetBookmark; 
  First; 
end; 
{ ligne d'en-tête : on met le nom des zones } 
for i:= 0 to FieldCount - 1 do 
begin 
  if (i > 0) then 
    write(fichier,separateur + ds.Fields[i].FieldName) 
  else 
    write(fichier,ds.Fields[i].FieldName); 
end; 
writeln(fichier);  { passe à la ligne suivante dans le fichier } 
while not Eof do 
begin 
  { écriture de chaque colonne de l'enregistrement courant } 
  for i := 0 to FieldCount - 1 do 
  begin 
    { ajout du délimiteur si le champ est de type texte } 
    if (delimiteur <> #0) and 
      (Fields[i].DataType in [ftString, ftMemo, ftFmtMemo, ftFixedChar, ftWideString]) then 
      valeur := AnsiQuotedStr(Fields[i].Text,delimiteur) 
    else 
      valeur := Fields[i].Text; 
    { à partir du second champ, on ajoute le séparateur } 
    if (i > 0) then 
      write(fichier,separateur + valeur) 
    else 
      write(fichier,valeur) 
  end; 
  writeln(fichier); { passe à la ligne suivante dans le fichier } 
  Next; 
end; { while not eof } 
      end; { with ds } 
    finally 
      { si on a ouvert le ds, on le ferme } 
      if openDS then 
ds.Close 
      else 
      { sinon, on se repositionne sur l'enregistrement initial } 
      begin 
ds.GotoBookmark(bm); 
ds.FreeBookmark(bm); 
      end; 
      ds.EnableControls; 
      CloseFile(fichier); 
    end; 
  finally 
    Screen.Cursor := sCursor; 
  end; 
end;

Exemples :
Code delphi : Sélectionner tout
1
2
3
datasetToTextFile(query1,'c:\temp\test1.csv'); 
datasetToTextFile(query1,'c:\temp\test2.csv',';','"'); 
datasetToTextFile(query1,'c:\temp\test3.csv',#9,''''); { #9 : tabulation }

Mis à jour le 19 octobre 2013 Bloon

Lors d'une connexion à une base de donnée une fenêtre apparaît pour demander le nom d'utilisateur et le mot de passe. Ceci est le comportement par défaut de tous les composants de connexion à une base même si les informations de connexion sont correctement renseignées.

Tous les composants de connexion disposent d'un propriété LoginPrompt permettant de demander le login à l'utilisateur (TSQLConnection, TDCOMConnection, TDataBase, TAdoConnection, TIBDatabase, etc.). Il suffit de mettre cette propriété à faux pour désactiver cette demande.

Mis à jour le 18 janvier 2014 Nono40

On ne peut appliquer de requête sur le résultat d'une requête (à moins d'en copier le résultat dans une table intermédiaire, mais ce n'est pas je but ici) Par contre les composants descendant du TDataSet possèdent des fonctions de filtrage.

Filtrage Simple

Il suffit de mettre à jour le propriété Filter du DataSet et de mettre Filtered à True. Filter contient la condition d'affichage des champs. Par exemple pour ne conserver que les lignes dont le champ C2 est supérieur ou égal à 2 :

Code delphi : Sélectionner tout
1
2
DataSet.Filter:='C2>=2'; 
DataSet.Filtered:=True;
Il est possible d'utiliser des opérateur AND, OR, etc dans un filtre.

Filtrage sur évènement

Il est possible aussi d'utiliser l'évènement OnFilterRecord pour filtrer les enregistrements de la table. En reprenant l'exemple précédent le code serait le suivant :
Code delphi : Sélectionner tout
1
2
3
4
5
procedure TForm1.Table1FilterRecord(DataSet: TDataSet; 
  var Accept: Boolean); 
begin 
  Accept:=DataSet.FieldByName('C2').AsInteger>=2; 
end;
Cette technique permet de créer des filtres plus complexes que d'utiliser la propriété Filter.

Mis à jour le 18 janvier 2014 Nono40

Les dates dans les filtres doivent être comparées comme des chaînes, il faut donc mettre la date entre quotes pour la comparaison :

Code delphi : Sélectionner tout
Filter:='DateDebut=''12/01/04''';

Mis à jour le 18 janvier 2014 Nono40

Un champ de référence permet de proposer une liste de valeurs provenant ( référençant) d'une colonne d'une seconde table. La relation se faisant grâce à une clé primaire ou étrangère.

Pour définir un champ de référence il faut suivre les étapes suivantes :

  • Double-cliquer sur le composant DataSet lié à la table
  • Effectuer un click droit sur la liste puis Nouveau Champ
  • Entrer un nom de champ avec son type.
  • Mettre le type de champ sur référence
  • Sélectionner l'ensemble de données contenant la référence ( liste de valeur )
  • Choisir dans le champ clé le champ devant recevoir la référence
  • Choisir dans clé de référence le champ de la table de référence qui doit être comparé au champ clé
  • Choisir dans champ résultat la valeur du champ de référence quand champ clé = clé de référence

Une fois ceci effectué, la saisie dans une grille fait apparaître un ComboBox dans la cellule en cours d'édition afin de sélectionner la valeur dans la liste de référence.

Mis à jour le 18 janvier 2014 Nono40

Il existe deux méthodes principales pour définir les colonnes d'une grille avant que celle-ci ne soit liée à une table ouverte.

Méthode des champs persistants
Cette méthode est appelée ainsi car les champs du composant DataSet sont créés bien que la table ne soit pas ouverte. Pour définir les champs persistants il faut double-cliquer sur le DataSet voulu et ajouter les champs :

  • Soit en ajoutant un champ en fonction de la table liée. Cette méthode est la plus simple mais impose que le composant DataSet puisse être connecté au serveur et que la table puisse être ouverte.
  • Soit en ajoutant des nouveaux champs et en les définissants tels qu'ils le sont dans la table.

Une fois les champs définis, il suffit de cliquer dessus dans la liste et d'afficher l'éditeur de propriétés afin de modifier son affichage. L'ordre des champs dans la liste des champs définit l'ordre d'affichage dans une grille. Il est possible de modifier cet ordre simplement en glissant les champs à la bonne position dans la liste.

Cette méthode va fixer le nom et les caractéristiques des champs du DataSet en dur dans le programme, si un des champs défini dans la liste n'existe pas dans la table, une exception sera levée à l'ouverture de la table.

Méthode des colonnes prédéfinies
Cette méthode permet de modifier l'affichage de la grille sans modifier l'affichage des autres composants liée au DataSet. Il suffit de double-cliquer sur le DBGrid pour afficher la liste des colonnes. La propriété FieldName de la colonne permet de lier la colonne à un champ du DataSet.

Si un champ n'existe pas dans la table lié au DataSet dont dépend la grille, ceci ne provoque pas d'exception. De même si le type du champ n'est pas celui attendu.

Mis à jour le 18 janvier 2014 Nono40

La méthode recordCount permet de déterminer le nombre total d'enregistrements d'un ensemble de données. Attention cependant, cette propriété ne devrait être utilisée qu'avec des tables Paradox ou DBase. Signalons encore que si la propriété filter est utilisée, RecordCount ne retourne que 0 (si vide) et 1 (si non vide).

La méthode enregCount définie ci-dessous illustre une utilisation possible de la propriété RecordCount. enregCount le nombre de lignes de l'ensemble de résultats passé en paramètre sinon renvoie la valeur -1 en cas d'échec.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
... 
   Interface 
    uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,  
                            Db, StdCtrls, Grids, DBGrids, DBTables; 
  
     function enregCount(dataset: TDataSet):longInt; overload; 
     function enregCount(dataSource: TDataSource):longInt; overload; 
     function enregCount(DBGrid: TDBGrid):longInt; overload; 
  
   Implementation 
  
     function enregCount(dataset: TDataSet):longInt; 
     begin 
        if assigned(dataSet) 
          then if dataSet.Active 
             then result := dataset.RecordCount 
             else result := -1 
          else result := -1 
     end; 
  
     function enregCount(dataSource: TDataSource):longInt; 
     begin 
       if assigned(dataSource) 
         then result := enregCount(dataSource.DataSet) 
         else result := -1; 
     end; 
  
     function enregCount(DBGrid: TDBGrid):longInt; 
     begin 
       if assigned(DBGrid) 
         then result := enregCount(DBGrid.DataSource) 
         else result := -1; 
     end; 
...
Exemples d'utilisation.
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
nb_enreg := enregCount(Query1);  
//ou  
nb_enreg := enregCount(Table1);  
// ou  
nb_enreg := enregCount(DataSource1);  
// ou  
nb_enreg := enregCount(DBGrid1);

Remarque :
Etant donné les trops grandes restrictions pour utiliser de la propriété recordCount, nous préconisons l'utilisation de l'instruction SQL count.

Mis à jour le 18 janvier 2014 Pascal Jankowski

Certains composants de connexion, en particulier TSQLConnection et TDatabase proposent la propriété SQLHourGlass, de type booléen, qui permet de spécifier si le curseur prend la forme du sablier jusqu'à ce que le serveur de base de données renvoie le résultat de la requête.
Pour les autres composants (TTable et TQuery), il faut explicitement recourir à un objet TSession pour accéder à cette propriété.

Ainsi, pour désactiver simplement l'affichage du sablier (le curseur devient le curseur par défaut : crArrow), il faut écrire :

Code delphi : Sélectionner tout
DataBase1.Session.SQLHourGlass := False; //accès à la session par défaut
ou placer un TSession sur la fiche, le nommer (dans l'exemple ci-dessus on lui donne le nom MaSession), mettre SQLHourGlass à False et attribuer à la propriété SessionName d'un objet TTable (par exemple) cette session :
Code delphi : Sélectionner tout
Table1.SessionName := MaSession;
Pour utiliser un autre curseur, on peut faire reférence au curseur de l'écran lors de l'exécution d'une requête :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
procedure btnExecuteRequete(Sender : TObject); 
var Save_cuseur: TCursor;  
begin  
  Save_curseur := screen.cursor;  
  Screen.Cursor := XXX;  // afficher le cuseur voulu  
  try  
    // Traitement  
  finally  
    Screen.Cursor := save_curseur;  
  end;  
end;
où xxx peut être une des valeurs :
  • crArrow : Flèche normale
  • crCross : curseur en forme de croix
  • crIBeam : curseur d'édition dans les grilles
  • crHourGlass : curseur en forme de sablier

La liste des différents curseurs peut être trouvée en demandant l'aide sur TCursor.

Mis à jour le 18 janvier 2014 Giovanny Temgoua

Dans une application, les sources de données possèdent généralement des ensembles de données sous-jacents qui lui sont connectés à travers un DataSource. A partir de ce moment, ces ensembles de données réagissent à tout évènement qui se produit sur la source de données et en particulier sur l'évènement BeforeScroll. Ceci a pour avantage d'avoir des données toujours actualisées. Cependant, dans le cas de recherche (tri ou recherche incrémentale) dans la source, l'inconvénient sera de ralentir énormément la recherche (du fait du rafraîchissement constant des ensembles de données). À ce moment, il est nécessaire d'appeler la méthode DisableControls avant le début de la recherche et EnableControls juste après celle-ci.

Code delphi : Sélectionner tout
1
2
3
4
5
6
Table1.DisablesControls; 
try 
  // Opération de recherche ou de tri 
finally 
  Table1.EnableControls; 
end;

Mis à jour le 18 janvier 2014 Giovanny Temgoua

  • En utilisant DELETE
    L'instruction DELETE permet de supprimer tout ou partie des lignes d'une table. Pour supprimer la totalité des lignes d'une table on utilise la syntaxe suivante :
    Code sql : Sélectionner tout
    Delete from NomDeTable;
  • Sous Oracle l'instruction TRUNCATE permet également de supprimer toutes les lignes d'une table.
    Cette instruction contient un commit implicite, il ne peut donc y avoir de RollBack après cette instruction.
    Code sql : Sélectionner tout
    Truncate Table NomDeSchema.NomDeTable;
    Cette instruction est aussi plus efficace que la suite d'instructions
    Code sql : Sélectionner tout
    1
    2
    Drop Table; 
     Create Table(champ1 type1, champN typeN );
    Note : Cette commande contient quelques restrictions notamment :
    Vous ne pouvez pas tronquer une table si elle contient des contraintes d'intégrité référentielle. Vous devez désactiver les contraintes avant de tronquer la table.
  • Avec les tables Paradox/DBase sous le BDE il est possible d'utiliser TTable.EmptyTable. A la différence prêt que la table doit être ouverte en mode exclusif pour que cette opération fonctionne. Par contre la taille du fichier DB ou DBF est réellement réduit par cette opération, contrairement au autres opérations de suppression de tous les enregistrements.

Mis à jour le 18 janvier 2014 Laurent Dardenne

Tous les descendants de TDataset possèdent des évènements qui nous permettent de contrôler l'état de l'opération en cours. Il s'agit des évènements Beforexxx. Par exemple, il existe un évènement BeforePost qui nous permet de faire un dernier test sur les données et décider si finalement celles-ci doivent êtres écrites dans la base de données ou non. Pour l'annulation, on utilise simplement la procédure abort :

Code delphi : Sélectionner tout
1
2
3
4
5
procedure TForm1.Table1BeforePost(DataSet: TDataSet); 
begin 
  if Table1Champ1.Value < 100 then 
    abort; // Les données ne seront pas validées 
end;

Mis à jour le 18 janvier 2014 Giovanny Temgoua

La version personnelle de Delphi ne fournit pas l'accès en natif à des composants pour les bases de données. Il est cependant possible d'y accéder à partir de composants tiers ou en attaquant directement l'API de la BDD en question ou encore par l'intermédiaire d'un autre langage.

Mis à jour le 18 janvier 2014 Guigui_

Afin d'avoir un composant DBGrid qui affiche toutes les données d'une table plus un libellé en clair provenant d'une autre table, nous allons nous appuyer sur un clientDataSet.

Dans un premier temps, créez tous les champs de votre table de base. Ensuite ajoutez dans votre Dataset un nouveau champ (double clic sur le ClientDataSet, clic droit > Nouveau champ).

Les zones nom, type et taille du champ sont à remplir comme pour un champ classique. Ce qui va changer c'est la zone "Type de champ" : on va cocher ici Référence. Un champ référence fonctionne exactement comme un DBLookUpComboBox ; il affiche le libellé d'une autre table en se basant sur un index de la table en cours faisant le lien.

Description des champs Définition de la référence
Champs clé C'est le champ dans la table en cours qui fera le lien vers l'autre table
Ensemble de données C'est la table contenant les libellés qu'on veut afficher
Clés de référence C'est le champ qui fera le lien avec « Champs clé » qu'on a choisi avant
Champ résultat C'est le champ libellé que l'on veut afficher dans notre DBGrid

Mis à jour le 10 février 2014 Manopower

Cette QR prendra exemple avec les composants ADO mais elle est fonctionnelle avec n'importe quel composant de base de données.

Dans les exemples qui vont suivre, on considèrera que nous travaillons sur la structure de table suivante :

Code other : Sélectionner tout
1
2
3
Id : Champ auto incrémenté 
Nom : Champ texte/varchar de 100 en taille 
Fichier : Champ Blob
A- L'insertion

Il y a 2 méthodes pour insérer des documents (Images ,Documents Texte, programmes, etc.) dans une base de données :
  1. Par chargement
    1. Avec une requête

      Code delphi : Sélectionner tout
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      if OpenDialog.execute then 
        With AdoQuery do 
        begin 
          Close; 
          SQL.Clear; 
          SQL.add('insert into MaTable(Nom,Fichier)'); 
          SQL.Add('Values(:PNom,:PFichier)'); 
          ParamCheck := True; 
          Parameters.ParamByName('PNom').Value := ExtractFileName(OpenDialog.Filename); 
          Parameters.ParamByName('PFichier').LoadFromFile(OpenDialog.Filename, ftBlob); 
        try 
          ExecSQL; 
        Except on E:Exception do 
          begin 
            Showmessage('Erreur lors de l''insertion de l''image dans la base de données : ' +  
             E.Message); 
          end; 
        end;  
      end;
    2. Avec une Table
      Code delphi : Sélectionner tout
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      if OpenDialog.execute then 
        With AdoTable do 
        begin 
           // Met la table en mode insertion de données 
           Append;  
          // enregistrement du nom de fichier dans la base de données 
          FieldByName('Nom').asString := ExtractFileName(OpenDialog.Filename); 
          // Enregistrement du fichier dans la base de données 
          (FieldByName('Fichier') as TBlobField).LoadFromFile(OpenDialog.Filename, ftBlob); 
        try 
           // On ajoute dans la base de données 
           Post;  
        Except on E:Exception do 
          begin 
            // On annule la tentative d'ajout dans la base de données 
            Cancel;  
            Showmessage('Erreur lors de l''insertion de l''image dans la base de données : ' +  
              E.Message); 
          end; 
        end;  
      end;
  2. Par assignation

    Cette méthode nécessite que l'on connaisse à l'avance le type de données que l'on va transmettre à la base de données.
    Dans les deux exemples qui vont suivre, nous utiliserons des images.
    1. Avec une Requête
      Code delphi : Sélectionner tout
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      var 
        Img : TBitmap; 
      begin 
        if OpenDialog.execute then 
        try 
           img := TBitmap.Create; 
           img.LoadFromFile(OpenDialog.FileName); 
          With AdoQuery do 
          begin 
            Close; 
            SQL.Clear; 
            SQL.Add('insert into MaTable(Nom,Fichier)'); 
            SQL.Add('Values(:PNom,:PFichier)'); 
            ParamCheck := True; 
            Parameters.ParamByName('PNom').Value := ExtractFileName(OpenDialog.Filename); 
            Parameters.ParamByName('PFichier').Assign(Img); 
            try 
              ExecSQL; 
            Except on E:Exception do 
              begin 
                Showmessage('Erreur lors de l''insertion de l''image dans la base de données : ' +  
                E.Message); 
              end; 
            end;  
          end; 
        finally 
          img.free; 
        end; 
      end;
    2. Avec une Table
      Code delphi : Sélectionner tout
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      var 
        Img : TBitmap; 
      begin 
        if OpenDialog.execute then 
        try 
           img := TBitmap.Create; 
           img.LoadFromFile(OpenDialog.FileName); 
           With AdoTable do 
          begin 
           // Met la table en mode insertion de données 
           Append;  
           // enregistrement du nom de fichier dans la base de données 
           FieldByName('Nom').asString := ExtractFileName(OpenDialog.Filename); 
           // Enregistrement du fichier dans la base de données 
           FieldByName('Fichier').Assign(Img); 
           try 
             // On ajoute dans la base de données 
             Post;  
           Except on E:Exception do 
             begin 
               // On annule la tentative d'ajout dans la base de données 
                Cancel;  
               Showmessage('Erreur lors de l''insertion de l''image dans la base de données : ' +  
                E.Message); 
             end; 
           end;  
         end; 
        finally 
          img.free; 
        end; 
      end;

B- La récupération
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
var 
  sPath : String 
begin 
  With AdoTable do 
  begin 
    // Récupération du nom du fichier 
    sPath := ExtractFilePath(Application.ExeName) + FieldByName('Nom').AsString; 
    // sauvegarde du fichier 
    TBlobField(FieldByName('Fichier')).SaveToFile(sPath); 
  end; 
end;

Mis à jour le 11 février 2014 Rayek

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2019 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Responsables bénévoles de la rubrique Delphi : Gilles Vasseur - Alcatîz -

Partenaire : Hébergement Web