Konwertuj .xls / .xlsx arkusze kalkulacyjne do wielu .csv na podstawie listy

10

Muszę przekonwertować wszystkie arkusze jednego pliku .xls / .xlsx na plik .csv. Zostanie to wykonane we wszystkich plikach .xls we wszystkich katalogach i podkatalogach (rekurencyjnie).

Krok 1 : Przenieś nazwy arkuszy wszystkich plików .xls do pliku .csv, używając:

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

filename-sheetnames-list.csv może działać jako lista:

sheetname1
sheetname2
sheetname3

Krok 2 : Kod do konwersji określonego arkusza na plik .csv przy użyciu in2csv to:

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

Jak mogę uzyskać każdą nazwę arkusza w .xls / x i napisać każdy arkusz osobno dla wszystkich katalogów zawierających .xls / x?

in2csv --write-sheets "-" filename.xls > filename-sheet1.csv filename-sheet2.csv .... daje wynik tylko na arkusz1.csv, nie jestem pewien, jak uzyskać z tego wszystkie arkusze.

csheth
źródło
2
Dlaczego po prostu nie findkażdy .xls{,x}i pętla nad każdym arkuszu przy użyciu -exec?
deser
1
@glennjackman jest tutaj doskonale na ten temat, podobnie jak w systemach Unix i Linux .
terdon

Odpowiedzi:

10

Możesz po prostu umieścić pętlę w innej pętli.

Aby uniknąć błędów, nie używaj forz findwynikami.

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
źródło
@muru ah crap. Masz całkowitą rację. Testowałem w środowisku, w którym IFS został już zmieniony, więc oczywiście rozprzestrzenił się w dół. Idiota . Dzięki, edycja została cofnięta.
terdon
@RoVo pierwsza opcja działa dobrze. Drugi jednak nie daje mi żadnego wyjścia ani błędu. Nie jestem pewien, dlaczego; dla jednego .xls in2csv --write-sheets "-" filename.xls > sheetname.csvdaje tylko pierwszy arkusz. Nie wiem, jakie dodatkowe informacje dodać, aby napisać wszystkie arkusze. To da nam wskazówki do poprawienia twojego kodu.
csheth
1
czy zaktualizowałeś do tej wersji 1.0.2? pip install csvkit -U. Myślę, że sposób, w jaki to działa, nie jest tym, co lubisz, dzięki prostemu skryptowi z 1. opcji masz więcej sposobów kontrolowania danych wyjściowych i nazw plików itp.
pLumo,
wciąż nie działa z aktualizacją, i tak wolałbym używać listy niż --write-sheets Być może możesz ustawić tę alternatywną opcję jako inną odpowiedź ... Akceptuję wtedy pierwszą opcję jako odpowiedź. Dzięki @RoVo
csheth
1
Może ogólnie dobrym pomysłem jest posiadanie alternatywnych opcji w innej odpowiedzi. Dzięki, cieszę się, że mogłem pomóc.
pLumo,
7

Pomijanie znajdowania i używania 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
źródło
ten skrypt wygląda elegancko, ale jego dane wyjściowe filename-{}.csvnie zawierają danych. Jestem nowicjuszem i nie mogę znaleźć błędu, edytując skrypt i czytając. Trochę pomocy?
csheth
@ChintanSheth mój zły, zapomniałem, że przekierowanie będzie na zewnątrz xargs. Poprawiony, teraz nie tak elegancki.
mur
xargsi >jest zły :-P. Dlatego wolę inną pętlę, jest mniej podatna na błędy.
pLumo,
@RoVo Zwykle też wybrałem kolejną pętlę, chciałem tylko pokazać tutaj inną metodę.
mur
Działa to teraz, jednak nieco wolniej niż odpowiedź @RoVo.
csheth
3

Wersja csvkit> 1.0.2 ma wbudowaną funkcję zapisywania wszystkich arkuszy:

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

Więc możesz spróbować:

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

Uwaga:

To wydaje się nie działać w 100% zgodnie z oczekiwaniami. Ale warto spróbować, a ponieważ jest to pierwsza wersja z tą opcją, być może w przyszłych wersjach implementacja jest lepsza / łatwiejsza.

pLumo
źródło
0

Użyj Gnumeric:

ssconvert -S filename.xlsx filename.csv

aby uzyskać jeden csvplik na arkusz.

James Hirschorn
źródło