Exporter des données au format CSV

VeillardVeillard Membre
16:53 modifié dans API AppKit #1
Salut à  tous  ;)

Bon, allez un petit post.
Quelqu'un a-t-il une expérience concernant l'exportation de données dans un fichier au format CSV ?
En fait, dans ce fichier, je cherche à  mettre les différentes infos relatives aux plongées du carnet en cours.

Voilà , je vais continuer mes recherches de mon côté.

Merci

Réponses

  • fouffouf Membre
    16:53 modifié #2
    Je sais pas si ca peut t'aider mais j'ai trouvé ca avec Google :
    http://www.imf.org/external/help/csv.htm
  • fouffouf Membre
    16:53 modifié #3
    J'ai aussi trouvé ca : http://en.wikipedia.org/wiki/Comma-separated_values

    Ya de tout, exemples, codes, types MIME, ....
  • août 2005 modifié #4
    Le format CSV est très simple à  générer. C'est un bête format texte, les différentes colonnes sont séparées par des ";" et les lignes par des retours chariots. Tu peux mettre pour la première ligne les en-têtes de colonnes, mais ce n'est pas obligatoire.

    Donc pour le tableau
    [tt]
    Col1 Col2 Col3
    a    b
    c         d
    e    f    g
    [/tt]

    Sa représentation CSV est:
    [tt]Col1;Col2;Col3
    a;b;
    c;;d
    e;f;g
    [/tt]

    Rien de bien sorcier comme tu vois.

    Je suppose que le code pour faire ce genre de chose ne posera pas de problèmes ;). Je te conseille juste pour la fonction qui va générer le CSV de ne pas mettre le @; et le @\n directement dans la boucle, pas plutôt de les placer en argument de cette fonction. Il y a d'autres formats de textes très semblables dans le principe, mais avec des séparateurs différents. Un autre qui est très répandu est le "tab separated value"
  • VeillardVeillard Membre
    août 2005 modifié #5
    Merci à  tous les deux.

    J'avais pensé faire une boucle pour passer en revue chaque plongée du carnet. Ensuite faire appel à  un NSMutableString avec quelquechose du style :

    [exportText appendString:[NSString stringWithFormat:@&quot;%@;%d;%d;%d&#092;n&quot;, lieu, site, profondeur, temps]];<br />
    


    Je n'ai mis que 4 paramètres, or il y en a environ une soixantaine si je prends tout (je pense me limiter à  une vingtaine). Ca risque tout de même d'être un peu long avec 20 paramètres avec un "NSString stringWithFormat:" ?
    Une fois que j'ai mon texte, je l'enregistre au format "txt" avec l'extension "csv".

    Voilà  a vous les studios  :)
  • VeillardVeillard Membre
    16:53 modifié #6
    J'ai pensé au tab. Les utilisateurs souhaiteraient un csv mais je peux faire les deux.
  • fouffouf Membre
    16:53 modifié #7
    C'est quoi le tab ?

    Sinon, pour les proprités, si elles sont rangées dans un tableau, tu fais une boucle avec un enumérateur et puis avec une NSMutableString un petit appendStringWithFormat: fera l'affaire ;)
  • août 2005 modifié #8
    Comme ton appli n'est pas déjà  pas compatible, je te conseille de passer par les joies du KVC (n'en déplaise à  mpergand, c'est pour moi un réel apport de Panther). La méthode doit avoir 4 arguments: le tableau "données", un tableau contenant les colonnes que tu souhaites avoir dans ton CSV, le séparateur de colonnes, et le séparateur de lignes.

    ça donnerait un truc dans le genre (je suppose que ton tableau de plongée contient des instances d'une classe perso):
    [tt]-(NSString*)textRepresentationOfItems:(NSArray*)items
    columns:(NSArray*)columnsID
    columnSeparator:(NSString*)columnSeparator
        rowSeparator:(NSString*)rowSeparator
    {
    NSMutableString* str = [NSMutableString string];
    NSEnumerator *f, *e = [items objectEnumerator];
    id<NSKeyValueCoding> item;
    NSString* key;
    while (item = [e nextObject]) {
    f = [columnsID objectEnumerator];
    while (key = [f nextObject]) {
    [str appendFormat:@%@%@",
    [[item valueForKey:key] description],
    ([key isEqual:[columnsID lastObject])]?rowSeparator:columnSeparator];
    }
    }
    return str;
    }[/tt]

    Pour columnsID, tu peux mettre les noms de tes variables d'instance, sous forme de NSString, donc dans l'exemple donné: [tt][NSArray arrayWithObjects:@lieu,@site,@profondeur,@temps,nil][/tt]. J'ai juste un petit doute pour les variables stockées sous forme de types C (float, double,...) dans le le sens où je ne sais pas si valueForKey: les renvoies sous forme de NSNumber ou de leur type d'origine. Logiquement, ça devrait être NSNumber.

    Avec ce genre de méthode, le CSV et le tab ne causent vraiment pas de problèmes.
  • odjauodjau Membre
    16:53 modifié #9
    dans 1123240332:

    C'est quoi le tab ?


    Ben,  une tabulation à  la place de ";", non ???
  • VeillardVeillard Membre
    16:53 modifié #10
    Merci Renaud.
    En étudiant ton code, l'export en csv ne concerne que les objets contenus dans les colonnes de ma TableView. Je dois rajouter quelques infos complémentaires ne figurant pas dans la Table.
    Dans tous les cas, je vois ce qu'il faut faire.
    Il ne me reste plus qu'à  voir l'enregistrement  ::)
  • août 2005 modifié #11
    Non, tu mets les clés tu veux dans l'argument ColumnsID, y compris celle qui ne sont pas dans la table. Tout ce qu'il faut, c'est qu'il existe une valeur pour valueForKey: (par exemple une variable d'instance de la classe de item qui porte ce nom). Il s'appelle ColumnsID parce que ce seront les colonnes du CSV.
  • VeillardVeillard Membre
    août 2005 modifié #12
    D'ac, c'est plus clair.

    J'ai regardé pour l'enregistrement. J'ai rajouté dans les propriétés du Target l'extension csv dans la classe "Carnet". J'ai maintenant le choix des deux possibilités dans la fenêtre d'enregistrement.
    Pour l'enregistrement du carnet proprement dit, j'utilise NSCoder:
    - (NSData *)dataRepresentationOfType:(NSString *)aType<br />{<br />&nbsp; &nbsp; return [NSArchiver archivedDataWithRootObject:_carnet];<br />}<br />
    


    Maintenant pour avoir le choix entre le format NSCoder ou CSV je voudrais faire ceci :

    - (NSData *)dataRepresentationOfType:(NSString *)aType<br />{<br />&nbsp; &nbsp; if (extension plg sélectionnée)<br />&nbsp; &nbsp; return [NSArchiver archivedDataWithRootObject:_carnet];<br />	<br />&nbsp; &nbsp; if (extension csv sélectionnée)<br />&nbsp;  return [textCSV dataUsingEncoding:NSUTF8StringEncoding];<br />}<br />
    


    Que mettre à  la place de "if (extension plg sélectionnée)" ?
  • fouffouf Membre
    16:53 modifié #13
    Normalement dans le Get Info de ta target, dans l'onglet Properties, les types sont les "Name" des types de fichiers que tu géres.
  • VeillardVeillard Membre
    16:53 modifié #14
    Merci Fouf, ça marche !  :brule:
  • fouffouf Membre
    août 2005 modifié #15
    Je vais me faire lapider  :

    Je le savais ::)
    :fouf): :P
  • 16:53 modifié #16
    Je crois qu'un nouveau smiley va s'imposer par la force des choses:

    fouf.gif
  • AliGatorAliGator Membre, Modérateur
    août 2005 modifié #17
    Pourquoi ne pas utliser "componentsJoinedByString:" de NSArray ?
    Si une ligne de ton tableau est un NSArray (ordonné selon les colonnes), tu fais un componentsJoinedByString: @; dessus (sur chaque ligne) et ça te donne la représentation d'une ligne à  mettre dans ton fichier CSV.

    Pour aller dans la même idée, une fois que tu as ton tableau de lignes -- qui était à  l'origine un tableau de tableau (une ligne = 1 NSArray, toutes les lignes = un NSArray de NSArray) --, tu fais un componentsJoinedByString:@\n dessus pour récupérer tout le texte converti en CSV que tu n'as plus qu'à  écrire dans un fichier texte.

    M'enfin un NSEnumerator marche aussi
    NSEnumerator* lignes = [tab2d objectEnumerator];<br />NSMutableArray* tabLignes = [NSMutableArray array];<br />id item;<br />while (item = [e nextObject])<br />{<br />      [tabLignes addObject:[item componentsJoinedByString:@&quot;;&quot;]]; // une ligne convertie<br />}<br />return [tabLignes componentsJoinedByString:@&quot;&#092;n&quot;];
    
    (ouaiiiis mon premier post avec un bout de code Cocoa, ça se fête, non ? :) :) :p)
  • AliGatorAliGator Membre, Modérateur
    16:53 modifié #18
    Ah oui une chose qu'on n'a pas précisé, concernant le CSV : Y'a des petits pièges à  éviter.

    Si tes données (dans tes cellules) contiennent le caractère de séparation, forcément ça va poser des problèmes.
    Pour ça faut que tu ailles lire la spec du format.
    Normalement les chaà®nes de caractères sont mises entre guillemets, ce qui veut dire qu'un ";" qui est à  l'intérieur d'une chaà®ne prise entre guillements n'est pas interprété comme un séparateur mais bien comme un caractère de la chaà®ne.
    Bien sûr ça ne fait que reporter le problème un peu plus loin, car si ta chaà®ne contient un guillemet dans son contenu...
    Et bien là  il faut faire intervenir le caractère d'échappement (antislash, comme dans bcp de formats) : si un guillemet se trouve à  l'intérieur de ta chaà®ne, il faut le remplacer par \" avant d'entourer ta chaà®ne de guillemets. Et si un antislash se trouve dans ta chaà®ne de caractères, il faut le remplacer par \\ aussi...

    Bref des tas de petites c*nneries auxquelles faut penser, si t'as que des nombres ou que tu as des chaà®nes dont tu es sûr qu'elles n'auront pas de ";" dedans, pas de soucis, mais sinon (en particulier pour faire un truc générique comme le proposais Renaud...)

    Tu peux aussi choisir le caractère de séparation en fonction de ça. Par exemple préférer une tabulation plutôt qu'un point-virgule si tes chaà®nes de caractères peuvent avoir un ";" mais n'auront pas une seule tabulation...

    Bref, comment réussir à  se prendre la tête pour des choses parfois simples...
  • VeillardVeillard Membre
    16:53 modifié #19
    Ca y est, j'ai fait une bidouille provisoire mais ça fonctionne. Il faut que je revoie les paramètres à  inclure avant de proposer ma dernière version à  Alex  ::)
Connectez-vous ou Inscrivez-vous pour répondre.