Home » excel » excel – How to convert multiple xls files to csv using powershell?

excel – How to convert multiple xls files to csv using powershell?

Posted by: admin March 9, 2020 Leave a comment

Questions:

I’m trying to convert multiple Excel files (xls) to csv using the following powershell script:

$excel = new-object -ComObject "Excel.Application"
$excel.DisplayAlerts=$True
$excel.Visible =$false
foreach ($file in get-childitem $src_dir) {
    $wb = $excel.Workbooks.Open($file.FullName)
    $wb.SaveAs($dst_dir + $file.Name + ".csv", 6)# 6 -> csv
    $wb.Close($True)
}
$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

In principle this works e.g. I get csv files. However, for a few files (varying per run) I get an exception:

Exception calling "SaveAs" with "2" argument(s): "Microsoft Office Excel cannot access the file 'C:\Users\...\AppData\Local\Temp'. ...

Additionally, I get a message box asking if I want to save the changes to the source xls.

Once I call SaveAs, $wb references the new file. So how do I save or discard the changes to the source file? Why does this happen only for a few files? Are there any other problems with this script?

Update

I divided the input files (ca. 200) arbitrarily (i.e. don’t know the size of the groups) into 10 groups and processed each group in its own run. That worked so it is somewhat inconvenient.

thanks in advance

How to&Answers:

Try moving the code to launch and quit excel INSIDE your loop.

Yeah, it’s slower that way, but it’ll encourage Excel to clean up its temp files between each operation.

It won’t be as slow as you think because Windows and COM are smart enough to keep Excel mostly in memory even after you quit for a few seconds so that the next time you create an Excel object it’ll happen fast, exactly for situations like this.

Answer:

Maybe you can implement a timer to wait a while? Or you have a look inside the direcotry while you script is running and then remove the temp files after each cycle (one xls file conversion).

Answer:

I believe you can avoid the message box asking if you want to save by using $wb.Close($False) instead of $wb.Close($True). That’s what I use normally and I don’t get any message boxes.

Answer:

My updated script with timer – may not be exact answer but will help someone looking for a script:

$excel = new-object -ComObject "Excel.Application"
$excel.DisplayAlerts=$True
$excel.Visible =$false
$src_dir='D:\folderwithxlsx\'
$dst_dir='D:\folderwithcsv\'
Get-ChildItem $src_dir -Filter *.xlsx |
Foreach-Object{
  'processing '+$_.FullName
  $wb = $excel.Workbooks.Open($_.FullName)
  $dst_file=$dst_dir + $_.BaseName + ".csv"
  $wb.SaveAs($dst_file, 6)# 6 -> csv
  'saved '+$dst_file
  $wb.Close($True)
  Start-Sleep -Seconds 2
 }
$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)