How to convert Excel xlsx file to xls file in batch by PowerShell - excel

I am having multiple .xlsx file genrated from SAP BO4.2
But user reads .xls only so wanted to write some script which will convert .xlsx to .xls
Referred-
https://gallery.technet.microsoft.com/How-to-convert-Excel-xlsx-d9521619
and tried to use same for .xls
$ErrorActionPreference = 'Stop'
Function Convert-xlsInBatch
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$Folder
)
$ExcelFiles = Get-ChildItem -Path $Folder -Filter *.xlsx -Recurse
$excelApp = New-Object -ComObject Excel.Application
$excelApp.DisplayAlerts = $false
$ExcelFiles | ForEach-Object {
$workbook = $excelApp.Workbooks.Open($_.FullName)
$xlsFilePath = $_.FullName -replace "\.xlsx$", ".xls"
$workbook.SaveAs($xlsFilePath, [Microsoft.Office.Interop.Excel.XlFileFormat]::xlExcel7)
$workbook.Close()
}
# Release Excel Com Object resource
$excelApp.Workbooks.Close()
$excelApp.Visible = $true
Start-Sleep 5
$excelApp.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelApp) | Out-Null
}
#
# 0. Prepare the folder path which contains all excel files
$FolderPath = "D:\XXX\AA\BB\Apr-2018"
Convert-XlsInBatch -Folder $FolderPath
Error I am getting-
PS D:\Batch Script> D:\Batch Script\ConvertExcelToXlsInBatch.ps1
New-Object : Retrieving the COM class factory for component with CLSID {00000000-0000-0000-0000-000000000000} failed
due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
At D:\Batch Script\ConvertExcelToXlsInBatch.ps1:27 char:14
+ $excelApp = New-Object -ComObject Excel.Application
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand

Not sure if you've seen this solution. It's 4 years old but it seems to work.
https://superuser.com/questions/875831/using-powershell-is-it-possible-to-convert-an-xlsx-file-to-xls

Related

Powershell Excel SaveAs requires confirmation

I use below script to convert bunch of xls files to xlsx.
$folderpath = %tempPath%
$filetype ="*xls"
Add-Type -AssemblyName Microsoft.Office.Interop.Excel
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
write-host $xlFixedFormat
$excel = New-Object -ComObject excel.application
$excel.visible = $true
Get-ChildItem -Path $folderpath -Include $filetype -recurse |
ForEach-Object `
{
$path = ($_.fullname).substring(0, ($_.FullName).lastindexOf("."))
"Converting $path"
$workbook = $excel.workbooks.open($_.fullname)
$path += ".xlsx"
$workbook.saveas($path, $xlFixedFormat)
$workbook.close()
}
$excel.Quit()
$excel = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()
It used to work perfectly running on VM.
Unfortunately with changing folder path I realised there are popup windows to confirm saving that didn't come up before and the script gets stuck on that.
Any simple corrections that could prevent that error?
"scriptError": {
"localizedName": "Error",
"value": "Unable to get the SaveAs property of the Workbook class\r\nAt C:\\Users\\~
"variableName": "ScriptError"
}
Here's an example of how I set the path when saving an Excel file using PowerShell. I set the path using a combination of the Get-Location cmdlet, Get-Date cmdlet and the file name, which is stored in a string variable for use when saving the script.
Add-Type -AssemblyName Microsoft.Office.Interop.Excel
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
$htFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlHtml
$Date = get-date -format R
$CurrentLocation = Get-Location
$CurrentDir = Get-location
$Timestamp = get-date -format d
$xlsx = [String] $CurrentLocation + "\MyNewExcelStuff-" + $Timestamp + ".xlsx"
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$excel.DisplayAlerts = $False
$workbook = $excel.Workbooks.add()
$sheet1 = $workbook.worksheets.Item(1)
$sheet1.name = "Stuff"
$Sheet1.Cells.Item(1,1) = "Reporting Stack Stuff"
$title = $Sheet1.Range("A1:K1")
$title.Select()
$title.MergeCells = $true
$title.VerticalAlignment = -4108 # Centre (vertically) heading
$title.HorizontalAlignment = -4108 # Centre (horizontally) heading
$Title.Interior.ColorIndex = 0
$Excel.ActiveWorkbook.SaveAs($xlsx, $xlFixedFormat)
Start-Sleep -s 2
$Excel.Quit()
$Excel = $Null
You should use $workbook.Close($false).

Converting an Excel file into CSV file in PowerShell

I tried this code as follows:
param(
$inputPath = "N:\Disease_Prevention\....\Samplename.xlsx",
$outputPath = "N:\Disease_Prevention\...\Output.csv"
)
$xlCSV=6
$inputPath = (Resolve-path $inputPath).Path
$outputpath = (Resolve-path $outputpath).Path
get-childitem $inputPath -File | foreach {
write-host "processing $_ "
$Excelfilename = $_.fullname
if(!$outputPath)
{
$outputPath = $_.DirectoryName
}
$CSVfilename =join-path $outputpath $_.BaseName
$CSVfilename+=".csv";
#open excel and save
$Excel = New-Object -comobject Excel.Application
$Excel.Visible = $False
$Excel.displayalerts=$False
$Workbook = $Excel.Workbooks.Open($ExcelFileName)
$Workbook.SaveAs($CSVfilename,$xlCSV)
$Excel.Quit()
If(ps excel){
kill -name excel
}
}
And received the following error as follows:
The error says "Unable to get the SaveAs property of the Workbook class"
Would you know why it could be?
And if it's a permission issue, then would you recommend an alternative way to convert excel into csv? Should I use cmdlet to read each line at the excel file and convert one by one?
The issues I encountered with your code are
$outputpath = (Resolve-path $outputpath).Path
Presumably this CSV file doesn't exist, so when you try to resolve the path it gives you nothing.
if(!$outputPath)
{
$outputPath = $_.DirectoryName
}
$CSVfilename =join-path $outputpath $_.BaseName
$CSVfilename+=".csv";
If you don't pass in an outputpath argument, then this will build the file properly. However, if you pass in an outputpath as a csvfile, then you build out a path that looks like
"N:\Disease_Prevention\...\Output.csv\inputpath basename.csv"
as you're appending the current file's basename and .csv to an already full path.
The adjusted code below worked fine.
param(
$inputPath = "N:\Disease_Prevention\....\Samplename.xlsx",
$outputPath = "N:\Disease_Prevention\...\Output.csv"
)
$xlCSV=6
$inputPath = (Resolve-path $inputPath).Path
get-childitem $inputPath -File | foreach {
write-host "processing $_ "
$Excelfilename = $_.fullname
if(!$outputPath)
{
$outputPath = $_.DirectoryName
$CSVfilename = join-path $outputpath $_.BaseName
$CSVfilename+=".csv"
}
else{
$CSVfilename = $outputPath
}
#open excel and save
$Excel = New-Object -comobject Excel.Application
$Excel.Visible = $False
$Excel.displayalerts=$False
$Workbook = $Excel.Workbooks.Open($ExcelFileName)
$Workbook.SaveAs($CSVfilename,$xlCSV)
$Excel.Quit()
If(ps excel){
kill -name excel
}
}
I also encourage you to check out Doug Finke's ImportExcel powershell module. Makes working with Excel files so much easier and it doesn't require Excel be installed on the machine that runs the script.

saving xlsx as xls without compability check with powershell

I need to save some xlsx files as xls file because our SAS 9.2 cannot read xlsx.
When I save in my powershell script I get this message
I am using this code:
function convert_xlst_to_xls([string]$File) {
$Filepath = Get-Item -Path $File
Write-Host $Filepath
$NewFilepath = Join-Path -Path $FilePath.directory.FullName -ChildPath "$($Filepath.basename).xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true #or false
$workbook.CheckCompatibility = $false
$Workbook = $Excel.Workbooks.Open($Filepath.FullName, [Type]::Missing, $true)
if (Test-Path $NewFilepath) {
Remove-Item $NewFilepath
}
$Workbook.SaveAs($NewFilepath,56)
$Workbook.Close()
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Remove-Variable Excel
return "$NewFilepath"
}
$New_Excel_File = convert_xlst_to_xls("$filePath")
It will not accept the checkcompalility property on workbook.
My console:
The property 'CheckCompatibility' cannot be found on this object. Verify
that the property exists and can be set.
At S:\UO4\DWH\SIJ\CONVERT-EXCEL BACKGRUND3.ps1:32 char:1
+ $workbook.CheckCompatibility = $false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Is there anyway to force the saveas to save without showing this compabilitycontrol.

"Unable to get the Open property of the Workbooks class" when automated

I have some PowerShell scripts that invoke SQL commands, take the results and put them into a CSV file, then the CSV file is put into an excel workbook and it's emailed out to a distribution list. I had no issues running these reports through Windows Scheduled tasks on my older Windows 2008 server running SQL 2008. But I have migrated over to Windows 2016 running SQL 2016. Now when I run this process through Scheduled tasks I get the following error:
Unable to get the Open property of the Workbooks class
At C:\PowerShell\scrpits\ArtiReport3.ps1:607 char:1
+ $workbook = $excel.Workbooks.Open($csvFilePath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
If I run the PowerShell script manually I have no issues and everything runs fine. I'm using the same login to run the scripts manually as I do through scheduled tasks. Here is the script.
$query = "*SQL Query runs here*"
#Edit these peramters for the server this will be running on#
$smtpServer = "*server*";
$smtpFrom = "I3Reports#server.com";
$smtpTo = "*email list here*”
$messageSubject = "I3 Report";
#create anonymus loging for sending e-mail#
$User = "anonymous";
$PWord = ConvertTo-SecureString -String "anonymous" -AsPlainText -Force
$Creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pword
$date = (Get-Date).AddDays(-1).ToString('yyyy-MM-dd')
$date = $date+"_I3Report.xls";
$csvFilePath = "c:\Scripts\queryresults.csv"
$excelFilePath = "c:\scripts\$date"
$instanceName = "*server*"
Import-Module "sqlps"
$results = Invoke-Sqlcmd -QueryTimeout 7200 -Query $query -ServerInstance $instanceName
# Output to CSV
$results | export-csv $csvFilePath -Delimiter " " -NoTypeInformation
#this line will remove all the quotation marks from the csv file
(Get-Content $csvFilePath) | % {$_ -replace '"', ""} | out-file -FilePath $csvFilePath -Force
# Convert CSV file to Excel
$excel = New-Object -ComObject excel.application
$excel.visible = $False
$excel.displayalerts=$False
$workbook = $excel.Workbooks.Open($csvFilePath) #<-- Program fails here
$workSheet = $workbook.worksheets.Item(1)
#$workSheet.cells.item(3,3) = "HOPLA"
#for freezing pane#
$workSheet.application.activewindow.splitcolumn = 0
$workSheet.application.activewindow.splitrow = 1
$workSheet.Range("A2").application.activewindow.freezepanes = $true
$resize = $workSheet.UsedRange
$resize.EntireColumn.AutoFit() | Out-Null
$xlExcel8 = 43
$workbook.SaveAs($excelFilePath, $xlExcel8)
$workbook.Close()
$excel.quit()
$excel = $null
send-mailmessage -from $smtpFrom -to $smtpTo -subject "$messageSubject" -body "Attachment" -Attachments $excelFilePath -smtpServer $smtpServer -Credential $creds;
As mentioned this works when I run it in PowerShell manually, but through scheduled tasks it gets that error and it references the section I noted in the code. I've been working on this for days and I can't seem to figure out what is causing the issue. Any help or suggestions is welcomed. Thanks for taking the time.
I found the solution to this problem here
Powershell Excel Automation - Save/Open fails in Scheduled Task
Creating the folders and gaining access to the directories that they are in did it for me.

PowerShell Error Creating XLSX

Okay, I have 6 CSVs each containing one column. For this example, the data from the first CSV is used to create the initial document, and each after that is attempting to save to the document.
#ID
$csvFile = "$path\ID.csv"
$fpath = $Filename
$processes = Import-Csv -Path $csvFile
$Excel = New-Object -ComObject excel.application
$Excel.visible = $false
$workbook = $Excel.workbooks.add()
$excel.cells.item(1,1) = "ID"
$i = 2
foreach($process in $processes)
{
$excel.cells.item($i,1) = $process.ID
$i++
} #end foreach process
$workbook.saveas($fpath)
$Excel.Quit()
Remove-Variable -Name excel
[gc]::collect()
[gc]::WaitForPendingFinalizers()
#SRP
$csvFile = "$path\SRP.csv"
$processes = Import-Csv -Path $csvFile
$Excel = New-Object -ComObject excel.application
$Excel.visible = $false
$workbook = $Excel.workbooks.add()
$excel.cells.item(1,2) = "SRP"
$i = 2
foreach($process in $processes)
{
$excel.cells.item($i,2) = $process.SRP
$i++
} #end foreach process
$workbook.save($fpath)
$Excel.Quit()
Remove-Variable -Name excel
[gc]::collect()
[gc]::WaitForPendingFinalizers()
When I get down to the save line on the second one (#SRP section) I get the following error:
Cannot find an overload for "Save" and the argument count: "1".
At D:\UserAdminScripts\0_Powershell_Test_Scripts\Scripts_For_Lisa\NED Stuff\NED_Reports.ps1:130 char:15
+ $workbook.save <<<< ($fpath)
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
If I let the script run after the error, I get the same result for each column.
I'm aware this script isn't clean, because I don't need to close and reopen Excel for each run, but I butchered this script from http://blogs.technet.com/b/heyscriptingguy/archive/2010/09/09/copy-csv-columns-to-an-excel-spreadsheet-by-using-powershell.aspx. The saveas works correctly in the first attempt, it's just the save causing an error.
I find when I break the script, I get a pop-up to confirm whether or not I want to make changes to Book2.xlsx. I tell it yes and I check and Book2 has the 2nd column filled out with the data I wanted as the second column on my original sheet.
Any help is appreciated.
Have a look at the $Workbook object with Get-Member:
Save Method void Save ()
The Save() method doesn't accept any arguments and it's failing to work out what to do with that method and your file name argument.
You Quit the Excel app in the #ID section (thus closing the file) so you need to reopen the file before accessing the workbook and trying to write to it.
Well, it looks like I answered my own question, due to ConanW's inspiration to actually, you know, think critically. The answer to my issue is as follows:
#ID
$csvFile = "$path\ID.csv"
$fpath = $Filename
$processes = Import-Csv -Path $csvFile
$Excel = New-Object -ComObject excel.application
$Excel.visible = $false
$workbook = $Excel.workbooks.add()
$excel.cells.item(1,1) = "ID"
$i = 2
foreach($process in $processes)
{
$excel.cells.item($i,1) = $process.ID
$i++
} #end foreach process
#SRP
$csvFile = "$path\SRP.csv"
$processes = Import-Csv -Path $csvFile
$excel.cells.item(1,2) = "SRP"
$i = 2
foreach($process in $processes)
{
$excel.cells.item($i,2) = $process.SRP
$i++
} #end foreach process
$workbook.saveas($fpath)
$Excel.Quit()
Remove-Variable -Name excel
[gc]::collect()
[gc]::WaitForPendingFinalizers()

Resources