I currently have a PS script that refreshes Excel files that have 1 data connection and it works perfectly. The issue is that I've built other Excel files that have 3 data connections. When I try to use the below code for the files with 3 data connection strings, the data gets processed, but only one of the data connections gets updated. Can anyone tell me what I need to do to get all data connections updated? I tried repeating the "refresh all"/"Save" part of the code, but that gave me error messages. Any help would be appreciated.
$excel = new-object -comobject excel.application
$excel.DisplayAlerts = $false
$excelFiles = Get-ChildItem -Path "File Folder Location (ex. C:\Documents)" -Include *.xls, *.xlsm,*.xlsx, *.lnk -Recurse
Foreach($file in $excelFiles)
{
$workbook = $excel.workbooks.open($file.fullname)
$worksheet = $workbook.worksheets.item(1)
$workBook.RefreshAll()
$workbook.save()
$workbook.close()
}
$excel.quit()
Depending on your connections, one the methods might help you (untested)
$excel = new-object -comobject excel.application
$excel.DisplayAlerts = $false
$excelFiles = Get-ChildItem -Path "$($env:userprofile)\Documents)" -Include *.xls, *.xlsm,*.xlsx, *.lnk -Recurse
Foreach($file in $excelFiles) {
$workbook = $excel.workbooks.open($file.fullname)
# ---- this method ----
foreach ($Conn in $workbook.Connections){
$Conn.OLEDBConnection.BackgroundQuery = $false
$Conn.refresh()
}
# ---- and/or this method ----
foreach ($Sheet in $workbook.Worksheets) {
foreach ($QTable in $Sheet.QueryTables) {
$QTable.BackgroundQuery = $false
}
}
# ----- might get you further, depneding on your connections ----
$workBook.RefreshAll()
$workbook.save()
$workbook.close()
}
$excel.quit()
Related
I am taking an excel report moving it from a share drive with a partial file name changing it to an txt file then renaming it than removing the one from citrix. Problem is the file is not changing to a txt or renaming and also not removing itself from citrix
I am very new to powershell could anybody offer insight?
Move-Item -Path 'S:\test\test*.xls' -destination c:\test
$files = Get-ChildItem c:\test\test*.xls
$Excel = New-Object -ComObject Excel.Application
$Excel.visible = $false
$Excel.DisplayAlerts = $false
ForEach ($file in $files) {
Write "Loading File '$($file.Name)'..."
$WorkBook = $Excel.Workbooks.Open($file.Fullname)
$NewFilePath = [System.IO.Path]::ChangeExtension($file.Fullname,".txt")
$Workbook.SaveAs($NewFilepath, 42) # xlUnicodeText
}
# cleanup
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($WorkBook) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Rename-Item -Path "C:\test\test*.txt" -NewName "test1.txt"
Remove-Item -Path C:\test\test*.txt `
I've written a code that tries to go through my company server and set all the excel files, under a certain folder, to shared so that multiple people can edit them at once. This has been a problem for a very long time here and I thought I had a nice code to fix this but I can't seem to access the property correctly. Can anyone help?
$ErrorActionPreference = "Stop"
$root = "P:\A N G"
$excelFiles = Get-ChildItem -path $root -File "*.xlsx" -Recurse
foreach ($excelFile in $excelFiles.FullName)
{
$excel = New-Object -ComObject Excel.Application
$excelWorkBook = $excel.Workbooks.Open($excelFile)
if (!$excelWorkBook.MultiUserEditing)
{
Write-Host $excelFile
$excelWorkBook._SaveAs([Microsoft.Office.Interop.Excel.XlSaveAsAccessMode]::xlShared)
$excelWorkBook.Close
}
}
With some help from a friend I managed to come up with a solution actually.
$ErrorActionPreference = "Stop"
$root = "P:\A N G"
$excelFiles = Get-ChildItem -path $root -File "*.xlsx" -Recurse
foreach ($excelFile in $excelFiles.FullName)
{
$excel = New-Object -ComObject Excel.Application
$excelWorkBook = $excel.Workbooks.Open($excelFile)
if (!$excelWorkBook.MultiUserEditing)
{
Write-Host $excelWorkBook.FullName
$accessMode = [Microsoft.Office.Interop.Excel.XlSaveAsAccessMode]::xlShared
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
$excelWorkBook.SaveAs($excelWorkBook.FullName,$xlFixedFormat,$null,$null,$null,$null,$accessMode,$null,$null,$null,$null,$null)
$excelWorkBook.Close
}
}
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
I used below code to convert file from CSV to xlsx. But it only convert single file at a time. I want this to convert all the files in directory at a time.
$xl = New-Object -ComObject Excel.Application
$xl.Visible = $true
$Workbook = $xl.Workbooks.Open("$loglocation\errors_$server.csv")
$Worksheets = $Workbooks.Worksheets
$Workbook.SaveAs("$loglocation\errors_$server.xls",1)
$Workbook.Saved = $true
$xl.Quit()
With the PSExcel Module you can use Export-XLSX which makes this process very simple:
$loglocation = "C:\folder"
Get-ChildItem -Path $loglocation -Filter *.csv | foreach {
Export-XLSX -InputObject $_ -Path "$loglocation\$($_.BaseName).xlsx"
}
Try this, should work:
$filePath = Get-ChildItem -Path "path to csv" -filter *.csv
foreach ($file in $filePath )
{
$filename = $file.FullName
$filename
$xl = new-object -comobject excel.application
$xl.visible = $true
$Workbook = $xl.workbooks.open($filename)
$Worksheets = $Workbooks.worksheets
$Workbook.SaveAs($filename.Substring(0,$filename.Length-4) + ".xlsx",1)
$Workbook.Saved = $True
$xl.Quit()
}
Can move the excel connections outside the loop as well if you need to speed it up
I am trying to create automatically a report out of an excel file. I already analyzed one specific file and the report is saved local.
Now I want to use this macro to run it on other files. Therefore I have to change the path in the powershell.
Now I want to run the macro automatically (let`s say at 1am) with powershell.
$excel = New-Object -comobject Excel.Application
$wbPersonalXLSB = $excel.workbooks.open("C:\Users\fami\AppData\Roaming\Microsoft\Excel\XLSTART\PERSONAL.XLSB")
$FilePath = "C:\Users\fami\Desktop\example.xls"
$workbook = $excel.Workbooks.Open($FilePath)
$excel.Visible = $false
$worksheet = $workbook.worksheets.item(1)
$excel.Run("PERSONAL.XLSB!run")
$wbPersonalXLSB.Close()
$workbook.save()
$workbook.close()
$excel.quit()
Only the $FilePath needs to be variable.
You just need to use a Parameter for the $FilePath variable instead of hard coding it. Like this:
param([string]$FilePath)
$excel = New-Object -comobject Excel.Application
$wbPersonalXLSB = $excel.workbooks.open("C:\Users\fami\AppData\Roaming\Microsoft\Excel\XLSTART\PERSONAL.XLSB")
$workbook = $excel.Workbooks.Open($FilePath)
$excel.Visible = $false
$worksheet = $workbook.worksheets.item(1)
$excel.Run("PERSONAL.XLSB!run")
$wbPersonalXLSB.Close()
$workbook.save()
$workbook.close()
$excel.quit()
Then you would schedule the script and specify the -FilePath paramater like so:
powershell.exe -file C:\folder\yourscript.ps1 -FilePath "C:\Users\fami\Desktop\example.xls"
EDIT: To read a list of files from a text file (with one file on each line) would be this.
param(
[string]$FileList,
[string]$PersonalXLSB="C:\Users\fami\AppData\Roaming\Microsoft\Excel\XLSTART\PERSONAL.XLSB",
[string]$RunMacro="PERSONAL.XLSB!run"
)
$Files = Get-Content $FileList
foreach ($FilePath in $Files) {
$excel = New-Object -comobject Excel.Application
$wbPersonalXLSB = $excel.workbooks.open($PersonalXLSB)
$workbook = $excel.Workbooks.Open($FilePath)
$excel.Visible = $false
$worksheet = $workbook.worksheets.item(1)
$excel.Run($RunMacro)
$wbPersonalXLSB.Close()
$workbook.save()
$workbook.close()
$excel.quit()
}
I've also moved the PersonalXLSB and Macro to Params, as they have a value set this will be used as default if you don't specify anything else. It's most basic form is like this:
powershell.exe -file C:\folder\yourscript.ps1 -FileList "C:\folder\name.text"
You can change the other params like this:
powershell.exe -file C:\folder\yourscript.ps1 -FileList "C:\folder\name.text" -RunMacro="PERSONAL.XLSB!macroname"
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()