Affichage du LF rebolien sous Excel
Philippe5-Jan-2010/14:24:32+1:00
Bonjour,

Via du parsing sur des retours de requêtes web, je récupère des informations que j'inscris à la volée dans un fichier csv.
Lorsque je consulte via Excel mon fichier de résultat, l'affichage d'une cellule multilignes n'est pas terrible.
Le fichier test.csv créé par le code suivant vous illustre cela :

a: rejoin [ {"} "valeur1" lf "valeur2" lf "valeur3" {"}  ]
b: rejoin [ {"} "valeur4" cr "valeur5" cr "valeur6" {"}  ]
c: rejoin [ {"} "valeur7" newline "valeur8" newline "valeur9" {"}  ]
write %/C/test.csv rejoin [ a ";" b ";" c]


Voir sous Excel ce fichier C:/test.csv

Est-ce un pb de représentation du LF (chr(10)) sous REBOL vs Windows ou un pb d'Excel ..ou les deux ? Si quelqu'un connait une astuce pour éviter ce petit désagrément, je suis preneur.

===Philippe
guest25-Jan-2010/19:22:19+1:00
Ben sous openoffice tout parait OK.
C'est ça aussi d'utiliser des trucs payants mal foutus, faut pas se plaindre après...
Philippe6-Jan-2010/10:13:25+1:00
Salut,
Je me disais aussi qu'en postant une question comme celle-ci, je risquais une réponse sur le sempiternel débat windows-linux, open source-propriétaire. Bon, tant mieux si çà marche sur OpenOffice, c'est déjà çà.

===Philippe
DocKimbel6-Jan-2010/12:35:04+1:00
Salut,

Sous Excel 2003 SP3, j'obtiens un affichage correct dans la cellule quand LF est utilisé :

valeur1
valeur2
valeur3

--
DocKimbel
guest26-Jan-2010/15:57:40+1:00
J'utilise openoffice sous Vista, gratuitement aussi, merci.
Philippe7-Jan-2010/0:01:14+1:00
salut,

Merci pour les réponses, j'ai le problème d'affichage (un carré pour le caractère lf ) sous XP Pro Excel SP2, et XP Pro Excel 2007, avec View 2.7.6, et 2.7.7. Bizarre.

===Philippe
Didec11-Jan-2010/10:13:24+1:00
Salut Philippe.

Tu es sur la bonne voie, mais tu as oublié un détails : 'write sans rafinement réalise un enregistrement en format texte et effectue les conversions de saut de ligne selon le système hôte.
Donc sous Windows, il remplace tes LF par des CRLF !!

En utilisant write/binary, tu auras dans le fichier texte ce que tu avais en mémoire.

Pour info, ce sont bien des LF qu'il faut utiliser dans les valeurs de cellules pour sauter des lignes, et des CRLF entre les enregistrements du fichier.

Sinon, voici 2 fonctions pour convertir un block de blocks de valeurs depuis/vers un format csv. Attention, il reste à effectuer la lecture et l'enregistrement de la chaine CSV en utilisant /binary sous R2 pour éviter les modifs automatiques de sauts de lignes.

;***** Conversion function from/to CSV format
csv-to-block: func [
	"Convert a string of CSV formated data to a Rebol block. First line is header."
	csv-data [string!] "CSV data."
	/separator separ [char!] "Separator to use if different of comma (,)."
	/without-header "Do not include header in the result."
	/local out line start end this-string header record value data chars spaces chars-but-space
	; CSV format information http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
] [
	out: copy []
	separ: any [separ #","]
	
	; This function handle replacement of dual double-quote by quote while copying substring
	this-string: func [s e] [replace/all copy/part s e {""} {"}]
	; CSV parsing rules
	header: [(line: copy []) value any [separ value] (if not without-header [append/only out line])]
	record: [(line: copy []) value any [separ value] (append/only out line)]
	value: [any spaces data any spaces (append line this-string start end)]
	data: [start: some chars-but-space end: | #"^"" start: any [some chars | {""} | #"," | newline] end: #"^""]
	chars: complement charset rejoin [ {"} separ newline]
	spaces: charset exclude { ^-} form separ
	chars-but-space: exclude chars spaces
	
	parse/all csv-data [header any [newline record] any newline end]
	out
]

block-to-csv: func [
	"Convert a block of blocks to a CSV formated string." 
	blk-data [block!] "block of data to convert"
	/separator separ "Separator to use if different of comma (,)."
	/local out csv-string record value v
] [
	out: copy ""
	separ: any [separ #","]
	; This function convert a string to a CSV formated one
	csv-string: func [val] [head insert next copy {""} replace/all copy val {"} {""} ]
	record: [into [some [value (append out #",")]]]
	value: [set v string! (append out csv-string v) | set v any-type! (append out form v)]
	
	parse/all blk-data [any [record (remove back tail out append out newline)]]
	out
]
Philippe11-Jan-2010/10:45:52+1:00
Bien vu Didec, effectivement, le détail change tout.
Merci !

===Philippe
trigram27-Jan-2011/12:31+1:00
Et le cas du texte qui n'est pas délimité par " ?

J'ai des enregistrements du type :

1;27/01/2011;Mme TOTO Céline;1, Rue de Paris;BRUXELLES

Cela me renvoit un block avec
1 27/01/2011 Mme

Et il s'arrête.
Didec27-Jan-2011/12:58:56+1:00
Comme toujours, un petit bout de code et un exemple de données que l'on puisse tester et voir ce qui ne va pas SVP !
trigram27-Jan-2011/13:49:27+1:00
>>do %duplex_csv.r
>> data: "1;27/01/2011;Mme TOTO Céline;1, Rue de Paris;BRUXELLES"
== {1;27/01/2011;Mme TOTO Céline;1, Rue de Paris;BRUXELLES}
>> csv-to-block/separator data #";"
== [["1" "27/01/2011" "Mme"]]
>>
trigram27-Jan-2011/13:54:30+1:00
J'aurais espéré avoir :

== [["1" "27/01/2011" "Mme TOTO Céline" "1, Rue de Paris" "BRUXELLES"]]


Pour y arriver, il faut que chaque zone de texte soit délimitée par ", comme dans l'exemple :

>> data: {1;27/01/2011;"Mme TOTO Céline";"1, Rue de Paris";"BRUXELLES"}
== {1;27/01/2011;"Mme TOTO Céline";"1, Rue de Paris";"BRUXELLES"}
>> csv-to-block/separator data #";"
== [["1" "27/01/2011" "Mme TOTO Céline" "1, Rue de Paris" "BRUXELLES"]]
guest227-Jan-2011/14:19:04+1:00
Ben j'aurais simplement fait

>> parse/all data ";"
== ["1" "27/01/2011" "Mme TOTO Céline" "1, Rue de Paris" "BRUXELLES"]
trigram27-Jan-2011/14:25:12+1:00
Je vous ai peut-être enduit de l'erreur... :(
J'ai juste mis une ligne pour l'exemple.
Mais en réalité, j'ai un fichier avec des centaines de lignes...
Si je fais le parse/all j'aurai un seul block!.
guest227-Jan-2011/14:39:12+1:00
Ah, faut tout t'écrire alors

data: read/lines %mon-fichier
forall data [
data/1: parse/all data/1 ";"
]
Didec27-Jan-2011/15:28:54+1:00
C'est un peu loin ce bout de code ! Je crois qu'il attend systématiquement qu'un texte avec espace soit encadré par des guillemets. De plus, il enlève les espaces avant et après la chaine.
En fait il fait exactement ce que dit l'URL... sauf qu'apparemment il bug sur les espaces !

Voici une correction qui fonctionne avec ton test tout en gardant les mêmes spec.

;***** Conversion function from/to CSV format
csv-to-block: func [
	"Convert a string of CSV formated data to a Rebol block. First line is header."
	csv-data [string!] "CSV data."
	/separator separ [char!] "Separator to use if different of comma (,)."
	/without-header "Do not include header in the result."
	/local out line start end this-string header record value data chars spaces chars-but-space
	; CSV format information http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
] [
	out: copy []
	separ: any [separ #","]
	
	; This function handle replacement of dual double-quote by quote while copying substring
	this-string: func [s e] [replace/all copy/part s e {""} {"}]
	; CSV parsing rules
	header: [(line: copy []) value any [separ value] (if not without-header [append/only out line])]
	record: [(line: copy []) value any [separ value] (append/only out line)]
	value: [any spaces data any spaces (append line this-string start end)]
	data: [start: some chars-but-space any [some spaces some chars-but-space] end: | #"^"" start: any [some chars | {""} | separ | newline] end: #"^""]
	chars: complement charset rejoin [ {"} separ newline]
	spaces: charset exclude { ^-} form separ
	chars-but-space: exclude chars spaces
	
	parse/all csv-data [header any [newline record] any newline end]
	out
]

block-to-csv: func [
	"Convert a block of blocks to a CSV formated string." 
	blk-data [block!] "block of data to convert"
	/separator separ "Separator to use if different of comma (,)."
	/local out csv-string record value v
] [
	out: copy ""
	separ: any [separ #","]
	; This function convert a string to a CSV formated one
	csv-string: func [val] [head insert next copy {""} replace/all copy val {"} {""} ]
	record: [into [some [value (append out separ)]]]
	value: [set v string! (append out csv-string v) | set v any-type! (append out form v)]
	
	parse/all blk-data [any [record (remove back tail out append out newline)]]
	out
]

Je précise que le format CSV n'est pas normalisé, donc on voit de tout. Dans certains cas simple, il suffit de faire un 'read/line et un "parse/all line le-separateur" pour avoir le résultat.
Mais si on veut gérer les valeurs avec saut de lignes ou caractères séparateur dans les valeurs, ça se complique.
trigram27-Jan-2011/15:41:37+1:00
@guest2

Ok merci, ca peut dépanner.

@Didec

C'est un peu mieux, mais il me bloque dès qu'il tombe sur une colonne vide.

Voici l'exemple :

>> do %duplex_csv.r
>> data: "1;;Mme TOTO Céline;1, Rue de Paris;BRUXELLES"
== "1;;Mme TOTO Céline;1, Rue de Paris;BRUXELLES"
>> csv-to-block/separator data #";"
== [["1"]]
>>
Didec27-Jan-2011/16:03:49+1:00
Mais c'est qu'il est exigeant ce petit !
;***** Conversion function from/to CSV format
csv-to-block: func [
	"Convert a string of CSV formated data to a Rebol block. First line is header."
	csv-data [string!] "CSV data."
	/separator separ [char!] "Separator to use if different of comma (,)."
	/without-header "Do not include header in the result."
	/local out line start end this-string header record value data chars spaces chars-but-space
	; CSV format information http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
] [
	out: copy []
	separ: any [separ #","]
	
	; This function handle replacement of dual double-quote by quote while copying substring
	this-string: func [s e] [replace/all copy/part s e {""} {"}]
	; CSV parsing rules
	header: [(line: copy []) value any [separ value | separ (append line none)] (if not without-header [append/only out line])]
	record: [(line: copy []) value any [separ value | separ (append line none)] (append/only out line)]
	value: [any spaces data any spaces (append line this-string start end)]
	data: [start: some chars-but-space any [some spaces some chars-but-space] end: | #"^"" start: any [some chars | {""} | separ | newline] end: #"^""]
	chars: complement charset rejoin [ {"} separ newline]
	spaces: charset exclude { ^-} form separ
	chars-but-space: exclude chars spaces
	
	parse/all csv-data [header any [newline record] any newline end]
	out
]

A noter : ça met des 'nones pour les valeurs "vide". Si ça ne te convient pas et que tu préfère des chaines vides, tu change les "append line none" (y'en a 2) par des "append line {}".
trigram27-Jan-2011/16:31:30+1:00
@Didec

Ba en fait, de un je suis un débutant, de deux je me transforme en utilisateur de base pour ce genre de demande.

Effectivement, c'est beaucoup mieux.
Maintenant, je n'ai plus qu'a faire une interface en VID pour sélectionner le fichier et afficher les lignes en anomalies.
Pour être plus précis, j'ai un fichier type CSV que je reçois d'un tiers et lorsque je l'intègre dans mon système, j'ai le problème classique des zones qui sont trop petites.
Avec ces quelques lignes de REBOL je peux ressortir les lignes et zones qui posent pb.
REBOL couteau Suisse.
coccinelle27-Jan-2011/17:27:46+1:00
A noter que sql-protocol que vous trouver sur rebol.org propose en plus du SQL: un protocol CSV: qui permet d'accéder facilement à ce genre de fichier avec les fonctions standard de manipulation des séries (INSERT, APPEND, REMOVE, CHANGE, COPY, PICK, etc...).

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2