11

I'm trying to convert multiple excel files (xls) to csv which is located in a folder using powershell.

I can convert a single file but need help converting multiple files in a folder. But need advise on how to convert multiple files.

$ExcelWB = new-object -comobject excel.application
$Workbook = $ExcelWB.Workbooks.Open(c:\temp\temp.xls) 
$Workbook.SaveAs("c:\temp\temp.csv",6)
$Workbook.Close($false)
$ExcelWB.quit()
1
  • 1
    You should share your code, how do you convert 1 file? Commented Dec 4, 2014 at 11:56

4 Answers 4

20

You can just wrap it in a loop that iterates over all the files and change the xls extension to csv:

$ExcelWB = new-object -comobject excel.application

foreach($file in (Get-ChildItem "C:\temp" -filter "*.xls")) {
  $newname = $file.FullName -replace '\.xls$', '.csv'
  $Workbook = $ExcelWB.Workbooks.Open($file.FullName) 
  $Workbook.SaveAs($newname,6)
  $Workbook.Close($false)
}

$ExcelWB.quit()
Sign up to request clarification or add additional context in comments.

2 Comments

Pro tip: only put XLS files in this folder, as it will also convert other files, and don't have them open at the time of running the script above!
Minor suggestion: It might be more robust to use the System.IO.Path.ChangeExtension function instead of the -replace operator.
12

There are caveats with this untested code but it should help wrap your head around your issue

$ExcelWB = new-object -comobject excel.application

Get-ChildItem -Path c:\folder -Filter "*.xls" | ForEach-Object{
    $Workbook = $ExcelWB.Workbooks.Open($_.Fullname) 
    $newName = ($_.Fullname).Replace($_.Extension,".csv")
    $Workbook.SaveAs($newName,6)
    $Workbook.Close($false)
}
$ExcelWB.quit()

Take the lines in between the first and last and build a loop. Use Get-ChildItem to grab your xls files and then build a new name by replacing the extension if the FullName of the file

1 Comment

This answer has some improvements over the accepted answer: 1. creation of the excel object outside the loop for performance improvements, 2. Filter on the filetype to avoid handling non xls files 3. Generic extension replacement so you can easily convert xls, xlsx or both in one loop!
2

The conversion from xlsx files to csv can be done far quicker and without COM Objects - so without Excel installed - using the ImportExcel module developped by Doug Finke:

Install-Module -Name ImportExcel -RequiredVersion 5.4.2 
gci *.xlsx | %{Import-Excel $_ | Export-Csv ($_.basename + ".csv")}

Or the other way around:

gci *.csv | %{Import-Csv $_ | Export-Excel ($_.basename + ".xlsx")}

Parameters available for the Import-Excel cmdlet:

WorksheetName

Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported.

DataOnly

Import only rows and columns that contain data, empty rows and empty columns are not imported.

HeaderName

Specifies custom property names to use, instead of the values defined in the column headers of the TopRow.

NoHeader

Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow.

StartRow

The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.

EndRow

By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row.

StartColumn

The number of the first column to read data from (1 by default).

EndColumn

By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number.

Password

Accepts a string that will be used to open a password protected Excel file.

5 Comments

This module is truly great, but relies on the source spreadsheet to be in a clean, tabular format. The files I'm processing are not, but the accepted answer will let me force them into CSV files that I can then clean up in an automated fashion, then import and process the data. Also, of course, OP was talking about converting TO CSV files, not FROM.
Thank you for raising my mistake, I hope it is now more precise. You may use the start/end row/column parameters but I guess it would not be enough for your use. Another limitation: it only accepts xlsx files, and not xls as originally asked.
Holy smokes... I didn't know there were start/end row/column parameters. That would totally solve my particular issue.
Well done @BenoîtMayer for sharing this module. That being said, I must say the NoHeader option is quite counter-intuitive when you consider its name, vs the description of what it does! I wasted a few precious minutes on account of this!
FYI: Import-Excel does not support reading this extension type .xls
-1

To save multiple files you can surround your code with a loop and rename generically using the original xls name. To save on memory and processing time you should create and close the excel object outside the loop for a much more performant conversion.

$ExcelWB = new-object -comobject excel.application

foreach($file in (Get-ChildItem "C:\temp")) {
  $newname = $file.FullName -replace '\.xls$', '.csv'
  $Workbook = $ExcelWB.Workbooks.Open($file.FullName) 
  $Workbook.SaveAs($newname,6)
  $Workbook.Close($false)
}

$ExcelWB.quit()

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.