Converti i fogli di calcolo .xls / .xlsx in più .csv in base a un elenco


9

Devo convertire tutti i fogli di un singolo file .xls / .xlsx in un .csv. Questo sarà fatto su tutti i file .xls in tutte le directory e sottodirectory (ricorsivamente).

Passaggio 1 : ottieni i nomi dei fogli di tutti i .xls in un .csv usando:

for file in $(find . -name '*.xls' -o -name '*.xlsx');do in2csv -n "$file" > ${file%.xls}-sheetnames-list.csv; done

filename-sheetnames-list.csv può agire come un elenco:

sheetname1
sheetname2
sheetname3

Passaggio 2 : Il codice per convertire un foglio specifico in un .csv utilizzando in2csv è:

in2csv --sheet "SHEETNAME" filename.xls > filename-SHEETNAME.csv

Come posso ottenere ogni nome di foglio in un .xls / x e scrivere ogni foglio separatamente per tutte le directory che contengono un .xls / x?

in2csv --write-sheets "-" filename.xls > filename-sheet1.csv filename-sheet2.csv .... fornisce output solo su sheet1.csv, non sono sicuro di come ottenere tutti i fogli da questo.


2
Perché non usare findtutti .xls{,x}e scorrere su ogni foglio usando -exec?
dessert

1
@glennjackman questo è perfettamente in tema qui, proprio come su Unix e Linux .
terdon,

Risposte:


10

Puoi semplicemente inserire un loop all'interno di un altro loop.

Per evitare errori, non utilizzare forcon i findrisultati.

while IFS= read -r file; do
    while IFS= read -r sheet; do
        in2csv --sheet "$sheet" "$file" > "${file%.*}-${sheet}.csv"
    done < <(in2csv -n "$file")
done < <(find . -name '*.xls' -o -name '*.xlsx')

@muru ah merda. Hai assolutamente ragione. Avevo testato in un ambiente in cui l'IFS era già stato modificato, quindi ovviamente si propagava verso il basso. Idiot . Grazie, modifica ripristinata.
terdon,

@RoVo la prima opzione funziona bene. Il secondo però non mi dà alcun output o errore. Non sono sicuro del perché; per un singolo .xls in2csv --write-sheets "-" filename.xls > sheetname.csvdà solo il primo foglio. Non so quali informazioni aggiuntive aggiungere per scrivere tutti i fogli. Questo ci fornirà indizi per correggere il tuo codice.
csheth,

1
hai aggiornato a quella versione 1.0.2? pip install csvkit -U. Penso che il modo in cui funziona non è quello che ti piace, con il semplice script della prima opzione hai più modi per controllare l'output, i nomi dei file, ecc.
pLumo

non funziona ancora con l'aggiornamento, e sì, preferirei usare un elenco di --write-sheets Forse puoi impostare questa opzione alternativa come un'altra risposta ... Accetterò la prima opzione come risposta allora. Grazie @RoVo
csheth

1
Forse in genere è una buona idea avere opzioni alternative in un'altra risposta. Grazie, felice di poterti aiutare.
pLumo,

6

Saltare la ricerca e usare bash:

shopt -s globstar  # enable recursive globbing
for f in **/*.xls{,x}  # for files ending in .xls or .xlsx
do
    in2csv -n "$f" |   # get the sheetnames
      xargs -I {} bash -c 'in2csv --sheet "$2" "$1" > "${1%.*}"-"$2".csv' _ "$f" {} # {} will be replaced with the sheetname
done

questo script sembra elegante ma il suo output filename-{}.csvnon contiene dati. Sono un principiante e non riesco a trovare l'errore modificando la sceneggiatura e leggendo. Qualche aiuto?
csheth

@ChintanSheth il mio male, avevo dimenticato che il reindirizzamento sarebbe stato fuori xargs. Corretto, non così elegante ora.
Muru,

xargsed >è il male :-P. Ecco perché preferisco un altro loop, è meno soggetto a errori.
pLumo,

@RoVo Di solito avrei scelto anche un altro loop, volevo solo mostrare un altro metodo qui.
Muru,

Funziona ora, anche se leggermente più lentamente della risposta @RoVo.
csheth

3

La versione csvkit> 1.0.2 ha una funzione integrata per scrivere tutti i fogli:

--write-sheets: WRITE_SHEETS
                      The names of the Excel sheets to write to files, or
                      "-" to write all sheets.

Quindi potresti provare quanto segue:

find . -name '*.xls' -o -name '*.xlsx' -exec in2csv --write-sheets "-" {} \;

Nota:

Questo sembra non funzionare al 100% come previsto. Ma vale la pena provare e poiché questa è la prima versione con quell'opzione, forse nelle versioni future l'implementazione è migliore / più facile.


0

Utilizzare Gnumeric:

ssconvert -S filename.xlsx filename.csv

per ottenere un csvfile per foglio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.