Convierta hojas de cálculo .xls / .xlsx a múltiples .csv basados ​​en una lista

9

Necesito convertir todas las hojas de un solo archivo .xls / .xlsx a un archivo .csv. Esto se hará en todos los archivos .xls en todos los directorios y subdirectorios (recursivamente).

Paso 1 : Obtenga los nombres de las hojas de todos los .xls en 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 puede actuar como una lista:

sheetname1
sheetname2
sheetname3

Paso 2 : El código para convertir una hoja específica en un archivo .csv usando in2csv es:

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

¿Cómo puedo obtener cada nombre de hoja en un .xls / x y escribir cada hoja por separado para todos los directorios que contienen un .xls / x?

in2csv --write-sheets "-" filename.xls > filename-sheet1.csv filename-sheet2.csv .... da salida solo en sheet1.csv, no estoy seguro de cómo obtener todas las hojas de esto.

csheth
fuente
2
¿Por qué no solo findcada .xls{,x}y recorrer cada hoja usando -exec?
postre
1
@glennjackman, este es el tema perfecto aquí, tal como lo sería en Unix y Linux .
terdon

Respuestas:

10

Simplemente puede poner un bucle dentro de otro bucle.

Para evitar errores, no lo use forcon findresultados.

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')
pLumo
fuente
@muru ah mierda. Estás absolutamente en lo correcto. Lo había probado en un entorno donde el IFS ya había cambiado, por lo que, por supuesto, se propagó hacia abajo. Idiot . Gracias, editar revertido.
terdon
@RoVo la primera opción funciona bien. Sin embargo, el segundo no me da salida o error. No estoy seguro de por qué; para un solo .xls in2csv --write-sheets "-" filename.xls > sheetname.csvda solo la primera hoja. No sé qué información adicional agregar para escribir todas las hojas. Eso nos dará pistas para corregir su código.
csheth
1
¿Actualizaste a esa versión 1.0.2? pip install csvkit -U. Creo que la forma en que funciona no es lo que te gusta, con la simple skript de primera opción que tiene más formas de controlar la salida y el nombre de archivo, etc
Plumo
todavía no funciona con la actualización, y sí, preferiría usar una lista que --write-sheets Tal vez pueda configurar esta opción alternativa como otra respuesta ... A continuación, aceptaré la primera opción como respuesta. Gracias @RoVo
csheth
1
Tal vez, en general, es una buena idea tener opciones alternativas en otra respuesta. Gracias, me alegro de poder ayudar.
pLumo
6

Saltar encontrar y usar 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
muru
fuente
Este script se ve elegante pero su salida filename-{}.csvno contiene datos. Soy un novato y parece que no puedo encontrar el error editando el script y leyendo. ¿Un poco de ayuda?
csheth
@ChintanSheth mi mal, había olvidado que la redirección estaría afuera xargs. Corregido, no tan elegante ahora.
muru
xargsy >es malvado :-P. Es por eso que prefiero otro bucle, es menos propenso a errores.
pLumo
@RoVo Por lo general, también hubiera optado por otro ciclo, solo quería mostrar otro método aquí.
muru
Esto funciona ahora, aunque un poco más lento que la respuesta de @RoVo.
csheth
3

csvkit versión> 1.0.2 tiene una función integrada para escribir todas las hojas:

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

Entonces puedes probar lo siguiente:

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

Nota:

Esto parece no funcionar al 100% como se esperaba. Pero vale la pena intentarlo y como esta es la primera versión con esa opción, tal vez en futuras versiones la implementación sea mejor / más fácil.

pLumo
fuente
0

Uso Gnumeric:

ssconvert -S filename.xlsx filename.csv

para obtener un csvarchivo por hoja.

James Hirschorn
fuente