Compare commits

..

23 Commits

Author SHA1 Message Date
dfinke
b90087bd63 Updated to include ConvertTo-ExcelXlsx 2017-07-03 13:44:01 -04:00
Doug Finke
c39a012205 Merge pull request #195 from NordbergKMD/master
Update and rename ConvertTo-ExcelXlsx.ps1 to ConvertToExcelXlsx.ps1
2017-06-29 16:16:10 -04:00
Mikkel Nordberg
675ba9d664 Update and rename ConvertTo-ExcelXlsx.ps1 to ConvertToExcelXlsx.ps1 2017-06-29 16:19:07 +02:00
Doug Finke
a8b20df16c Merge pull request #192 from NordbergKMD/master
ConvertTo-ExcelXlsx
2017-06-29 08:41:55 -04:00
Mikkel Nordberg
097f11a661 Minor patch
Consolidated parameter validation.
Added error handling on -Force if destination file cannot be deleted.
2017-06-29 14:18:29 +02:00
Mikkel Nordberg
c359560fd8 Removed case-sesitivity check.
-ne comparison operator is case insensitive so there is no need for .ToLower()
2017-06-29 12:23:24 +02:00
Mikkel Nordberg
ea0a5a7c76 Update and rename Convert-XLSToXLSX.ps1 to ConvertTo-ExcelXlsx.ps1 2017-06-27 13:20:38 +02:00
Mikkel Nordberg
8344118c11 Rename Convert-XLSToXLSX to Convert-XLSToXLSX.ps1 2017-06-23 15:56:10 +02:00
Mikkel Nordberg
1b695478e7 Create Convert-XLSToXLSX 2017-06-23 15:55:06 +02:00
dfinke
39d176e31b Updated 2017-06-15 19:56:43 -04:00
dfinke
ed84db6b2e tweaked 2017-06-15 19:56:36 -04:00
dfinke
b33223460e Added example 2017-06-15 19:43:54 -04:00
dfinke
822e63a667 Updated for copying 2017-06-15 19:42:51 -04:00
Doug Finke
f9aa52cdae Merge pull request #190 from dfinke/CodeGen-SQL
Code gen sql
2017-06-15 19:35:40 -04:00
dfinke
615f677b2e Added convert from Excel 2017-06-15 19:34:04 -04:00
dfinke
26f6df7168 Added Export-ExcelAsSQLInsert 2017-06-14 22:44:11 -04:00
Doug Finke
dc67012590 Merge pull request #187 from DarkLite1/master
Major update to 'Export-Excel'
2017-06-10 10:54:33 -04:00
DarkLite1
2ae32dae7c Merge pull request #2 from DarkLite1/ImportExcel
Snall fixe verbose
2017-05-19 14:54:31 +02:00
DarkLite1
e8a027c951 Snall fixe verbose
Verbose for the header was not in the right place
2017-05-19 14:49:14 +02:00
DarkLite1
363deae40d Merge pull request #1 from DarkLite1/ImportExcel
Small fix for ConvertTo-Number
2017-05-16 12:43:28 +02:00
DarkLite1
1cfa5c2115 Small fix for ConvertTo-Number
Forgot to initialize the variable
2017-05-16 12:41:00 +02:00
DarkLite1
2354636edd Major update
Added parameter ‘NoNumberConversion'
- Allows us to pass on data to Excel without trying to parse it as a
number
Some code clean-up:
- Removed repeating code by using functions
- Some syntax clean-up for better readability
- More clear verbose messages
- Improved error handling
Improved help
- Added parameter explanations
- Added more examples
2017-05-15 14:55:04 +02:00
DarkLite1
81fa60dad8 Merge remote-tracking branch 'refs/remotes/origin/master' into dfinke/master 2017-02-23 08:59:39 +01:00
10 changed files with 617 additions and 181 deletions

50
ConvertFromExcelData.ps1 Normal file
View File

@@ -0,0 +1,50 @@
function ConvertFrom-ExcelData {
<#
.SYNOPSIS
Reads data from a sheet, and for each row, calls a custom scriptblock with a list of property names and the row of data.
.EXAMPLE
ConvertFrom-ExcelData .\testSQLGen.xlsx {
param($propertyNames, $record)
$reportRecord = @()
foreach ($pn in $propertyNames) {
$reportRecord += "{0}: {1}" -f $pn, $record.$pn
}
$reportRecord +=""
$reportRecord -join "`r`n"
}
First: John
Last: Doe
The Zip: 12345
....
#>
param(
[Alias("FullName")]
[Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true)]
[ValidateScript( { Test-Path $_ -PathType Leaf })]
$Path,
[ScriptBlock]$scriptBlock,
[Alias("Sheet")]
$WorkSheetname = 1,
[int]$HeaderRow = 1,
[string[]]$Header,
[switch]$NoHeader,
[switch]$DataOnly
)
$null = $PSBoundParameters.Remove('scriptBlock')
$params = @{} + $PSBoundParameters
$data = Import-Excel @params
$PropertyNames = $data[0].psobject.Properties |
Where-Object {$_.membertype -match 'property'} |
Select-Object -ExpandProperty name
foreach ($record in $data) {
& $scriptBlock $PropertyNames $record
}
}

View File

@@ -0,0 +1,46 @@
function ConvertFrom-ExcelToSQLInsert {
param(
[Parameter(Mandatory = $true)]
$TableName,
[Alias("FullName")]
[Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true)]
[ValidateScript( { Test-Path $_ -PathType Leaf })]
$Path,
[Alias("Sheet")]
$WorkSheetname = 1,
[int]$HeaderRow = 1,
[string[]]$Header,
[switch]$NoHeader,
[switch]$DataOnly
)
$null = $PSBoundParameters.Remove('TableName')
$params = @{} + $PSBoundParameters
ConvertFrom-ExcelData @params {
param($propertyNames, $record)
$ColumnNames = "'" + ($PropertyNames -join "', '") + "'"
$values = foreach ($propertyName in $PropertyNames) { $record.$propertyName }
$targetValues = "'" + ($values -join "', '") + "'"
"INSERT INTO {0} ({1}) Values({2});" -f $TableName, $ColumnNames, $targetValues
}
# $data = Import-Excel @params
# $PropertyNames = $data[0].psobject.Properties |
# Where-Object {$_.membertype -match 'property'} |
# Select-Object -ExpandProperty name
# $ColumnNames = "'" + ($PropertyNames -join "', '") + "'"
# foreach ($record in $data) {
# $values = $(foreach ($propertyName in $PropertyNames) {
# $record.$propertyName
# })
# $targetValues = "'" + ($values -join "', '") + "'"
# "INSERT INTO {0} ({1}) Values({2});" -f $TableName, $ColumnNames, $targetValues
# }
}

53
ConvertToExcelXlsx.ps1 Normal file
View File

@@ -0,0 +1,53 @@
Function ConvertTo-ExcelXlsx {
[CmdletBinding()]
Param
(
[parameter(Mandatory=$true, ValueFromPipeline)]
[string]$Path,
[parameter(Mandatory=$false)]
[switch]$Force
)
Process
{
if(-Not ($Path | Test-Path) ){
throw "File not found"
}
if(-Not ($Path | Test-Path -PathType Leaf) ){
throw "Folder paths are not allowed"
}
$xlFixedFormat = 51 #Constant for XLSX Workbook
$xlsFile = Get-Item -Path $Path
$xlsxPath = "{0}x" -f $xlsFile.FullName
if($xlsFile.Extension -ne ".xls"){
throw "Expected .xls extension"
}
if(Test-Path -Path $xlsxPath){
if($Force){
try {
Remove-Item $xlsxPath -Force
} catch {
throw "{0} already exists and cannot be removed. The file may be locked by another application." -f $xlsxPath
}
Write-Verbose $("Removed {0}" -f $xlsxPath)
} else {
throw "{0} already exists!" -f $xlsxPath
}
}
try{
$Excel = New-Object -ComObject "Excel.Application"
} catch {
throw "Could not create Excel.Application ComObject. Please verify that Excel is installed."
}
$Excel.Visible = $false
$Excel.Workbooks.Open($xlsFile.FullName) | Out-Null
$Excel.ActiveWorkbook.SaveAs($xlsxPath, $xlFixedFormat)
$Excel.ActiveWorkbook.Close()
$Excel.Quit()
}
}

View File

@@ -0,0 +1,13 @@
ConvertFrom-ExcelToSQLInsert People .\testSQLGen.xlsx
ConvertFrom-ExcelData .\testSQLGen.xlsx {
param($propertyNames, $record)
$reportRecord = @()
foreach ($pn in $propertyNames) {
$reportRecord += "{0}: {1}" -f $pn, $record.$pn
}
$reportRecord +=""
$reportRecord -join "`r`n"
}

Binary file not shown.

View File

@@ -1,13 +1,151 @@
Function Export-Excel {
<#
.SYNOPSIS
Export data to an Excel work sheet.
Export data to an Excel worksheet.
.DESCRIPTION
Export data to an Excel file and where possible try to convert numbers so Excel recognizes them as numbers instead of text. After all. Excel is a spreadsheet program used for number manipulation and calculations. In case the number conversion is not desired, use the parameter '-NoNumberConversion *'.
.PARAMETER ConditionalText
Applies a 'Conditional formatting rule' in Excel on all the cells. When specific conditions are met a rule is triggered.
.PARAMETER NoNumberConversion
By default we convert all values to numbers if possible, but this isn't always desirable. NoNumberConversion allows you to add exceptions for the conversion. Wildcards (like '*') are allowed.
.PARAMETER AutoFilter
Enables the 'Filter' in Excel on the complete header row. So users can easily sort, filter and/or search the data in the select column from within Excel.
.PARAMETER AutoSize
Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell.
.PARAMETER Now
The 'Now' switch is a shortcut that creates automatically a temporary file, enables 'AutoSize', 'AutoFiler' and 'Show', and opens the file immediately.
.PARAMETER NumberFormat
Formats all values that can be converted to a number to the format specified.
Examples:
# integer (not really needed unless you need to round numbers, Excel with use default cell properties)
'0'
# integer without displaying the number 0 in the cell
'#'
# number with 1 decimal place
'0.0'
# number with 2 decimal places
'0.00'
# number with 2 decimal places and thousand separator
'#,##0.00'
# number with 2 decimal places and thousand separator and money symbol
'<27>#,##0.00'
# percentage (1 = 100%, 0.01 = 1%)
'0%'
# Blue color for positive numbers and a red color for negative numbers. All numbers will proceed a dollar sign '$'.
'[Blue]$#,##0.00;[Red]-$#,##0.00'
.PARAMETER Show
Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first.
.EXAMPLE
Get-Service | Export-Excel .\test.xlsx
Get-Process | Export-Excel .\Test.xlsx -show
Export all the processes to the Excel file 'Test.xlsx' and open the file immediately.
.EXAMPLE
Get-Process | Export-Excel .\test.xlsx -show\
$ExcelParams = @{
Path = $env:TEMP + '\Excel.xlsx'
Show = $true
Verbose = $true
}
Remove-Item -Path $ExcelParams.Path -Force -EA Ignore
Write-Output -1 668 34 777 860 -0.5 119 -0.1 234 788 |
Export-Excel @ExcelParams -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00'
Exports all data to the Excel file 'Excel.xslx' and colors the negative values in 'Red' and the positive values in 'Blue'. It will also add a dollar sign '$' in front of the rounded numbers to two decimal characters behind the comma.
.EXAMPLE
$ExcelParams = @{
Path = $env:TEMP + '\Excel.xlsx'
Show = $true
Verbose = $true
}
Remove-Item -Path $ExcelParams.Path -Force -EA Ignore
[PSCustOmobject][Ordered]@{
Date = Get-Date
Formula1 = '=SUM(F2:G2)'
String1 = 'My String'
String2 = 'a'
IPAddress = '10.10.25.5'
Number1 = '07670'
Number2 = '0,26'
Number3 = '1.555,83'
Number4 = '1.2'
Number5 = '-31'
PhoneNr1 = '+32 44'
PhoneNr2 = '+32 4 4444 444'
PhoneNr3 = '+3244444444'
} | Export-Excel @ExcelParams -NoNumberConversion IPAddress, Number1
Exports all data to the Excel file 'Excel.xslx' and tries to convert all values to numbers where possible except for 'IPAddress' and 'Number1'. These are stored in the sheet 'as is', without being converted to a number.
.EXAMPLE
$ExcelParams = @{
Path = $env:TEMP + '\Excel.xlsx'
Show = $true
Verbose = $true
}
Remove-Item -Path $ExcelParams.Path -Force -EA Ignore
[PSCustOmobject][Ordered]@{
Date = Get-Date
Formula1 = '=SUM(F2:G2)'
String1 = 'My String'
String2 = 'a'
IPAddress = '10.10.25.5'
Number1 = '07670'
Number2 = '0,26'
Number3 = '1.555,83'
Number4 = '1.2'
Number5 = '-31'
PhoneNr1 = '+32 44'
PhoneNr2 = '+32 4 4444 444'
PhoneNr3 = '+3244444444'
} | Export-Excel @ExcelParams -NoNumberConversion *
Exports all data to the Excel file 'Excel.xslx' as is, no number conversion will take place. This means that Excel will show the exact same data that you handed over to the 'Export-Excel' function.
.EXAMPLE
$ExcelParams = @{
Path = $env:TEMP + '\Excel.xlsx'
Show = $true
Verbose = $true
}
Remove-Item -Path $ExcelParams.Path -Force -EA Ignore
Write-Output 489 668 299 777 860 151 119 497 234 788 |
Export-Excel @ExcelParams -ConditionalText $(
New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor DarkRed -BackgroundColor LightPink
)
Exports data that will have a 'Conditional formatting rule' in Excel on these cells that will show the background fill color in 'LightPink' and the text color in 'DarkRed' when the value is greater then '525'. In case this condition is not met the color will be the default, black text on a white background.
.EXAMPLE
$ExcelParams = @{
Path = $env:TEMP + '\Excel.xlsx'
Show = $true
Verbose = $true
}
Remove-Item -Path $ExcelParams.Path -Force -EA Ignore
Get-Service | Select Name, Status, DisplayName, ServiceName |
Export-Excel @ExcelParams -ConditionalText $(
New-ConditionalText Stop DarkRed LightPink
New-ConditionalText Running Blue Cyan
)
Export all services to an Excel sheet where all cells have a 'Conditional formatting rule' in Excel that will show the background fill color in 'LightPink' and the text color in 'DarkRed' when the value contains the word 'Stop'. If the value contains the word 'Running' it will have a background fill color in 'Cyan' and a text color 'Blue'. In case none of these conditions are met the color will be the default, black text on a white background.
.EXAMPLE
Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM
@@ -16,28 +154,26 @@ Function Export-Excel {
Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -ChartType PieExploded3D -IncludePivotChart -IncludePivotTable -Show -PivotRows Company -PivotData PM
.EXAMPLE
Remove-Item "c:\temp\test.xlsx" -ErrorAction Ignore
Get-Service | Export-Excel "c:\temp\test.xlsx" -Show -IncludePivotTable -PivotRows status -PivotData @{status='count'}
Get-Service | Export-Excel 'c:\temp\test.xlsx' -Show -IncludePivotTable -PivotRows status -PivotData @{status='count'}
#>
[CmdLetBinding()]
Param(
#[Parameter(Mandatory=$true)]
$Path,
[Parameter(ValueFromPipeline=$true)]
$TargetData,
[String]$WorkSheetname='Sheet1',
[String]$WorkSheetname = 'Sheet1',
[String]$Title,
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern='None',
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None',
[Switch]$TitleBold,
[Int]$TitleSize=22,
[Int]$TitleSize = 22,
[System.Drawing.Color]$TitleBackgroundColor,
[String[]]$PivotRows,
[String[]]$PivotColumns,
$PivotData,
[Switch]$PivotDataToColumn,
[String]$Password,
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType='Pie',
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie',
[Switch]$IncludePivotTable,
[Switch]$IncludePivotChart,
[Switch]$NoLegend,
@@ -69,43 +205,160 @@ Function Export-Excel {
}
})]
[String]$TableName,
[OfficeOpenXml.Table.TableStyles]$TableStyle='Medium6',
[Object[]]$ConditionalFormat,
[Object[]]$ConditionalText,
[OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6',
[Object[]]$ExcelChartDefinition,
[ScriptBlock]$CellStyleSB,
[String[]]$HideSheet,
[Switch]$KillExcel,
[Switch]$AutoNameRange,
$StartRow=1,
$StartColumn=1,
[Int]$StartRow = 1,
[Int]$StartColumn = 1,
[Switch]$PassThru,
[String]$Numberformat='General',
[String]$Numberformat = 'General',
[String[]]$NoNumberConversion,
[Object[]]$ConditionalFormat,
[Object[]]$ConditionalText,
[ScriptBlock]$CellStyleSB,
[Switch]$Now
)
Begin {
$script:Header = $null
if ($KillExcel) {
Function Add-CellValue {
<#
.SYNOPSIS
Save a value in an Excel cell.
.DESCRIPTION
DateTime objects are always converted to a DateTime format in Excel. And formulas are always
saved as formulas.
Numerical values will be converted to numbers as defined in the regional settings of the local
system. In case the parameter 'NoNumberConversion' is used, we don't convert to number and leave
the value 'as is'. In case of conversion failure, we also leave the value 'as is'.
#>
Param (
[Object]$TargetCell,
[Object]$CellValue
)
Switch ($CellValue) {
{($_ -is [String]) -and ($_.StartsWith('='))} {
#region Save an Excel formula
$TargetCell.Formula = $_
Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$_' as formula"
break
#endregion
}
{$_ -is [DateTime]} {
#region Save a date with an international valid format
$TargetCell.Value = $_
$TargetCell.Style.Numberformat.Format = 'm/d/yy h:mm'
Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$_' as date"
break
#endregion
}
{(($NoNumberConversion) -and ($NoNumberConversion -contains $Name)) -or
($NoNumberConversion -eq '*')} {
#regioon Save a value without converting to number
$TargetCell.Value = $_
Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($TargetCell.Value)' unconverted"
break
#endregion
}
Default {
#region Save a value as a number if possible
if ($Number = ConvertTo-Number $_) {
$TargetCell.Value = $Number
$targetCell.Style.Numberformat.Format = $Numberformat
Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($TargetCell.Value)' as number converted from '$_' with format '$Numberformat'"
}
else {
$TargetCell.Value = $_
Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($TargetCell.Value)' as string"
}
break
#endregion
}
}
}
Function Add-Title {
<#
.SYNOPSIS
Add a title row to the Excel worksheet.
#>
$ws.Cells[$Row, $StartColumn].Value = $Title
$ws.Cells[$Row, $StartColumn].Style.Font.Size = $TitleSize
if ($TitleBold) {
#set title to Bold if -TitleBold was specified.
#Otherwise the default will be unbolded.
$ws.Cells[$Row, $StartColumn].Style.Font.Bold = $True
}
$ws.Cells[$Row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern
#can only set TitleBackgroundColor if TitleFillPattern is something other than None
if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) {
$ws.Cells[$Row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
}
else {
Write-Warning "Title Background Color ignored. You must set the TitleFillPattern parameter to a value other than 'None'. Try 'Solid'."
}
}
Function ConvertTo-Number {
<#
.SYNOPSIS
Convert a value to a number
#>
Param (
[String]$Value
)
$R = $null
if ([Double]::TryParse([String]$Value,[System.Globalization.NumberStyles]::Any,
[System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$R)) {
$R
}
}
Function Stop-ExcelProcess {
<#
.SYNOPSIS
Stop the Excel process when it's running.
#>
Get-Process excel -ErrorAction Ignore | Stop-Process
while (Get-Process excel -ErrorAction Ignore) {}
}
Try {
$script:Header = $null
if ($KillExcel) {
Stop-ExcelProcess
}
if ($Now) {
$Path=[System.IO.Path]::GetTempFileName() -replace '\.tmp','.xlsx'
$Show=$true
$AutoSize=$true
$AutoFilter=$true
$Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp','.xlsx'
$Show = $true
$AutoSize = $true
$AutoFilter = $true
}
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
if (Test-Path $path) {
Write-Debug "File `"$Path`" already exists"
if (Test-Path $Path) {
Write-Debug "Path '$Path' already exists"
}
$pkg = New-Object OfficeOpenXml.ExcelPackage $Path
$pkg = New-Object OfficeOpenXml.ExcelPackage $Path
$ws = $pkg | Add-WorkSheet -WorkSheetname $WorkSheetname -NoClobber:$NoClobber
foreach ($format in $ConditionalFormat ) {
@@ -114,138 +367,72 @@ Function Export-Excel {
$rule.Reverse = $format.Reverse
}
# Force at least one cell value
#$ws.Cells[1, 1].Value = ''
$Row = $StartRow
if ($Title) {
$ws.Cells[$Row, $StartColumn].Value = $Title
$ws.Cells[$Row, $StartColumn].Style.Font.Size = $TitleSize
if ($TitleBold) {
#set title to Bold if -TitleBold was specified.
#Otherwise the default will be unbolded.
$ws.Cells[$Row, $StartColumn].Style.Font.Bold = $True
}
$ws.Cells[$Row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern
#can only set TitleBackgroundColor if TitleFillPattern is something other than None
if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) {
$ws.Cells[$Row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
}
else {
Write-Warning "Title Background Color ignored. You must set the TitleFillPattern parameter to a value other than 'None'. Try 'Solid'."
}
Add-Title
$Row += 1
}
$firstTimeThru = $true
$isDataTypeValueType = $false
$pattern = 'string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort'
}
Catch {
if ($AlreadyExists) {
throw "$WorkSheetname already exists."
} else {
throw $Error[0].Exception.Message
throw "Failed exporting worksheet '$WorkSheetname' to '$Path': The worksheet '$WorkSheetname' already exists."
}
else {
throw "Failed exporting worksheet '$WorkSheetname' to '$Path': $_"
}
}
$firstTimeThru = $true
$isDataTypeValueType=$false
$pattern = "string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort"
}
Process {
if ($firstTimeThru) {
$firstTimeThru=$false
$isDataTypeValueType = $TargetData.GetType().name -match "string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort"
Write-Verbose "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType $isDataTypeValueType"
$firstTimeThru = $false
$isDataTypeValueType = $TargetData.GetType().name -match $pattern
Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'"
}
if ($isDataTypeValueType) {
$ColumnIndex = $StartColumn
$targetCell = $ws.Cells[$Row, $ColumnIndex]
$r=$null
$cellValue=$TargetData
if ([Double]::TryParse([string]$cellValue,[System.Globalization.NumberStyles]::Any,[System.Globalization.NumberFormatInfo]::CurrentInfo, [ref]$r)) {
$targetCell.Value = $r
$targetCell.Style.Numberformat.Format=$Numberformat
} else {
$targetCell.Value = $cellValue
}
switch ($TargetData.$Name) {
{$_ -is [datetime]} {$targetCell.Style.Numberformat.Format = "m/d/yy h:mm"}
}
Add-CellValue -TargetCell $ws.Cells[$Row, $ColumnIndex] -CellValue $TargetData
$ColumnIndex += 1
$Row += 1
} else {
if (!$script:Header) {
}
else {
#region Add headers
if (-not $script:Header) {
$ColumnIndex = $StartColumn
$script:Header = $TargetData.psobject.properties.name
$script:Header = $TargetData.PSObject.Properties.Name
if ($NoHeader) {
# Don't push the headers to the spread sheet
$Row -= 1
} else {
}
else {
foreach ($Name in $script:Header) {
Write-Verbose "Add header '$Name'"
$ws.Cells[$Row, $ColumnIndex].Value = $Name
Write-Verbose "Cell '$Row`:$ColumnIndex' add header '$Name'"
$ColumnIndex += 1
}
}
}
#endregion
$Row += 1
$ColumnIndex = $StartColumn
foreach ($Name in $script:Header) {
$targetCell = $ws.Cells[$Row, $ColumnIndex]
$cellValue=$TargetData.$Name
if ($cellValue -is [string] -and $cellValue.StartsWith('=')) {
$targetCell.Formula = $cellValue
} else {
$r=$null
if ([Double]::TryParse([string]$cellValue,[System.Globalization.NumberStyles]::Any,[System.Globalization.NumberFormatInfo]::CurrentInfo, [ref]$r)) {
$targetCell.Value = $r
$targetCell.Style.Numberformat.Format=$Numberformat
Write-Verbose "Add cell value '$r' in Numberformat '$Numberformat'"
} else {
$targetCell.Value = $cellValue
Write-Verbose "Add cell value '$cellValue' as String"
}
}
switch ($TargetData.$Name) {
{$_ -is [datetime]} {
$targetCell.Style.Numberformat.Format = "m/d/yy h:mm"
}
}
#[ref]$uriResult=$null
#if ([uri]::TryCreate($cellValue, [System.UriKind]::Absolute, $uriResult)) {
# $targetCell.Hyperlink = [uri]$cellValue
# $namedStyle=$ws.Workbook.Styles.NamedStyles | where {$_.Name -eq 'HyperLink'}
# if (!$namedStyle) {
# $namedStyle=$ws.Workbook.Styles.CreateNamedStyle("HyperLink")
# $namedStyle.Style.Font.UnderLine = $true
# $namedStyle.Style.Font.Color.SetColor("Blue")
# }
# $targetCell.StyleName = "HyperLink"
#}
#region Add non header values
Add-CellValue -TargetCell $ws.Cells[$Row, $ColumnIndex] -CellValue $TargetData.$Name
$ColumnIndex += 1
#endregion
}
}
}
@@ -253,8 +440,8 @@ Function Export-Excel {
End {
Try {
if ($AutoNameRange) {
$totalRows=$ws.Dimension.Rows
$totalColumns=$ws.Dimension.Columns
$totalRows = $ws.Dimension.Rows
$totalColumns = $ws.Dimension.Columns
foreach($c in 0..($totalColumns-1)) {
$targetRangeName = "$($script:Header[$c])"
@@ -272,60 +459,59 @@ Function Export-Excel {
$startAddress=$ws.Dimension.Start.Address
$dataRange="{0}:{1}" -f $startAddress, $ws.Dimension.End.Address
Write-Debug "Data Range $dataRange"
Write-Debug "Data Range '$dataRange'"
if (-not [string]::IsNullOrEmpty($RangeName)) {
if (-not [String]::IsNullOrEmpty($RangeName)) {
$ws.Names.Add($RangeName, $ws.Cells[$dataRange]) | Out-Null
}
if (-not [string]::IsNullOrEmpty($TableName)) {
#$ws.Tables.Add($ws.Cells[$dataRange], $TableName) | Out-Null
#"$($StartRow),$($StartColumn),$($ws.Dimension.End.Row-$StartRow),$($Header.Count)"
$csr=$StartRow
$csc=$StartColumn
$cer=$ws.Dimension.End.Row #-$StartRow+1
$cec=$script:Header.Count
$targetRange=$ws.Cells[$csr, $csc, $cer,$cec]
if (-not [String]::IsNullOrEmpty($TableName)) {
$csr = $StartRow
$csc = $StartColumn
$cer = $ws.Dimension.End.Row
$cec = $script:Header.Count
$targetRange = $ws.Cells[$csr, $csc, $cer,$cec]
$tbl = $ws.Tables.Add($targetRange, $TableName)
$tbl.TableStyle=$TableStyle
$tbl.TableStyle = $TableStyle
}
if ($IncludePivotTable) {
$pivotTableName = $WorkSheetname + "PivotTable"
$pivotTableName = $WorkSheetname + 'PivotTable'
$wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber
$wsPivot.View.TabSelected = $true
$pivotTableDataName=$WorkSheetname + "PivotTableData"
$pivotTableDataName=$WorkSheetname + 'PivotTableData'
if ($Title) {$startAddress="A2"}
$pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells["A1"], $ws.Cells[$dataRange], $pivotTableDataName)
if ($Title) {
$startAddress = 'A2'
}
$pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells['A1'], $ws.Cells[$dataRange], $pivotTableDataName)
if ($PivotRows) {
foreach ($Row in $PivotRows) {
$null=$pivotTable.RowFields.Add($pivotTable.Fields[$Row])
$null = $pivotTable.RowFields.Add($pivotTable.Fields[$Row])
}
}
if ($PivotColumns) {
foreach ($Column in $PivotColumns) {
$null=$pivotTable.ColumnFields.Add($pivotTable.Fields[$Column])
$null = $pivotTable.ColumnFields.Add($pivotTable.Fields[$Column])
}
}
if ($PivotData) {
if ($PivotData -is [hashtable] -or $PivotData -is [System.Collections.Specialized.OrderedDictionary]) {
$PivotData.Keys | % {
$df=$pivotTable.DataFields.Add($pivotTable.Fields[$_])
if ($PivotData -is [HashTable] -or $PivotData -is [System.Collections.Specialized.OrderedDictionary]) {
$PivotData.Keys | ForEach-Object {
$df = $pivotTable.DataFields.Add($pivotTable.Fields[$_])
$df.Function = $PivotData.$_
}
} else {
}
else {
foreach ($Item in $PivotData) {
$df=$pivotTable.DataFields.Add($pivotTable.Fields[$Item])
$df = $pivotTable.DataFields.Add($pivotTable.Fields[$Item])
$df.Function = 'Count'
}
}
@@ -335,60 +521,70 @@ Function Export-Excel {
}
if ($IncludePivotChart) {
$chart = $wsPivot.Drawings.AddChart("PivotChart", $ChartType, $pivotTable)
$chart = $wsPivot.Drawings.AddChart('PivotChart', $ChartType, $pivotTable)
$chart.DataLabel.ShowCategory = $ShowCategory
$chart.DataLabel.ShowPercent = $ShowPercent
$chart.DataLabel.ShowCategory=$ShowCategory
$chart.DataLabel.ShowPercent=$ShowPercent
if ($NoLegend) { $chart.Legend.Remove() }
if ($NoLegend) {
$chart.Legend.Remove()
}
$chart.SetPosition(1, 0, 6, 0)
$chart.SetSize(600, 400)
}
}
if ($Password) { $ws.Protection.SetPassword($Password) }
if ($Password) {
$ws.Protection.SetPassword($Password)
}
if ($AutoFilter) {
$ws.Cells[$dataRange].AutoFilter=$true
}
if ($FreezeTopRow) { $ws.View.FreezePanes(2,1) }
if ($FreezeTopRowFirstColumn) { $ws.View.FreezePanes(2,2) }
if ($FreezeFirstColumn) { $ws.View.FreezePanes(1,2) }
if ($FreezeTopRow) {
$ws.View.FreezePanes(2,1)
}
if ($FreezeTopRowFirstColumn) {
$ws.View.FreezePanes(2,2)
}
if ($FreezeFirstColumn) {
$ws.View.FreezePanes(1,2)
}
if ($FreezePane) {
$freezeRow,$freezeColumn=$FreezePane
if (!$freezeColumn -or $freezeColumn -eq 0) {$freezeColumn=1}
if (-not $freezeColumn -or $freezeColumn -eq 0) {
$freezeColumn=1
}
if ($freezeRow -gt 1) {
$ws.View.FreezePanes($freezeRow,$freezeColumn)
}
}
if ($BoldTopRow) {
$range=$ws.Dimension.Address -replace $ws.Dimension.Rows, "1"
$ws.Cells[$range].Style.Font.Bold=$true
$range=$ws.Dimension.Address -replace $ws.Dimension.Rows, '1'
$ws.Cells[$range].Style.Font.Bold = $true
}
if ($AutoSize) {
$ws.Cells.AutoFitColumns()
}
if ($AutoSize) { $ws.Cells.AutoFitColumns() }
#$pkg.Workbook.View.ActiveTab = $ws.SheetID
foreach ($Sheet in $HideSheet) {
$pkg.Workbook.WorkSheets[$Sheet].Hidden="Hidden"
$pkg.Workbook.WorkSheets[$Sheet].Hidden = 'Hidden'
}
$chartCount=0
foreach ($chartDef in $ExcelChartDefinition) {
$ChartName = "Chart"+(Split-Path -Leaf ([System.IO.path]::GetTempFileName())) -replace 'tmp|\.',''
$ChartName = 'Chart' + (Split-Path -Leaf ([System.IO.path]::GetTempFileName())) -replace 'tmp|\.',''
$chart = $ws.Drawings.AddChart($ChartName, $chartDef.ChartType)
$chart.Title.Text = $chartDef.Title
if ($chartDef.NoLegend) {
$chart.Legend.Remove()
}
#$chart.Datalabel.ShowLegendKey = $true
if ($chart.Datalabel -ne $null) {
$chart.Datalabel.ShowCategory = $chartDef.ShowCategory
@@ -403,21 +599,25 @@ Function Export-Excel {
$Series=$chart.Series.Add($chartDef.YRange, $chartDef.XRange)
$SeriesHeader=$chartDef.SeriesHeader
if (!$SeriesHeader) {$SeriesHeader="Series 1"}
if (-not $SeriesHeader) {
$SeriesHeader = 'Series 1'
}
$Series.Header = $SeriesHeader
} else {
for($idx=0; $idx -lt $chartDefCount; $idx+=1) {
for($idx = 0; $idx -lt $chartDefCount; $idx += 1) {
$Series=$chart.Series.Add($chartDef.YRange[$idx], $chartDef.XRange)
if ($chartDef.SeriesHeader.Count -gt 0) {
$SeriesHeader=$chartDef.SeriesHeader[$idx]
$SeriesHeader = $chartDef.SeriesHeader[$idx]
}
if (!$SeriesHeader) {$SeriesHeader="Series $($idx)"}
if (-not $SeriesHeader) {
$SeriesHeader = "Series $($idx)"
}
$Series.Header = $SeriesHeader
$SeriesHeader=$null
$SeriesHeader = $null
}
}
}
@@ -427,41 +627,47 @@ Function Export-Excel {
$target = "Add$($targetConditionalText.ConditionalType)"
$Range=$targetConditionalText.Range
if (!$Range) { $Range=$ws.Dimension.Address }
if (-not $Range) {
$Range = $ws.Dimension.Address
}
$rule=($ws.Cells[$Range].ConditionalFormatting).PSObject.Methods[$target].Invoke()
if ($targetConditionalText.Text) {
if ($targetConditionalText.ConditionalType -match "equal|notequal|lessthan|lessthanorequal|greaterthan|greaterthanorequal") {
$rule.Formula= $targetConditionalText.Text
} else {
if ($targetConditionalText.ConditionalType -match 'equal|notequal|lessthan|lessthanorequal|greaterthan|greaterthanorequal') {
$rule.Formula = $targetConditionalText.Text
}
else {
$rule.Text = $targetConditionalText.Text
}
}
$rule.Style.Font.Color.Color = $targetConditionalText.ConditionalTextColor
$rule.Style.Fill.PatternType=$targetConditionalText.PatternType
$rule.Style.Fill.BackgroundColor.Color=$targetConditionalText.BackgroundColor
$rule.Style.Fill.PatternType = $targetConditionalText.PatternType
$rule.Style.Fill.BackgroundColor.Color = $targetConditionalText.BackgroundColor
}
}
if ($CellStyleSB) {
$TotalRows=$ws.Dimension.Rows
$LastColumn=(Get-ExcelColumnName $ws.Dimension.Columns).ColumnName
$TotalRows = $ws.Dimension.Rows
$LastColumn = (Get-ExcelColumnName $ws.Dimension.Columns).ColumnName
& $CellStyleSB $ws $TotalRows $LastColumn
}
if ($PassThru) {
$pkg
} else {
}
else {
$pkg.Save()
$pkg.Dispose()
if ($Show) {Invoke-Item $Path}
if ($Show) {
Invoke-Item $Path
}
}
}
Catch {
throw "Failed exporting the worksheet: $_"
throw "Failed exporting worksheet '$WorkSheetname' to '$Path': $_"
}
}
}

View File

@@ -4,7 +4,7 @@
RootModule = 'ImportExcel.psm1'
# Version number of this module.
ModuleVersion = '2.4.0'
ModuleVersion = '3.0.1'
# ID used to uniquely identify this module
GUID = '60dd4136-feff-401a-ba27-a84458c57ede'

View File

@@ -20,6 +20,9 @@ Add-Type -Path "$($PSScriptRoot)\EPPlus.dll"
. $PSScriptRoot\TrackingUtils.ps1
. $PSScriptRoot\Copy-ExcelWorkSheet.ps1
. $PSScriptRoot\Set-CellStyle.ps1
. $PSScriptRoot\ConvertFromExcelData.ps1
. $PSScriptRoot\ConvertFromExcelToSQLInsert.ps1
. $PSScriptRoot\ConvertToExcelXlsx.ps1
if($PSVersionTable.PSVersion.Major -ge 5) {
. $PSScriptRoot\plot.ps1

View File

@@ -29,6 +29,9 @@ $targetFiles = echo `
TrackingUtils.ps1 `
Copy-ExcelWorkSheet.ps1 `
Set-CellStyle.ps1 `
ConvertFromExcelToSQLInsert.ps1 `
ConvertFromExcelData.ps1 `
ConvertToExcelXlsx.ps1 `
plot.ps1
Get-ChildItem $targetFiles |

View File

@@ -27,6 +27,68 @@ iex (new-object System.Net.WebClient).DownloadString('https://raw.github.com/dfi
```
# What's new
#### 7/3/2017
Thanks to [Mikkel Nordberg](https://www.linkedin.com/in/mikkelnordberg). He contributed a `ConvertTo-ExcelXlsx`. To use it, Excel needs to be installed. I converts older Excel files `xls` to 'xlsx'.
#### 6/15/2017
Huge thank you to [DarkLite1](https://github.com/DarkLite1)! Refactoring of code, adding help, adding features, fixing bugs. Specifically this long outstanding one:
[Export-Excel: Numeric values not correct](https://github.com/dfinke/ImportExcel/issues/168)
It is fantasic to work with and have folks like `DarkLite1` in the community, helping make PowerShells so much better.
A hat to you.
Another shout out to [Damian Reeves](https://twitter.com/DamReev)! His questions turn into great features. He asked can you import and Excel sheet and transform the data into SQL Insert statements. The answer is now yes!
```powershell
ConvertFrom-ExcelToSQLInsert People .\testSQLGen.xlsx
```
```
INSERT INTO People ('First', 'Last', 'The Zip') Values('John', 'Doe', '12345');
INSERT INTO People ('First', 'Last', 'The Zip') Values('Jim', 'Doe', '12345');
INSERT INTO People ('First', 'Last', 'The Zip') Values('Tom', 'Doe', '12345');
INSERT INTO People ('First', 'Last', 'The Zip') Values('Harry', 'Doe', '12345');
INSERT INTO People ('First', 'Last', 'The Zip') Values('Jane', 'Doe', '12345');
```
## Bonus Points
Use the underlying `ConvertFrom-ExcelData` and you can use a scriptblock to transform the data your way.
```powershell
ConvertFrom-ExcelData .\testSQLGen.xlsx {
param($propertyNames, $record)
$reportRecord = @()
foreach ($pn in $propertyNames) {
$reportRecord += "{0}: {1}" -f $pn, $record.$pn
}
$reportRecord +=""
$reportRecord -join "`r`n"
}
```
Prints
```
First: John
Last: Doe
The Zip: 12345
First: Jim
Last: Doe
The Zip: 12345
First: Tom
Last: Doe
The Zip: 12345
First: Harry
Last: Doe
The Zip: 12345
First: Jane
Last: Doe
The Zip: 12345
```
#### 2/2/2017
Thank you to [DarkLite1](https://github.com/DarkLite1) for more updates