Converting the Excel properties to a Number Format - excel

I have this automation script that will take a .htm file and generate a custom object to be generated into a spreadsheet.
Unfortunately, one of the items in my object is a very long number, so when it does get exported to a .xlsx, it looks like this:
1.04511E+11
I understand that just changing the format to a number with no decimals is possible within Excel, but I wanted to know if there is a way I can change the format within my script; especially since this is intended to be an automated process.
Here is the segment of my script:
## Build custom object which allows for modification of the spreadsheet that will be generated
$xls = ForEach ($item in $spreadsheet | Where-Object {$PSItem.P4 -match '\w+'}) {
[pscustomobject]#{
## Define the colums for the CSV file
'MnsTransTy' = $item.P1.TrimStart()
'Del. Date' = $item.P2
'Time' = $item.P3
'Name 1' = $item.P4
'Purch.Doc.' = $item.P5
## Remove white space
'Cases' = $item.P6.TrimStart()
## Remove white space
'line' = $item.P7.TrimStart()
'Name' = $item.P8
## Remove white space
'Tot Pallet' = $Item.P9.TrimStart()
}
}
The item in question is P5. I am using the ImportExcel Module which is found here: https://github.com/dfinke/ImportExcel.
Any help on this would be greatly appreciated! Thanks in advance!

This is probably happens because you are getting values from cells as string data type.
You could try to specify explicitly the data type(Double in your case). Like so:
[pscustomobject]#{
## Define the colums for the CSV file
'MnsTransTy' = $item.P1.TrimStart()
'Del. Date' = $item.P2
'Time' = $item.P3
'Name 1' = $item.P4
'Purch.Doc.' = [Double]$item.P5
## Remove white space
'Cases' = $item.P6.TrimStart()
## Remove white space
'line' = $item.P7.TrimStart()
'Name' = $item.P8
## Remove white space
'Tot Pallet' = $Item.P9.TrimStart()
}

Related

XML File Mapping to get CSV Value then Open Excel using PowerShell

I have here my XML, CSV and Excel files.
I'm trying to get all the Numbers from the "Key" of my XML file.
$DocNo = $XML.Settings.Setting.Key
then get all the Corresponding File Name of that Numbers from my CSV file.
Foreach ($Line in $CSVContent) {
# (-split) the Array of Strings by Separating them from ","
$LineSplit = $Line -split ","
# Find the $Line that has the Value of $DocNo
If ($LineSplit -like $DocNo) {
# Store the String Value of $DocNo in "$FileNames"
$FileNames = $LineSplit
}
}
Write-Host $FileNames
then use the $FileNames as the File Name to be opened as a workbook.
# For every Number of Key
ForEach($Files in $DocNo){
# Open their Excel Workbook (INSERT THE FILENAME OF THE FILE NO. FROM CSV)
$WorkBook = $Excel.Workbooks.Open($Files.$FileNames)
}
The problem is there's no value showing in my $FileNames.
I can display the $FileNames but I have to specifically call them one by one.
Any suggestions and help will be appreciated :)
In the first block of code, $LineSplit is the result of using -split on a line from a CSV file. $LineSplit is an array, in your case the array contains two elements for each line from the CSV file:
$LineSplit[0] = '1'
$LineSplit[1] = 'File1.xlsx'
The square bracket notation allows you to select an element from the array by its position in the array, starting from zero.
The issue with the first block of code is that a condition ($LineSplit -like $DocNo) is comparing an array to an array using the like operator, I'm not sure what that will do but it's hard to follow. I would consider recoding it as follows:
if ($LineSplit[0] -in $DocNo)
This asks if the first column of the CSV row is in the list pulled from your XML file, then proceed.
The next issue is the building of the $FileNames variable. Each time this statement is executed in your code:
$FileNames = $LineSplit
The two element array $LineSplit representing the current CSV row, split by comma, overwrites the value of $FileNames. By the end of the loop, this only contains the last CSV line which matched the condition. This should be recoded as an array. Before the loop set up an empty array:
$FileNames = #()
Now, during the loop when the condition is met:
$FileNames += $LineSplit[1]
Recalling that $LineSplit[1] contains the filename, as it is the second element of the CSV row when split by comma. By the end of the loop the $FileNames variable should contain an array of files that are in both the CSV and the XML. The += bit is an operator that adds new elements without overwriting.
Finally, the second block of code is close, but not quite there. The loop runs through the values in $DocNo, which according to your screenshot are:
1,2,3,4,5,6
These values are placed into the $Files variable for each loop - and then the $File.$FileNames syntax is incorrect, it is attempting to retrieve a property from the numbers retrieved from the $DocNo values. The values are just integers, so there is no $FileNames property to retrieve. The loop should run through the list we already constructed
ForEach ($File in $FileNames) {
# Open their Excel Workbook (INSERT THE FILENAME OF THE FILE NO. FROM CSV)
$WorkBook = $Excel.Workbooks.Open($File)
}
Final tip, use Write-Host to display the value of variables as you go, e.g.
Write-Host $LineSplit[0]

Powershell: Script for converting excel sheet to csv using pre-installed functionality

I am trying to write a script in powershell that can loop through Excel sheets from a prepared Excel file and extract a range of values in each sheet, which I then pipe into the import-csv cmdlet. This is the first step in a larger script that acts on the csv files; I am trying to consolidate all the steps into 1 convenient script.
My problem is that I need:
the script to work without Excel installed (rules out COM object Excel.Application)
cannot install powershell modules (rules out the popular ImportExcel).
is usable on xlsx files (rules out jet 4.0 with excel object 8.0)
Doesn't require downloads/admin permissions to directories or has simple workarounds for this.
In short:
Is importing an excel sheet to CSV via a PowerShell script possible with only pre-installed Windows functionalities?
The next best thing would be minimal adjustments, such as bundling a small library with the script that can be easily referenced in the script (would Open XML SDK or EPPlus 4.5.3.3 fall into this category?).
Thank you.
It's possible to work with the raw Excel data, but you will have to "reverse engineer" the format. I was able to get some useful data from a very simple sheet.
To test and play around with this create an empty folder and save an Excel document as Book1xlsx with some values like this:
| Name | Value |
| adf | 5 |
| fgfdg | 4 |
| dfgdsfg | 3 |
Then place this script there, and see the result. If your data is any more advanced with this, you probably have to spend quite a bit of time figuring out how different types and sheets are named, and how to look them up.
unzip Book1.xlsx
[xml]$sheet = Get-Content "xl\worksheets\sheet1.xml"
[xml]$strings = Get-Content "xl\sharedStrings.xml"
$stringsTable = $strings.sst.si.t
$data = $sheet.worksheet.sheetData.row | % {
# Each column for each row is in the "c" variable
# (The ,#() is a hack to avoid powershell from turning everything into a single array)
return ,#($_.c | % {
# There is a "t" property that represents the type.
if ($_.t -like "s") {
# "s" means a string. To get the actual content we need to look up in the strings xml
return $stringsTable[$_.v]
} elseif ($_.t -like "") {
# Empty type means integer, we can return the value as is
return $_.v
}
})
}
# Data will be a 2 dimensional array
# $data[0][0] will refer to A1
# $data[1][0] will refer to A2
# $data[0][1] will refer to B1
$data
Hopefully this will be enough to get you started.
Edit:
Here is also some code to convert the 2 dimensional array into a PSObject you can use with Export-Csv.
$headers = $data[0]
$dataObject = $data | Select-Object -Skip 1 | % {
$row = $_
$index = 0
$object = #{}
foreach ($column in $row) {
$object[$headers[$index]] += $column
$index++
}
return [PSCustomObject]$object
}
$dataObject | Export-Csv ...

Pull data from a specified row in Excel spreadsheet

I'm working on a PS script to take a row of data from an Excel spreadsheet and populate that data in certain places in a Word document. To elaborate, we have a contract tracking MASTER worksheet that among other things contains data such as name of firm, address, services, contact name. Additionally, we have another TASK worksheet in the same workbook that tracks information such as project owner, project name, contract number, task agree number.
I'm writing a script that does the following:
Ask the user through a message box what kind of contract is being written ("Master", or "Task")
Opens the workbook with the appropriate worksheet opened ("Master" tab or "Task" tab)
Asks the user through a VB InputBox from which Excel row of data they want to use to populate the Word contract
Extracts that row of data from Excel
Outputs certain portions of that row of data to certain location in a Word document
Saves the Word document
Opens the Word document so the user can continue editing it
My question is this - using something like PSExcel, how do I extract that row of data out to variables that can be placed in a Word document. For reference, in case you're going to reply with a snippet of code, here are what the variables are defined as for the Excel portion my script:
$Filepath = "C:\temp\ContractScript\Subconsultant Information Spreadsheet.xlsx"
$Excel = New-Object -ComObject Excel.Application
$Workbook = $Excel.Workbooks.Open($Filepath)
$Worksheet = $Workbook.sheets.item($AgreementType)
$Excel.Visible = $true
#Choosing which row of data
[int]$RowNumber = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the row of data from $AgreementType worksheet you wish to use", "Row")
Additionally, the first row of data in the excel worksheets are the column headings, in case it matters.
I've gotten this far so far:
import-module psexcel
$Consultant = new-object System.Collections.Arraylist
foreach ($data in (Import-XLSX -path $Filepath -Sheet $AgreementType -RowStart $RowNumber))
{
$Consultant.add($data)'
But I'm currently stuck because I can't figure out how to reference the data being added to $consultant.$data. Somehow I need to read in the column headings first so the $data variable can be defined in some way, so when I add the variable $consultant.Address in Word it finds it. Right now I think the variable name is going to end up "$Consultant.1402 S Broadway" which obviously won't work.
Thanks for any help. I'm fairly new to powershell scripting, so anything is much appreciated.
I have the same issue and searching online for solutions in a royal PITA.
I'd love to find a simple way to loop through all of the rows like you're doing.
$myData = Import-XLSX -Path "path to the file"
foreach ($row in $myData.Rows)
{
$row.ColumnName
}
But sadly something logical like that doesn't seem to work. I see examples online that use ForEach-Object and Where-Object which is cumbersome. So any good answers to the OP's question would be helpful for me too.
UPDATE:
Matthew, thanks for coming back and updating the OP with the solution you found. I appreciate it! That will help in the future.
For my current project, I went about this a different way since I ran into lack of good examples for Import-XLSX. It's just quick code to do a local task when needed, so it's not in a production environment. I changed var names, etc. to show an example:
$myDataField1 = New-Object Collections.Generic.List[String]
$myDataField2 = New-Object Collections.Generic.List[String]
# ...
$myDataField10 = New-Object Collections.Generic.List[String]
# PSExcel, the third party library, might want to install it first
Import-Module PSExcel
# Get spreadsheet, workbook, then sheet
try
{
$mySpreadsheet = New-Excel -Path "path to my spreadsheet file"
$myWorkbook = $mySpreadsheet | Get-Workbook
$myWorksheet = $myWorkbook | Get-Worksheet -Name Sheet1
}
catch { #whatever error handling code you want }
# calculate total number of records
$recordCount = $myWorksheet.Dimension.Rows
$itemCount = $recordCount - 1
# specify column positions
$r, $my1stColumn = 1, 1
$r, $my2ndColumn = 1, 2
# ...
$r, $my10thColumn = 1, 10
if ($recordCount -gt 1)
{
# loop through all rows and get data for each cell's value according to column
for ($i = 1; $i -le $recordCount - 1; $i++)
{
$myDataField1.Add($myWorksheet.Cells.Item($r + $i, $my1stColumn).text)
$myDataField2.Add($myWorksheet.Cells.Item($r + $i, $my2ndColumn).text)
# ...
$myDataField10.Add($myWorksheet.Cells.Item($r + $i, $my10thColumn).text)
}
}
#loop through all imported cell values
for ([int]$i = 0; $i -lt $itemCount; $i++)
{
# use the data
$myDataField1[$i]
$myDataField2[$i]
# ...
$myDataField10[$i]
}

Powershell search excel document for exact match

I am using PowerShell to search a document for a key word (TTF) and then import some data. I am searching a few thousand excel documents and about half way through it started picking up unwanted data.
The code I have is as follows
$condition1 = "TTF"
$fs1 = $ws.cells.find($condition1)
It started getting unwanted data as the excel documents started using "TTF All Day" in another cell which was at the start of the document.
How do I get powershell to only look for "TTF" exactly and not "TTF" followed by more characters.
Thanks
Try using the LookAt:=xlWhole option to specify cells containing only "TTF":
$condition1 = "TTF"
$fs1 = $ws.cells.find($condition1, LookAt:=xlWhole)
This will work
$condition1 = "TTF"
$fs1 = [void]$ws.cells.find($condition1, [Microsoft.Office.Interop.Excel.XlLookAt]::xlWhole)
# This script illustrates how to use the Range.Find method
# with parameters to find exact match
# ------------------------------------------------------------------------------------
# Learn More:
# Range.Find Method: https://learn.microsoft.com/en-us/office/vba/api/Excel.Range.Find
# XlFindLookIn: https://learn.microsoft.com/en-us/office/vba/api/excel.xlfindlookin
# XlLookAt: https://learn.microsoft.com/en-us/office/vba/api/excel.xllookat
# Open Excel
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible=$false
$Excel.DisplayAlerts=$false
# Open Spreadsheet you want to test
$xlSource = "C:\Temp\YourSpreadsheetNameGoesHere.xlsx"
$xlBook = $Excel.Workbooks.Open($xlSource)
$xlSheet = $xlBook.worksheets.item("SheetNameGoesHere")
# What you want to seach
$searchString = "John Smith"
# Column or Range you want to seach
$searchRange = $xlSheet.Range("A1").EntireColumn
# Search
$search = $searchRange.find($searchString,
$searchRange.Cells(1,1),
[Microsoft.Office.Interop.Excel.XlFindLookIn]::xlValues,
[Microsoft.Office.Interop.Excel.XlLookAt]::xlWhole
)
# NOT FOUND
if ($search -eq $null) {
Write-Host "Not found"
}
else { # FOUND
Write-Host "Found at row #" -NoNewline
Write-Host $search.Row
}
# Close Objects
if ($xlBook) { $xlBook.close() }
if ($Excel) { $Excel.quit() }

Powershell Column Removal Script - SharePoint

I have a csv file that has multiple lines of text and columns. I want to write a script that will assign each column a variable from a single row one at a time and move to the next row. Basically, what should happen is that the first column should be stored as URL, the second as list and the third as field and then perform these tasks. Then move to the next row.
$web = Get-SPWeb (Your site URL)
$list = $web.Lists[“Your List Name”]
$field = $list.Fields[“Your Column Name”]
$field.AllowDeletion = “true”
$field.Sealed = “false”
$field.Delete()
$list.Update()
$web.Dispose()
I can do it line by line, but I would like to find out a better way to do this. I've tried writing code a number of ways, but I can't figure out how to do this with a "foreach" loop. Please help.
Without knowing the format of the CSV fields, it's hard to say for sure but something like this might work in terms of adapting your code (assuming here you have csv column names of URL, List and Column):
$csv = import-csv C:\yourpath\yourfile.csv
$csv | select * | foreach {
$web = Get-SPWeb ($_.URL)
$list = $web.Lists[$_.List]
$field = $list.Fields[$_.Column]
$field.AllowDeletion = “true”
$field.Sealed = “false”
$field.Delete()
$list.Update()
$web.Dispose()
}
I can't test the sharepoint elements but importing the csv (if it has a header row) then iterating through each object/row using a foreach loop will work.
Importance of header row is that Import-CSV will automatically create a NoteProperty named for each heading that you can then use to access that value in the current object/row.

Resources