That and much more is already supported in Spreadsheet::Read's xlscat utility. See -s option to alter the default | to whatever you like, and -c and -m for CSV output:
usage: xlscat [-s <sep>] [-L] [-u] [ Selection ] file.xls
[-c | -m] [-u] [ Selection ] file.xls
-i [ -S sheets ] file.xls
Generic options:
-v[#] Set verbose level (xlscat)
-d[#] Set debug level (Spreadsheet::Read)
-u Use unformatted values
--noclip Do not strip empty sheets and
trailing empty rows and columns
Input CSV:
--in-sep=c Set input sep_char for CSV
Output Text (default):
-s <sep> Use separator <sep>. Default '|', \n allowed
-L Line up the columns
Output Index only:
-i Show sheet names and size only
Output CSV:
-c Output CSV, separator = ','
-m Output CSV, separator = ';'
Selection:
-S <sheets> Only print sheets <sheets>. 'all' is a valid set
Default only prints the first sheet
-R <rows> Only print rows <rows>. Default is 'all'
-C <cols> Only print columns <cols>. Default is 'all'
-F <flds> Only fields <flds> e.g. -FA3,B16