Split Excelfile .xlxs with Powershell based on column values - excel

I need to split and save an excel file based on the values of the first column via a powershell script. Here is how the excel file is build up (app 30.000 rows)
´´´Column1 # Column2 # Column3´´´
´´´AA # data # data # data´´´
´´´AA # data # data # data´´´
´´´AB # data # data # data´´´
´´´AC # data # data # data´´´
´´´AC # data # data # data´´´
The result should be multiple files with filenames AA.xlxs, AB.xlxs, AC.xlxs and of course the according rows data.
What I have so far is the following code:
$objexcel = New-Object -ComObject Excel.Application
$wb = $objexcel.WorkBooks.Open("C:\Test.xlsx")
$objexcel.Visible = $true
$objexcel.DisplayAlerts = $False
$ws = $wb.Worksheets.Item(1)
$doc = $ws.Range("A:A")
foreach ($doc in $docs) {
$newfile,$objexcel = $objexcel.where({$doc -eq $doc})
$newfile | Export-Excel "C:\$doc.xlxs"
}
It just opens the file, but nothing happens.
It would be great if some coder could have a look at the code or provide a working one.
Thanks in advance.

Following is a working code that will iterate through unique elements in column one and make a copy of it in a new spreadsheet and save it.
Function Create-Excel-Spreadsheet {
Param($NameOfSpreadsheet)
# open excel
$excel = New-Object -ComObject excel.application
$excel.visible = $true
# add a worksheet
$workbook = $excel.Workbooks.Add()
$xl_wksht= $workbook.Worksheets.Item(1)
$xl_wksht.Name = $NameOfSpreadsheet
return $workbook
}
$objexcel = New-Object -ComObject Excel.Application
$wb = $objexcel.WorkBooks.Open("C:\Temp\Test.xlsx") # Changing path for test.xlsx file.
$objexcel.Visible = $true
$objexcel.DisplayAlerts = $False
$ws = $wb.Worksheets.Item(1)
$usedRange = $ws.UsedRange
$usedRange.AutoFilter()
$totalRows = $usedRange.Rows.Count
$rangeForUnique = $usedRange.Offset(1, 0).Resize($UsedRange.Rows.Count-1)
[string[]]$UniqueListOfRowValues = $rangeForUnique.Columns.Item(1).Value2 | sort -Unique
for ($i = 0; $i -lt $UniqueListOfRowValues.Count; $i++) {
$newRange = $usedRange.AutoFilter(1, $UniqueListOfRowValues[$i])
$workbook = Create-Excel-Spreadsheet $UniqueListOfRowValues[$i]
$wksheet = $workbook.Worksheets.Item(1)
$range = $ws.UsedRange.Cells
$range.Copy()
$wksheet.Paste($wksheet.Range("A1"))
$workbook.SaveAs("C:\temp\" + $UniqueListOfRowValues[$i], $xlFixedFormat)
$workbook.Close()
}

Reason nothing is happening is because you are iterating over $docs which does not contain any elements. It is currently null.
When you make a reference to look up the data, you are using $objexcel, but thats your excel application.. not the worksheet that you want to iterate over. Use $as for accessing the worksheet.
You need to iterate over Cells of your $ws and take the data when cells.Item(x, 0) and create a new file based on that with values in other two columns.
Link to example on SO -> Create and Update excel file

Related

How to run in a loop for column A , find a value and print the corresponding data from column B

I am working on xlsx file and i need to read values from column A and display the values in column B
For an example column A has 100 rows and some of them have a string. At column B (Also 100 rows) i have also values. I want to run in a loop a search for all the cells in column A, Store them and print the corresponding values in column B
I want to search for # and display 1,2,7 from B
I need an object that holds the values from A and object for B (For further actions)
The code below search in all the columns and display the values.
What i need is to read only from a specific column. and i need an object that holds the values from A and B
$data holds the data of column A.
I want to in a loop and search for data and then display the same data in the same row in column B?
$ExcelFile = "C:\Temp\SharedFolder\Test.xlsx"
$excel = New-Object -ComObject Excel.Application
$Excel.visible = $false
$Excel.DisplayAlerts = $False # Disable comfirmation prompts
$workbook = $excel.Workbooks.Open($ExcelFile)
$data = $workbook.Worksheets['Sheet1'].UsedRange.Rows.Columns[1].Value2
Doing this in Excel can be done, but takes a bit more work.
If this is your Excel file:
$ExcelFile = "D:\Test\Test.xlsx"
$searchValue = '#'
$excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Excel.DisplayAlerts = $False # Disable comfirmation prompts
$workbook = $excel.Workbooks.Open($ExcelFile)
$worksheet = $workbook.Worksheets.Item(1)
# get the number of rows in the sheet
$rowMax = $worksheet.UsedRange.Rows.Count
# loop through the rows to test if the value in column 1 equals whatever is in $searchValue
# and capture the results in variable $result
$result = for ($row = 1; $row -le $rowMax; $row++) {
$val = $worksheet.Cells.Item($row, 1).Value2
if ($val -eq $searchValue) {
# output an object with both values from columns A and B
[PsCustomObject]#{A = $val; B = $worksheet.Cells.Item($row, 2).Value2}
}
}
# when done, quit Excel and remove the used COM objects from memory (important)
$excel.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Now you can process the objects in $result. For demo just output:
$result
A B
- -
# 1
# 2
# 7
Of course, it would be far easier if you save your Excel file as CSV..
$searchValue = '#'
$result = Import-Csv -Path 'D:\Test\Test.csv' -UseCulture | Where-Object { $_.A -eq $searchValue }
$result
When exporting an Excel file to Csv, Excel won't always use the comma as delimiter character. That depends on your machine's local settings. This is the reason I added switch -UseCulture to the Import-Csv cmdlet which will make sure it uses the same delimiter character your locally installed Excel uses for its output.

[powershell]Pasting table from Excel to Word, autofit table

Currently working on a robot where I want to download an excel file from a system, copy paste the contents of the excel file to a word file as an embedded excel table, but the table is wider than the page (it is already in landscape mode). I am using a powershell script in DAS to execute this step. To solve the problem normally, I would simply right-click on the table and use Autofit -> Fit to Window. How do I do this in powershell?
My script is currently like this:
$word = new-object -comobject Word.application
$word.visible = $true
$doc1 = $word.documents.open($destination)
$bookmark1 = $doc1.Bookmarks.Item("FacilitySheet")
$xl = New-Object -comobject Excel.Application
$xl.Visible = $true
$xl.DisplayAlerts = $False
$wb = $xl.Workbooks.Open("C:\Users\Pater\Downloads\spreadsheet.xlsx")
$ws = $wb.ActiveSheet
$Range1 = $ws.UsedRange.Cells
$RowCount = $Range1.rows.count
$CopyRange = $ws.Range("A1:O$RowCount").Copy()
$bookmark1.Range.Paste()
To solve this you must set the AutoFitBehavior to the desired value. Please check https://learn.microsoft.com/en-us/office/vba/api/word.table.autofitbehavior for the allowed values and take into account that the values wdAutoFitContent, etc may not be accessed from Powershell, so you must set the raw values (1 for wdAutoFitContent, for example)
$word = new-object -comobject Word.application
$word.visible = $true
$doc1 = $word.documents.open($destination)
$bookmark1 = $doc1.Bookmarks.Item("FacilitySheet")
$xl = New-Object -comobject Excel.Application
$xl.Visible = $true
$xl.DisplayAlerts = $False
$wb = $xl.Workbooks.Open("C:\Users\Pater\Downloads\spreadsheet.xlsx")
$ws = $wb.ActiveSheet
$Range1 = $ws.UsedRange.Cells
$RowCount = $Range1.rows.count
$CopyRange = $ws.Range("A1:O$RowCount").Copy()
$bookmark1.Range.Paste()
$bookmark1.Range.AutoFitBehavior(1)

How to export a DataTable into an Excel file via Powershell?

I was searching for a simple and fast option to export an existing DataTable-object via Powershell into an Excel file.
At the end I came up with this code. I hope it helps others with same challenge:
# get XML-schema and XML-data from the table:
$schema = [System.IO.StringWriter]::new()
$myTable.WriteXmlSchema($schema)
$data = [System.IO.StringWriter]::new()
$myTable.WriteXml($data)
# start Excel and prepare some objects:
$xls = New-Object -Comobject Excel.Application
$xls.DisplayAlerts = $false
$xls.Visible = $false
$book = $xls.Workbooks.Add()
$sheet = $book.Worksheets[1]
$range = $sheet.Range("A1")
# import the data and save the file:
$map = $book.XmlMaps.Add($schema)
[void]$book.XmlImportXml($data, $map, $true, $range)
$book.SaveAs("c:\temp\test.xlsx", 51)
$xls.Quit()

Powershell select entire row with already opened excel worksheet

I'm writing a little GUI to ease working on some excel documents. It has a button that starts this function to open excel file and select required row.
Function open_bible_file
{
$Excel = New-Object -ComObject excel.application
$Excel.WindowState= "xlMaximized"
$Excel.visible = $true
$WorkBook = $Excel.Workbooks.Open($SCOMBibleFile)
$Worksheet = $Workbook.WorkSheets.item("(1) Alerts")
$worksheet.activate()
$Range = $Worksheet.Cells.Item($excelrow,1).EntireRow
[void]$Range.Select()
}
}
It opens the file and selects the row as it should. But when I use this button again it just opens excel one more time and again selects another row. When I've tried to do another button to just select rows It does not know anything about already opened worksheets. How can I get around it?
The code should check if Excel is already running and if so, if the workbook (file $SCOMBibleFile) is present. If that is the case, re-activate Excel, otherwise start a new instance.
This should work:
function open_bible_file {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path,
[Parameter(Mandatory = $false, Position = 1)]
[int]$RowToSelect = 1
)
$WorkBook = $null
# check if Excel is already open
try {
# Note: this only gets the excel instances that were started
# by the same user that runs this powershell function.
$Excel = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
# test if the $Path workbook is present in this Excel instance
foreach ($wb in $Excel.Workbooks) {
if ($wb.FullName -match [regex]::Escape($Path)) {
$WorkBook = $wb
break
}
}
}
catch {
# Excel wasn't opened yet, create a new instance
$Excel = New-Object -ComObject Excel.Application
}
if (!($Excel)) { Write-Error "Error opening Excel"; return }
if (!($WorkBook)) {
$WorkBook = $Excel.Workbooks.Open($Path)
}
# see https://learn.microsoft.com/en-us/office/vba/api/excel.xlwindowstate
$xlMaximized = -4137
$Excel.Visible = $true
$Excel.WindowState = $xlMaximized
$Excel.ActiveWindow.Activate()
$Worksheet = $Workbook.WorkSheets.item("(1) Alerts")
$worksheet.activate()
$Range = $Worksheet.Cells.Item($RowToSelect, 1).EntireRow
[void]$Range.Select()
}
$SCOMBibleFile = '<PATH TO YOUR .xlsx FILE>'
open_bible_file -Path $SCOMBibleFile -RowToSelect 3
As you can see, I have changed the open_bible_file function to take parameters. The first (-Path) is where you give it the filename to open. The second (-RowToSelect) is the row number you want selected.
Hope this helps

How do I embed hyperlinks from one excel file into text from another excel file with powershell

Good Evening everyone,
I have a problem that I am having some issues with and I really need some help. I took two csv files and compared them and converted them to an xls. Now the part I am confused about is how will I be able to take the hyperlinks from Column 1, Row 1 in one excel document and embed them into the text in the other document Column 1, Row2.
is there an easy way to do this? I found the follow link which left me a little confused : https://social.technet.microsoft.com/Forums/scriptcenter/en-US/123d673a-f9a7-4ae6-ae9c-d4ae8ef65015/powershell-excel-how-do-i-create-a-hyperlink-to-a-cell-in-another-sheet-of-the-document?forum=ITCG
I appreciate any guidance and help you can offer.
#Define the file path and sheet name
$FilePath= `enter
code"C:\Users\cobre\Desktop\PowerShell\HomeWork2\Test3.csv"
$FilePath2="C:\Users\cobre\Desktop\PowerShell\HomeWork2\Test3.xls"
$FilePath3="C:\Users\cobre\Desktop\PowerShell\HomeWork2\Test4.xls"
$SheetName="Test3"
$SheetName2="HyperLinks"
#Compare two CSV files to look for matches
$CSV1 = import-csv -path
C:\Users\cobre\Desktop\PowerShell\HomeWork2\Test1.csv
$CSV2 = import-csv -path
C:\Users\cobre\Desktop\PowerShell\HomeWork2\Test2.csv
Compare-Object $CSV1 $CSV2 -property ShoppingList -IncludeEqual | where-
object {$_.SideIndicator -eq "=="}
# Create an Object Excel.Application using Com interface
$objExcel = New-Object -ComObject Excel.Application
# Enable the 'visible' property so the document will open in excel
$objExcel.Visible = $true
$objExcel.DisplayAlerts = $False
# Open the Excel file and save it in $WorkBook
$WorkBook = $objExcel.Workbooks.Open($FilePath)
# Load the WorkSheet "Test3"
$WorkSheet = $WorkBook.sheets.item($SheetName)
# Delete data from column
[void]$WorkSheet.Cells.Item(1,2).EntireColumn.Delete()
#Auto fit everything so it looks better
$usedRange = $WorkSheet.UsedRange
$usedRange.EntireColumn.AutoFit() | Out-Null
#Save and convert to XLS
$Workbook.SaveAs("C:\Users\cobre\Desktop\PowerShell\HomeWork2\Test3.xls",1)
$Workbook.Saved = $True
#Load
$excel = New-Object -comobject Excel.Application
$excel.Visible = $True
$workbook = $objExcel.Workbooks.Add()
$workbook.Worksheets.Item($FilePath2).Hyperlinks.Add( `
$workbook.Worksheets.Item($FilePath2).Cells.Item(1,2) , `
"" , $FilePath3, "https://community.spiceworks.com/topic/673034-powers
You can use something like this:
$excel = New-Object -comobject Excel.Application
$excel.Visible = $True
$workbook = $excel.Workbooks.Add()
$workbook.Worksheets.Item(1).Hyperlinks.Add($workbook.Worksheets.Item(1).Cells.Item(1,1) ,"" , "Sheet2!C4", "", "Link to sheet2")
Reference : Hyperlinks.Add Method
Hope it helps

Resources