From e1fe36699b37896becf84c90af6da09723ae6ec0 Mon Sep 17 00:00:00 2001 From: dfinke Date: Sun, 25 Nov 2018 16:16:16 -0500 Subject: [PATCH] Added Export-StocksToExcel --- Export-StocksToExcel.ps1 | 28 ++++++ ImportExcel.psm1 | 186 ++++++++++++++++++++------------------- 2 files changed, 122 insertions(+), 92 deletions(-) create mode 100644 Export-StocksToExcel.ps1 diff --git a/Export-StocksToExcel.ps1 b/Export-StocksToExcel.ps1 new file mode 100644 index 0000000..bf3672f --- /dev/null +++ b/Export-StocksToExcel.ps1 @@ -0,0 +1,28 @@ +function Export-StocksToExcel { + param( + [string]$symbols, + [ValidateSet("Open", "High", "Low", "Close", "Volume")] + $measure = "Open" + ) + + $xl = "$env:TEMP\Stocks.xlsx" + + Remove-Item $xl -ErrorAction SilentlyContinue + + $r = Invoke-RestMethod "https://azfnstockdata-fn83fffd32.azurewebsites.net/api/GetQuoteChart?symbol=$($symbols)" + + $chartColumn = $symbols.Split(',').count + 2 + $ptd = New-PivotTableDefinition ` + -SourceWorkSheet Sheet1 ` + -PivotTableName result ` + -PivotData @{$measure = 'sum'} ` + -PivotRows date ` + -PivotColumns symbol ` + -ChartType Line ` + -ChartTitle "Stock - $measure " ` + -IncludePivotChart -NoTotalsInPivot -ChartColumn $chartColumn -ChartRow 3 -Activate + + $r | Sort-Object Date, symbol | Export-Excel $xl -PivotTableDefinition $ptd -AutoSize -AutoFilter -Show +} + +# Export-StocksToExcel -symbols 'ibm,aapl,msft' -measure High \ No newline at end of file diff --git a/ImportExcel.psm1 b/ImportExcel.psm1 index b4e955b..da35415 100644 --- a/ImportExcel.psm1 +++ b/ImportExcel.psm1 @@ -1,62 +1,63 @@ #region import everything we need - Add-Type -Path "$($PSScriptRoot)\EPPlus.dll" - . $PSScriptRoot\AddConditionalFormatting.ps1 - . $PSScriptRoot\Charting.ps1 - . $PSScriptRoot\ColorCompletion.ps1 - . $PSScriptRoot\ConvertExcelToImageFile.ps1 - . $PSScriptRoot\Compare-WorkSheet.ps1 - . $PSScriptRoot\ConvertFromExcelData.ps1 - . $PSScriptRoot\ConvertFromExcelToSQLInsert.ps1 - . $PSScriptRoot\ConvertToExcelXlsx.ps1 - . $PSScriptRoot\Copy-ExcelWorkSheet.ps1 - . $PSScriptRoot\Export-Excel.ps1 - . $PSScriptRoot\Export-ExcelSheet.ps1 - . $PSScriptRoot\Get-ExcelColumnName.ps1 - . $PSScriptRoot\Get-ExcelSheetInfo.ps1 - . $PSScriptRoot\Get-ExcelWorkbookInfo.ps1 - . $PSScriptRoot\Get-HtmlTable.ps1 - . $PSScriptRoot\Get-Range.ps1 - . $PSScriptRoot\Get-XYRange.ps1 - . $PSScriptRoot\Import-Html.ps1 - . $PSScriptRoot\InferData.ps1 - . $PSScriptRoot\Invoke-Sum.ps1 - . $PSScriptRoot\Join-WorkSheet.ps1 - . $PSScriptRoot\Merge-Worksheet.ps1 - . $PSScriptRoot\New-ConditionalFormattingIconSet.ps1 - . $PSScriptRoot\New-ConditionalText.ps1 - . $PSScriptRoot\New-ExcelChart.ps1 - . $PSScriptRoot\New-PSItem.ps1 - . $PSScriptRoot\Open-ExcelPackage.ps1 - . $PSScriptRoot\Pivot.ps1 - . $PSScriptRoot\PivotTable.ps1 - . $PSScriptRoot\Send-SQLDataToExcel.ps1 - . $PSScriptRoot\Set-CellStyle.ps1 - . $PSScriptRoot\Set-Column.ps1 - . $PSScriptRoot\Set-Row.ps1 - . $PSScriptRoot\SetFormat.ps1 - . $PSScriptRoot\TrackingUtils.ps1 - . $PSScriptRoot\Update-FirstObjectProperties.ps1 +Add-Type -Path "$($PSScriptRoot)\EPPlus.dll" +. $PSScriptRoot\AddConditionalFormatting.ps1 +. $PSScriptRoot\Charting.ps1 +. $PSScriptRoot\ColorCompletion.ps1 +. $PSScriptRoot\ConvertExcelToImageFile.ps1 +. $PSScriptRoot\Compare-WorkSheet.ps1 +. $PSScriptRoot\ConvertFromExcelData.ps1 +. $PSScriptRoot\ConvertFromExcelToSQLInsert.ps1 +. $PSScriptRoot\ConvertToExcelXlsx.ps1 +. $PSScriptRoot\Copy-ExcelWorkSheet.ps1 +. $PSScriptRoot\Export-Excel.ps1 +. $PSScriptRoot\Export-ExcelSheet.ps1 +. $PSScriptRoot\Export-StocksToExcel.ps1 +. $PSScriptRoot\Get-ExcelColumnName.ps1 +. $PSScriptRoot\Get-ExcelSheetInfo.ps1 +. $PSScriptRoot\Get-ExcelWorkbookInfo.ps1 +. $PSScriptRoot\Get-HtmlTable.ps1 +. $PSScriptRoot\Get-Range.ps1 +. $PSScriptRoot\Get-XYRange.ps1 +. $PSScriptRoot\Import-Html.ps1 +. $PSScriptRoot\InferData.ps1 +. $PSScriptRoot\Invoke-Sum.ps1 +. $PSScriptRoot\Join-WorkSheet.ps1 +. $PSScriptRoot\Merge-Worksheet.ps1 +. $PSScriptRoot\New-ConditionalFormattingIconSet.ps1 +. $PSScriptRoot\New-ConditionalText.ps1 +. $PSScriptRoot\New-ExcelChart.ps1 +. $PSScriptRoot\New-PSItem.ps1 +. $PSScriptRoot\Open-ExcelPackage.ps1 +. $PSScriptRoot\Pivot.ps1 +. $PSScriptRoot\PivotTable.ps1 +. $PSScriptRoot\Send-SQLDataToExcel.ps1 +. $PSScriptRoot\Set-CellStyle.ps1 +. $PSScriptRoot\Set-Column.ps1 +. $PSScriptRoot\Set-Row.ps1 +. $PSScriptRoot\SetFormat.ps1 +. $PSScriptRoot\TrackingUtils.ps1 +. $PSScriptRoot\Update-FirstObjectProperties.ps1 - New-Alias -Name Use-ExcelData -Value "ConvertFrom-ExcelData" -Force +New-Alias -Name Use-ExcelData -Value "ConvertFrom-ExcelData" -Force - if ($PSVersionTable.PSVersion.Major -ge 5) { - . $PSScriptRoot\Plot.ps1 +if ($PSVersionTable.PSVersion.Major -ge 5) { + . $PSScriptRoot\Plot.ps1 - Function New-Plot { - Param() - - [PSPlot]::new() - } + Function New-Plot { + Param() + [PSPlot]::new() } - else { - Write-Warning 'PowerShell 5 is required for plot.ps1' - Write-Warning 'PowerShell Excel is ready, except for that functionality' - } + +} +else { + Write-Warning 'PowerShell 5 is required for plot.ps1' + Write-Warning 'PowerShell Excel is ready, except for that functionality' +} #endregion function Import-Excel { - <# + <# .SYNOPSIS Create custom objects from the rows in an Excel worksheet. @@ -247,7 +248,7 @@ function Import-Excel { Write-SqlTableData -ServerInstance localhost\DEFAULT -Database BlankDB -SchemaName dbo -TableName MyNewTable_fromExcel -Force Imports data from an Excel file and pipe the data to the Write-SqlTableData to be INSERTed into a table in a SQL Server database. - The ",( ... )" around the Import-Excel command allows all rows to be imported from the Excel file, prior to pipelining to the Write-SqlTableData cmdlet. This helps prevent a RBAR scenario and is important when trying to import thousands of rows. + The ",( ... )" around the Import-Excel command allows all rows to be imported from the Excel file, prior to pipelining to the Write-SqlTableData cmdlet. This helps prevent a RBAR scenario and is important when trying to import thousands of rows. The -Force parameter will be ignored if the table already exists. However, if a table is not found that matches the values provided by -SchemaName and -TableName parameters, it will create a new table in SQL Server database. The Write-SqlTableData cmdlet will inherit the column names & datatypes for the new table from the object being piped in. NOTE: You need to install the SqlServer module from the PowerShell Gallery in oder to get the Write-SqlTableData cmdlet. @@ -258,24 +259,24 @@ function Import-Excel { #> [CmdLetBinding(DefaultParameterSetName)] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] Param ( [Alias('FullName')] - [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline, Position=0, Mandatory)] + [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0, Mandatory)] [ValidateScript( {(Test-Path -Path $_ -PathType Leaf) -and ($_ -match '.xls$|.xlsx$|.xlsm$')})] [String]$Path, [Alias('Sheet')] - [Parameter(Position=1)] + [Parameter(Position = 1)] [ValidateNotNullOrEmpty()] [String]$WorksheetName, - [Parameter(ParameterSetName='B', Mandatory)] + [Parameter(ParameterSetName = 'B', Mandatory)] [String[]]$HeaderName , - [Parameter(ParameterSetName='C', Mandatory)] + [Parameter(ParameterSetName = 'C', Mandatory)] [Switch]$NoHeader , - [Alias('HeaderRow','TopRow')] + [Alias('HeaderRow', 'TopRow')] [ValidateRange(1, 9999)] [Int]$StartRow = 1, - [Alias('StopRow','BottomRow')] + [Alias('StopRow', 'BottomRow')] [Int]$EndRow , [Alias('LeftColumn')] [Int]$StartColumn = 1, @@ -305,13 +306,13 @@ function Import-Excel { $i = 0 foreach ($C in $Columns) { $i++ - $C | Select-Object @{N='Column'; E={$_}}, @{N='Value'; E={'P' + $i}} + $C | Select-Object @{N = 'Column'; E = {$_}}, @{N = 'Value'; E = {'P' + $i}} } } elseif ($HeaderName) { $i = 0 foreach ($H in $HeaderName) { - $H | Select-Object @{N='Column'; E={$Columns[$i]}}, @{N='Value'; E={$H}} + $H | Select-Object @{N = 'Column'; E = {$Columns[$i]}}, @{N = 'Value'; E = {$H}} $i++ } } @@ -321,7 +322,7 @@ function Import-Excel { } foreach ($C in $Columns) { - $Worksheet.Cells[$StartRow,$C] | Where-Object {$_.Value} | Select-Object @{N='Column'; E={$C}}, Value + $Worksheet.Cells[$StartRow, $C] | Where-Object {$_.Value} | Select-Object @{N = 'Column'; E = {$C}}, Value } } } @@ -341,12 +342,14 @@ function Import-Excel { Catch {throw "Could not open $Path ; $_ "} if ($Password) { - Try {$Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage - $excel.Load( $Stream,$Password)} + Try { + $Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage + $excel.Load( $Stream, $Password) + } Catch { throw "Could not read $Path with the provided password." } } else { - try {$Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream} + try {$Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream} Catch {throw "Failed to read $Path"} } #endregion @@ -364,13 +367,13 @@ function Import-Excel { Write-Debug $sw.Elapsed.TotalMilliseconds #region Get rows and columns #If we are doing dataonly it is quicker to work out which rows to ignore before processing the cells. - if (-not $EndRow ) {$EndRow = $Worksheet.Dimension.End.Row } + if (-not $EndRow ) {$EndRow = $Worksheet.Dimension.End.Row } if (-not $EndColumn) {$EndColumn = $Worksheet.Dimension.End.Column } - $endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]",0,0) + $endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0) if ($DataOnly) { #If we are using headers startrow will be the headerrow so examine data from startRow + 1, if ($NoHeader) {$range = "A" + ($StartRow ) + ":" + $endAddress } - else {$range = "A" + ($StartRow + 1 ) + ":" + $endAddress } + else {$range = "A" + ($StartRow + 1 ) + ":" + $endAddress } #We're going to look at every cell and build 2 hash tables holding rows & columns which contain data. #Want to Avoid 'select unique' operations & large Sorts, becuse time time taken increases with square #of number of items (PS uses heapsort at large size). Instead keep a list of what we have seen, @@ -378,15 +381,15 @@ function Import-Excel { $colHash = @{} $rowHash = @{} foreach ($cell in $Worksheet.Cells[$range]) { - if ($null -ne $cell.Value ) {$colHash[$cell.Start.Column]=1; $rowHash[$cell.Start.row]=1 } + if ($null -ne $cell.Value ) {$colHash[$cell.Start.Column] = 1; $rowHash[$cell.Start.row] = 1 } } - $rows = ( $StartRow..$EndRow ).Where({$rowHash[$_]}) - $columns = ($StartColumn..$EndColumn).Where({$colHash[$_]}) + $rows = ( $StartRow..$EndRow ).Where( {$rowHash[$_]}) + $columns = ($StartColumn..$EndColumn).Where( {$colHash[$_]}) } else { - $Columns = $StartColumn..$EndColumn ; if ($StartColumn -gt $EndColumn) {Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results."} - if ($NoHeader) {$Rows = ( $StartRow)..$EndRow ; if ($StartRow -gt $EndRow) {Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results."} } - else {$Rows = (1 + $StartRow)..$EndRow ; if ($StartRow -ge $EndRow) {Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results."}} + $Columns = $StartColumn..$EndColumn ; if ($StartColumn -gt $EndColumn) {Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results."} + if ($NoHeader) {$Rows = ( $StartRow)..$EndRow ; if ($StartRow -gt $EndRow) {Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results."} } + else {$Rows = (1 + $StartRow)..$EndRow ; if ($StartRow -ge $EndRow) {Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results."}} } #endregion #region Create property names @@ -404,13 +407,13 @@ function Import-Excel { else { #region Create one object per row foreach ($R in $Rows) { - #Disabled write-verbose for speed - # Write-Verbose "Import row '$R'" + #Disabled write-verbose for speed + # Write-Verbose "Import row '$R'" $NewRow = [Ordered]@{} foreach ($P in $PropertyNames) { - $NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value - # Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'." + $NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value + # Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'." } [PSCustomObject]$NewRow @@ -455,11 +458,11 @@ function ConvertFrom-ExcelSheet { [String] $OutputPath = '.\', [String] - $SheetName="*", - [ValidateSet('ASCII', 'BigEndianUniCode','Default','OEM','UniCode','UTF32','UTF7','UTF8')] + $SheetName = "*", + [ValidateSet('ASCII', 'BigEndianUniCode', 'Default', 'OEM', 'UniCode', 'UTF32', 'UTF7', 'UTF8')] [string] $Encoding = 'UTF8', - [ValidateSet('.txt', '.log','.csv')] + [ValidateSet('.txt', '.log', '.csv')] [string] $Extension = '.csv', [ValidateSet(';', ',')] @@ -468,7 +471,7 @@ function ConvertFrom-ExcelSheet { ) $Path = (Resolve-Path $Path).Path - $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path,"Open","Read","ReadWrite" + $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, "Open", "Read", "ReadWrite" $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream $workbook = $xl.Workbook @@ -480,8 +483,7 @@ function ConvertFrom-ExcelSheet { $params.Remove('Extension') $params.NoTypeInformation = $true - Foreach ($sheet in $targetSheets) - { + Foreach ($sheet in $targetSheets) { Write-Verbose "Exporting sheet: $($sheet.Name)" $params.Path = "$OutputPath\$($Sheet.Name)$Extension" @@ -495,18 +497,18 @@ function ConvertFrom-ExcelSheet { } function Export-MultipleExcelSheets { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] param( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] $Path, - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [hashtable]$InfoMap, [string]$Password, [Switch]$Show, [Switch]$AutoSize ) - $parameters = @{}+$PSBoundParameters + $parameters = @{} + $PSBoundParameters $parameters.Remove("InfoMap") $parameters.Remove("Show") @@ -514,24 +516,24 @@ function Export-MultipleExcelSheets { foreach ($entry in $InfoMap.GetEnumerator()) { Write-Progress -Activity "Exporting" -Status "$($entry.Key)" - $parameters.WorkSheetname=$entry.Key + $parameters.WorkSheetname = $entry.Key & $entry.Value | Export-Excel @parameters } - if($Show) {Invoke-Item $Path} + if ($Show) {Invoke-Item $Path} } Function WorksheetArgumentCompleter { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) - $xlPath = $fakeBoundParameter['Path'] + $xlPath = $fakeBoundParameter['Path'] if (Test-Path -Path $xlPath) { $xlpkg = Open-ExcelPackage -Path $xlPath $WorksheetNames = $xlPkg.Workbook.Worksheets.Name Close-ExcelPackage -nosave -ExcelPackage $xlpkg - $WorksheetNames.where({$_ -like "*$wordToComplete*"}) | foreach-object { + $WorksheetNames.where( {$_ -like "*$wordToComplete*"}) | foreach-object { New-Object -TypeName System.Management.Automation.CompletionResult -ArgumentList "'$_'", - $_ , ([System.Management.Automation.CompletionResultType]::ParameterValue) ,$_ + $_ , ([System.Management.Automation.CompletionResultType]::ParameterValue) , $_ } } }