2011-05-19 89 views
6

Estoy tratando de convertir varios archivos de Excel (XLS) a CSV utilizando la siguiente secuencia de comandos de PowerShell:¿Cómo convertir múltiples archivos xls a csv usando powershell?

$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) 

En principio esto funciona, por ejemplo, Obtengo archivos csv. Sin embargo, para algunos archivos (que varía por corrida) consigo una excepción:

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

Además, aparece un cuadro de mensaje preguntando si desea guardar los cambios a la fuente xls.

Una vez que llamo a SaveAs, $ wb hace referencia al nuevo archivo. Entonces, ¿cómo puedo guardar o descartar los cambios en el archivo de origen? ¿Por qué sucede esto solo para algunos archivos? ¿Hay algún otro problema con este script?

actualización

dividí los archivos de entrada (ca. 200) de forma arbitraria (es decir, no sé el tamaño de los grupos) en 10 grupos y se procesa cada grupo en su propia carrera. Eso funcionó, así que es un poco inconveniente.

gracias de antemano

+0

¿Tiene una mirada al archivo tempory se muestra en el error, sólo para ver si hay no hay archivo restante. Me encontré con un problema similar en una secuencia de comandos de conversión de PDF y el archivo temprary antiguo que quedaba estaba en el origen del problema. – JPBlanc

+0

Desafortunadamente, el mensaje de error solo nombra el directorio Temp. Supervisé el directorio durante una ejecución y aparecieron y desaparecieron dos archivos (supuestamente para cada xls convertido) con nombres aleatorios. – wierob

Respuesta

0

Tal vez se puede implementar un temporizador que esperar un tiempo? O puede echar un vistazo dentro del directorio mientras se ejecuta el script y luego eliminar los archivos temporales después de cada ciclo (una conversión de archivo xls).

4

Intenta mover el código para iniciar y cerrar Excel DENTRO de tu ciclo.

Sí, es más lento de esa manera, pero alentará a Excel a limpiar sus archivos temporales entre cada operación.

No será tan lento como piensas porque Windows y COM son lo suficientemente inteligentes como para mantener a Excel en la memoria incluso después de que lo dejas por unos segundos para que la próxima vez que crees un objeto de Excel ocurra rápido , exactamente para situaciones como esta.

0

Creo que puede evitar el cuadro de mensaje preguntando si desea guardar usando $wb.Close($False) en lugar de $wb.Close($True). Eso es lo que uso normalmente y no recibo ningún cuadro de mensaje.

0

Mi secuencia de comandos actualizada con temporizador - puede no ser la respuesta exacta, pero le ayudará a alguien en busca de un 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)