Import fichiers csv dans une base de données

Description

Salut...
Je suis actuellement en stage.
Durant celui-ci je doit permettre l'automatisation d'ajout de materiel dans une Base De Données
J'ai utilisé le script de "caviar"
"http://www.phpcs.com/codes/IMPORT-CSV-VERS-BDD-MYSQL-AVEC-CHOIX-CHAMPS_39220.aspx"
Pour mes besoins, j'ai débugué et optimisé le script.
Je me permet donc de déposé le code source mis à jour.
@+

Source / Exemple :


<html>
<head>
<script language="JavaScript" type="text/JavaScript">
<!--
function MM_jumpMenu(targ,selObj,restore){ //v3.0
  eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'");
  if (restore) selObj.selectedIndex=0;
}
//-->
</script>
<LINK rel="StyleSheet" href="import.css" type="text/css" />
</head>
<body>
<?php
// Liste les données de la table
// -------------------------------------------
include ('./conf/config.inc.php');
include ('./functions/mysql.php');
?>

<?php
 // on affiche les tables de la bdd
//pour que ce script fonctionne il faut au moins un enregistrement dans la table sélectionnée
function display_one_table($tablename){
//$query="show fields from $tablename";
//$result=mysql_query($query);
$result = requette ("show fields from $tablename");
$rows = mysql_num_rows($result);
?>

<table width ="95%" cellspacing="0" cellpadding="4" border="1" style="font-family:courier new;font-size:12px" align="center">
<tr style="background-color:silver">
<th colspan="6" style="font-size:14px">Informations sur la table <i><?php echo $tablename?></i></th>
</tr>
<tr style="background-color:#ddd;font-size:12px">
<td>Field</td>
<td>Type</td>
<td>Null</td>
<td>Key</td>
<td>Default</td>
<td>Extra</td>
</tr>
<?php
while ($row = mysql_fetch_row($result)) {
?>
<tr style="background-color:<?php echo ($i++ %2 == 0 ? '#cee8ce' : '#f0f0f0') ?>">
<td><?php echo $row[0] ?>&nbsp;</td>
<td><?php echo $row[1] ?>&nbsp;</td>
<td><?php echo $row[2] ?>&nbsp;</td>
<td><?php echo $row[3] ?>&nbsp;</td>
<td><?php echo $row[4] ?>&nbsp;</td>
<td><?php echo $row[5] ?>&nbsp;</td>
</tr>
<?php
}
?>
</table>
<br />
<?php
}

///////////////////////
$result_tables = requette ("SHOW TABLES FROM `".$bdd."`");
?>

<form action="" name="form_bdd" id="form_bdd" method="post" enctype="multipart/form-data">
<h3>Table de la base de donnee qui va recevoir l'import</h3>
<select name="table">
<option value="" <?php if (!isset($_POST['table'])){ echo'selected'; } ?> >Choisissez une table</option>
<?php
while ($row = mysql_fetch_row($result_tables)) {
//   echo "Table : {$row[0]}\n"; // Morceau de code inutile non ? Du moins incorrect !

   echo " <option ";
   if (isset($_POST['table']) && $row[0]==$_POST['table']){ echo'selected '; }
   echo "value=\"".$row[0]."\">Table : ".$row[0]."</option>";  
  echo "\n";
}
?>
</select>
<p style="font-weight:bold">Fichier CSV ou TXT au format csv</p>
<p style="color:#00f;font-weight:bold">Preparation du fichier : </p>
<p><input type="file" name="fichiercsv" size="16">
Delimiteur : <select name="del">
<option value=";" selected>; Point virgule</option>
<option value=",">, Virgule</option>
<option value=":">: Deux points</option>
<option value="-">- Tiret</option>
<option value="/">/ Slash</option>
<option value="|">| Barre</option>
<option value="#"># Diese</option>
</select>
</p>
<p>
<input type="hidden" name="etape2" value="1">
<input type="submit" value="Correpondance des champs">
</p>
</form>

<?php if (isset($_POST['table']) && $_POST['table'] !="" && isset($_POST['etape2'])) {
$del = $_POST['del'];
if( empty($_FILES['fichiercsv']['tmp_name'])){
exit('<p style="color:red;font-weight:bold">Vous n\'avez pas choisi de fichier a uploader</p></body></html>.');
}
?>
<form action="" name="form_import" id="form_import" method="post">
<?php
// on crée cette variable ici avant de faire le test car elle peut servir ? la suppression aussi

$content_dir = 'tmp/'; // dossier où sera déplacé le fichier

//---------------------

      $tmp_file = $_FILES['fichiercsv']['tmp_name'];
    
       if( !is_uploaded_file($tmp_file) )
       {
           exit("Le fichier est introuvable.<br /> Vous n'avez pas choisi de fichier a uploader.");
       }
    
       // on v?rifie maintenant l'extension
       //$type_file = substr($_FILES['fichier']['name'], strrpos($_FILES['fichier']['name'], "."));
       $type_file = $_FILES['fichiercsv']['type'];
   //echo 'nom du fichier :'.$tmp_file.'<br />';
       //echo  'type du fichier : '.$type_file.'<br />';
  

$extensions_valides = array( 'csv' , 'txt' );
$extension_upload = substr(  strrchr($_FILES['fichiercsv']['name'], '.')  ,1);
if ( in_array($extension_upload,$extensions_valides) ){

       // on copie le fichier dans le dossier de destination
       $name_file = $_FILES['fichiercsv']['name'];
    
       if( !move_uploaded_file($tmp_file, $content_dir . $name_file) )
       {
           exit("Impossible de copier le fichier dans $content_dir");
       }
       ?>
<p>Le fichier <span style="color:#00f"><strong><?php echo '<a href="'.$content_dir.'/'.$name_file.'">'.$name_file.'</a>'?></strong></span> a bien ete uploade</p>
       <?php
   display_one_table($_POST['table']);
   echo '<p>&nbsp;&nbsp;&nbsp;</p>';

} else {
?>
<p style="color:red;font-weight:bold">Extension incorrecte. Vous pouvez uploader des <strong>csv, txt. </strong></p>
<?php
}

if(file_exists("$content_dir"."$name_file")) {

//on lis la 1ere ligne pour g?n?rer lles listes
$fp = fopen("$content_dir"."$name_file", 'r');
$str="";
$cpt=0;

$str .= fgets($fp, 99000);
//echo $str;
$str=trim($str);
if (substr($str,-1,1) != $del){
$str .= $del ;
}
//
$tabcsv = explode ($del, $str);
//echo $str;

fclose ($fp);
//on suppr les espaces
//print_r($tabcsv);
?>
<table  align="center" cellspacing="0" cellpadding="2" border="1" style="font-family:courier new;font-size:12px" >
<tr align="center" style="font-weight:bold">
<td>Champ de la table</td>
<td>Champ du fichier CSV</td>
</tr>

<?php
//génération des listes de gauche avec les champs de la bdd
$resQuery = requette("SHOW FIELDS FROM ".$_POST['table']." FROM ".$bdd);
$fields = mysql_num_rows($resQuery);

// g?n?ration des listes ---------------------------
//fonction permettant de récuperer les valeurs contenues dans le fichier csv 
function csv ($j, $tabcsv){
?>
<td>
<select name="colonecsv<?php echo $j ; ?>">
  <option value="" >AUCUNE VALEUR</option>

<?php

// on affiche les champs de la table choisie

  // titre des colonnes

  $i = 0;
  while ($i < count($tabcsv)) {
echo "<option ";
    if ($i == $j){ echo 'selected '; }
echo "value=\"";
echo $i;
echo "\">";
echo $tabcsv[$i];
echo "</option>";  
echo "\n";
   $i++;
  }
			
  echo "\n";
?>   </select>
</td>
<?php

 }

 
if (mysql_num_rows($resQuery) != 0) {
$j = 0;
while ($j < $fields) {
?>
<tr><td>
<select name="colone<?php echo $j ; ?>">
<option value="" <?php if (!isset($_POST['colone0'])){ echo'selected'; } ?> >Choisissez une colonne</option>
<?php

// on affiche les champs de la table choisie

  // titre des colonnes

  $i = 0;
    while ($i < $fields) {
    $savior = mysql_result($resQuery, $i);
echo '<option value="'.$savior.'"';
echo ($i == $j ? ' selected>' : '>');
echo $savior.'</option>';
echo "\n";
    $i++;
  }
  echo "\n";

?></select>
</td>
<?php
//appel de la fonction csv
csv($j, $tabcsv);
?>

<?php  
$j++;
} // fin while j
 
} 

} else {
echo 'erreur. Fichier csv mal uploadé.<p>&nbsp;&nbsp;&nbsp;</p>';
}

   ?>
</td>
</tr>
<tr>
<td colspan="2">
<input type="hidden" name="content_dir" value="<?php echo $content_dir ; ?>">
<input type="hidden" name="name_file" value="<?php echo $name_file ; ?>">
<input type="hidden" name="table" value="<?php echo $_POST['table'] ; ?>">
<input type="hidden" name="fields" value="<?php echo $fields ; ?>">
<input type="hidden" name="del" value="<?php echo $_POST['del'] ; ?>">
<input type="hidden" name="nb_colones_csv" value="<?php echo count($tabcsv)-1 ; ?>">
<input type="hidden" name="listeok" value="1"></td></tr>
<tr>
<td align="center" colspan="2">
<input  type="submit"  value =" Importer dans la BDD">
</tr>
</td>
</table>
</form>
<?php } //fin du if isset
else if (isset($_POST['etape2'])){
?>
<p style="color:red;font-weight:bold">Vous n'avez pas choisi de table ou importer les donnees !</p>
<?php
}
?>

<?php if (isset($_POST['listeok'])){
echo '<strong>Traitement du fichier CSV</strong> <br /><br />';
$del = $_POST['del']; //choix du d?limiteur
$content_dir = $_POST['content_dir'];
$name_file = $_POST['name_file'];
$table = $_POST['table'];
//nb de champs dans la table
$fields = $_POST['fields'];
$nb_colones_csv = $_POST['nb_colones_csv'];

//on lis la 1ere ligne pour g?n?rer lles listes
$fp = fopen("$content_dir"."$name_file", 'r');
$str="";
$cpt=0;
while (!feof($fp)) {
$str = fgets($fp, 99000);

//on ?vite les lignes vides
if(!empty($str)){
//si on a pas de ; ? la fin d'une ligne on en ajoute une
//$str = "azerty";
$str=trim($str);
//echo 'dernier car de la ligne = '.substr($str,-1,1).'<br>';
if (substr($str,-1,1) != $del){
$str .= $del ;
}
//on remplace les ' par \'
$str = str_replace ("'","\'",$str);

$nbcar = strlen($str);
//on cherche les caract?res de s?paration
//echo 'nb de char sur la ligne='.$nbcar.'<br>';
$valligne [] ="";
// pour placer la valeur chaque fois dans la case suivante du tableau temporaire valligne
$vallignecpt = 0;

//PARSAGE DES VALEURS
// SI ON DEBUTE PAR UN "

while ($nbcar != 0){

$pos1=0;
if (substr($str,0,1) == '"'){
$pos1 = 1;
$trouve=0;
for ($pos=0 ; $trouve!= 1; $pos++){
$sepa = substr($str,$pos,2);
//echo 'caractere analis?='.$sepa.'<br>';
if( $sepa== '"'.$del){
$pos2 = $pos; //on r?cup?re la position du debut de l'enregistrement
//echo 'pos1='.$pos1.'<br>';
//echo 'pos2='.$pos2.'<br>';
$long = $pos2 - $pos1; //longueuur de la chaine à extraire
$tempstr = substr($str, $pos1, $long ); //on recup le reste de la ligne
//echo 'compteur ='. $vallignecpt.'<br>';
//on regarde si on a remplis le champ pour forcer la valeur
$tempforce = 'force'.$vallignecpt;
if (isset($_POST[$tempforce]) && $_POST[$tempforce] != ""){
$valligne [$vallignecpt] = trim($_POST[$tempforce]);
} else {
//sinon on remplis avec la valeur trouvée
$valligne [$vallignecpt] = $tempstr ;
}
$vallignecpt++;
//echo "<strong>Valeur ajoutée=</strong>".$tempstr.'<br><br>';
$trouve=1;
$str = substr ($str, ($pos2+2));
//echo 'Nouvelle Phrase='.$str.'<br>';
$nbcar = strlen($str);
}
}
} else {
$pos1 = 0;
$trouve=0;
for ($pos=0 ; $trouve!= 1; $pos++){
$sepa = substr($str,$pos,1);
//echo 'caractere analis?='.$sepa.'<br>';
if( $sepa == $del){
$pos2 = $pos; //on r?cup?re la position du debut de l'enregistrement
//echo 'pos1='.$pos1.'<br>';
//echo 'pos2='.$pos2.'<br>';
$long = $pos2 - $pos1; //longueuur de la chaine ? extraire
$tempstr = substr($str, $pos1, $long ); //on recup la valeur
//echo 'compteur ='. $vallignecpt.'<br>';
//on regarde si on a remplis le champ pour forcer la valeur
$tempforce = 'force'.$vallignecpt;
if (isset($_POST[$tempforce]) && $_POST[$tempforce] != ""){
$valligne [$vallignecpt] = trim($_POST[$tempforce]);
} else {
//sinon on remplis avec la valeur trouvée
$valligne [$vallignecpt] = $tempstr ;
}
$vallignecpt++;
//echo "<strong> valeur ajout?e=</strong>".$tempstr.'<br><br>';
$trouve=1;
$str = substr ($str, ($pos2+1));
//echo 'nouvelle Phrase='.$str.'<br>';
$nbcar = strlen($str);
}
}

}

}

//print_r ($valligne);
$tabcsv[$cpt] = $valligne;
$valligne = "";
$cpt ++;
//echo $str.'<br>';
}
}
fclose ($fp);
//print_r ($tabcsv);

//g?n?ration de la requette

$colones = "(" ;
for ($g=0; $g<$fields; $g++) {

$colones .=  '`'.$_POST["colone$g"].'`';
//pour ne pas ajouter de virgule apres la derniere colone on teste
if ($g < ($fields-1)){
$colones .= ", ";
}
}
$colones .= " ) ";
//echo '<br>colones = '.$colones;
//echo '<br> csv : ';
//echo $_POST['colonecsv0'];

echo $nb_colones_csv.' champs dans le fichier '.$name_file.'<br />';
echo $fields.' champs dans la table '.$table.'<br />';

//génération de la requette
$numligneval = 1;//compteur qui va donner le numero ? la ligne des valeurs ...pour ne pas avoir de trou dans l'index du tableau
//on incr?mente les lignes
for ($u=1; $u<=($cpt-1) ; $u++) {
// on verrifie que le parsage de la ligne soit bien fait en regardant que tabcsv contient bien le même nombre de champs pour cette ligne que le nombre de champs de la 1ere ligne du fichier csv
if (count($tabcsv[$u]) == $nb_colones_csv) {
$valeurs[$numligneval] = "(" ;
//on remplis les valeurs en fonction du nb de colones
for ($m=0; $m<$fields ; $m++) {

$tempcol = 'colonecsv'.$m;

//on stocke la valeur sans les espaces avant et après
// on evite d'afficher un erreur d'index indefini sur la table si on a pas choisi de correspondance de champ avec @
@$valeurs[$numligneval] .= '\''.trim($tabcsv[$u][$_POST[$tempcol]]).'\'';

//pour ne pas ajouter de virgule apres la derniere colone on teste

if ($m < ($fields-1)){
$valeurs[$numligneval] .= ", ";
}
}
$valeurs[$numligneval] .= " ) ";
$numligneval++;
} else {
//print_r ($tabcsv[$numligneval]);
//echo'<br>';
echo '<font color="red">Ligne '.($numligneval+1).' du fichier '.$name_file.' -> Erreur : '.count($tabcsv[$u]).' champs au lieu de '.$nb_colones_csv.' </font> - Ligne ignor?e. <br />';
//on remplis quand m?me le tableau des valeurs mais cette ligne sera ignor?e lors des insert ... ?a permet de garder le compteur des lignes ? jour au niveau du journal des erreurs sql
$valeurs[$numligneval] = "";
$numligneval++;
}

}

// FONCTIONS D'IMPORT DANS LA BDD
/* ?a n'est pas tout ? fait la m?me que dans mysql.php qui est en include
car celle ci affiche les erreurs sans couper le traitement en cas d'erreurs.
C'est celle l ? qu'on va donc utiliser */

function requette_avec_erreur($str_query, $connect=1)
{
if ($connect==1){connecter();} // si connect =1 on se connect
$resultat = mysql_query($str_query);
if ($connect==1){deconnecter();} // si connect =1 on se deconnect
if ($resultat)
{
return $resultat;
}
else
{
return 0;
//erreur(3); //si on veux renvoyer ? une action pr?cise en cas d'erreur
}
}
echo '<br /><strong>import en cours</strong> <br /><br />';
$erreur_sql = ""; //on initialise le journal des erreurs

//insert dans la base
echo 'La ligne 1 du fichier CSV correspond à la définition des champs. <br />';
connecter();
for ($u=1; $u<$numligneval; $u++) {
if ($valeurs[$u] != ""){
$req = "INSERT INTO $table $colones VALUES $valeurs[$u] ";
echo "<br>".$req.'<br />';

if (requette_avec_erreur($req,0)) {
echo 'ajout de la ligne '.($u+1).' du fichier '.$name_file.'.<br />';
} else {
$erreur_sql .= '<span style="color:red">Ligne '.($u+1).' du fichier '.$name_file.' -> Erreur SQL '.mysql_errno().' : '.mysql_error().'</span><br />';
echo '<font color="red">ligne '.($u+1).' -> Erreur SQL</font><br />';
}
}

}

deconnecter();
?>
<br /><strong>Fin de l'import</strong><br />
<strong> JOURNAL DES ERREURS SQL</strong><br />
<?php
if (!empty($erreur_sql))
{
echo $erreur_sql;
}
else
{
?>
Pas d'erreurs detectees lors de l'import
<?php
}
}
?>

</body>
</html>

Conclusion :


Voici donc ma contribution.
Code fonctionnel en date du 7/06/10

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.