Bonjour
Je vous soumets cet article en tant qu’état de l’art enrichi.
L’objectif est de réunir les différentes façons d’importer et d’exporter des CSV en un seul endroit.
Cet article est basé sur InterSystems 2024.1 .
N'hésitez pas à commenter pour rajouter des précisions.
Si vous voulez une deuxième partie sur l'export de CSV, faites le moi savoir.
Contexte
Le format CSV (pour Comma Separated Values) est un format texte représentant des données tabulaires.
Voici le lien wikipédia pour les curieux : https://fr.wikipedia.org/wiki/Comma-separated_value
On peut donc l'importer : le programme lit le fichier CSV et récupère les données; et l'exporter : le programme génère un fichier CSV avec certaines données.
Le plus efficace : Python
La façon la plus simple pour manipuler le format CSV est d'utiliser les library Python :
- csv : https://docs.python.org/fr/3.13/library/csv.html
- pandas : https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html
Hélas, certains d'entre nous sont ophiophobes. C'est pourquoi le reste de l'article se concentre sur l'ObjectScript.
Importer un CSV
do ##class(%SQL.Util.Procedures).CSVTOCLASS()
La classMéthode CSVTOCLASS va recevoir en entrée un fichier et le type des colonnes.
Elle va créer la classe "Test.CSV" correspondante et insérer les données du CSV dans la table associée.
https://docs.intersystems.com/iris20252/csp/documatic/%25CSP.Documatic.c...
set rowtype = "Code VARCHAR(2),Name VARCHAR(9)"
set filename = "c:\temp\Country.csv"
do ##class(%SQL.Util.Procedures).CSVTOCLASS(2, .rowtype, filename,,,,"Test.CSV")
Son avantage : cette méthode créée la nouvelle classe et les méthodes associées ce qui permet un gain de temps et une adaptabilité.
LOAD DATA
LOAD DATA est une requête SQL recevant un CSV et insérant les données dans la table.
https://docs.intersystems.com/iris20252/csp/docbook/DocBook.UI.Page.cls?...
>>> CREATE TABLE Sample.Person (
Name VARCHAR(25),
Age INT,
DOB DATE)
>>> LOAD DATA FROM FILE 'C://sampledata/people.csv' INTO Sample.Person
Un article en parle très bien : https://community.intersystems.com/post/tips-and-tricks-brand-new-load-d...
%SQL.Import.Mgr
Une instanciation de la classe %SQL.Import.Mgr permet de définir beaucoup de paramètres afin de lire un CSV avec beaucoup de nuances.
https://docs.intersystems.com/iris20252/csp/documatic/%25CSP.Documatic.c...
//start of the transaction
TSTART
set SQLImport = ##class(%SQL.Import.Mgr).%New()
set SQLImport.HasHeaders = 1
set SQLImport.FileName = "$CSV_FILE"
set SQLImport.TableName = "$TABLE"
set SQLImport.ClassName = "$CLASS"
// add columns of the table
do SQLImport.ColumnNames.Insert("Code")
do SQLImport.ColumnNames.Insert("Name")
set SQLImport.Delimiter = ";"
// add of the escape character
set SQLImport.StringQuote = """"
do SQLImport.GenerateImportRoutine()
set tSC = SQLImport.Import()
// end of the transaction
if 'tSC { TROLLBACK } else { TCOMMIT }
Avantage : cela permet de choisir le format de date, le séparateur, si les valeurs sont entre quotes ...
CUSTOM
Pourquoi utiliser des méthodes existantes quand on peut faire son propre code?
Je vous propose cette méthode que j'ai créée. Il suffit de créer une classe avec les propriétés dans le même ordre que les colonnes du CSV.
/// Reçoit en entrée le stream d'un csv et le nom de classe associée
/// Renvoie la liste des objets
/// separator définit le séparateur du CSV
/// skipLine définit le nombre de ligne à passer au début du CSV
ClassMethod StreamToObjectList(stream As %Stream.TmpCharacter, className As %String, ByRef listObject, separator As %String = ";", skipLine As %Integer = 0) As %Status
{
Set status = $$$OK
Try {
Set listObject = ##class(%Library.ListOfObjects).%New()
Set sqlQuery = "SELECT * FROM %Dictionary.PropertyDefinition WHERE parent = ? ORDER BY SequenceNumber"
Set resultSet = ##class(%SQL.Statement).%New()
Set status = resultSet.%Prepare(sqlQuery)
$$$ThrowOnError(status)
Do stream.Rewind()
/// On parcourt le stream
While ('stream.AtEnd) {
Set line = stream.ReadLine() // on lit chaque ligne du CSV
If skipLine > 0
{
Set skipLine = skipLine - 1 // le nombre de ligne qu'il reste à passer diminue
}ElseIf($LENGTH(line)>0){ // pour ignorer les lignes vides
Set object = $CLASSMETHOD(className,"%New")
Set ii = 1
Set tResult = resultSet.%Execute(className)
While tResult.%Next() {
Set Name = tResult.%Get("Name")
Set $PROPERTY(object,Name) = $PIECE(line,separator,ii)
Set ii = ii + 1
}
Set status = listObject.Insert(object)
$$$ThrowOnError(status)
}
}
}
Catch exception {
Set status = exception.AsStatus()
}
Quit status
}
Avantage : Son but est de retourner la liste des données du CSV et de ne pas les enregistrer dans une table SQL.. La méthode custom qui peut être modifié par les différents besoins.
.png)
.png)
.png)
.png)
