Converta planilhas .xls / .xlsx em vários .csv com base em uma lista

9

Preciso converter todas as planilhas de um único arquivo .xls / .xlsx em um .csv. Isso será feito em todos os arquivos .xls em todos os diretórios e subdiretórios (recursivamente).

Etapa 1 : obtenha os nomes de planilha de todos os .xls em um .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 pode atuar como uma lista:

sheetname1
sheetname2
sheetname3

Etapa 2 : o código para converter uma planilha específica em um .csv usando o in2csv é:

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

Como posso obter todos os nomes de folhas em um arquivo .xls / xe escrever cada folha separadamente para todos os diretórios que contêm um arquivo .xls / x?

in2csv --write-sheets "-" filename.xls > filename-sheet1.csv filename-sheet2.csv .... fornece saída apenas em sheet1.csv, não sabe como obter todas as folhas disso.

csheth
fonte
2
Por que não apenas findtodos .xls{,x}e repetir cada folha usando -exec?
sobremesa
1
@glennjackman isso é perfeitamente sobre o tópico aqui, assim como seria no Unix e Linux .
Terdon # 16:

Respostas:

10

Você pode simplesmente colocar um loop dentro de outro loop.

Para evitar erros, não use forcom 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
fonte
@muru ah porcaria. Você está absolutamente correto. Eu havia testado em um ambiente em que o IFS já havia sido alterado e, é claro, se propagado para baixo. Idiota . Obrigado, editar revertido.
Terdon #
@RoVo a primeira opção funciona bem. O segundo, no entanto, não me dá saída ou erro. Não sei por que; para um único .xls in2csv --write-sheets "-" filename.xls > sheetname.csvfornece apenas a primeira folha. Não sei quais informações adicionais adicionar para escrever todas as folhas. Isso nos dará pistas para corrigir seu código.
Csheth 8/11
1
você atualizou para essa versão 1.0.2? pip install csvkit -U. Eu acho que a forma como ele funciona não é o que você gosta, com o simples skript partir de 1º de opção que você tem mais maneiras de controlar a saída e os nomes de arquivos etc.
pLumo
ainda não funciona com a atualização e, sim, eu preferiria usar uma lista do que --write-sheets talvez Você possa definir essa opção alternativa como outra resposta ... Aceitarei a primeira opção como resposta então. Obrigado @RoVo
csheth
1
Talvez seja geralmente uma boa ideia ter opções alternativas em outra resposta. Obrigado, feliz por eu poder ajudar.
PLumo
6

Ignorando a localização e o uso do 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
fonte
esse script parece elegante, mas sua saída filename-{}.csvnão contém dados. Sou iniciante e não consigo encontrar o erro editando o script e lendo. Alguma ajuda?
Csheth 8/11
@ChintanSheth meu mal, eu tinha esquecido que o redirecionamento estaria lá fora xargs. Corrigido, não tão elegante agora.
Muru
xargse >é mau :-P. É por isso que prefiro outro loop, é menos propenso a erros.
PLumo
@RoVo Eu também usaria outro loop também, só queria mostrar outro método aqui.
muru
Isso funciona agora, porém um pouco mais lento que a resposta do @RoVo.
Csheth
3

A versão do csvkit> 1.0.2 possui uma função interna para escrever todas as folhas:

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

Então você pode tentar o seguinte:

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

Nota:

Isso parece não funcionar 100% conforme o esperado. Mas vale a pena tentar e, como esta é a primeira versão com essa opção, talvez nas versões futuras a implementação seja melhor / mais fácil.

pLumo
fonte
0

Use Gnumeric:

ssconvert -S filename.xlsx filename.csv

para obter um csvarquivo por folha.

James Hirschorn
fonte