Export layers in csv

Hello,
I would like to compare the names of the layers present on several files in the same directory.
For this I made a code in Python which works but I get blank lines between each data.
I tried to add the newline=‘’ argument in the open function but Rhino said: ‘open() got unexpected keyword argument ‘newline’’

import rhinoscriptsyntax as rs
import os
import Rhino
import csv

# Chemin du repertoire contenant les fichiers .3dm
folder_path = "C:\Users\Utilisateur\AppData\Roaming\Z-Kreat\Moules_simp"

Fichiers = []
Calque = []
Calques = []

# Parcourir les fichiers dans le repertoire
for filename in os.listdir(folder_path):
    # Verifier que le fichier est un fichier .3dm
    if filename.endswith(".3dm"):
        # Ouvrir le fichier
        file_path = os.path.join(folder_path, filename)
        rs.DocumentModified(False) # Desactive la sauvegarde auto
        rs.Command("_-Open " + '"' + file_path + '"' + " _Enter") # Ouvre le fichier
        rs.Command("_-SelAll _Enter") # Selectionne tous les objets
        rs.Command("_-Properties _Enter") # Ouvre la fenetre des proprietes
        Fichiers.append(filename)
        #list of layer names
        layers = rs.LayerIds()
        # Recuperer les noms des calques
        for layer in layers:
            Calque=[(rs.LayerName(layer))]
            Calques.append(Calque)

print(Fichiers)
print(Calques)

with open('Calques.csv',"w", newline='') as f:
    writer = csv.writer(f)
    writer.writerow(Fichiers)
    writer.writerows(Calques)

Maybe it’s fixed by Iron Python supporting unicode natively under the hood, but the Python 2 csv module doesn’t add enough value to justify its criminal lack of support for unicode. To write a csv file with no commas in the entries, the simplest thing to do is:

with open('Calques.csv',"w", newline='') as f:
    f.write(','.join(Fichiers))
    f.write(','.join(Calques))

newline is only a supported keyword argument for open in Python 3:

Rhino runs Iron Python 2.7 (largely compliant with CPython 2.7’s core modules):

https://docs.python.org/2.7/library/functions.html#open

Thanks James.

I tried what you suggest but I get an error message “sequence item 0: expected string, list found”

Not sure if this is what you are looking for?

import rhinoscriptsyntax as rs
import os
import Rhino

# Chemin du repertoire contenant les fichiers .3dm
folder_path = r"C:\Users\User\Desktop\CSV_Test"

fichiers = []
calques = []

rs.EnableRedraw(False)
# Parcourir les fichiers dans le repertoire
for filename in os.listdir(folder_path):
    # Verifier que le fichier est un fichier .3dm
    if filename.endswith(".3dm"):
        # Ouvrir le fichier
        file_path = os.path.join(folder_path, filename)
        rs.DocumentModified(False) # Desactive la sauvegarde auto
        rs.Command("_-Open " + '"' + file_path + '"' + " _Enter") # Ouvre le fichier
        rs.Command("_-SelAll _Enter") # Selectionne tous les objets
        rs.Command("_-Properties _Enter") # Ouvre la fenetre des proprietes
        fichiers.append(filename)
        # Recuperer les noms des calques
        for layer_name in rs.LayerNames(): calques.append(layer_name)
        
#print(fichiers)
#print(calques)

with open(r'C:\Users\User\Desktop\CSV_Test\calques.csv',"w") as f:
    f.write(','.join(fichiers)+"\n")
    f.write('\n'.join(calques))

You might need to replace

f.write(','.join(fichiers)+"\n")
with
f.write(';'.join(fichiers)+"\n")

if you need semicolon separated values instead of comma separated values.

Not sure either why you need the lines to select all objects or open Properties, this should not affect anything concerning the export of the file or layer names…

1 Like

Thank’s a lot Helvetosaur,

You are right I don’t need the lines to select the objects nor to open the properties window.
In fact what I’m looking for is to have on the first line the names of each file and below in column the layers present in each file.
It will be easier to control the layers of each file.
For the moment I get the first line with the file names but all the layers are in a single column the first.

OK, that’s a bit more complicated, as a .csv is written row by row (line by line) with the separators on each line making the columns, one will have to re-matrix everything to write the lines that way. I can try later (have to go out now). Otherwise you need a real Excel writing tool.

OK, this was fun to figure out - never wrote a nested .csv export before… Try this out and let me know what you think.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import rhinoscriptsyntax as rs
import os
import Rhino

# Chemin du repertoire contenant les fichiers .3dm
folder_path = r"C:\Users\user\Desktop\CSV_Test"

fichiers = []
calques = []

rs.EnableRedraw(False)
#créer un compteur pour trouver la la liste de calques la plus longue
max_layer_count=1
# Parcourir les fichiers dans le repertoire
for filename in os.listdir(folder_path):
    # Verifier que le fichier est un fichier .3dm
    if filename.endswith(".3dm"):
        # Créer le cheminement
        file_path = os.path.join(folder_path, filename)
        # Desactive la sauvegarde auto
        rs.DocumentModified(False) 
        # Ouvre le fichier
        rs.Command("_-Open " + '"' + file_path + '"' + " _Enter") 
        #rajouter le nom du fichier à la liste de fichiers
        fichiers.append(filename)
        #rajouter la liste les noms des calques du fichier
        #pour une liste en ordre alphabétique mettre True au lieu de False
        layer_names=rs.LayerNames(False)
        #mettre a jour max_layer count
        if len(layer_names)>max_layer_count: max_layer_count=len(layer_names)
        calques.append(layer_names)

#nous avons maintenant deux listes parallèles:
# - les noms de fichiers
# - une liste des les listes(liste imbriquée/nested list) de calques par fichier
# - plus la longueur de la liste de calques la plus longue
#print "Max layer count={}".format(max_layer_count) #debug

#ouvrir le fichier .csv
with open(r'C:\Users\Mitch\Desktop\CSV_Test\calques.csv',"w") as f:
    #ecrire la première ligne (noms de fichiers/colonnes)
    f.write(','.join(fichiers)+"\n")
    #Nous avons maintenant besoin d'une clause "try except", car certains
    #fichiers auront probablement une liste de calques plus longue que d'autres.
    for i in range(max_layer_count):
        layer_name_list=[]
        for j in range(len(fichiers)):
            try:
                layer_name=calques[j][i]
            except:
                #null-->la liste des calques de ce fichier est plus courte que
                #la valeur actuelle de "i" - donc pour créer une case blanche,
                #on va mettre un "empty string"
                layer_name=""
            #rajouter le nom du calque a la liste
            layer_name_list.append(layer_name)
        #maintenant on a toute la ligne avec les evtls. cases blanches, écrire
        #print ','.join(layer_name_list) #debug
        f.write(','.join(layer_name_list)+"\n")
rs.EnableRedraw(True)
1 Like

Thank you so much Helvetosaur,

That’s exactly what I wanted. I will dissect the code to understand it more precisely.

P.S : merci pour les commentaires en français. Vu ton pseudo j’aurai du me douter.