Moltes dades que necessitem estan en format CSV
Introducció
En aquest enllaç tens el projecte de suport d'aquesta activitat: https://gitlab.com/xtec/typescript/csv
Entorn de treball
Crea un projecte react:
$ bun create vite csv --template react-swc-ts
PapaParse
PapaParse és un parser de dades CSV.
Afegeix una dependència amb papaparse
$ bun add papaparse
$ bun add --dev @types/papaparse
Afegeix aquest import al fitxer index.ts
:
import Papa from 'papaparse'
Imagina't que tenim aquestes dades CSV:
const csv = `name,age,email
John,32,jonn@gmail.com
Ruth,51,ruth@gmail.com`
Defineix el tipus Person
per les nostres dades CSV:
import Papa from "papaparse"
interface Person {
name: string
age: number
email: string
}
Amb aquesta interfície pots llegir les dades CSV:
const persons = Papa.parse<Person>(csv, {
header: true,
dynamicTyping: true
}).data
Al indicar que la primera fila és una capçalera ("header"), cada fila s'organitza pel nom del camp enlloc d'utilitzar un index.
Per defecte tot es converteix al tipus string
.
Amb dynamicTyping: true
fas que els números es converteixin en number
i els booleans en boolean
.
I ja pots mostrar tots els noms en una llista:
import Papa from 'papaparse'
interface Person {
name: string
age: number
email: string
}
export default function App() {
const csv = `name,age,email
John,32,jonn@gmail.com
Ruth,51,ruth@gmail.com`
const persons = Papa.parse<Person>(csv, {
header: true,
dynamicTyping: true
}).data
return (
<ul>
{persons.map(person => <li>{person.name}</li>)}
</ul>
)
}
Enlloc de mostrar una llista, mostra tots els resultats en una taula:
return (
<div className='container m-5'>
<div className='row align-items-center'>
<div className='col-6'>
<h3 className='text-center'>Data</h3>
<table className='table table-striped mt-5 text-center'>
<tr><th>Name</th><th>Age</th><th>Email</th></tr>
{persons.map(person => <tr><td>{person.name}</td><td>{person.age}</td><td>{person.email}</td></tr>)}
</table>
</div>
</div>
</div>
)
Mou tot el codi a un fitxer FromString.tsx
.
Modificar el fitxer App.tsx
amb aquest codi:
import FromString from "./FromString"
export default function App() {
return <FromString/>
}
Fitxer remot
Pots treballar amb fitxer remots has de passar una URL i un funció "callback":
import { useEffect, useState } from "react"
import Papa from 'papaparse'
export default function App() {
const [data, setData] = useState<any[]>([])
useEffect(() => {
// https://datos.gob.es/es/catalogo/ea0010587-numero-de-estudiantes-de-educacion-superior-que-han-recibido-becas-o-ayudas-segun-el-tipo-de-beca-o-ayuda-recibida-identificador-api-t13-p460-2019-l0-02014-px1
const url = "https://www.ine.es/jaxi/files/tpx/csv_bdsc/43494.csv"
Papa.parse(url, {
// El fitxer utilitza ; com a delimitador enlloc de ,
delimiter: ";",
download: true,
complete: function (results) {
setData(results.data);
}
}
)
}, [])
return (<><h3>Data</h3><ViewCSV csv={data} /></>
)
}
// Funció que crea una taula amb el contingut del fitxer CSV
function ViewCSV({ csv }: { csv: any[][] }) {
return <table className='table table-striped'>
{csv.map(row => <tr>
{row.map( item => <td>{item}</td> )}
</tr>)}
</table>
}
Gestiona l'error amb un missatge:
import { useEffect, useState } from "react"
import Papa from 'papaparse'
export default function App() {
const [result, setResult] = useState<{ message: string, data: any[] }>({ message: "Descargando", data: [] })
useEffect(() => {
// https://datos.gob.es/es/catalogo/ea0010587-numero-de-estudiantes-de-educacion-superior-que-han-recibido-becas-o-ayudas-segun-el-tipo-de-beca-o-ayuda-recibida-identificador-api-t13-p460-2019-l0-02014-px1
const url = "https://www.ine.es/jaxi/files/tpx/csv_bdsc/43494.csvXXX"
Papa.parse(url, {
// El fitxer utilitza ; com a delimitador enlloc de ,
delimiter: ";",
download: true,
complete: function (results) {
if (results.errors.length != 0) {
setResult({ message: "Error", data: [] });
} else {
setResult({ message: "Descargado", data: results.data });
}
}
}
)
}, [])
return (
<div className="container">
<h3 className="text-center">Data</h3>
<p className="border border-2 border-info rounded p-2 text-secondary">{result.message}</p>
<ViewCSV csv={result.data} />
</div>
)
}
// Funció que crea una taula amb el contingut del fitxer CSV
function ViewCSV({ csv }: { csv: any[][] }) {
return <table className='table table-striped'>
{csv.map(row => <tr>
{row.map(item => <td>{item}</td>)}
</tr>)}
</table>
}
Seguir explicat: https://www.papaparse.com/
Plot
https://github.com/javascriptdata/danfojs
import Plot from 'react-plotly.js';
import Papa from 'papaparse';
import { useEffect, useState } from "react";
export default function App() {
const [result, setResult] = useState({message:"Descargando", data:[]})
useEffect(() => {
// https://datos.gob.es/es/catalogo/ea0010587-numero-de-estudiantes-de-educacion-superior-que-han-recibido-becas-o-ayudas-segun-el-tipo-de-beca-o-ayuda-recibida-identificador-api-t13-p460-2019-l0-02014-px1
const url = "https://www.ine.es/jaxi/files/tpx/csv_bdsc/43494.csv";
Papa.parse(url, {
// El fitxer utilitza ; com a delimitador enlloc de ,
delimiter: ";",
download: true,
complete: function (results) {
if(results.errors.length > 0){
setResult({message:"Error", data: []});
}else{
setResult({message:"Listo", data: results.data});
}
}
}
)
}, [])
console.log(result.data)
const graphData = [{
x: result.data.slice(1, result.data.length - 1).map(row => row[0]),
y: (result.data.slice(1, result.data.length - 1))
.map(row => row[1])
.map(str => str.replace(/\./gi, ''))
.map(num => Number(num)),
text: result.data.slice(1, result.data.length - 1).map(row => row[1]),
type: 'bar'
}]
// debugger
const layout = {
title: "Num of students that have recived a scholarship",
}
return <Plot data={graphData} layout={layout} />;
}
TODO
-
<https://www.ine.es/dyngs/INEbase/listaoperaciones.htm >
-
https://typescript.tv/hands-on/parsing-csv-files-in-typescript-with-papa-parse/
-
https://www.basedash.com/blog/how-to-use-papaparse-with-typescript