Première version affichant les données du fichier dans un tableau HTML.

This commit is contained in:
Fabrice PENHOËT 2021-08-10 15:56:53 +02:00
parent 35379b8236
commit a7f1ecc5f9
4 changed files with 225 additions and 17 deletions

View File

@ -1,5 +1,9 @@
module.exports = module.exports =
{ {
datasNotFound : "Aucune donnée n'a été trouvée.",
elementNotFound : "Aucun élément HTML n'a été trouvé ayant comme \"id\" : ", elementNotFound : "Aucun élément HTML n'a été trouvé ayant comme \"id\" : ",
urlNotValid: "L'url fournie pour le fichier CSV n'a pas un format correcte : ", needDatasElt: "Merci de fournir un id valide pour l'élément où afficher les données.",
needNaturalNumber: "Merci de fournir un nombre entier supérieur ou égal à zéro pour désigner chaque colonne.",
needUrl: "Merci de fournir l'url du fichier CSV à parser.",
parserFail: "La lecture des données du fichier a échoué.",
}; };

View File

@ -0,0 +1,90 @@
import { freeCSV2HTML } from "./freeCSV2HTML";
const initialise = async () =>
{
try
{
let converter=new freeCSV2HTML();
converter.datasViewElt={ id:"datas" };
converter.datasSourceUrl="http://localhost:8080/datas/elements-chimiques.csv";
await converter.run();
}
catch(e)
{
console.error(e);
}
}
initialise();
/*
public async setDatasUrl(url: string) : Promise<any> // pas de setter classique à cause asynchrone
{
const converter=this; // nécessaire pour éviter confusion avec this à l'intérieur de XMLHttpRequest
await fetch(url).then(function(response)
{
if(response.ok)
{
converter._datasUrl=url;
}
})
if(converter._datasUrl!=="")
return true;
else
return false;
}
/*
let req = new XMLHttpRequest();
req.open("GET", url);
req.addEventListener("load", function ()
{
if (req.status >= 200 && req.status < 400)
{
converter._datasUrl=url;
return true;
}
else
{
console.error("Fichier non trouvé");
return false;
}
});
}*/
/* Exemple d'appelle complet à papaparse :
Papa.parse(url, {
delimiter :"",
newline: "",
quoteChar:'"',// à proposer en option
escapeChar:"",// idem
header:true,
transformHeader:"",
dynamicTyping:false,
preview:0,
encoding:"",
worker:true,
comments:"",
step:"",// prévoir en option pour très gros fichiers ?
complete: function(results :any)
{
console.log(results.meta);
console.log(results.data[35]);
console.log(results.errors);
},
error:function(error :any)
{
console.log(error);
},
download: true,// nécessaire pour un accès via "http..."
downloadRequestBody:false,
skipEmptyLines: true,
chunk:"",
fastMode:"",
beforeFirstChunk:"",
withCredentials:false,
transform: "", // à revoir
delimitersToGuess:""
});
* // https://www.papaparse.com/docs#config*/

View File

@ -1,44 +1,135 @@
const Papa = require("papaparse");
import { papaParseDatas, papaParseErrors, papaParseMeta } from "./papaParseInterfaces";
const errors=require("./errors.js"); const errors=require("./errors.js");
interface selectors interface domElement
{
id: string;
eltDOM?: HTMLElement;
}
interface selectors extends domElement
{ {
colCSV: number; colCSV: number;
idElt: string;
eltDOM?: HTMLElement;
} }
export class freeCSV2HTML export class freeCSV2HTML
{ {
private _datasEltId: string = ""; // Configuration :
private _datasUrl: string = ""; private _datasViewElt: domElement = { id:"", eltDOM:undefined };
private _datasSourceUrl: string = "";
private _datasSelectors: selectors[] = []; private _datasSelectors: selectors[] = [];
// Données reçues ou générées suite parsage du fichier CSV :
public parseMeta: papaParseMeta|undefined = undefined;
public parseDatas: papaParseDatas[] = [];
public parseErrors: papaParseErrors[] = [];
private datasHTML: string = "";
set datasEltId(id: string) set datasViewElt(elt: domElement)
{ {
let checkContainerExist=document.getElementById(id); let checkContainerExist=document.getElementById(elt.id);
if(checkContainerExist === null) if(checkContainerExist === null)
throw new Error(errors.elementNotFound+id); throw new Error(errors.elementNotFound+elt.id);
else else
this._datasEltId=id; {
this._datasViewElt.id=elt.id;
this._datasViewElt.eltDOM=checkContainerExist;
}
} }
set datasUrl(url: string) // Pas plus de tests car nombreux protocoles possibles pour l'url du fichier, pas uniquement http(s). À revoir.
set datasSourceUrl(url: string)
{ {
this._datasUrl=url; if(url.trim().length === 0)
throw new Error(errors.needUrl);
else
this._datasSourceUrl=url.trim();
} }
// La validité du numéro de colonne ne peut être vérifée qu'après le parsage.
set datasSelectors(selectors: selectors[]) set datasSelectors(selectors: selectors[])
{ {
let checkContainerExist: HTMLElement; let checkContainerExist: HTMLElement|null;
for(let i = 0; i < selectors.length; i++) for(let i = 0; i < selectors.length; i++)
{ {
checkContainerExist=document.getElementById(selectors[i].idElt); checkContainerExist=document.getElementById(selectors[i].id);
if(checkContainerExist === null) if(checkContainerExist === null)
throw new Error(errors.elementNotFound+selectors[i].idElt); throw new Error(errors.elementNotFound+selectors[i].id);
else if(Number.isInteger(selectors[i].colCSV) === false || selectors[i].colCSV < 0)
throw new Error(errors.needNaturalNumber);
else else
selectors[i].eltDOM=checkContainerExist; selectors[i].eltDOM=checkContainerExist;
} }
this._datasSelectors=selectors; this._datasSelectors=selectors;
} }
public async parse(): Promise<any>
{
const converter=this; // nécessaire pour éviter confusion avec le "this" de la promise
return new Promise((resolve,reject) =>
{
if(this._datasSourceUrl !== "" )
{
Papa.parse(this._datasSourceUrl,
{
quoteChar:'"', // à proposer en option ?
header:true,
complete: function(results :any)
{
converter.parseMeta=results.meta;
converter.parseErrors=results.errors; // prévoir option bloquant la suite à la moindre erreur trouvée ?
converter.parseDatas=results.data;
resolve(true);
},
error:function(error :any)
{
reject(new Error(errors.parserFail));
},
download: true,
skipEmptyLines: true, // à proposer en option ?
});
}
else
resolve(new Error(errors.needUrl));
});
}
public async run(): Promise<any>
{
if (this._datasViewElt.eltDOM === undefined)
throw new Error(errors.needDatasElt);
if(this._datasSourceUrl === "" )
throw new Error(errors.needUrl);
if(await this.parse() === true)
{
if(this.parseDatas.length === 0 || this.parseMeta === undefined || this.parseMeta.fields === undefined)
{
this._datasViewElt.eltDOM.innerHTML=errors.datasNotFound;
return false;
}
else
{
this.datasHTML="<table><thead>";
for (let i in this.parseMeta.fields)
this.datasHTML+="<th>"+this.parseMeta.fields[i]+"</th>";
this.datasHTML+="</thead><tbody>";
for (let row in this.parseDatas)
{
this.datasHTML+="<tr>";
for(let field in this.parseDatas[row])
{
if( this.parseMeta.fields.indexOf(field) !== -1) // si les erreurs papaParse sont acceptées, il peut y avoir des données en trop : "__parsed_extra"
this.datasHTML+="<td>"+this.parseDatas[row][field]+"</td>";
}
this.datasHTML+="</tr>";
}
this.datasHTML+="</tbody></table>";
this._datasViewElt.eltDOM.innerHTML=this.datasHTML;
return true;
}
}
}
} }

View File

@ -0,0 +1,23 @@
// cf. https://www.papaparse.com/docs#results
export interface papaParseDatas
{
[key: string]: string;
}
export interface papaParseErrors
{
type: string;
code: string;
message: string;
row: number;
}
export interface papaParseMeta
{
delimiter?: string;
linebreak?: string;
aborted?: boolean;
fields?: string[];
truncated?: boolean;
}