diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..872c4f5d --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 30 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..11be2f39 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +on: + push: + branches: + - master + - Set-up-GHA-CI/CD + paths-ignore: + - 'Examples/**' + + pull_request: + + +jobs: + validate: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + steps: + - uses: actions/checkout@v1 + - name: Run Continuous Integration + shell: pwsh + run : | + if($PSVersionTable.Platform -eq 'Win32NT') { + $null = mkdir ./ace + Invoke-Restmethod https://download.microsoft.com/download/3/5/C/35C84C36-661A-44E6-9324-8786B8DBE231/accessdatabaseengine_X64.exe -OutFile ./ace/ace.exe + Start-Process ./ace/ace.exe -Wait -ArgumentList "/quiet /passive /norestart" + } + + cd ./__tests__ + Invoke-Pester -Output Detailed \ No newline at end of file diff --git a/.gitignore b/.gitignore index bc21761f..691bf10a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ Thumbs.db ehthumbs.db +*.gitignore + # Folder config file Desktop.ini @@ -14,6 +16,8 @@ $RECYCLE.BIN/ *.msm *.msp +*.dll + # Windows shortcuts *.lnk @@ -42,6 +46,7 @@ Network Trash Folder Temporary Items .apdisk testExport.xlsx +test.xlsx test.ps1 testPwd.xlsx test.csv @@ -55,3 +60,9 @@ test.xlsx testCCFMT.ps1 testHide.ps1 ImportExcel.zip +.vscode/settings.json + +~$* +# InstallModule.ps1 +# PublishToGallery.ps1 +.vscode/* diff --git a/.vscode/spellright.dict b/.vscode/spellright.dict new file mode 100644 index 00000000..fc115898 --- /dev/null +++ b/.vscode/spellright.dict @@ -0,0 +1,37 @@ +databar +appveyor +SqlDataToExcel +xlsm +jameseholt +params +robinmalik +scriptblock +headsphere +xelsirko +importexcel +Mihalicz +idx +Möller +redoz +dir +pivotables +WorkSheetname +Lachance-Guillemette +ints +pscookiemonster +ps +pwd +Nuget +EPPLus +intellisense +PivtoTableName +New-Excelchart +paypal +dll +enums +Numberformat +ChartDefiniton +hashtables +Agramont +AGramont +Jhoneill diff --git a/Add-Subtotals.ps1 b/Add-Subtotals.ps1 new file mode 100644 index 00000000..024f8faa --- /dev/null +++ b/Add-Subtotals.ps1 @@ -0,0 +1,133 @@ +Function Add-Subtotals { + param( + [Parameter(Mandatory=$true, Position=0)] + $ChangeColumnName , # = "Location" + + [Parameter(Mandatory=$true, Position=1)] + [hashtable]$AggregateColumn , #= @{"Sales" = "SUM" } + + [Parameter(Position=2)] + $ExcelPath = ([System.IO.Path]::GetTempFileName() -replace "\.tmp", ".xlsx") , + + [Parameter(Position=3)] + $WorksheetName = "Sheet1", + + [Parameter(ValueFromPipeline=$true)] + $InputObject, #$DataToPivot | Sort location, product + + [switch]$HideSingleRows, + [switch]$NoSort, + [switch]$NoOutLine, + [switch]$Show + + ) + begin { + if (-not $PSBoundParameters.ContainsKey('ExcelPath')) {$Show = $true} + $data = @() + $aggFunctions = [ordered]@{ + "AVERAGE" = 1; "COUNT" = 2; "COUNTA" = 3 #(non empty cells) f + "MAX" = 4; "MIN" = 5; "PRODUCT" = 6; "STDEV" = 7 # (sample) + "STDEVP" = 8 # (whole population); + "SUM" = 9; "VAR" = 10 # (Variance sample) + "VARP" = 11 # (whole population) #add 100 to ignore hidden cells + } + } + process { + $data += $InputObject + } + end { + if (-not $NoSort) {$data = $data | Sort-Object $changeColumnName} + $Header = $data[0].PSObject.Properties.Name + #region turn each entry in $AggregateColumn "=SUBTOTAL(a,x{0}}:x{1})" where a is the aggregate function number and x is the column letter + $aggFormulas = @{} + foreach ($k in $AggregateColumn.Keys) { + $columnNo = 0 ; + while ($columnNo -lt $header.count -and $header[$columnNo] -ne $k) {$columnNo ++} + if ($columnNo -eq $header.count) { + throw "'$k' isn't a property of the first row of data."; return + } + if ($AggregateColumn[$k] -is [string]) { + $aggfn = $aggFunctions[$AggregateColumn[$k]] + if (-not $aggfn) { + throw "$($AggregateColumn[$k]) is not a valid aggregation function - these are $($aggFunctions.keys -join ', ')" ; return + } + } + else {$aggfn = $AggregateColumn[$k]} + $aggFormulas[$k] = "=SUBTOTAL({0},{1}{{0}}:{1}{{1}})" -f $aggfn , (Get-ExcelColumnName ($columnNo+1) ).ColumnName + } + if ($aggformulas.count -lt 1) {throw "We didn't get any aggregation formulas"} + $aggFormulas | out-string -Stream | Write-Verbose -Verbose + #endregion + $insertedRows = @() + $singleRows = @() + $previousValue = $data[0].$changeColumnName + $currentRow = $lastChangeRow = 2 + #region insert subtotals and send to excel: + #each time there is a change in the column we're intetersted in. + #either Add a row with the value and subtotal(s) function(s) if there is more than one row to total + #or note the row if there was only one row with that value (we may hide it later.) + $excel = $data | + ForEach-Object -process { + if ($_.$changeColumnName -ne $previousValue) { + if ($lastChangeRow -lt ($currentrow - 1)) { + $NewObj = @{$changeColumnName = $previousValue} + foreach ($k in $aggFormulas.Keys) { + $newobj[$k] = $aggformulas[$k] -f $lastChangeRow, ($currentRow - 1) + } + $insertedRows += $currentRow + [pscustomobject]$newobj + $currentRow += 1 + } + else {$singleRows += $currentRow } + $lastChangeRow = $currentRow + $previousValue = $_.$changeColumnName + } + $_ + $currentRow += 1 + } -end { # the process block won't output the last row + if ($lastChangeRow -lt ($currentrow - 1)) { + $NewObj = @{$changeColumnName = $previousValue} + foreach ($k in $aggFormulas.Keys) { + $newobj[$k] = $aggformulas[$k] -f $lastChangeRow, ($currentRow - 1) + } + $insertedRows += $currentRow + [pscustomobject]$newobj + } + else {$singleRows += $currentRow } + } | Export-Excel -Path $ExcelPath -PassThru -AutoSize -AutoFilter -AutoNameRange -BoldTopRow -WorksheetName $WorksheetName -Activate -ClearSheet #-MaxAutoSizeRows 10000 + #endregion + #Put the subtotal rows in bold optionally hide rows where only one has the value of interest. + $ws = $excel.$WorksheetName + #We kept lists of the total rows Since 1 rows won't get expand/collapse we can hide them. + foreach ($r in $insertedrows) {$ws.Row($r).style.font.bold = $true } + if ($HideSingleRows) { + foreach ($r in $hideRows) { $ws.Row($r).hidden = $true} + } + $range = $ws.Dimension.Address + $ExcelPath = $excel.File.FullName + $SheetIndex = $ws.index + if ($NoOutline) { + Close-ExcelPackage $excel -show:$Show + return + } + else { + Close-ExcelPackage $excel + + try { $excelApp = New-Object -ComObject "Excel.Application" } + catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return } + + try { $excelWorkBook = $excelApp.Workbooks.Open($ExcelPath) } + catch { Write-Warning -Message "Could not Open $ExcelPath." ; return } + $ws = $excelWorkBook.Worksheets.item($SheetIndex) + $null = $ws.Range($range).Select() + $null = $excelapp.ActiveCell.AutoOutline() + $null = $ws.Outline.ShowLevels(1,$null) + $excelWorkBook.Save() + if ($show) {$excelApp.Visible = $true} + else { + [void]$excelWorkBook.close() + $excelapp.Quit() + } + } + } +} \ No newline at end of file diff --git a/AddConditionalFormatting.ps1 b/AddConditionalFormatting.ps1 deleted file mode 100644 index fc89b8f5..00000000 --- a/AddConditionalFormatting.ps1 +++ /dev/null @@ -1,117 +0,0 @@ -Function Add-ConditionalFormatting { -<# -.Synopsis - Adds contitional formatting to worksheet -.Example - $excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru - - Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b":b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003" - Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled" - $excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern - $excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true - $excel.Save() ; $excel.Dispose() - - Here Export-Excel is called with the -passThru parameter so the Excel Package object is stored in $Excel - The desired worksheet is selected and the then columns B and i are conditially formatted (excluding the top row) to show - Fixed formats are then applied to dates in columns D..G and the top row is formatted - Finally the workbook is saved and the Excel closed. - -#> - Param ( - #The worksheet where the format is to be applied - [Parameter(Mandatory = $true, ParameterSetName = "NamedRule")] - [Parameter(Mandatory = $true, ParameterSetName = "DataBar")] - [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "FourIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSet")] - [OfficeOpenXml.ExcelWorksheet]$WorkSheet , - #The area of the worksheet where the format is to be applied - [Parameter(Mandatory = $true, ParameterSetName = "NamedRule")] - [Parameter(Mandatory = $true, ParameterSetName = "DataBar")] - [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "FourIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSet")] - [OfficeOpenXml.ExcelAddress]$Range , - #One or more row(s), Column(s) and/or block(s) of cells to format - [Parameter(Mandatory = $true, ParameterSetName = "NamedRuleAddress")] - [Parameter(Mandatory = $true, ParameterSetName = "DataBarAddress")] - [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSetAddress")] - [Parameter(Mandatory = $true, ParameterSetName = "FourIconSetAddress")] - [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSetAddress")] - $Address , - #One of the standard named rules - Top / Bottom / Less than / Greater than / Contains etc - [Parameter(Mandatory = $true, ParameterSetName = "NamedRule", Position = 3)] - [Parameter(Mandatory = $true, ParameterSetName = "NamedRuleAddress", Position = 3)] - [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType]$RuleType , - #Text colour for matching objects - [Alias("ForeGroundColour")] - [System.Drawing.Color]$ForeGroundColor, - #colour for databar type charts - [Parameter(Mandatory = $true, ParameterSetName = "DataBar")] - [Parameter(Mandatory = $true, ParameterSetName = "DataBarAddress")] - [Alias("DataBarColour")] - [System.Drawing.Color]$DataBarColor, - #One of the three-icon set types (e.g. Traffic Lights) - [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSetAddress")] - [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting3IconsSetType]$ThreeIconsSet, - #A four-icon set name - [Parameter(Mandatory = $true, ParameterSetName = "FourIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "FourIconSetAddress")] - [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting4IconsSetType]$FourIconsSet, - #A five-icon set name - [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSet")] - [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSetAddress")] - [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting5IconsSetType]$FiveIconsSet, - #A value for the condition (e.g. "2000" if the test is 'lessthan 2000') - [string]$ConditionValue, - #A second value for the conditions like between x and Y - [string]$ConditionValue2, - #Background colour for matching items - [System.Drawing.Color]$BackgroundColor, - #Background pattern for matching items - [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid, - #Secondary colour when a background pattern requires it - [System.Drawing.Color]$PatternColor, - #Sets the numeric format for matching items - $NumberFormat, - #Put matching items in bold face - [switch]$Bold, - #Put matching items in italic - [switch]$Italic, - #Underline matching items - [switch]$Underline, - #Strikethrough text of matching items - [switch]$StrikeThru - ) - #Allow add conditional formatting to work like Set-Format (with single ADDRESS parameter) split it to get worksheet and Range of cells. - If ($Address -and -not $WorkSheet -and -not $Range) { - $WorkSheet = $Address.Worksheet[0] - $Range = $Address.Address - } - If ($ThreeIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Range , $ThreeIconsSet)} - elseif ($FourIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFourIconSet( $Range , $FourIconsSet) } - elseif ($FiveIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFiveIconSet( $Range , $IconType) } - elseif ($DataBarColor) {$rule = $WorkSheet.ConditionalFormatting.AddDatabar( $Range , $DataBarColor) } - else { $rule = ($WorkSheet.ConditionalFormatting)."Add$RuleType"($Range)} - - if ($ConditionValue -and $RuleType -match "Top|Botom") {$rule.Rank = $ConditionValue } - if ($ConditionValue -and $RuleType -match "StdDev") {$rule.StdDev = $ConditionValue } - if ($ConditionValue -and $RuleType -match "Than|Equal|Expression") {$rule.Formula = $ConditionValue } - if ($ConditionValue -and $RuleType -match "Text|With") {$rule.Text = $ConditionValue } - if ($ConditionValue -and - $ConditionValue2 -and $RuleType -match "Between") { - $rule.Formula = $ConditionValue - $rule.Formula2 = $ConditionValue2 - } - - if ($NumberFormat) {$rule.Style.NumberFormat.Format = $NumberFormat } - if ($Underline) {$rule.Style.Font.Underline = [OfficeOpenXml.Style.ExcelUnderLineType]::Single } - if ($Bold) {$rule.Style.Font.Bold = $true} - if ($Italic) {$rule.Style.Font.Italic = $true} - if ($StrikeThru) {$rule.Style.Font.Strike = $true} - if ($ForeGroundColor) {$rule.Style.Font.Color.color = $ForeGroundColor } - if ($BackgroundColor) {$rule.Style.Fill.BackgroundColor.color = $BackgroundColor } - if ($BackgroundPattern) {$rule.Style.Fill.PatternType = $BackgroundPattern } - if ($PatternColor) {$rule.Style.Fill.PatternColor.color = $PatternColor } -} \ No newline at end of file diff --git a/CI/CI.ps1 b/CI/CI.ps1 new file mode 100644 index 00000000..0f041821 --- /dev/null +++ b/CI/CI.ps1 @@ -0,0 +1,228 @@ +<# + .SYNOPSIS + Handel Continuous Integration Testing in AppVeyor and Azure DevOps Pipelines. +#> +param +( + # AppVeyor Only - Update AppVeyor build name. + [Switch]$Initialize, + # Installs the module and invoke the Pester tests with the current version of PowerShell. + [Switch]$Test, + # AppVeyor Only - Upload results to AppVeyor "Tests" tab. + [Switch]$Finalize, + # AppVeyor and Azure - Upload module as AppVeyor Artifact. + [Switch]$Artifact, + # Azure - Runs PsScriptAnalyzer against one or more folders and pivots the results to form a report. + [Switch]$Analyzer, + # Installs the module and invokes only the ModuleImport test. + # Used for validating that the module imports still when external dependencies are missing, e.g. mono-libgdiplus on macOS. + [Switch]$TestImportOnly +) +$ErrorActionPreference = 'Stop' +if ($Initialize) { + $Psd1 = (Get-ChildItem -File -Filter *.psd1 -Name -Path (Split-Path $PSScriptRoot)).PSPath + $ModuleVersion = (. ([Scriptblock]::Create((Get-Content -Path $Psd1 | Out-String)))).ModuleVersion + Update-AppveyorBuild -Version "$ModuleVersion ($env:APPVEYOR_BUILD_NUMBER) $env:APPVEYOR_REPO_BRANCH" +} +if ($Test -or $TestImportOnly) { + function Get-EnvironmentInfo { + if ([environment]::OSVersion.Platform -like "win*") { + # Get Windows Version + try { + $WinRelease, $WinVer = Get-ItemPropertyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" ReleaseId, CurrentMajorVersionNumber, CurrentMinorVersionNumber, CurrentBuildNumber, UBR + $WindowsVersion = "$($WinVer -join '.') ($WinRelease)" + } + catch { + $WindowsVersion = [System.Environment]::OSVersion.Version + } +#TODO FIXME BUG this gets the latest version of the .NET Framework on the machine (ok for powershell.exe), not the version of .NET CORE in use by PWSH.EXE +<# +$VersionFilePath = (Get-Process -Id $PID | Select-Object -ExpandProperty Modules | + Where-Object -Property modulename -eq "clrjit.dll").FileName +if (-not $VersionFilePath) { + $VersionFilePath = [System.Reflection.Assembly]::LoadWithPartialName("System.Core").location + } + (Get-ItemProperty -Path $VersionFilePath).VersionInfo | + Select-Object -Property @{n="Version"; e={$_.ProductName + " " + $_.FileVersion}}, ProductName, FileVersionRaw, FileName +#> + + # Get .Net Version + # https://stackoverflow.com/questions/3487265/powershell-script-to-return-versions-of-net-framework-on-a-machine + $Lookup = @{ + 378389 = [version]'4.5' + 378675 = [version]'4.5.1' + 378758 = [version]'4.5.1' + 379893 = [version]'4.5.2' + 393295 = [version]'4.6' + 393297 = [version]'4.6' + 394254 = [version]'4.6.1' + 394271 = [version]'4.6.1' + 394802 = [version]'4.6.2' + 394806 = [version]'4.6.2' + 460798 = [version]'4.7' + 460805 = [version]'4.7' + 461308 = [version]'4.7.1' + 461310 = [version]'4.7.1' + 461808 = [version]'4.7.2' + 461814 = [version]'4.7.2' + 528040 = [version]'4.8' + 528049 = [version]'4.8' + } + + # For One True framework (latest .NET 4x), change the Where-Object match + # to PSChildName -eq "Full": + $DotNetVersion = Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | + Get-ItemProperty -name Version, Release -EA 0 | + Where-Object { $_.PSChildName -eq "Full" } | + Select-Object @{name = ".NET Framework"; expression = { $_.PSChildName } }, + @{name = "Product"; expression = { $Lookup[$_.Release] } }, + Version, Release + + # Output + [PSCustomObject]($PSVersionTable + @{ + ComputerName = $env:Computername + WindowsVersion = $WindowsVersion + '.Net Version' = '{0} (Version: {1}, Release: {2})' -f $DotNetVersion.Product, $DotNetVersion.Version, $DotNetVersion.Release + #EnvironmentPath = $env:Path + }) + } + else { + # Output + [PSCustomObject]($PSVersionTable + @{ + ComputerName = $env:Computername + #EnvironmentPath = $env:Path + }) + } + } + + '[Info] Testing On:' + Get-EnvironmentInfo + '[Progress] Installing Module.' + . .\CI\Install.ps1 + '[Progress] Invoking Pester.' + $pesterParams = @{ + OutputFile = ('TestResultsPS{0}.xml' -f $PSVersionTable.PSVersion) + PassThru = $true + } + if ($TestImportOnly) { + $pesterParams['Tag'] = 'TestImportOnly' + } + else { + $pesterParams['ExcludeTag'] = 'TestImportOnly' + } + $testResults = Invoke-Pester @pesterParams + 'Pester invocation complete!' + if ($testResults.FailedCount -gt 0) { + "Test failures:" + $testResults.TestResult | Where-Object {-not $_.Passed} | Format-List + Write-Error "$($testResults.FailedCount) Pester tests failed. Build cannot continue!" + } +} +if ($Finalize) { + '[Progress] Finalizing.' + $Failure = $false + $AppVeyorResultsUri = 'https://ci.appveyor.com/api/testresults/nunit/{0}' -f $env:APPVEYOR_JOB_ID + foreach ($TestResultsFile in Get-ChildItem -Path 'TestResultsPS*.xml') { + $TestResultsFilePath = $TestResultsFile.FullName + "[Info] Uploading Files: $AppVeyorResultsUri, $TestResultsFilePath." + # Add PowerShell version to test results + $PSVersion = $TestResultsFile.Name.Replace('TestResults', '').Replace('.xml', '') + [Xml]$Xml = Get-Content -Path $TestResultsFilePath + Select-Xml -Xml $Xml -XPath '//test-case' | ForEach-Object { $_.Node.name = "$PSVersion " + $_.Node.name } + $Xml.OuterXml | Out-File -FilePath $TestResultsFilePath + + #Invoke-RestMethod -Method Post -Uri $AppVeyorResultsUri -Body $Xml + [Net.WebClient]::new().UploadFile($AppVeyorResultsUri, $TestResultsFilePath) + + if ($Xml.'test-results'.failures -ne '0') { + $Failure = $true + } + } + if ($Failure) { + throw 'Tests failed.' + } +} +if ($Artifact) { + # Get Module Info + $ModuleName = [System.IO.Path]::GetFileNameWithoutExtension((Get-ChildItem -File -Filter *.psm1 -Name -Path (Split-Path $PSScriptRoot))) + $ModulePath = (Get-Module -Name $ModuleName -ListAvailable).ModuleBase | Split-Path + $VersionLocal = ((Get-Module -Name $ModuleName -ListAvailable).Version | Measure-Object -Maximum).Maximum + "[Progress] Artifact Start for Module: $ModuleName, Version: $VersionLocal." + if ($env:APPVEYOR) { + $ZipFileName = "{0} {1} {2} {3:yyyy-MM-dd HH-mm-ss}.zip" -f $ModuleName, $VersionLocal, $env:APPVEYOR_REPO_BRANCH, (Get-Date) + $ZipFileName = $ZipFileName -replace ("[{0}]" -f [RegEx]::Escape([IO.Path]::GetInvalidFileNameChars() -join '')) + $ZipFileFullPath = Join-Path -Path $PSScriptRoot -ChildPath $ZipFileName + "[Info] Artifact. $ModuleName, ZipFileName: $ZipFileName." + #Compress-Archive -Path $ModulePath -DestinationPath $ZipFileFullPath + [System.IO.Compression.ZipFile]::CreateFromDirectory($ModulePath, $ZipFileFullPath, [System.IO.Compression.CompressionLevel]::Optimal, $true) + Push-AppveyorArtifact $ZipFileFullPath -DeploymentName $ModuleName + } + elseif ($env:AGENT_NAME) { + #Write-Host "##vso[task.setvariable variable=ModuleName]$ModuleName" + Copy-Item -Path $ModulePath -Destination $env:Build_ArtifactStagingDirectory -Recurse + } +} +if ($Analyzer) { + if (!(Get-Module -Name PSScriptAnalyzer -ListAvailable)) { + '[Progress] Installing PSScriptAnalyzer.' + Install-Module -Name PSScriptAnalyzer -Force + } + + if ($env:System_PullRequest_TargetBranch) { + '[Progress] Get target branch.' + $TempGitClone = Join-Path ([IO.Path]::GetTempPath()) (New-Guid) + Copy-Item -Path $PWD -Destination $TempGitClone -Recurse + (Get-Item (Join-Path $TempGitClone '.git')).Attributes += 'Hidden' + "[Progress] git clean." + git -C $TempGitClone clean -f + "[Progress] git reset." + git -C $TempGitClone reset --hard + "[Progress] git checkout." + git -C $TempGitClone checkout -q $env:System_PullRequest_TargetBranch + + $DirsToProcess = @{ 'Pull Request' = $PWD ; $env:System_PullRequest_TargetBranch = $TempGitClone } + } + else { + $DirsToProcess = @{ 'GitHub' = $PWD } + } + + "[Progress] Running Script Analyzer." + $AnalyzerResults = $DirsToProcess.GetEnumerator() | ForEach-Object { + $DirName = $_.Key + Write-Verbose "[Progress] Running Script Analyzer on $DirName." + Invoke-ScriptAnalyzer -Path $_.Value -Recurse -ErrorAction SilentlyContinue | + Add-Member -MemberType NoteProperty -Name Location -Value $DirName -PassThru + } + + if ($AnalyzerResults) { + if (!(Get-Module -Name ImportExcel -ListAvailable)) { + '[Progress] Installing ImportExcel.' + Install-Module -Name ImportExcel -Force + } + '[Progress] Creating ScriptAnalyzer.xlsx.' + $ExcelParams = @{ + Path = 'ScriptAnalyzer.xlsx' + WorksheetName = 'FullResults' + Now = $true + Activate = $true + Show = $false + } + $PivotParams = @{ + PivotTableName = 'BreakDown' + PivotData = @{RuleName = 'Count' } + PivotRows = 'Severity', 'RuleName' + PivotColumns = 'Location' + PivotTotals = 'Rows' + } + Remove-Item -Path $ExcelParams['Path'] -ErrorAction SilentlyContinue + + $PivotParams['PivotChartDefinition'] = New-ExcelChartDefinition -ChartType 'BarClustered' -Column (1 + $DirsToProcess.Count) -Title "Script analysis" -LegendBold + $ExcelParams['PivotTableDefinition'] = New-PivotTableDefinition @PivotParams + + $AnalyzerResults | Export-Excel @ExcelParams + '[Progress] Analyzer finished.' + } + else { + "[Info] Invoke-ScriptAnalyzer didn't return any problems." + } +} diff --git a/CI/Install.ps1 b/CI/Install.ps1 new file mode 100644 index 00000000..1e8d801e --- /dev/null +++ b/CI/Install.ps1 @@ -0,0 +1,191 @@ +<# + .SYNOPSIS + Installs module from Git clone or directly from GitHub. + File must not have BOM for GitHub deploy to work. +#> +[CmdletBinding(DefaultParameterSetName = 'Default')] +param( + # Path to install the module to, if not provided -Scope used. + [Parameter(Mandatory, ParameterSetName = 'ModulePath')] + [ValidateNotNullOrEmpty()] + [String]$ModulePath, + + # Path to install the module to, PSModulePath "CurrentUser" or "AllUsers", if not provided "CurrentUser" used. + [Parameter(Mandatory, ParameterSetName = 'Scope')] + [ValidateSet('CurrentUser', 'AllUsers')] + [string] + $Scope = 'CurrentUser', + + # Get module from GitHub instead of local Git clone, for example "https://raw.githubusercontent.com/ili101/Module.Template/master/Install.ps1" + [ValidateNotNullOrEmpty()] + [Uri]$FromGitHub +) +# Set Files and Folders patterns to Include/Exclude. +$IncludeFiles = @( + 'EPPlus.dll', + '*.psd1', + '*.psm1', + '*.ps1' + 'Charting', + 'en-US', + 'Examples', + 'Public', + 'Private', + 'images', + 'InferData', + 'InternalFunctions', + 'Pivot', + 'spikes', + 'Testimonials', + 'README.md', + 'LICENSE.txt' + ) +$ExcludeFiles = @( + 'Install.ps1', + 'InstallModule.ps1', + 'PublishToGallery.PS1' +) + + +function Invoke-MultiLike { + [alias("LikeAny")] + [CmdletBinding()] + param + ( + $InputObject, + [Parameter(Mandatory)] + [String[]]$Filters, + [Switch]$Not + ) + $FiltersRegex = foreach ($Filter In $Filters) { + $Filter = [regex]::Escape($Filter) + if ($Filter -match "^\\\*") { + $Filter = $Filter.Remove(0, 2) + } + else { + $Filter = '^' + $Filter + } + if ($Filter -match "\\\*$") { + $Filter = $Filter.Substring(0, $Filter.Length - 2) + } + else { + $Filter = $Filter + '$' + } + $Filter + } + if ($Not) { + $InputObject -notmatch ($FiltersRegex -join '|').replace('\*', '.*').replace('\?', '.') + } + else { + $InputObject -match ($FiltersRegex -join '|').replace('\*', '.*').replace('\?', '.') + } +} + +Push-Location "$PSScriptRoot\.." +try { + Write-Verbose -Message "Module installation started. Installing from $PWD" + + if (!$ModulePath) { + if ($Scope -eq 'CurrentUser') { + $ModulePathIndex = 0 + } + else { + $ModulePathIndex = 1 + } + if ($IsLinux -or $IsMacOS) { + $ModulePathSeparator = ':' + } + else { + $ModulePathSeparator = ';' + } + $ModulePath = ($env:PSModulePath -split $ModulePathSeparator)[$ModulePathIndex] + } + Write-Verbose -Message "Installing to $ModulePath" + + # Get $ModuleName, $TargetPath, [$Links] + if ($FromGitHub) { + # Fix Could not create SSL/TLS secure channel + #$SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol + #[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + $WebClient = [System.Net.WebClient]::new() + $GitUri = $FromGitHub.AbsolutePath.Split('/')[1, 2] -join '/' + $GitBranch = $FromGitHub.AbsolutePath.Split('/')[3] + $Links = (Invoke-RestMethod -Uri "https://api.github.com/repos/$GitUri/contents" -Body @{ref = $GitBranch }) | Where-Object { (LikeAny $_.name $IncludeFiles) -and (LikeAny $_.name $ExcludeFiles -Not) } + + $ModuleName = [System.IO.Path]::GetFileNameWithoutExtension(($Links | Where-Object { $_.name -like '*.psm1' }).name) + $ModuleVersion = (. ([Scriptblock]::Create((Invoke-WebRequest -Uri ($Links | Where-Object { $_.name -eq "$ModuleName.psd1" }).download_url)))).ModuleVersion + } + else { + $ModuleName = [System.IO.Path]::GetFileNameWithoutExtension((Get-ChildItem -File -Filter *.psm1 -Name -Path $PWD)) + $ModuleVersion = (. ([Scriptblock]::Create((Get-Content -Path (Join-Path $PWD "$ModuleName.psd1") | Out-String)))).ModuleVersion + } + $TargetPath = Join-Path -Path $ModulePath -ChildPath $ModuleName + $TargetPath = Join-Path -Path $TargetPath -ChildPath $ModuleVersion + + # Create Directory + if (-not (Test-Path -Path $TargetPath)) { + $null = New-Item -Path $TargetPath -ItemType Directory -ErrorAction Stop + Write-Verbose -Message ('Created module folder: "{0}"' -f $TargetPath) + } + + # Copy Files + if ($FromGitHub) { + foreach ($Link in $Links) { + $TargetPathItem = Join-Path -Path $TargetPath -ChildPath $Link.name + if ($Link.type -ne 'dir') { + $WebClient.DownloadFile($Link.download_url, $TargetPathItem) + Write-Verbose -Message ('Installed module file: "{0}"' -f $Link.name) + } + else { + if (-not (Test-Path -Path $TargetPathItem)) { + $null = New-Item -Path $TargetPathItem -ItemType Directory -ErrorAction Stop + Write-Verbose -Message 'Created module folder: "{0}"' -f $TargetPathItem + } + $SubLinks = (Invoke-RestMethod -Uri $Link.git_url -Body @{recursive = '1' }).tree + foreach ($SubLink in $SubLinks) { + $TargetPathSub = Join-Path -Path $TargetPathItem -ChildPath $SubLink.path + if ($SubLink.'type' -EQ 'tree') { + if (-not (Test-Path -Path $TargetPathSub)) { + $null = New-Item -Path $TargetPathSub -ItemType Directory -ErrorAction Stop + Write-Verbose -Message 'Created module folder: "{0}"' -f $TargetPathSub + } + } + else { + $WebClient.DownloadFile( + ('https://raw.githubusercontent.com/{0}/{1}/{2}/{3}' -f $GitUri, $GitBranch, $Link.name, $SubLink.path), + $TargetPathSub + ) + } + } + } + } + } + else { + Get-ChildItem -Path $PWD -Exclude $ExcludeFiles | Where-Object { LikeAny $_.Name $IncludeFiles } | ForEach-Object { + if ($_.Attributes -ne 'Directory') { + Copy-Item -Path $_ -Destination $TargetPath + Write-Verbose -Message ('Installed module file "{0}"' -f $_) + } + else { + Copy-Item -Path $_ -Destination $TargetPath -Recurse -Force + Write-Verbose -Message ('Installed module folder "{0}"' -f $_) + } + } + } + + # Import Module + Write-Verbose -Message "$ModuleName module installation successful to $TargetPath" + Import-Module -Name $ModuleName -Force + Write-Verbose -Message "Module installed" +} +catch { + throw ('Failed installing module "{0}". Error: "{1}" in Line {2}' -f $ModuleName, $_, $_.InvocationInfo.ScriptLineNumber) +} +finally { + #if ($FromGitHub) { + # [Net.ServicePointManager]::SecurityProtocol = $SecurityProtocol + #} + Write-Verbose -Message 'Module installation end' + Pop-Location +} \ No newline at end of file diff --git a/CI/InstallPowerShell.ps1 b/CI/InstallPowerShell.ps1 new file mode 100644 index 00000000..e49b21cf --- /dev/null +++ b/CI/InstallPowerShell.ps1 @@ -0,0 +1,30 @@ +<# + .SYNOPSIS + Installs PowerShell Core on Windows. +#> +[CmdLetBinding()] +Param +( + # Version to install in the format from the .msi, for example "7.0.0-preview.1" + [String]$Version +) +$ErrorActionPreference = 'Stop' + +if (-not $Version) { + $Version = (Invoke-RestMethod https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/metadata.json).StableReleaseTag +} +$Version = $Version -replace "^v","" + +'[Progress] Downloading PowerShell Core.' +$MsiPath = Join-Path $env:TEMP "PowerShell-$Version-win-x64.msi" +[System.Net.WebClient]::new().DownloadFile("https://github.com/PowerShell/PowerShell/releases/download/v$Version/PowerShell-$Version-win-x64.msi", $MsiPath) + +'[Progress] Installing PowerShell Core.' +Start-Process 'msiexec.exe' -Wait -ArgumentList "/i $MsiPath /quiet" +Remove-Item -Path $MsiPath +$PowerShellFolder = $Version[0] +if ($Version -like "*preview*") { + $PowerShellFolder += '-preview' +} +$env:Path = "$env:ProgramFiles\PowerShell\$PowerShellFolder;$env:Path" +'[Progress] PowerShell Core Installed.' \ No newline at end of file diff --git a/CI/PS-CI.ps1 b/CI/PS-CI.ps1 new file mode 100644 index 00000000..b881fe10 --- /dev/null +++ b/CI/PS-CI.ps1 @@ -0,0 +1,266 @@ +[cmdletbinding(DefaultParameterSetName = 'Scope')] +Param( + [Parameter(Mandatory = $true, ParameterSetName = 'ModulePath')] + [ValidateNotNullOrEmpty()] + [String]$ModulePath, + + # Path to install the module to, PSModulePath "CurrentUser" or "AllUsers", if not provided "CurrentUser" used. + [Parameter(ParameterSetName = 'Scope')] + [ValidateSet('CurrentUser', 'AllUsers')] + [string] + $Scope = 'CurrentUser', + + [Parameter(Mandatory = $true, ParameterSetName = 'PreCheckOnly')] + [switch]$PreCheckOnly, + [Parameter(ParameterSetName = 'ModulePath')] + [Parameter(ParameterSetName = 'Scope')] + [switch]$SkipPreChecks, + [Parameter(ParameterSetName = 'ModulePath')] + [Parameter(ParameterSetName = 'Scope')] + [switch]$SkipPostChecks, + [Parameter(ParameterSetName = 'ModulePath')] + [Parameter(ParameterSetName = 'Scope')] + [switch]$SkipPesterTests, + [Parameter(ParameterSetName = 'ModulePath')] + [Parameter(ParameterSetName = 'Scope')] + [switch]$SkipHelp, + [Parameter(ParameterSetName = 'ModulePath')] + [Parameter(ParameterSetName = 'Scope')] + [switch]$CleanModuleDir +) +Function Show-Warning { + param( + [Parameter(Position = 0, ValueFromPipeline = $true)] + $message + ) + process { + write-output "##vso[task.logissue type=warning]File $message" + $message >> $script:warningfile + } +} + +if ($PSScriptRoot) { + $workingdir = Split-Path -Parent $PSScriptRoot + Push-Location $workingdir +} +$psdpath = Get-Item "*.psd1" +if (-not $psdpath -or $psdpath.count -gt 1) { + if ($PSScriptRoot) { Pop-Location } + throw "Did not find a unique PSD file " +} +else { + try { $null = Test-ModuleManifest -Path $psdpath -ErrorAction stop } + catch { throw $_ ; return } + $ModuleName = $psdpath.Name -replace '\.psd1$' , '' + $Settings = $(& ([scriptblock]::Create(($psdpath | Get-Content -Raw)))) + $approvedVerbs = Get-Verb | Select-Object -ExpandProperty verb + $script:warningfile = Join-Path -Path $pwd -ChildPath "warnings.txt" +} + +#pre-build checks - manifest found, files in it found, public functions and aliases loaded in it. Public functions correct. +if (-not $SkipPreChecks) { + + #Check files in the manifest are present + foreach ($file in $Settings.FileList) { + if (-not (Test-Path $file)) { + Show-Warning "File $file in the manifest file list is not present" + } + } + + #Check files in public have Approved_verb-noun names and are 1 function using the file name as its name with + # its name and any alias names in the manifest; function should have a param block and help should be in an MD file + # We will want a regex which captures from "function verb-noun {" to its closing "}" + # need to match each { to a } - $reg is based on https://stackoverflow.com/questions/7898310/using-regex-to-balance-match-parenthesis + $reg = [Regex]::new(@" + function\s*[-\w]+\s*{ # The function name and opening '{' + (?: + [^{}]+ # Match all non-braces + | + (? { ) # Match '{', and capture into 'open' + | + (?<-open> } ) # Match '}', and delete the 'open' capture + )* + (?(open)(?!)) # Fails if 'open' stack isn't empty + } # Functions closing '}' +"@, 57) # 57 = compile,multi-line ignore case and white space. + foreach ($file in (Get-Item .\Public\*.ps1)) { + $name = $file.name -replace (".ps1", "") + if ($name -notmatch ("(\w+)-\w+")) { Show-Warning "$name in the public folder is not a verb-noun name" } + elseif ($Matches[1] -notin $approvedVerbs) { Show-Warning "$name in the public folder does not start with an approved verb" } + if (-not ($Settings.FunctionsToExport -ceq $name)) { + Show-Warning ('File {0} in the public folder does not match an exported function in the manifest' -f $file.name) + } + else { + $fileContent = Get-Content $file -Raw + $m = $reg.Matches($fileContent) + if ($m.Count -eq 0) { Show-Warning ('Could not find {0} function in {1}' -f $name, $file.name); continue } + elseif ($m.Count -ge 2) { Show-Warning ('Multiple functions in {0}' -f $item.name) ; Continue } + elseif ($m[0] -imatch "^\function\s" -and + $m[0] -cnotmatch "^\w+\s+$name") { Show-Warning ('function name does not match file name for {0}' -f $file.name) } + #$m[0] runs form the f of function to its final } -find the section up to param, check for aliases & comment-based help + $m2 = [regex]::Match($m[0], "^.*?param", 17) # 17 = multi-line, ignnore case + if (-not $m2.Success) { Show-Warning "function $name has no param() block" } + else { + if ($m2.value -match "(? +[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "Success")] +[CmdletBinding(DefaultParameterSetName = 'ModuleName')] +Param +( + # The name of the installed module to be deployed, if not provided the name of the .psm1 file in the parent folder is used. + [Parameter(ParameterSetName = 'ModuleName')] + [ValidateNotNullOrEmpty()] + [String]$ModuleName, + + # Publish module from path (module folder), if not provided -ModuleName is used. + [Parameter(Mandatory, ParameterSetName = 'Path')] + [ValidateNotNullOrEmpty()] + [String]$Path, + + # Key for PowerShellGallery deployment, if not provided $env:NugetApiKey is used. + [ValidateNotNullOrEmpty()] + [String]$NugetApiKey, + + # Skip Version verification for PowerShellGallery deployment, can be used for first release. + [Switch]$Force +) +$ErrorActionPreference = 'Stop' + +if ($Path) { + $Path = Resolve-Path -Path $Path + if ($Path.Count -ne 1) { + throw ('Invalid Path, $Path.Count: {0}.' -f $Path.Count) + } + $Psd1Path = (Get-ChildItem -File -Filter *.psd1 -Path $Path -Recurse)[0].FullName + $ModuleName = [System.IO.Path]::GetFileNameWithoutExtension($Psd1Path) + $VersionLocal = (. ([Scriptblock]::Create((Get-Content -Path $Psd1Path | Out-String)))).ModuleVersion +} +else { + # Get Script Root + if ($PSScriptRoot) { + $ScriptRoot = $PSScriptRoot + } + elseif ($psISE.CurrentFile.IsUntitled -eq $false) { + $ScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath + } + elseif ($null -ne $psEditor.GetEditorContext().CurrentFile.Path -and $psEditor.GetEditorContext().CurrentFile.Path -notlike 'untitled:*') { + $ScriptRoot = Split-Path -Path $psEditor.GetEditorContext().CurrentFile.Path + } + else { + $ScriptRoot = '.' + } + + # Get Module Info + if (!$ModuleName) { + $ModuleName = [System.IO.Path]::GetFileNameWithoutExtension((Get-ChildItem -File -Filter *.psm1 -Name -Path (Split-Path $ScriptRoot))) + } + $VersionLocal = ((Get-Module -Name $ModuleName -ListAvailable).Version | Measure-Object -Maximum).Maximum +} + +"[Progress] Deploy Script Start for Module: $ModuleName, Version: $VersionLocal." + +# Deploy to PowerShell Gallery if run locally OR from AppVeyor & GitHub master +if (!$env:APPVEYOR -or $env:APPVEYOR_REPO_BRANCH -eq 'master') { + if ($env:APPVEYOR) { + $Success = $true + $AppVeyorProject = Invoke-RestMethod -Uri "https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG" + $AppVeyorProject.build.jobs | ForEach-Object { + '[Info] AppVeyor job name: "{0}", Id: {1}, Status: {2}.' -f $_.name, $_.jobId, $_.status + if ($_.jobId -ne $env:APPVEYOR_JOB_ID -and $_.status -ne "success") { + $Success = $false + } + } + if (!$Success) { + '[Info] There are filed jobs skipping PowerShell Gallery deploy.' + break + } + } + try { + $VersionGallery = (Find-Module -Name $ModuleName -ErrorAction Stop).Version + } + catch { + if ($_.Exception.Message -notlike 'No match was found for the specified search criteria*' -or !$Force) { + throw $_ + } + } + + "[Info] PowerShellGallery. $ModuleName, VersionGallery: $VersionGallery, VersionLocal: $VersionLocal." + if ($VersionGallery -lt $VersionLocal -or $Force) { + if (!$NugetApiKey) { + $NugetApiKey = $env:NugetApiKey + } + "[Info] PowerShellGallery. Deploying $ModuleName version $VersionLocal." + if ($Path) { + Publish-Module -NuGetApiKey $NugetApiKey -Path $Path + } + else { + Publish-Module -NuGetApiKey $NugetApiKey -Name $ModuleName -RequiredVersion $VersionLocal + } + } + else { + '[Info] PowerShellGallery Deploy Skipped (Version Check).' + } +} +else { + '[Info] PowerShellGallery Deploy Skipped.' +} +'[Progress] Deploy Ended.' \ No newline at end of file diff --git a/CI/PublishToGallery.ps1 b/CI/PublishToGallery.ps1 new file mode 100644 index 00000000..0b55bd13 --- /dev/null +++ b/CI/PublishToGallery.ps1 @@ -0,0 +1,6 @@ +$p = @{ + Name = "ImportExcel" + NuGetApiKey = $NuGetApiKey +} + +Publish-Module @p \ No newline at end of file diff --git a/CI/Test-SingleFunctions.ps1 b/CI/Test-SingleFunctions.ps1 new file mode 100644 index 00000000..ac83cbb6 --- /dev/null +++ b/CI/Test-SingleFunctions.ps1 @@ -0,0 +1,54 @@ + +function Test-SingleFunction { + param ( + [parameter(ValueFromPipeline=$true)] + $path ) + begin { + $psd = Get-Content -Raw "$PSScriptRoot\..\ImportExcel.psd1" + $exportedFunctions = (Invoke-Command ([scriptblock]::Create($psd))).functionsToExport + $reg = [Regex]::new(@" + function\s*[-\w]+\s*{ # The function name and opening '{' + (?: + [^{}]+ # Match all non-braces + | + (? { ) # Match '{', and capture into 'open' + | + (?<-open> } ) # Match '}', and delete the 'open' capture + )* + (?(open)(?!)) # Fails if 'open' stack isn't empty + } # Functions closing '}' +"@, 57) # 41 = compile ignore case and white space. +$reg2 = [Regex]::new(@" + ^function\s*[-\w]+\s*{ # The function name and opening '{' + ( + \#.*?[\r\n]+ # single line comment + | # or + \s*<\#.*?\#> # <#comment block#> + | # or + \s*\[.*?\] # [attribute tags] + )* +"@, 57) +# 43 = compile, multi-line, ignore case and white space. + } + process { + $item = Get-item $Path + $name = $item.Name -replace "\.\w+$","" + Write-Verbose $name + $file = Get-Content $item -Raw + $m = $reg.Matches($file) + + #based on https://stackoverflow.com/questions/7898310/using-regex-to-balance-match-parenthesis + if ($m.Count -eq 0) {return "Could not find $name function in $($item.name)"} + elseif ($m.Count -ge 2) {return "Multiple functions in $($item.name)"} + elseif ($exportedFunctions -cnotcontains $name) {return "$name not exported (or in the wrong case)"} + elseif ($m[0] -cnotmatch "^\w+\s+$name") {return "function $name in wrong case"} + $m2 = [regex]::Match($m[0],"param",[System.Text.RegularExpressions.RegexOptions]::IgnoreCase) + if (-not $m2.Success) {return "No param block in $name"} + # elseif ($m[0] -inotmatch "(?s)^function\s*$name\s*{(\s*<\#.*?\#>|\s*\[.*?\])*\s*param") + # elseif ($reg2.IsMatch($m[0].Value)) {return "function $name has comment-based help"} + elseif ($m[0] -inotmatch "\[CmdletBinding\(" -and + $m[0] -inotmatch "\[parameter\(" ) {return "$name has is not an advanced function"} + #elseif (-not (& $Name -?).synopsis) {return "$name has no help"} + else {Write-Verbose "$name OK"} + } +} \ No newline at end of file diff --git a/CI/build.ps1 b/CI/build.ps1 new file mode 100644 index 00000000..dbfd870d --- /dev/null +++ b/CI/build.ps1 @@ -0,0 +1,80 @@ +[CmdletBinding(DefaultParameterSetName = 'Default')] +param( + # Path to install the module to, if not provided -Scope used. + [Parameter(Mandatory, ParameterSetName = 'ModulePath')] + [ValidateNotNullOrEmpty()] + [String]$ModulePath, + + # Path to install the module to, PSModulePath "CurrentUser" or "AllUsers", if not provided "CurrentUser" used. + [Parameter(Mandatory, ParameterSetName = 'Scope')] + [ValidateSet('CurrentUser', 'AllUsers')] + [string] + $Scope = 'CurrentUser', + [switch]$Passthru +) + +if ($PSScriptRoot) { Push-Location "$PSScriptRoot\.." } + +$psdpath = Get-Item "*.psd1" +if (-not $psdpath -or $psdpath.count -gt 1) { + throw "Did not find a unique PSD file " +} +else { + $ModuleName = $psdpath.Name -replace '\.psd1$' , '' + $Settings = $(& ([scriptblock]::Create(($psdpath | Get-Content -Raw)))) +} + +try { + Write-Verbose -Message 'Module installation started' + + if (!$ModulePath) { + if ($IsLinux -or $IsMacOS) {$ModulePathSeparator = ':' } + else {$ModulePathSeparator = ';' } + + if ($Scope -eq 'CurrentUser') { $dir = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::UserProfile) } + else { $dir = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::ProgramFiles) } + $ModulePath = ($env:PSModulePath -split $ModulePathSeparator).where({$_ -like "$dir*"},"First",1) + $ModulePath = Join-Path -Path $ModulePath -ChildPath $ModuleName + $ModulePath = Join-Path -Path $ModulePath -ChildPath $Settings.ModuleVersion + } + + # Create Directory + if (-not (Test-Path -Path $ModulePath)) { + $null = New-Item -Path $ModulePath -ItemType Directory -ErrorAction Stop + Write-Verbose -Message ('Created module folder: "{0}"' -f $ModulePath) + } + + Write-Verbose -Message ('Copying files to "{0}"' -f $ModulePath) + $outputFile = $psdpath | Copy-Item -Destination $ModulePath -PassThru + Foreach ($file in $Settings.FileList) { + if ($file -like '.\*') { + $dest = ($file -replace '\.\\',"$ModulePath\") + if (-not (Test-Path -PathType Container (Split-Path -Parent $dest))) { + $null = New-item -Type Directory -Path (Split-Path -Parent $dest) + } + } + else {$dest = $ModulePath } + Copy-Item $file -Destination $dest -Force -Recurse + } + + if (Test-Path -PathType Container "mdHelp") { + if (-not (Get-Module -ListAvailable platyPS)) { + Write-Verbose-Message ('Installing Platyps to build help files') + Install-Module -Name platyPS -Force -SkipPublisherCheck + } + Import-Module platyPS + Get-ChildItem .\mdHelp -Directory | ForEach-Object { + New-ExternalHelp -Path $_.FullName -OutputPath (Join-Path $ModulePath $_.Name) -Force -Verbose + } + } + $env:PSNewBuildModule = $ModulePath + + if ($Passthru) {$outputFile} +} +catch { + throw ('Failed installing module "{0}". Error: "{1}" in Line {2}' -f $ModuleName, $_, $_.InvocationInfo.ScriptLineNumber) +} +finally { + if ($PSScriptRoot) { Pop-Location } + Write-Verbose -Message 'Module installation end' +} \ No newline at end of file diff --git a/CI/pipeline.yml b/CI/pipeline.yml new file mode 100644 index 00000000..ca0324c8 --- /dev/null +++ b/CI/pipeline.yml @@ -0,0 +1,75 @@ +# https://aka.ms/yaml + +trigger: + branches: + include: + - '*' + # - master + # - releases/* + paths: + exclude: + - README.md + - CHANGELOG.md + +jobs: + - job: 'Windows_PowerShell_all_options' + pool: + vmImage: 'windows-latest' + steps: + - powershell: 'Install-Module -Name Pester -Force -SkipPublisherCheck' + displayName: 'Update Pester' + - powershell: './CI/PS-CI.ps1 ' + displayName: 'Check Build Check Pack Test' + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + - task: PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)/ImportExcel' + artifact: 'ImportExcel' + + - job: 'PowerShell_Core_on_Windows_Build_and_Pester_only' + pool: + vmImage: 'windows-latest' + steps: + - pwsh: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - pwsh: '.\CI\PS-CI.ps1 -SkipPreChecks -SkipHelp -SkipPostChecks' + displayName: 'Install and Test' + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + + - job: 'Ubuntu_Build_and_Pester_Only' + pool: + vmImage: 'ubuntu-latest' + steps: + - powershell: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - powershell: './CI/PS-CI.ps1 -SkipPreChecks -SkipHelp -SkipPostChecks ' + displayName: 'Install and Test' + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + + - job: 'macOS_Build_and_Pester_Only' + pool: + vmImage: 'macOS-latest' + steps: + - script: brew install mono-libgdiplus + displayName: 'Install mono-libgdiplus' + - powershell: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - powershell: './CI/PS-CI.ps1 -SkipPreChecks -SkipHelp -SkipPostChecks' + displayName: 'Install and Test' + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true diff --git a/Charting.ps1 b/Charting/Charting.ps1 similarity index 92% rename from Charting.ps1 rename to Charting/Charting.ps1 index 17c6ee11..bd21b187 100644 --- a/Charting.ps1 +++ b/Charting/Charting.ps1 @@ -9,7 +9,7 @@ function DoChart { ) if($targetData[0] -is [System.ValueType]) { - $chart = New-ExcelChart -YRange "A1:A$($targetData.count)" -Title $title -ChartType $ChartType + $chart = New-ExcelChartDefinition -YRange "A1:A$($targetData.count)" -Title $title -ChartType $ChartType } else { $xyRange = Get-XYRange $targetData @@ -19,7 +19,7 @@ function DoChart { $Y = $xyRange.YRange.ExcelColumn $YRange = "{0}2:{0}{1}" -f $Y,($targetData.count+1) - $chart = New-ExcelChart -XRange $xRange -YRange $yRange -Title $title -ChartType $ChartType ` + $chart = New-ExcelChartDefinition -XRange $xRange -YRange $yRange -Title $title -ChartType $ChartType ` -NoLegend:$NoLegend -ShowCategory:$ShowCategory -ShowPercent:$ShowPercent } diff --git a/ColorCompletion.ps1 b/ColorCompletion.ps1 deleted file mode 100644 index 12b6f81d..00000000 --- a/ColorCompletion.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -Function ColorCompletion { - param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) - [System.Drawing.KnownColor].GetFields() | Where-Object {$_.IsStatic -and $_.name -like "$wordToComplete*" } | - Sort-Object name | ForEach-Object {New-CompletionResult $_.name $_.name - } -} - -if (Get-Command -Name register-argumentCompleter -ErrorAction SilentlyContinue) { - Register-ArgumentCompleter -CommandName Export-Excel -ParameterName TitleBackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName DataBarColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName ForeGroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName AllDataBackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName FontColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName TabColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Format -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Format -ParameterName FontColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Format -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Column -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Column -ParameterName FontColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Column -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Row -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Row -ParameterName FontColor -ScriptBlock $Function:ColorCompletion - Register-ArgumentCompleter -CommandName Set-Row -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion -} \ No newline at end of file diff --git a/ConvertExcelToImageFile.ps1 b/ConvertExcelToImageFile.ps1 deleted file mode 100644 index 63817590..00000000 --- a/ConvertExcelToImageFile.ps1 +++ /dev/null @@ -1,74 +0,0 @@ -Function Convert-XlRangeToImage { -<# - .Synopsis - Gets the specified part of an Excel file and exports it as an image - .Description - Excel allows charts to be exported directly to a file, but can't do this with the rest of a sheet. To work round this this function - * Opens a copy of Excel and loads a file - * Selects a worksheet and then a range of cells in that worksheet - * Copies the select to the clipboard - * Saves the clipboard contents as an image file (it will save as .JPG unless the file name ends .BMP or .PNG) - * Copies a single cell to the clipboard (to prevent the "you have put a lot in the clipboard" message appearing) - * Closes Excel -#> -Param ( - #Path to the Excel file - [parameter(Mandatory=$true)] - $Path, - #Worksheet name - if none is specified "Sheet1" will be assumed - $workSheetname = "Sheet1" , - #Range of cells within the sheet, e.g "A1:Z99" - [parameter(Mandatory=$true)] - $range, - #A bmp, png or jpg file where the result will be saved - $destination = "$pwd\temp.png", - #If specified opens the image in the default viewer. - [switch]$show -) - $extension = $destination -replace '^.*\.(\w+)$' ,'$1' - if ($extension -in @('JPEG','BMP','PNG')) { - $Format = [system.Drawing.Imaging.ImageFormat]$extension - } #if we don't recognise the extension OR if it is JPG with an E, use JPEG format - else { $Format = [system.Drawing.Imaging.ImageFormat]::Jpeg} - Write-Progress -Activity "Exporting $range of $workSheetname in $Path" -Status "Starting Excel" - $xlApp = New-Object -ComObject "Excel.Application" - Write-Progress -Activity "Exporting $range of $workSheetname in $Path" -Status "Opening Workbook and copying data" - $xlWbk = $xlApp.Workbooks.Open($Path) - $xlWbk.Worksheets($workSheetname).Select() - $xlWbk.ActiveSheet.Range($range).Select() | Out-Null - $xlApp.Selection.Copy() | Out-Null - Write-Progress -Activity "Exporting $range of $workSheetname in $Path" -Status "Saving copied data" - # Get-Clipboard came in with PS5. Older versions can use [System.Windows.Clipboard] but it is ugly. - $image = Get-Clipboard -Format Image - $image.Save($destination, $Format) - Write-Progress -Activity "Exporting $range of $workSheetname in $Path" -Status "Closing Excel" - $xlWbk.ActiveSheet.Range("a1").Select() | Out-Null - $xlApp.Selection.Copy() | Out-Null - $xlApp.Quit() - Write-Progress -Activity "Exporting $range of $workSheetname in $Path" -Completed - if ($show) {Start-Process -FilePath $destination} - else {Get-Item -Path $destination} -} -<# -del demo*.xlsx - -$workSheetname = 'Processes' -$Path = "$pwd\demo.xlsx" -$myData = Get-Process | Select-Object -Property Name,WS,CPU,Description,company,startTime - -$excelPackage = $myData | Export-Excel -KillExcel -Path $Path -WorkSheetname $workSheetname -ClearSheet -AutoSize -AutoFilter -BoldTopRow -FreezeTopRow -PassThru -$workSheet = $excelPackage.Workbook.Worksheets[$workSheetname] -$range = $workSheet.Dimension.Address -Set-Format -WorkSheet $workSheet -Range "b:b" -NumberFormat "#,###" -AutoFit -Set-Format -WorkSheet $workSheet -Range "C:C" -NumberFormat "#,##0.00" -AutoFit -Set-Format -WorkSheet $workSheet -Range "F:F" -NumberFormat "dd MMMM HH:mm:ss" -AutoFit -Add-ConditionalFormatting -WorkSheet $workSheet -Range "c2:c1000" -DataBarColor Blue -Add-ConditionalFormatting -WorkSheet $workSheet -Range "b2:B1000" -RuleType GreaterThan -ConditionValue '104857600' -ForeGroundColor "Red" -Bold - -Export-Excel -ExcelPackage $excelPackage -WorkSheetname $workSheetname - -Convert-XlRangeToImage -Path $Path -workSheetname $workSheetname -range $range -destination "$pwd\temp.png" -show -#> - - -#Convert-XlRangeToImage -Path $Path -workSheetname $workSheetname -range $range -destination "$pwd\temp.png" -show \ No newline at end of file diff --git a/ConvertFromExcelData.ps1 b/ConvertFromExcelData.ps1 deleted file mode 100644 index bd758950..00000000 --- a/ConvertFromExcelData.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -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 - } -} \ No newline at end of file diff --git a/ConvertFromExcelToSQLInsert.ps1 b/ConvertFromExcelToSQLInsert.ps1 deleted file mode 100644 index a1fd3947..00000000 --- a/ConvertFromExcelToSQLInsert.ps1 +++ /dev/null @@ -1,130 +0,0 @@ -function ConvertFrom-ExcelToSQLInsert { - <# - .SYNOPSIS - Generate SQL insert statements from Excel spreadsheet. - - .DESCRIPTION - Generate SQL insert statements from Excel spreadsheet. - - .PARAMETER TableName - Name of the target database table. - - .PARAMETER Path - Path to an existing .XLSX file - - This parameter is passed to Import-Excel as is. - - .PARAMETER WorkSheetname - Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. - - This parameter is passed to Import-Excel as is. - - .PARAMETER StartRow - The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. - - When the parameters ‘-NoHeader’ and ‘-HeaderName’ are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data. - - .PARAMETER Header - Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. - - In case you provide less header names than there is data in the worksheet, then only the data with a corresponding header name will be imported and the data without header name will be disregarded. - - In case you provide more header names than there is data in the worksheet, then all data will be imported and all objects will have all the property names you defined in the header names. As such, the last properties will be blanc as there is no data for them. - - .PARAMETER NoHeader - Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. - - This switch is best used when you want to import the complete worksheet ‘as is’ and are not concerned with the property names. - - .PARAMETER DataOnly - Import only rows and columns that contain data, empty rows and empty columns are not imported. - - - .PARAMETER ConvertEmptyStringsToNull - If specified, cells without any data are replaced with NULL, instead of an empty string. - - This is to address behviors in certain DBMS where an empty string is insert as 0 for INT column, instead of a NULL value. - - .EXAMPLE - Generate SQL insert statements from Movies.xlsx file, leaving blank cells as empty strings: - - ---------------------------------------------------------- - | File: Movies.xlsx - Sheet: Sheet1 | - ---------------------------------------------------------- - | A B C | - |1 Movie Name Year Rating | - |2 The Bodyguard 1992 9 | - |3 The Matrix 1999 8 | - |4 Skyfall 2012 9 | - |5 The Avengers 2012 | - ---------------------------------------------------------- - - PS C:\> Import-Excel -TableName "Movies" -Path 'C:\Movies.xlsx' - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Bodyguard', '1992', '9'); - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Matrix', '1999', '8'); - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('Skyfall', '2012', '9'); - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Avengers', '2012', ''); - - .EXAMPLE - Generate SQL insert statements from Movies.xlsx file, specify NULL instead of an empty string. - - ---------------------------------------------------------- - | File: Movies.xlsx - Sheet: Sheet1 | - ---------------------------------------------------------- - | A B C | - |1 Movie Name Year Rating | - |2 The Bodyguard 1992 9 | - |3 The Matrix 1999 8 | - |4 Skyfall 2012 9 | - |5 The Avengers 2012 | - ---------------------------------------------------------- - - PS C:\> ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path "C:\Movies.xlsx" -ConvertEmptyStringsToNull - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Bodyguard', '1992', '9'); - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Matrix', '1999', '8'); - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('Skyfall', '2012', '9'); - INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Avengers', '2012', NULL); - - .NOTES - #> - [CmdletBinding()] - param( - [Parameter(Mandatory = $true)] - $TableName, - [Alias("FullName")] - [Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true)] - [ValidateScript( { Test-Path $_ -PathType Leaf })] - $Path, - [Alias("Sheet")] - $WorkSheetname = 1, - [Alias('HeaderRow', 'TopRow')] - [ValidateRange(1, 9999)] - [Int]$StartRow, - [string[]]$Header, - [switch]$NoHeader, - [switch]$DataOnly, - [switch]$ConvertEmptyStringsToNull - ) - - $null = $PSBoundParameters.Remove('TableName') - $null = $PSBoundParameters.Remove('ConvertEmptyStringsToNull') - - $params = @{} + $PSBoundParameters - - ConvertFrom-ExcelData @params { - param($propertyNames, $record) - - $ColumnNames = "'" + ($PropertyNames -join "', '") + "'" - $values = foreach ($propertyName in $PropertyNames) { - if ($ConvertEmptyStringsToNull.IsPresent -and [string]::IsNullOrEmpty($record.$propertyName)) { - 'NULL' - } - else { - "'" + $record.$propertyName + "'" - } - } - $targetValues = ($values -join ", ") - - "INSERT INTO {0} ({1}) Values({2});" -f $TableName, $ColumnNames, $targetValues - } -} \ No newline at end of file diff --git a/ConvertFromExcelToSQLInsert.tests.ps1 b/ConvertFromExcelToSQLInsert.tests.ps1 deleted file mode 100644 index 1b6a31b5..00000000 --- a/ConvertFromExcelToSQLInsert.tests.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -Import-Module .\ImportExcel.psd1 -Force - -$xlFile = ".\testSQL.xlsx" - -Describe "ConvertFrom-ExcelToSQLInsert" { - - BeforeEach { - - $([PSCustomObject]@{ - Name="John" - Age=$null - }) | Export-Excel $xlFile - } - - AfterAll { - Remove-Item $xlFile -Recurse -Force -ErrorAction Ignore - } - - It "Should be empty double single quotes" { - $expected="INSERT INTO Sheet1 ('Name', 'Age') Values('John', '');" - - $actual = ConvertFrom-ExcelToSQLInsert -Path $xlFile Sheet1 - - $actual | should be $expected - } - - It "Should have NULL" { - $expected="INSERT INTO Sheet1 ('Name', 'Age') Values('John', NULL);" - - $actual = ConvertFrom-ExcelToSQLInsert -Path $xlFile Sheet1 -ConvertEmptyStringsToNull - - $actual | should be $expected - } -} \ No newline at end of file diff --git a/ConvertToExcelXlsx.ps1 b/ConvertToExcelXlsx.ps1 deleted file mode 100644 index eb62c651..00000000 --- a/ConvertToExcelXlsx.ps1 +++ /dev/null @@ -1,53 +0,0 @@ -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() - } -} - diff --git a/Copy-ExcelWorkSheet.ps1 b/Copy-ExcelWorkSheet.ps1 deleted file mode 100644 index 87503e49..00000000 --- a/Copy-ExcelWorkSheet.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -function Copy-ExcelWorkSheet { - [CmdletBinding()] - param( - [Parameter(Mandatory=$true)] - $SourceWorkbook, - [Parameter(Mandatory=$true)] - $SourceWorkSheet, - [Parameter(Mandatory=$true)] - $DestinationWorkbook, - $DestinationWorkSheet, - [Switch]$Show - ) - - Write-Verbose "Copying $($SourceWorkSheet) from $($SourceWorkbook) to $($DestinationWorkSheet) in $($DestinationWorkbook)" - - if(!$DestinationWorkSheet) { - $DestinationWorkSheet = $SourceWorkSheet - } - - Import-Excel -Path $SourceWorkbook -WorkSheetname $SourceWorkSheet | - Export-Excel -Path $DestinationWorkbook -WorkSheetname $DestinationWorkSheet -Show:$Show -} \ No newline at end of file diff --git a/DoTests.ps1 b/DoTests.ps1 deleted file mode 100644 index b4246311..00000000 --- a/DoTests.ps1 +++ /dev/null @@ -1,8 +0,0 @@ - -# Get-Module -ListAvailable pester | Out-Host -# return -if ((Get-Module -ListAvailable pester) -eq $null) { - Install-Module -Name Pester -Repository PSGallery -Force -} - -Invoke-Pester -Script $PSScriptRoot\UnitTests \ No newline at end of file diff --git a/EPPlus.dll b/EPPlus.dll index 39e62955..ff31f76b 100644 Binary files a/EPPlus.dll and b/EPPlus.dll differ diff --git a/Examples/AddImage/Add-ExcelImage.ps1 b/Examples/AddImage/Add-ExcelImage.ps1 new file mode 100644 index 00000000..38ce80e0 --- /dev/null +++ b/Examples/AddImage/Add-ExcelImage.ps1 @@ -0,0 +1,119 @@ +function Add-ExcelImage { + <# + .SYNOPSIS + Adds an image to a worksheet in an Excel package. + .DESCRIPTION + Adds an image to a worksheet in an Excel package using the + `WorkSheet.Drawings.AddPicture(name, image)` method, and places the + image at the location specified by the Row and Column parameters. + + Additional position adjustment can be made by providing RowOffset and + ColumnOffset values in pixels. + .EXAMPLE + $image = [System.Drawing.Image]::FromFile($octocat) + $xlpkg = $data | Export-Excel -Path $path -PassThru + $xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell + + Where $octocat is a path to an image file, and $data is a collection of + data to be exported, and $path is the output path for the Excel document, + Add-Excel places the image at row 4 and column 6, resizing the column + and row as needed to fit the image. + .INPUTS + [OfficeOpenXml.ExcelWorksheet] + .OUTPUTS + None + #> + [CmdletBinding()] + param( + # Specifies the worksheet to add the image to. + [Parameter(Mandatory, ValueFromPipeline)] + [OfficeOpenXml.ExcelWorksheet] + $WorkSheet, + + # Specifies the Image to be added to the worksheet. + [Parameter(Mandatory)] + [System.Drawing.Image] + $Image, + + # Specifies the row where the image will be placed. Rows are counted from 1. + [Parameter(Mandatory)] + [ValidateRange(1, [int]::MaxValue)] + [int] + $Row, + + # Specifies the column where the image will be placed. Columns are counted from 1. + [Parameter(Mandatory)] + [ValidateRange(1, [int]::MaxValue)] + [int] + $Column, + + # Specifies the name to associate with the image. Names must be unique per sheet. + # Omit the name and a GUID will be used instead. + [Parameter()] + [string] + $Name, + + # Specifies the number of pixels to offset the image on the Y-axis. A + # positive number moves the image down by the specified number of pixels + # from the top border of the cell. + [Parameter()] + [int] + $RowOffset = 1, + + # Specifies the number of pixels to offset the image on the X-axis. A + # positive number moves the image to the right by the specified number + # of pixels from the left border of the cell. + [Parameter()] + [int] + $ColumnOffset = 1, + + # Increase the column width and row height to fit the image if the current + # dimensions are smaller than the image provided. + [Parameter()] + [switch] + $ResizeCell + ) + + begin { + if ($IsWindows -eq $false) { + throw "This only works on Windows and won't run on $([environment]::OSVersion)" + } + + <# + These ratios work on my machine but it feels fragile. Need to better + understand how row and column sizing works in Excel and what the + width and height units represent. + #> + $widthFactor = 1 / 7 + $heightFactor = 3 / 4 + } + + process { + if ([string]::IsNullOrWhiteSpace($Name)) { + $Name = (New-Guid).ToString() + } + if ($null -ne $WorkSheet.Drawings[$Name]) { + Write-Error "A picture with the name `"$Name`" already exists in worksheet $($WorkSheet.Name)." + return + } + + <# + The row and column offsets of 1 ensures that the image lands just + inside the gray cell borders at the top left. + #> + $picture = $WorkSheet.Drawings.AddPicture($Name, $Image) + $picture.SetPosition($Row - 1, $RowOffset, $Column - 1, $ColumnOffset) + + if ($ResizeCell) { + <# + Adding 1 to the image height and width ensures that when the + row and column are resized, the bottom right of the image lands + just inside the gray cell borders at the bottom right. + #> + $width = $widthFactor * ($Image.Width + 1) + $height = $heightFactor * ($Image.Height + 1) + $WorkSheet.Column($Column).Width = [Math]::Max($width, $WorkSheet.Column($Column).Width) + $WorkSheet.Row($Row).Height = [Math]::Max($height, $WorkSheet.Row($Row).Height) + } + } +} \ No newline at end of file diff --git a/Examples/AddImage/AddImage.ps1 b/Examples/AddImage/AddImage.ps1 new file mode 100644 index 00000000..4d38e09f --- /dev/null +++ b/Examples/AddImage/AddImage.ps1 @@ -0,0 +1,39 @@ +if ($IsWindows -eq $false) { + throw "This only works on Windows and won't run on $([environment]::OSVersion)" +} + +Add-Type -AssemblyName System.Drawing + +. $PSScriptRoot\Add-ExcelImage.ps1 + +$data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + +$path = "$PSScriptRoot/Add-Picture-test.xlsx" +Remove-Item $path -ErrorAction SilentlyContinue + + +try { + $octocat = "$PSScriptRoot/Octocat.jpg" + $image = [System.Drawing.Image]::FromFile($octocat) + $xlpkg = $data | Export-Excel -Path $path -PassThru + $xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell +} +finally { + if ($image) { + $image.Dispose() + } + if ($xlpkg) { + Close-ExcelPackage -ExcelPackage $xlpkg -Show + } +} diff --git a/Examples/AddImage/Octocat.jpg b/Examples/AddImage/Octocat.jpg new file mode 100644 index 00000000..a48c3499 Binary files /dev/null and b/Examples/AddImage/Octocat.jpg differ diff --git a/Examples/AddImage/README.md b/Examples/AddImage/README.md new file mode 100644 index 00000000..4d711417 --- /dev/null +++ b/Examples/AddImage/README.md @@ -0,0 +1,33 @@ +# Add-ExcelImage Example + +Adding pictures to an Excel worksheet is possible by calling the `AddPicture(name, image)` +method on the `Drawings` property of an `ExcelWorksheet` object. + +The `Add-ExcelImage` example here demonstrates how to add a picture at a given +cell location, and optionally resize the row and column to fit the image. + +## Running the example + +To try this example, run the script `AddImage.ps1`. The `Add-ExcelImage` +function will be dot-sourced, and an Excel document will be created in the same +folder with a sample data set. The Octocat image will then be embedded into +Sheet1. + +The creation of the Excel document and the `System.Drawing.Image` object +representing Octocat are properly disposed within a `finally` block to ensure +that the resources are released, even if an error occurs in the `try` block. + +## Note about column and row sizing + +Care has been taken in this example to get the image placement to be just inside +the cell border, and if the `-ResizeCell` switch is present, the height and width +of the row and column will be increased, if needed, so that the bottom right of +the image also lands just inside the cell border. + +The Excel row and column sizes are measured in "point" units rather than pixels, +and a fixed multiplication factor is used to convert the size of the image in +pixels, to the corresponding height and width values in Excel. + +It's possible that different DPI or text scaling options could result in +imperfect column and row sizing and if a better strategy is found for converting +the image dimensions to column and row sizes, this example will be updated. diff --git a/Examples/AddWorkSheet/AddMultiWorkSheet.ps1 b/Examples/AddWorkSheet/AddMultiWorkSheet.ps1 new file mode 100644 index 00000000..4a15bb3a --- /dev/null +++ b/Examples/AddWorkSheet/AddMultiWorkSheet.ps1 @@ -0,0 +1,15 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Put some simple data in a worksheet and Get an excel package object to represent the file +1..5 | Export-Excel $xlSourcefile -WorksheetName 'Tab1' -AutoSize -AutoFilter + +#Add another tab. Replace the $TabData2 with your data +1..10 | Export-Excel $xlSourcefile -WorksheetName 'Tab 2' -AutoSize -AutoFilter + +#Add another tab. Replace the $TabData3 with your data +1..15 | Export-Excel $xlSourcefile -WorksheetName 'Tab 3' -AutoSize -AutoFilter -Show diff --git a/Examples/AddWorkSheet/AddWorkSheet.ps1 b/Examples/AddWorkSheet/AddWorkSheet.ps1 new file mode 100644 index 00000000..f22c9461 --- /dev/null +++ b/Examples/AddWorkSheet/AddWorkSheet.ps1 @@ -0,0 +1,13 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Put some simple data in a worksheet and Get an excel package object to represent the file +$excel = 1..10 | Export-Excel $xlSourcefile -PassThru +#Add a new worksheet named 'NewSheet' and copying the sheet that was just made (Sheet1) to the new sheet +Add-Worksheet -ExcelPackage $excel -WorkSheetname "NewSheet" -CopySource $excel.Workbook.Worksheets["Sheet1"] +#Save and open in Excel +Close-ExcelPackage -ExcelPackage $excel -Show diff --git a/Examples/Charts/ChartAndTrendlines.ps1 b/Examples/Charts/ChartAndTrendlines.ps1 new file mode 100644 index 00000000..f80b4ccb --- /dev/null +++ b/Examples/Charts/ChartAndTrendlines.ps1 @@ -0,0 +1,24 @@ +# Creates a worksheet, addes a chart and then a Linear trendline +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screws,60 +South,lemon,48 +South,apple,71 +East,screwdriver,70 +East,kiwi,32 +West,screwdriver,1 +South,melon,21 +East,apple,79 +South,apple,68 +South,avocado,73 +"@ + +$cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine Linear +$data | Export-Excel $xlSourcefile -ExcelChartDefinition $cd -AutoNameRange -Show diff --git a/Examples/Charts/ChartDataSeparatePage.ps1 b/Examples/Charts/ChartDataSeparatePage.ps1 new file mode 100644 index 00000000..889e5351 --- /dev/null +++ b/Examples/Charts/ChartDataSeparatePage.ps1 @@ -0,0 +1,35 @@ +$data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + +$xlfile = "$PSScriptRoot\spike.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$xlpkg = $data | Export-Excel $xlfile -WorksheetName Data -AutoNameRange -PassThru + +$null = Add-Worksheet -ExcelPackage $xlpkg -WorksheetName Summary -Activate + +$params = @{ + Worksheet = $xlpkg.Summary + Title = "Sales by Region" + ChartType = 'ColumnClustered' + + # XRange = "Data!A2:A10" + # YRange = "Data!C2:C10" + + XRange = 'Data!Region' + YRange = 'Data!Units' +} + +Add-ExcelChart @params + +Close-ExcelPackage $xlpkg -Show diff --git a/Examples/Charts/MultiSeries.ps1 b/Examples/Charts/MultiSeries.ps1 index f98a0a4c..1f980a90 100644 --- a/Examples/Charts/MultiSeries.ps1 +++ b/Examples/Charts/MultiSeries.ps1 @@ -1,12 +1,17 @@ -rm temp.xlsx -ErrorAction Ignore +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -$data = invoke-sum (ps) company handles,pm,VirtualMemorySize +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore -$c = New-ExcelChart -Title Stats ` +$data = Invoke-Sum -data (Get-Process) -dimension Company -measure Handles, PM, VirtualMemorySize + +$c = New-ExcelChartDefinition -Title "ProcessStats" ` -ChartType LineMarkersStacked ` - -Header "Stuff" ` - -XRange "Processes[Company]" ` - -YRange "Processes[PM]","Processes[VirtualMemorySize]" - -$data | - Export-Excel temp.xlsx -AutoSize -TableName Processes -Show -ExcelChartDefinition $c + -XRange "Processes[Name]" ` + -YRange "Processes[PM]","Processes[VirtualMemorySize]" ` + -SeriesHeader "PM","VM" + +$data | + Export-Excel -Path $xlSourcefile -AutoSize -TableName Processes -ExcelChartDefinition $c -Show diff --git a/Examples/Charts/MultiSeries1.ps1 b/Examples/Charts/MultiSeries1.ps1 index e3732135..46f78daf 100644 --- a/Examples/Charts/MultiSeries1.ps1 +++ b/Examples/Charts/MultiSeries1.ps1 @@ -1,16 +1,22 @@ -rm temp.xlsx -ErrorAction Ignore +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore $data = @" A,B,C,Date 2,1,1,2016-03-29 5,10,1,2016-03-29 -"@ | ConvertFrom-Csv +"@ -$c = New-ExcelChart -Title Impressions ` - -ChartType Line -Header "Something" ` +$c = New-ExcelChartDefinition -Title Impressions ` + -ChartType Line ` -XRange "Impressions[Date]" ` -YRange @("Impressions[B]","Impressions[A]") ` - -SeriesHeader 'B data','A data' + -SeriesHeader 'B data','A data' ` + -Row 0 -Column 0 -$data | - Export-Excel temp.xlsx -AutoSize -TableName Impressions -Show -ExcelChartDefinition $c \ No newline at end of file +$data | ConvertFrom-Csv | Export-Excel -path $xlSourcefile -AutoSize -TableName Impressions +Export-Excel -path $xlSourcefile -worksheetName chartPage -ExcelChartDefinition $c -show diff --git a/Examples/Charts/MultipleCharts.ps1 b/Examples/Charts/MultipleCharts.ps1 index 45ac050c..10410019 100644 --- a/Examples/Charts/MultipleCharts.ps1 +++ b/Examples/Charts/MultipleCharts.ps1 @@ -1,19 +1,22 @@ -rm *.xlsx +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore $data = @" ID,Product,Quantity,Price,Total 12001,Nails,37,3.99,147.63 12002,Hammer,5,12.10,60.5 12003,Saw,12,15.37,184.44 -12010,Drill,20,8,160 +12010,Drill,20,8,160 12011,Crowbar,7,23.48,164.36 -"@ | ConvertFrom-Csv - -$xRange = "Product" +"@ -$yRange="Price"; $c1 = New-ExcelChart -YRange $yRange -XRange $xRange -Title $yRange -Height 225 -$yRange="Total"; $c2 = New-ExcelChart -YRange $yRange -XRange $xRange -Title $yRange -Row 9 -Column 15 -Height 225 -$yRange="Quantity"; $c3 = New-ExcelChart -YRange $yRange -XRange $xRange -Title $yRange -Row 15 -Height 225 +$c1 = New-ExcelChartDefinition -YRange "Price" -XRange "Product" -Title "Item price" -NoLegend -Height 225 +$c2 = New-ExcelChartDefinition -YRange "Total "-XRange "Product" -Title "Total sales" -NoLegend -Height 225 -Row 9 -Column 15 +$c3 = New-ExcelChartDefinition -YRange "Quantity"-XRange "Product" -Title "Sales volume" -NoLegend -Height 225 -Row 15 -$data | - Export-Excel -ExcelChartDefinition $c1,$c2,$c3 Tools.xlsx -Show -AutoFilter -AutoNameRange -AutoSize +$data | ConvertFrom-Csv | + Export-Excel -Path $xlSourcefile -AutoFilter -AutoNameRange -AutoSize -ExcelChartDefinition $c1,$c2,$c3 -Show \ No newline at end of file diff --git a/Examples/Charts/Multiplecharts.png b/Examples/Charts/Multiplecharts.png new file mode 100644 index 00000000..d97a211b Binary files /dev/null and b/Examples/Charts/Multiplecharts.png differ diff --git a/Examples/Charts/NumberOfVisitors.ps1 b/Examples/Charts/NumberOfVisitors.ps1 new file mode 100644 index 00000000..806af8d1 --- /dev/null +++ b/Examples/Charts/NumberOfVisitors.ps1 @@ -0,0 +1,31 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Week, TotalVisitors +1,11916 +2,11665 +3,13901 +4,15444 +5,21592 +6,15057 +7,26187 +8,20662 +9,28935 +10,32443 +"@ + +$cd = New-ExcelChartDefinition ` + -XRange Week ` + -YRange TotalVisitors ` + -Title "No. Of Visitors" ` + -ChartType ColumnClustered ` + -NoLegend ` + -ChartTrendLine Linear + +$data | Export-Excel $xlSourcefile -Show -AutoNameRange -AutoSize -TableName Visitors -ExcelChartDefinition $cd + diff --git a/Examples/Charts/Tools.xlsx b/Examples/Charts/Tools.xlsx deleted file mode 100644 index 714f93c1..00000000 Binary files a/Examples/Charts/Tools.xlsx and /dev/null differ diff --git a/Examples/Charts/plot.ps1 b/Examples/Charts/plot.ps1 index f4c367ae..afcb7a94 100644 --- a/Examples/Charts/plot.ps1 +++ b/Examples/Charts/plot.ps1 @@ -1,3 +1,5 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + function plot { param( $f, @@ -7,20 +9,22 @@ function plot { $minx=[math]::Round($minx,1) $maxx=[math]::Round($maxx,1) - - $file = 'C:\temp\plot.xlsx' - rm $file -ErrorAction Ignore - $c = New-ExcelChart -XRange X -YRange Y -ChartType Line -NoLegend -Title Plot -Column 2 -ColumnOffSetPixels 35 - + #Get rid of pre-exisiting sheet + $xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" + Write-Verbose -Verbose -Message "Save location: $xlSourcefile" + Remove-Item $xlSourcefile -ErrorAction Ignore + + # $c = New-ExcelChart -XRange X -YRange Y -ChartType Line -NoLegend -Title Plot -Column 2 -ColumnOffSetPixels 35 + $(for ($i = $minx; $i -lt $maxx-.1; $i+=.1) { [pscustomobject]@{ X=$i.ToString("N1") Y=(&$f $i) } - }) | Export-Excel $file -Show -AutoNameRange -ExcelChartDefinition $c + }) | Export-Excel $xlSourcefile -Show -AutoNameRange -LineChart -NoLegend #-ExcelChartDefinition $c } function pi {[math]::pi} -plot {[math]::Tan($args[0])} (pi) (3*(pi)/2-.01) \ No newline at end of file +plot -f {[math]::Tan($args[0])} -minx (pi) -maxx (3*(pi)/2-.01) \ No newline at end of file diff --git a/Examples/CommunityContributions/MultipleWorksheets.ps1 b/Examples/CommunityContributions/MultipleWorksheets.ps1 new file mode 100644 index 00000000..c7b2f6bb --- /dev/null +++ b/Examples/CommunityContributions/MultipleWorksheets.ps1 @@ -0,0 +1,27 @@ +<# + To see this written up with example screenshots, head over to the IT Splat blog + URL: http://bit.ly/2SxieeM +#> + +## Create an Excel file with multiple worksheets +# Get a list of processes on the system +$processes = Get-Process | Sort-Object -Property ProcessName | Group-Object -Property ProcessName | Where-Object {$_.Count -gt 2} + +# Export the processes to Excel, each process on its own sheet +$processes | ForEach-Object { $_.Group | Export-Excel -Path MultiSheetExample.xlsx -WorksheetName $_.Name -AutoSize -AutoFilter } + +# Show the completed file +Invoke-Item .\MultiSheetExample.xlsx + +## Add an additional sheet to the new workbook +# Use Open-ExcelPackage to open the workbook +$excelPackage = Open-ExcelPackage -Path .\MultiSheetExample.xlsx + +# Create a new worksheet and give it a name, set MoveToStart to make it the first sheet +$ws = Add-Worksheet -ExcelPackage $excelPackage -WorksheetName 'All Services' -MoveToStart + +# Get all the running services on the system +Get-Service | Export-Excel -ExcelPackage $excelPackage -WorksheetName $ws -AutoSize -AutoFilter + +# Close the package and show the final result +Close-ExcelPackage -ExcelPackage $excelPackage -Show diff --git a/Examples/ConditionalFormatting/CodeGenExamples.ps1 b/Examples/ConditionalFormatting/CodeGenExamples.ps1 index d81854a5..2927d4ad 100644 --- a/Examples/ConditionalFormatting/CodeGenExamples.ps1 +++ b/Examples/ConditionalFormatting/CodeGenExamples.ps1 @@ -1,9 +1,9 @@ -echo Last7Days LastMonth LastWeek NextMonth NextWeek ThisMonth ThisWeek Today Tomorrow Yesterday | - % { +"Last7Days", "LastMonth", "LastWeek", "NextMonth", "NextWeek", "ThisMonth", "ThisWeek", "Today", "Tomorrow", "Yesterday" | + Foreach-Object { $text = @" `$f = ".\testExport.xlsx" -rm `$f -ErrorAction Ignore +remove-item `$f -ErrorAction Ignore .\GenDates.ps1 | Export-Excel `$f -Show -AutoSize -ConditionalText `$( diff --git a/Examples/ConditionalFormatting/ConditionalFormattingIcontSetOnlyIcon.ps1 b/Examples/ConditionalFormatting/ConditionalFormattingIcontSetOnlyIcon.ps1 new file mode 100644 index 00000000..619d8641 --- /dev/null +++ b/Examples/ConditionalFormatting/ConditionalFormattingIcontSetOnlyIcon.ps1 @@ -0,0 +1,22 @@ +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$data = ConvertFrom-Csv @" +Region,State,Other,Units,Price,InStock +West,Texas,1,927,923.71,1 +North,Tennessee,3,466,770.67,0 +East,Florida,0,1520,458.68,1 +East,Maine,1,1828,661.24,0 +West,Virginia,1,465,053.58,1 +North,Missouri,1,436,235.67,1 +South,Kansas,0,214,992.47,1 +North,North Dakota,1,789,640.72,0 +South,Delaware,-1,712,508.55,1 +"@ + +$xlfile = "$PSScriptRoot\test.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly +$cfi2 = New-ConditionalFormattingIconSet -Range F:F -ConditionalFormat ThreeIconSet -IconType Symbols2 -ShowIconOnly + +$data | Export-Excel $xlfile -AutoSize -ConditionalFormat $cfi1, $cfi2 -Show \ No newline at end of file diff --git a/Examples/ConditionalFormatting/ConditionalText.ps1 b/Examples/ConditionalFormatting/ConditionalText.ps1 index 76d0cfaf..da10b1e6 100644 --- a/Examples/ConditionalFormatting/ConditionalText.ps1 +++ b/Examples/ConditionalFormatting/ConditionalText.ps1 @@ -1,11 +1,15 @@ -$file = ".\conditionalTextFormatting.xlsx" -rm $file -ErrorAction Ignore +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -Get-Service | - Select Status, Name, DisplayName, ServiceName | - Export-Excel $file -Show -AutoSize -AutoFilter -ConditionalText $( - New-ConditionalText stop - New-ConditionalText runn darkblue cyan - New-ConditionalText -ConditionalType EndsWith svc wheat green - New-ConditionalText -ConditionalType BeginsWith windows darkgreen wheat +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +Get-Service | + Select-Object Status, Name, DisplayName, ServiceName | + Export-Excel $xlSourcefile -Show -AutoSize -AutoFilter -ConditionalText $( + New-ConditionalText stop #Stop is the condition value, the rule is defaults to 'Contains text' and the default Colors are used + New-ConditionalText runn darkblue cyan #runn is the condition value, the rule is defaults to 'Contains text'; the foregroundColur is darkblue and the background is cyan + New-ConditionalText -ConditionalType EndsWith svc wheat green #the rule here is 'Ends with' and the value is 'svc' the forground is wheat and the background dark green + New-ConditionalText -ConditionalType BeginsWith windows darkgreen wheat #this is 'Begins with "Windows"' the forground is dark green and the background wheat ) \ No newline at end of file diff --git a/Examples/ConditionalFormatting/ContainsBlanks.ps1 b/Examples/ConditionalFormatting/ContainsBlanks.ps1 index bc6f7440..0590ac9d 100644 --- a/Examples/ConditionalFormatting/ContainsBlanks.ps1 +++ b/Examples/ConditionalFormatting/ContainsBlanks.ps1 @@ -1,15 +1,21 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Define a "Contains blanks" rule. No format is specified so it default to dark-red text on light-pink background. $ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks $data = $( - New-PSItem a b c (echo p1 p2 p3) - New-PSItem + New-PSItem a b c @('p1', 'p2', 'p3') + New-PSItem New-PSItem d e f - New-PSItem - New-PSItem - New-PSItem g h i + New-PSItem + New-PSItem + New-PSItem g h i ) -$file ="c:\temp\testblanks.xlsx" +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore -rm $file -ErrorAction Ignore -$data | Export-Excel $file -show -ConditionalText $ContainsBlanks \ No newline at end of file +#use the conditional format definition created above +$data | Export-Excel $xlSourcefile -show -ConditionalText $ContainsBlanks \ No newline at end of file diff --git a/Examples/ConditionalFormatting/Databar.ps1 b/Examples/ConditionalFormatting/Databar.ps1 new file mode 100644 index 00000000..12120509 --- /dev/null +++ b/Examples/ConditionalFormatting/Databar.ps1 @@ -0,0 +1,34 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Export processes, and get an ExcelPackage object representing the file. +$excel = Get-Process | + Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | + Export-Excel -Path $xlSourcefile -ClearSheet -WorkSheetname "Processes" -PassThru + +$sheet = $excel.Workbook.Worksheets["Processes"] + +#Apply fixed formatting to columns. -NFormat is an alias for numberformat +$sheet.Column(1) | Set-ExcelRange -Bold -AutoFit +$sheet.Column(2) | Set-ExcelRange -Width 29 -WrapText +$sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NFormat "#,###" + +Set-ExcelRange -Range $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" + +Set-ExcelRange -Range $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold +#In Set-ExcelRange "-Address" is an alias for "-Range" +Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center + +#Create a Red Data-bar for the values in Column D +Add-ConditionalFormatting -Worksheet $sheet -Address "D2:D1048576" -DataBarColor Red +# Conditional formatting applies to "Addreses" aliases allow either "Range" or "Address" to be used in Set-ExcelRange or Add-Conditional formatting. +Add-ConditionalFormatting -Worksheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red + +foreach ($c in 5..9) {Set-ExcelRange -Address $sheet.Column($c) -AutoFit } + +#Create a pivot and save the file. +Export-Excel -ExcelPackage $excel -WorkSheetname "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show \ No newline at end of file diff --git a/Examples/ConditionalFormatting/FormatCalculations.ps1 b/Examples/ConditionalFormatting/FormatCalculations.ps1 index 47e5fa8e..a275a5fa 100644 --- a/Examples/ConditionalFormatting/FormatCalculations.ps1 +++ b/Examples/ConditionalFormatting/FormatCalculations.ps1 @@ -1,11 +1,14 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore $data = $( - New-PSItem North 111 (echo Region Amount ) - New-PSItem East 111 + New-PSItem North 111 @( 'Region', 'Amount' ) + New-PSItem East 111 New-PSItem West 122 New-PSItem South 200 @@ -14,13 +17,15 @@ $data = $( New-PSItem SouthWest 136 New-PSItem South 127 - New-PSItem NorthByNory 100 - New-PSItem NothEast 110 - New-PSItem Westerly 120 + New-PSItem NorthByNory 100 + New-PSItem NothEast 110 + New-PSItem Westerly 120 New-PSItem SouthWest 118 -) +) +# in this example instead of doing $variable = New-Conditional text .... ; Export-excel -ConditionalText $variable +# the syntax is used is Export-excel -ConditionalText (New-Conditional text ) -#$data | Export-Excel $f -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType AboveAverage) -$data | Export-Excel $f -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType BelowAverage) -#$data | Export-Excel $f -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType TopPercent) +#$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType AboveAverage) +$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType BelowAverage) +#$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType TopPercent) diff --git a/Examples/ConditionalFormatting/GenDates.ps1 b/Examples/ConditionalFormatting/GenDates.ps1 index 5a9a9941..e5e77d9e 100644 --- a/Examples/ConditionalFormatting/GenDates.ps1 +++ b/Examples/ConditionalFormatting/GenDates.ps1 @@ -1,6 +1,8 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + function Get-DateOffset { param($days=0) - + (Get-Date).AddDays($days).ToShortDateString() } @@ -8,7 +10,7 @@ function Get-Number { Get-Random -Minimum 10 -Maximum 100 } -New-PSItem (Get-DateOffset -7) (Get-Number) 'LastWeek,Last7Days,ThisMonth' (echo Date Amount Label) +New-PSItem (Get-DateOffset -7) (Get-Number) 'LastWeek,Last7Days,ThisMonth' @('Date', 'Amount', 'Label') New-PSItem (Get-DateOffset) (Get-Number) 'Today,ThisMonth,ThisWeek' New-PSItem (Get-DateOffset -30) (Get-Number) LastMonth New-PSItem (Get-DateOffset -1) (Get-Number) 'Yesterday,ThisMonth,ThisWeek' diff --git a/Examples/ConditionalFormatting/GetConditionalFormatting.ps1 b/Examples/ConditionalFormatting/GetConditionalFormatting.ps1 new file mode 100644 index 00000000..e123fc80 --- /dev/null +++ b/Examples/ConditionalFormatting/GetConditionalFormatting.ps1 @@ -0,0 +1,21 @@ +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return} + +# This example is using Excel generated by Highlight-DiffCells.ps1 +# The displayed rule should be the same as in the PS script + +function Get-ConditionalFormatting { + param ( + [string] $xlSourcefile + ) + $excel = Open-ExcelPackage -Path $xlSourcefile + + $excel.Workbook.Worksheets | ForEach-Object { + $wsNme = $_.Name + $_.ConditionalFormatting | ForEach-Object { + "Add-ConditionalFormatting -Worksheet `$excel[""$wsNme""] -Range '$($_.Address)' -ConditionValue '=$($_.Formula)' -RuleType $($_.Type) " + } + } +} + +$xlSourcefile = "$PSScriptRoot\GetConditionalFormatting.xlsx" +Get-ConditionalFormatting -xlSourcefile $xlSourcefile \ No newline at end of file diff --git a/Examples/ConditionalFormatting/GetConditionalFormatting.xlsx b/Examples/ConditionalFormatting/GetConditionalFormatting.xlsx new file mode 100644 index 00000000..bfa1cba7 Binary files /dev/null and b/Examples/ConditionalFormatting/GetConditionalFormatting.xlsx differ diff --git a/Examples/ConditionalFormatting/GetProcess.ps1 b/Examples/ConditionalFormatting/GetProcess.ps1 index 2a1bcad7..036c85fa 100644 --- a/Examples/ConditionalFormatting/GetProcess.ps1 +++ b/Examples/ConditionalFormatting/GetProcess.ps1 @@ -1,8 +1,15 @@ -rm .\testExport.xlsx -ErrorAction Ignore +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -ps | where Company | select Company, Name, PM, Handles, *mem* | +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore - Export-Excel .\testExport.xlsx -Show -AutoSize -AutoNameRange ` +Get-Process | Where-Object Company | Select-Object Company, Name, PM, Handles, *mem* | + +#This example creates a 3 Icon set for the values in the "PM column, and Highlights company names (anywhere in the data) with different colors + + Export-Excel -Path $xlSourcefile -Show -AutoSize -AutoNameRange ` -ConditionalFormat $( New-ConditionalFormattingIconSet -Range "C:C" ` -ConditionalFormat ThreeIconSet -IconType Arrows diff --git a/Examples/ConditionalFormatting/Highlight-DiffCells.ps1 b/Examples/ConditionalFormatting/Highlight-DiffCells.ps1 new file mode 100644 index 00000000..29f90a6e --- /dev/null +++ b/Examples/ConditionalFormatting/Highlight-DiffCells.ps1 @@ -0,0 +1,26 @@ +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" + +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Region,State,Units2021,Units2022 +West,Texas,927,925 +North,Tennessee,466,466 +East,Florida,520,458 +East,Maine,828,661 +West,Virginia,465,465 +North,Missouri,436,235 +South,Kansas,214,214 +North,North Dakota,789,640 +South,Delaware,712,508 +"@ + +$excel = $data | Export-Excel $xlSourcefile -AutoSize -PassThru + +Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "C2:D10" -ConditionValue '=$C2=$D2' -RuleType Expression -BackgroundColor ([System.Drawing.Color]::Thistle) -Bold +Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "A2:D10" -ConditionValue '=$C2=$D2' -RuleType Expression -BackgroundColor ([System.Drawing.Color]::LavenderBlush) + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/ConditionalFormatting/Highlight-Last7Days.ps1 b/Examples/ConditionalFormatting/Highlight-Last7Days.ps1 index c414312e..d8315fee 100644 --- a/Examples/ConditionalFormatting/Highlight-Last7Days.ps1 +++ b/Examples/ConditionalFormatting/Highlight-Last7Days.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType Last7Days ) diff --git a/Examples/ConditionalFormatting/Highlight-LastMonth.ps1 b/Examples/ConditionalFormatting/Highlight-LastMonth.ps1 index c9405f38..1147bdf5 100644 --- a/Examples/ConditionalFormatting/Highlight-LastMonth.ps1 +++ b/Examples/ConditionalFormatting/Highlight-LastMonth.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType LastMonth ) diff --git a/Examples/ConditionalFormatting/Highlight-LastWeek.ps1 b/Examples/ConditionalFormatting/Highlight-LastWeek.ps1 index 112fdab3..c730304d 100644 --- a/Examples/ConditionalFormatting/Highlight-LastWeek.ps1 +++ b/Examples/ConditionalFormatting/Highlight-LastWeek.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType LastWeek ) diff --git a/Examples/ConditionalFormatting/Highlight-NextMonth.ps1 b/Examples/ConditionalFormatting/Highlight-NextMonth.ps1 index 1872ec83..25e1db3e 100644 --- a/Examples/ConditionalFormatting/Highlight-NextMonth.ps1 +++ b/Examples/ConditionalFormatting/Highlight-NextMonth.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType NextMonth ) diff --git a/Examples/ConditionalFormatting/Highlight-NextWeek.ps1 b/Examples/ConditionalFormatting/Highlight-NextWeek.ps1 index a52d123b..88cf7cd2 100644 --- a/Examples/ConditionalFormatting/Highlight-NextWeek.ps1 +++ b/Examples/ConditionalFormatting/Highlight-NextWeek.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType NextWeek ) diff --git a/Examples/ConditionalFormatting/Highlight-ThisMonth.ps1 b/Examples/ConditionalFormatting/Highlight-ThisMonth.ps1 index ec7beaea..2ae7079d 100644 --- a/Examples/ConditionalFormatting/Highlight-ThisMonth.ps1 +++ b/Examples/ConditionalFormatting/Highlight-ThisMonth.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType ThisMonth ) diff --git a/Examples/ConditionalFormatting/Highlight-ThisWeek.ps1 b/Examples/ConditionalFormatting/Highlight-ThisWeek.ps1 index 36fca344..37ada655 100644 --- a/Examples/ConditionalFormatting/Highlight-ThisWeek.ps1 +++ b/Examples/ConditionalFormatting/Highlight-ThisWeek.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType ThisWeek ) diff --git a/Examples/ConditionalFormatting/Highlight-Today.ps1 b/Examples/ConditionalFormatting/Highlight-Today.ps1 index 0d12f942..c0095788 100644 --- a/Examples/ConditionalFormatting/Highlight-Today.ps1 +++ b/Examples/ConditionalFormatting/Highlight-Today.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType Today ) diff --git a/Examples/ConditionalFormatting/Highlight-Tomorrow.ps1 b/Examples/ConditionalFormatting/Highlight-Tomorrow.ps1 index 60292ade..6d9ccea7 100644 --- a/Examples/ConditionalFormatting/Highlight-Tomorrow.ps1 +++ b/Examples/ConditionalFormatting/Highlight-Tomorrow.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType Tomorrow ) diff --git a/Examples/ConditionalFormatting/Highlight-Yesterday.ps1 b/Examples/ConditionalFormatting/Highlight-Yesterday.ps1 index f5f0816e..f13059cb 100644 --- a/Examples/ConditionalFormatting/Highlight-Yesterday.ps1 +++ b/Examples/ConditionalFormatting/Highlight-Yesterday.ps1 @@ -1,8 +1,11 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore .\GenDates.ps1 | - Export-Excel $f -Show -AutoSize -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( New-ConditionalText -ConditionalType Yesterday ) diff --git a/Examples/ConditionalFormatting/HighlightDuplicates.ps1 b/Examples/ConditionalFormatting/HighlightDuplicates.ps1 index b21784a4..8d1629f5 100644 --- a/Examples/ConditionalFormatting/HighlightDuplicates.ps1 +++ b/Examples/ConditionalFormatting/HighlightDuplicates.ps1 @@ -1,23 +1,26 @@ -$f = ".\testExport.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore $data = $( - New-PSItem North 111 (echo Region Amount ) - New-PSItem East 11 - New-PSItem West 12 - New-PSItem South 1000 + New-PSItem North 111 @('Region', 'Amount' ) + New-PSItem East 11 + New-PSItem West 12 + New-PSItem South 1000 - New-PSItem NorthEast 10 - New-PSItem SouthEast 14 - New-PSItem SouthWest 13 - New-PSItem South 12 + New-PSItem NorthEast 10 + New-PSItem SouthEast 14 + New-PSItem SouthWest 13 + New-PSItem South 12 - New-PSItem NorthByNory 100 - New-PSItem NothEast 110 - New-PSItem Westerly 120 - New-PSItem SouthWest 11 -) + New-PSItem NorthByNory 100 + New-PSItem NothEast 110 + New-PSItem Westerly 120 + New-PSItem SouthWest 11 +) -$data | Export-Excel $f -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType DuplicateValues) \ No newline at end of file +$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType DuplicateValues) \ No newline at end of file diff --git a/Examples/ConditionalFormatting/MonthlyTemperatuesDatabar.ps1 b/Examples/ConditionalFormatting/MonthlyTemperatuesDatabar.ps1 new file mode 100644 index 00000000..a2606bb6 --- /dev/null +++ b/Examples/ConditionalFormatting/MonthlyTemperatuesDatabar.ps1 @@ -0,0 +1,28 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$excel = @" +Month,New York City,Austin Texas,Portland Oregon +Jan,39,61,46 +Feb,42,65,51 +Mar,50,73,56 +Apr,62,80,61 +May,72,86,67 +Jun,80,92,73 +Jul,85,95,80 +Aug,84,96,80 +Sep,76,90,75 +Oct,65,82,63 +Nov,54,71,52 +Dec,44,63,46 +"@ | ConvertFrom-csv | + Export-Excel -Path $xlSourcefile -WorkSheetname Sheet1 -AutoNameRange -AutoSize -Title "Monthly Temperatures" -PassThru + +$sheet = $excel.Workbook.Worksheets["Sheet1"] +Add-ConditionalFormatting -Worksheet $sheet -Range "B1:D14" -DataBarColor CornflowerBlue + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/ConditionalFormatting/RangeFormatting.ps1 b/Examples/ConditionalFormatting/RangeFormatting.ps1 index 4437aea0..2de17671 100644 --- a/Examples/ConditionalFormatting/RangeFormatting.ps1 +++ b/Examples/ConditionalFormatting/RangeFormatting.ps1 @@ -1,18 +1,21 @@ -ipmo ImportExcel -Force -$f = ".\testExport.xlsx" -rm $f -ErrorAction Ignore +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -function Get-DateOffset ($days=0) { +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +function Get-DateOffset ($days=0) { (Get-Date).AddDays($days).ToShortDateString() } $( - New-PSItem (Get-DateOffset -1) (Get-DateOffset 1) (echo Start End) - New-PSItem (Get-DateOffset) (Get-DateOffset 7) - New-PSItem (Get-DateOffset -10) (Get-DateOffset -1) -) | + New-PSItem (Get-DateOffset -1) (Get-DateOffset 1) @("Start", "End") + New-PSItem (Get-DateOffset) (Get-DateOffset 7) + New-PSItem (Get-DateOffset -10) (Get-DateOffset -1) +) | - Export-Excel $f -Show -AutoSize -AutoNameRange -ConditionalText $( + Export-Excel $xlSourcefile -Show -AutoSize -AutoNameRange -ConditionalText $( New-ConditionalText -Range Start -ConditionalType Yesterday -ConditionalTextColor Red New-ConditionalText -Range End -ConditionalType Yesterday -BackgroundColor Blue -ConditionalTextColor Red ) \ No newline at end of file diff --git a/Examples/ConditionalFormatting/SalesReportWithDatabar.ps1 b/Examples/ConditionalFormatting/SalesReportWithDatabar.ps1 new file mode 100644 index 00000000..ef94be08 --- /dev/null +++ b/Examples/ConditionalFormatting/SalesReportWithDatabar.ps1 @@ -0,0 +1,25 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$excel = @" +Month,Sales +Jan,1277 +Feb,1003 +Mar,1105 +Apr,952 +May,770 +Jun,621 +"@ | ConvertFrom-csv | + Export-Excel -Path $xlSourcefile -WorkSheetname Sheet1 -AutoNameRange -PassThru + +$sheet = $excel.Workbook.Worksheets["Sheet1"] +Add-ConditionalFormatting -Worksheet $sheet -Range "B1:B7" -DataBarColor LawnGreen + +Set-ExcelRange -Address $sheet.Cells["A8"] -Value "Total" +Set-ExcelRange -Address $sheet.Cells["B8"] -Formula "=Sum(Sales)" + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/ConditionalFormatting/TextComparisons.ps1 b/Examples/ConditionalFormatting/TextComparisons.ps1 index 78ccbb63..55837f2c 100644 --- a/Examples/ConditionalFormatting/TextComparisons.ps1 +++ b/Examples/ConditionalFormatting/TextComparisons.ps1 @@ -1,27 +1,29 @@ -cls + try {Import-Module ..\..\ImportExcel.psd1 -Force} catch {throw ; return} -ipmo ..\..\ImportExcel.psd1 -Force + $data = $( + New-PSItem 100 @('test', 'testx') + New-PSItem 200 + New-PSItem 300 + New-PSItem 400 + New-PSItem 500 + ) -$data = $( - New-PSItem 100 (echo test testx) - New-PSItem 200 - New-PSItem 300 - New-PSItem 400 - New-PSItem 500 -) + #Get rid of pre-exisiting sheet + $xlSourcefile1 = "$env:TEMP\ImportExcelExample1.xlsx" + $xlSourcefile2 = "$env:TEMP\ImportExcelExample2.xlsx" -$file1 = "tryComparison1.xlsx" -$file2 = "tryComparison2.xlsx" + Write-Verbose -Verbose -Message "Save location: $xlSourcefile1" + Write-Verbose -Verbose -Message "Save location: $xlSourcefile2" -rm $file1 -ErrorAction Ignore -rm $file2 -ErrorAction Ignore + Remove-Item $xlSourcefile1 -ErrorAction Ignore + Remove-Item $xlSourcefile2 -ErrorAction Ignore -$data | Export-Excel $file1 -Show -ConditionalText $( - New-ConditionalText -ConditionalType GreaterThan 300 - New-ConditionalText -ConditionalType LessThan 300 -BackgroundColor cyan -) + $data | Export-Excel $xlSourcefile1 -Show -ConditionalText $( + New-ConditionalText -ConditionalType GreaterThan 300 + New-ConditionalText -ConditionalType LessThan 300 -BackgroundColor cyan + ) -$data | Export-Excel $file2 -Show -ConditionalText $( - New-ConditionalText -ConditionalType GreaterThanOrEqual 275 - New-ConditionalText -ConditionalType LessThanOrEqual 250 -BackgroundColor cyan -) + $data | Export-Excel $xlSourcefile2 -Show -ConditionalText $( + New-ConditionalText -ConditionalType GreaterThanOrEqual 275 + New-ConditionalText -ConditionalType LessThanOrEqual 250 -BackgroundColor cyan + ) diff --git a/Examples/ConditionalFormatting/Top10-DataBar-TwoColorScale.ps1 b/Examples/ConditionalFormatting/Top10-DataBar-TwoColorScale.ps1 new file mode 100644 index 00000000..4680c1a2 --- /dev/null +++ b/Examples/ConditionalFormatting/Top10-DataBar-TwoColorScale.ps1 @@ -0,0 +1,37 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-csv @" +Store,January,February,March,April,May,June +store27,99511,64582,45216,48690,64921,54066 +store82,22275,23708,28223,26699,41388,31648 +store41,24683,22583,97947,31999,39092,41201 +store16,16568,48040,68589,20394,63202,26197 +store21,99353,23470,28398,21788,94101,88608 +store86,66662,83321,27489,92627,54084,24278 +store07,92692,53300,29284,39643,33556,53885 +store58,68875,83705,66635,81025,30207,75570 +store01,21292,82341,81339,12505,29516,41634 +store82,74047,93325,25002,40113,76278,45707 +"@ + +Export-Excel -InputObject $data -Path $xlSourcefile -TableName RawData -WorksheetName RawData +Export-Excel -InputObject $data -Path $xlSourcefile -TableName TopData -WorksheetName StoresTop10Sales +Export-Excel -InputObject $data -Path $xlSourcefile -TableName Databar -WorksheetName StoresSalesDataBar +Export-Excel -InputObject $data -Path $xlSourcefile -TableName TwoColorScale -WorksheetName StoresSalesTwoColorScale + +$xl = Open-ExcelPackage -Path $xlSourcefile + +Set-ExcelRange -Worksheet $xl.StoresTop10Sales -Range $xl.StoresTop10Sales.dimension.address -NumberFormat 'Currency' -AutoSize +Set-ExcelRange -Worksheet $xl.StoresSalesDataBar -Range $xl.StoresSalesDataBar.dimension.address -NumberFormat 'Currency' -AutoSize +Set-ExcelRange -Worksheet $xl.StoresSalesTwoColorScale -Range $xl.StoresSalesDataBar.dimension.address -NumberFormat 'Currency' -AutoSize + +Add-ConditionalFormatting -Worksheet $xl.StoresTop10Sales -Address $xl.StoresTop10Sales.dimension.address -RuleType Top -ForegroundColor white -BackgroundColor green -ConditionValue 10 +Add-ConditionalFormatting -Worksheet $xl.StoresSalesDataBar -Address $xl.StoresSalesDataBar.dimension.address -DataBarColor Red +Add-ConditionalFormatting -Worksheet $xl.StoresSalesTwoColorScale -Address $xl.StoresSalesDataBar.dimension.address -RuleType TwoColorScale + +Close-ExcelPackage $xl -Show \ No newline at end of file diff --git a/Examples/ConvertFrom/ConvertFrom.ps1 b/Examples/ConvertFrom/ConvertFrom.ps1 index d7451c37..8885a59c 100644 --- a/Examples/ConvertFrom/ConvertFrom.ps1 +++ b/Examples/ConvertFrom/ConvertFrom.ps1 @@ -1,3 +1,4 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} ConvertFrom-ExcelToSQLInsert People .\testSQLGen.xlsx diff --git a/Examples/CustomNumbers/ShortenNumbers.ps1 b/Examples/CustomNumbers/ShortenNumbers.ps1 new file mode 100644 index 00000000..1484d3ab --- /dev/null +++ b/Examples/CustomNumbers/ShortenNumbers.ps1 @@ -0,0 +1,23 @@ +# How to convert abbreviate or shorten long numbers in Excel + +Remove-Item .\custom.xlsx -ErrorAction SilentlyContinue + +$data = $( + 12000 + 1000 + 2000 + 3000 + 2400 + 3600 + 6000 + 13000 + 40000 + 400000 + 1000000 +) + +$excel = $data | Export-Excel .\custom.xlsx -PassThru + +Set-ExcelRange -Worksheet $excel.Sheet1 -Range "A:A" -NumberFormat '[>999999]#,,"M";#,"K"' + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/CustomReporting/CustomReport.ps1 b/Examples/CustomReporting/CustomReport.ps1 index 3aa3c6d0..b501819c 100644 --- a/Examples/CustomReporting/CustomReport.ps1 +++ b/Examples/CustomReporting/CustomReport.ps1 @@ -1,7 +1,9 @@ -Import-Module ..\..\ImportExcel.psd1 -Force +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -$f = ".\dashboard.xlsx" -Remove-Item $f -ErrorAction Ignore +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore $data = @" From,To,RDollars,RPercent,MDollars,MPercent,Revenue,Margin @@ -13,60 +15,60 @@ New York,San Francisco,3221000,.0629,1088000,.04,436,21 New York,Phoneix,2782000,.0723,467000,.10,674,33 "@ | ConvertFrom-Csv -$data | Export-Excel $f -AutoSize +$data | Export-Excel $xlSourcefile -AutoSize -$excel = Open-ExcelPackage $f +$excel = Open-ExcelPackage $xlSourcefile $sheet1 = $excel.Workbook.Worksheets["sheet1"] $sheet1.View.ShowGridLines = $false $sheet1.View.ShowHeaders = $false -Set-Format -Address $sheet1.Cells["C:C"] -NumberFormat "$#,##0" -WrapText -HorizontalAlignment Center -Set-Format -Address $sheet1.Cells["D:D"] -NumberFormat "#.#0%" -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["C:C"] -NumberFormat "$#,##0" -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["D:D"] -NumberFormat "#.#0%" -WrapText -HorizontalAlignment Center -Set-Format -Address $sheet1.Cells["E:E"] -NumberFormat "$#,##0" -WrapText -HorizontalAlignment Center -Set-Format -Address $sheet1.Cells["F:F"] -NumberFormat "#.#0%" -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["E:E"] -NumberFormat "$#,##0" -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["F:F"] -NumberFormat "#.#0%" -WrapText -HorizontalAlignment Center -Set-Format -Address $sheet1.Cells["G:H"] -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["G:H"] -WrapText -HorizontalAlignment Center ## Insert Rows/Columns $sheet1.InsertRow(1, 1) -foreach ($col in Write-Output 2 4 6 8 10 12 14) { +foreach ($col in @(2, 4, 6, 8, 10, 12, 14)) { $sheet1.InsertColumn($col, 1) $sheet1.Column($col).width = .75 } -Set-Format -Address $sheet1.Cells["E:E"] -Width 12 -Set-Format -Address $sheet1.Cells["I:I"] -Width 12 +Set-ExcelRange -Address $sheet1.Cells["E:E"] -Width 12 +Set-ExcelRange -Address $sheet1.Cells["I:I"] -Width 12 $BorderBottom = "Thick" $BorderColor = "Black" -Set-Format -Address $sheet1.Cells["A2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["A2"] -BorderBottom $BorderBottom -BorderColor $BorderColor -Set-Format -Address $sheet1.Cells["C2"] -BorderBottom $BorderBottom -BorderColor $BorderColor -Set-Format -Address $sheet1.Cells["E2:G2"] -BorderBottom $BorderBottom -BorderColor $BorderColor -Set-Format -Address $sheet1.Cells["I2:K2"] -BorderBottom $BorderBottom -BorderColor $BorderColor -Set-Format -Address $sheet1.Cells["M2:O2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["C2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["E2:G2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["I2:K2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["M2:O2"] -BorderBottom $BorderBottom -BorderColor $BorderColor -Set-Format -Address $sheet1.Cells["A2:C8"] -FontColor GrayText +Set-ExcelRange -Address $sheet1.Cells["A2:C8"] -FontColor Gray $HorizontalAlignment = "Center" -Set-Format -Address $sheet1.Cells["F1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Revenue -Set-Format -Address $sheet1.Cells["J1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Margin -Set-Format -Address $sheet1.Cells["N1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Passenger - -Set-Format -Address $sheet1.Cells["E2"] -Value '($)' -Set-Format -Address $sheet1.Cells["G2"] -Value '%' -Set-Format -Address $sheet1.Cells["I2"] -Value '($)' -Set-Format -Address $sheet1.Cells["K2"] -Value '%' - -Set-Format -Address $sheet1.Cells["C10"] -HorizontalAlignment Right -Bold -Value "Grand Total Calculation" -Set-Format -Address $sheet1.Cells["E10"] -Formula "=Sum(E3:E8)" -Bold -Set-Format -Address $sheet1.Cells["I10"] -Formula "=Sum(I3:I8)" -Bold -Set-Format -Address $sheet1.Cells["M10"] -Formula "=Sum(M3:M8)" -Bold -Set-Format -Address $sheet1.Cells["O10"] -Formula "=Sum(O3:O8)" -Bold - -Close-ExcelPackage $excel -Show \ No newline at end of file +Set-ExcelRange -Address $sheet1.Cells["F1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Revenue +Set-ExcelRange -Address $sheet1.Cells["J1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Margin +Set-ExcelRange -Address $sheet1.Cells["N1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Passenger + +Set-ExcelRange -Address $sheet1.Cells["E2"] -Value '($)' +Set-ExcelRange -Address $sheet1.Cells["G2"] -Value '%' +Set-ExcelRange -Address $sheet1.Cells["I2"] -Value '($)' +Set-ExcelRange -Address $sheet1.Cells["K2"] -Value '%' + +Set-ExcelRange -Address $sheet1.Cells["C10"] -HorizontalAlignment Right -Bold -Value "Grand Total Calculation" +Set-ExcelRange -Address $sheet1.Cells["E10"] -Formula "=Sum(E3:E8)" -Bold +Set-ExcelRange -Address $sheet1.Cells["I10"] -Formula "=Sum(I3:I8)" -Bold +Set-ExcelRange -Address $sheet1.Cells["M10"] -Formula "=Sum(M3:M8)" -Bold +Set-ExcelRange -Address $sheet1.Cells["O10"] -Formula "=Sum(O3:O8)" -Bold + +Close-ExcelPackage $excel -Show diff --git a/Examples/CustomReporting/dashboard.xlsx b/Examples/CustomReporting/dashboard.xlsx deleted file mode 100644 index 3da8e015..00000000 Binary files a/Examples/CustomReporting/dashboard.xlsx and /dev/null differ diff --git a/Examples/CustomizeExportExcel/Out-Excel.ps1 b/Examples/CustomizeExportExcel/Out-Excel.ps1 new file mode 100644 index 00000000..0845d24d --- /dev/null +++ b/Examples/CustomizeExportExcel/Out-Excel.ps1 @@ -0,0 +1,89 @@ +<# + This is an example on how to customize Export-Excel to your liking. + First select a name for your function, in ths example its "Out-Excel" you can even set the name to "Export-Excel". + You can customize the following things: + 1. To add parameters to the function define them in "param()", here I added "Preset1" and "Preset2". + The parameters need to be removed after use (see comments and code below). + 2. To remove parameters from the function add them to the list under "$_.Name -notmatch", I removed "Now". + 3. Add your custom code, here I defined what the Presets do: + Preset1 configure the TableStyle, name the table depending on WorksheetName and FreezeTopRow. + Preset2 will set AutoFilter and add the Title "Daily Report". + (see comments and code below). +#> +function Out-Excel { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param( + [switch] + ${Preset1}, + [switch] + ${Preset2} + ) + DynamicParam { + $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() + foreach ($P in (Get-Command -Name Export-Excel).Parameters.values.where( { $_.Name -notmatch 'Verbose|Debug|Action$|Variable$|Buffer$|Now' })) { + $paramDictionary.Add($P.Name, [System.Management.Automation.RuntimeDefinedParameter]::new( $P.Name, $P.ParameterType, $P.Attributes ) ) + } + return $paramDictionary + } + + begin { + try { + # Run you custom code here if it need to run before calling Export-Excel. + $PSBoundParameters['Now'] = $true + if ($Preset1) { + $PSBoundParameters['TableStyle'] = 'Medium7' + $PSBoundParameters['FreezeTopRow'] = $true + if ($PSBoundParameters['WorksheetName'] -and -not $PSBoundParameters['TableName']) { + $PSBoundParameters['TableName'] = $PSBoundParameters['WorksheetName'] + '_Table' + } + } + elseif ($Preset2) { + $PSBoundParameters['Title'] = 'Daily Report' + $PSBoundParameters['AutoFilter'] = $true + } + # Remove the extra params we added as Export-Excel will not know what to do with them: + $null = $PSBoundParameters.Remove('Preset1') + $null = $PSBoundParameters.Remove('Preset2') + + # The rest of the code was auto generated. + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Export-Excel', [System.Management.Automation.CommandTypes]::Function) + # You can add a pipe after @PSBoundParameters to manipulate the output. + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline() + $steppablePipeline.Begin($PSCmdlet) + } + catch { + throw + } + } + + process { + try { + $steppablePipeline.Process($_) + } + catch { + throw + } + } + + end { + try { + $steppablePipeline.End() + } + catch { + throw + } + } + <# + + .ForwardHelpTargetName Export-Excel + .ForwardHelpCategory Function + + #> +} \ No newline at end of file diff --git a/Examples/ExcelBuiltIns/DSUM.png b/Examples/ExcelBuiltIns/DSUM.png new file mode 100644 index 00000000..b9631fe3 Binary files /dev/null and b/Examples/ExcelBuiltIns/DSUM.png differ diff --git a/Examples/ExcelBuiltIns/DSUM.ps1 b/Examples/ExcelBuiltIns/DSUM.ps1 new file mode 100644 index 00000000..1e368e18 --- /dev/null +++ b/Examples/ExcelBuiltIns/DSUM.ps1 @@ -0,0 +1,34 @@ +# DSUM +# Adds the numbers in a field (column) of records in a list or database that match conditions that you specify. +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Color,Date,Sales +Red,1/15/2018,250 +Blue,1/15/2018,200 +Red,1/16/2018,175 +Blue,1/16/2018,325 +Red,1/17/2018,150 +Blue,1/17/2018,300 +"@ + +$xl = Export-Excel -InputObject $data -Path $xlSourcefile -AutoSize -AutoFilter -TableName SalesInfo -AutoNameRange -PassThru + +$databaseAddress = $xl.Sheet1.Dimension.Address +Set-Format -Worksheet $xl.Sheet1 -Range C:C -NumberFormat '$##0' + +Set-Format -Worksheet $xl.Sheet1 -Range E1 -Value Color +Set-Format -Worksheet $xl.Sheet1 -Range F1 -Value Date +Set-Format -Worksheet $xl.Sheet1 -Range G1 -Value Sales + +Set-Format -Worksheet $xl.Sheet1 -Range E2 -Value Red + +Set-Format -Worksheet $xl.Sheet1 -Range E4 -Value Sales +Set-Format -Worksheet $xl.Sheet1 -Range F4 -Formula ('=DSUM({0},"Sales",E1:G2)' -f $databaseAddress) -NumberFormat '$##0' + +Close-ExcelPackage $xl -Show \ No newline at end of file diff --git a/Examples/ExcelBuiltIns/VLOOKUP.ps1 b/Examples/ExcelBuiltIns/VLOOKUP.ps1 new file mode 100644 index 00000000..139d7832 --- /dev/null +++ b/Examples/ExcelBuiltIns/VLOOKUP.ps1 @@ -0,0 +1,23 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Fruit,Amount +Apples,50 +Oranges,20 +Bananas,60 +Lemons,40 +"@ + +$xl = Export-Excel -InputObject $data -Path $xlSourcefile -PassThru -AutoSize + +Set-ExcelRange -Worksheet $xl.Sheet1 -Range D2 -BackgroundColor LightBlue -Value Apples + +$rows = $xl.Sheet1.Dimension.Rows +Set-ExcelRange -Worksheet $xl.Sheet1 -Range E2 -Formula "=VLookup(D2,A2:B$($rows),2,FALSE)" + +Close-ExcelPackage $xl -Show \ No newline at end of file diff --git a/Examples/ExcelBuiltIns/VLookUp.png b/Examples/ExcelBuiltIns/VLookUp.png new file mode 100644 index 00000000..421775f8 Binary files /dev/null and b/Examples/ExcelBuiltIns/VLookUp.png differ diff --git a/Examples/ExcelDataValidation/MutipleValidations.ps1 b/Examples/ExcelDataValidation/MutipleValidations.ps1 new file mode 100644 index 00000000..f5970a56 --- /dev/null +++ b/Examples/ExcelDataValidation/MutipleValidations.ps1 @@ -0,0 +1,87 @@ +#region Setup +<# + This examples demos three types of validation: + * Creating a list using a PowerShell array + * Creating a list data from another Excel Worksheet + * Creating a rule for numbers to be between 0 an 10000 + + Run the script then try" + * Add random data in Column B + * Then choose from the drop down list + * Add random data in Column C + * Then choose from the drop down list + * Add .01 in column F +#> + +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv -InputObject @" +ID,Region,Product,Quantity,Price +12001,North,Nails,37,3.99 +12002,South,Hammer,5,12.10 +12003,East,Saw,12,15.37 +12010,West,Drill,20,8 +12011,North,Crowbar,7,23.48 +"@ + +# Export the raw data +$excelPackage = $Data | + Export-Excel -WorksheetName "Sales" -Path $xlSourcefile -PassThru + +# Creates a sheet with data that will be used in a validation rule +$excelPackage = @('Chisel', 'Crowbar', 'Drill', 'Hammer', 'Nails', 'Saw', 'Screwdriver', 'Wrench') | + Export-excel -ExcelPackage $excelPackage -WorksheetName Values -PassThru + +#endregion + +#region Creating a list using a PowerShell array +$ValidationParams = @{ + Worksheet = $excelPackage.sales + ShowErrorMessage = $true + ErrorStyle = 'stop' + ErrorTitle = 'Invalid Data' +} + + +$MoreValidationParams = @{ + Range = 'B2:B1001' + ValidationType = 'List' + ValueSet = @('North', 'South', 'East', 'West') + ErrorBody = "You must select an item from the list." +} + +Add-ExcelDataValidationRule @ValidationParams @MoreValidationParams +#endregion + +#region Creating a list data from another Excel Worksheet +$MoreValidationParams = @{ + Range = 'C2:C1001' + ValidationType = 'List' + Formula = 'values!$a$1:$a$10' + ErrorBody = "You must select an item from the list.`r`nYou can add to the list on the values page" #Bucket +} + +Add-ExcelDataValidationRule @ValidationParams @MoreValidationParams +#endregion + +#region Creating a rule for numbers to be between 0 an 10000 +$MoreValidationParams = @{ + Range = 'F2:F1001' + ValidationType = 'Integer' + Operator = 'between' + Value = 0 + Value2 = 10000 + ErrorBody = 'Quantity must be a whole number between 0 and 10000' +} + +Add-ExcelDataValidationRule @ValidationParams @MoreValidationParams +#endregion + +#region Close Package +Close-ExcelPackage -ExcelPackage $excelPackage -Show +#endregion \ No newline at end of file diff --git a/Examples/ExcelToSQLInsert/DemoSQLInsert.ps1 b/Examples/ExcelToSQLInsert/DemoSQLInsert.ps1 new file mode 100644 index 00000000..c29cf111 --- /dev/null +++ b/Examples/ExcelToSQLInsert/DemoSQLInsert.ps1 @@ -0,0 +1,6 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path ".\Movies.xlsx" -ConvertEmptyStringsToNull +'' +'# UseMSSQLSyntax' +ConvertFrom-ExcelToSQLInsert -UseMSSQLSyntax -TableName "Movies" -Path ".\Movies.xlsx" -ConvertEmptyStringsToNull \ No newline at end of file diff --git a/Examples/ExcelToSQLInsert/Movies.xlsx b/Examples/ExcelToSQLInsert/Movies.xlsx new file mode 100644 index 00000000..888a4d5f Binary files /dev/null and b/Examples/ExcelToSQLInsert/Movies.xlsx differ diff --git a/Examples/Experimental/Export-MultipleExcelSheets.ps1 b/Examples/Experimental/Export-MultipleExcelSheets.ps1 new file mode 100644 index 00000000..a922b446 --- /dev/null +++ b/Examples/Experimental/Export-MultipleExcelSheets.ps1 @@ -0,0 +1,46 @@ +function Export-MultipleExcelSheets { + <# + .Synopsis + Takes a hash table of scriptblocks and exports each as a sheet in an Excel file + + .Example +$p = Get-Process + +$InfoMap = @{ + PM = { $p | Select-Object company, pm } + Handles = { $p | Select-Object company, handles } + Services = { Get-Service } +} + +Export-MultipleExcelSheets -Path $xlfile -InfoMap $InfoMap -Show -AutoSize + #> + param( + [Parameter(Mandatory = $true)] + $Path, + [Parameter(Mandatory = $true)] + [hashtable]$InfoMap, + [string]$Password, + [Switch]$Show, + [Switch]$AutoSize + ) + + $parameters = @{ } + $PSBoundParameters + $parameters.Remove("InfoMap") + $parameters.Remove("Show") + + $parameters.Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) + + foreach ($entry in $InfoMap.GetEnumerator()) { + if ($entry.Value -is [scriptblock]) { + Write-Progress -Activity "Exporting" -Status "$($entry.Key)" + $parameters.WorkSheetname = $entry.Key + + & $entry.Value | Export-Excel @parameters + } + else { + Write-Warning "$($entry.Key) not exported, needs to be a scriptblock" + } + } + + if ($Show) { Invoke-Item $Path } +} diff --git a/Examples/Experimental/tryExportMultipleExcelSheets.ps1 b/Examples/Experimental/tryExportMultipleExcelSheets.ps1 new file mode 100644 index 00000000..922dd001 --- /dev/null +++ b/Examples/Experimental/tryExportMultipleExcelSheets.ps1 @@ -0,0 +1,19 @@ +. "$PSScriptRoot\Export-MultipleExcelSheets.ps1" + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$p = Get-Process + +$InfoMap = @{ + PM = { $p | Select-Object company, pm } + Handles = { $p | Select-Object company, handles } + Services = { Get-Service } + Files = { Get-ChildItem -File } + Albums = { ConvertFrom-Csv (Invoke-RestMethod https://raw.githubusercontent.com/dfinke/powershell-for-developers/master/chapter05/BeaverMusic/BeaverMusic.UI.Shell/albums.csv) } + WillNotGetExported = "Hello World" +} + +Export-MultipleExcelSheets -Path $xlSourcefile -InfoMap $InfoMap -Show -AutoSize \ No newline at end of file diff --git a/Examples/Extra/Get-ModuleStats.ps1 b/Examples/Extra/Get-ModuleStats.ps1 index e433d404..2c8252b5 100644 --- a/Examples/Extra/Get-ModuleStats.ps1 +++ b/Examples/Extra/Get-ModuleStats.ps1 @@ -6,15 +6,16 @@ #> param( - [Parameter(Mandatory=$true)] - $moduleName, + $moduleName = "ImportExcel", [ValidateSet('Column','Bar','Line','Pie')] $chartType="Line" ) -$galleryUrl = "https://www.powershellgallery.com/packages/$moduleName" -$nolegend = '-nolegend' -if($chartType -eq 'pie') {$nolegend = $null} -$code = "$($chartType)Chart (Get-HtmlTable $galleryUrl 0 | sort lastupdated -desc) -title 'Download stats for $moduleName' $nolegend" +$download = Get-HtmlTable "https://www.powershellgallery.com/packages/$moduleName" -FirstDataRow 1 | + Select-Object @{n="Version";e={$v = $Null ; if ($_.version -is [valuetype]) {[string][version]($_.version.tostring("0.0")) } + elseif ($_.version -is [string] -and [version]::TryParse($_.version.trim(),[ref]$v)) {$v} + else {$_.Version.trim() -replace "\s+"," " } }}, + Downloads, @{n="LastUpdated";e={[datetime]$_.last_updated}} | + Sort-Object lastupdated -Descending -$code | Invoke-Expression \ No newline at end of file +& "$($chartType)Chart" $download "Download stats for $moduleName" -nolegend:($chartype -ne 'pie') diff --git a/Examples/Fibonacci/ShowFibonacci.ps1 b/Examples/Fibonacci/ShowFibonacci.ps1 index d242b855..4948db66 100644 --- a/Examples/Fibonacci/ShowFibonacci.ps1 +++ b/Examples/Fibonacci/ShowFibonacci.ps1 @@ -1,16 +1,20 @@ param ($fibonacciDigits=10) -$file = "fib.xlsx" -rm "fib.xlsx" -ErrorAction Ignore +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore $( New-PSItem 0 New-PSItem 1 - + ( 2..$fibonacciDigits | - ForEach { + ForEach-Object { New-PSItem ('=a{0}+a{1}' -f ($_+1),$_) } ) -) | Export-Excel $file -Show +) | Export-Excel $xlSourcefile -Show diff --git a/Examples/Fibonacci/fib.xlsx b/Examples/Fibonacci/fib.xlsx deleted file mode 100644 index b4abac9e..00000000 Binary files a/Examples/Fibonacci/fib.xlsx and /dev/null differ diff --git a/Examples/FormatCellStyles/ApplyFormatInScriptBlock.ps1 b/Examples/FormatCellStyles/ApplyFormatInScriptBlock.ps1 index f158277e..9dca551a 100644 --- a/Examples/FormatCellStyles/ApplyFormatInScriptBlock.ps1 +++ b/Examples/FormatCellStyles/ApplyFormatInScriptBlock.ps1 @@ -1,12 +1,19 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + Get-Process | - Select-Object Company,Handles,PM, NPM| - Export-Excel $xlfile -Show -AutoSize -CellStyleSB { + Select-Object Company,Handles,PM, NPM| + Export-Excel $xlSourcefile -Show -AutoSize -CellStyleSB { param( $workSheet, $totalRows, $lastColumn ) - + Set-CellStyle $workSheet 1 $LastColumn Solid Cyan foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 0})) { diff --git a/Examples/FormatCellStyles/ApplyStyle.ps1 b/Examples/FormatCellStyles/ApplyStyle.ps1 new file mode 100644 index 00000000..8ec67081 --- /dev/null +++ b/Examples/FormatCellStyles/ApplyStyle.ps1 @@ -0,0 +1,26 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$data = ConvertFrom-Csv @' +Item,Quantity,Price,Total Cost +Footballs,9,21.95,197.55 +Cones,36,7.99,287.64 +Shin Guards,14,10.95,153.3 +Turf Shoes,22,79.95,1758.9 +Baseballs,68,7.99,543.32 +Baseball Gloves,31,65.00,2015.00 +Baseball Bats,38,159.00,6042.00 +'@ + +$f = "$env:TEMP\styles.xlsx" +Remove-Item $f -ErrorAction SilentlyContinue + +$pkg = $data | Export-Excel -Path $f -AutoSize -PassThru + +$ws = $pkg.Workbook.Worksheets["Sheet1"] + +Set-ExcelRange -Worksheet $ws -Range "A2:C6" -BackgroundColor PeachPuff -FontColor Purple -FontSize 12 -Width 12 +Set-ExcelRange -Worksheet $ws -Range "D2:D6" -BackgroundColor WhiteSmoke -FontColor Orange -Bold -FontSize 12 -Width 12 +Set-ExcelRange -Worksheet $ws -Range "A1:D1" -BackgroundColor BlueViolet -FontColor Wheat -FontSize 12 -Width 12 +Set-ExcelRange -Worksheet $ws -Range "A:A" -Width 15 + +Close-ExcelPackage -ExcelPackage $pkg -Show \ No newline at end of file diff --git a/Examples/FormatCellStyles/PassInScriptBlock.ps1 b/Examples/FormatCellStyles/PassInScriptBlock.ps1 index 044fff90..d043ff30 100644 --- a/Examples/FormatCellStyles/PassInScriptBlock.ps1 +++ b/Examples/FormatCellStyles/PassInScriptBlock.ps1 @@ -1,15 +1,22 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + $RandomStyle = { param( $workSheet, $totalRows, $lastColumn - ) + ) 2..$totalRows | ForEach-Object{ - Set-CellStyle $workSheet $_ $LastColumn Solid (Write-Output LightGreen Gray Red|Get-Random) + Set-CellStyle $workSheet $_ $LastColumn Solid (Get-Random @("LightGreen", "Gray", "Red")) } } Get-Process | - Select-Object Company,Handles,PM, NPM| - Export-Excel $xlfile -Show -AutoSize -CellStyleSB $RandomStyle + Select-Object Company,Handles,PM, NPM| + Export-Excel $xlSourcefile -Show -AutoSize -CellStyleSB $RandomStyle diff --git a/Examples/FormatResults/GetAsMarkdownTable.ps1 b/Examples/FormatResults/GetAsMarkdownTable.ps1 new file mode 100644 index 00000000..3a0c5846 --- /dev/null +++ b/Examples/FormatResults/GetAsMarkdownTable.ps1 @@ -0,0 +1,10 @@ +param( + [Alias('FullName')] + [String[]]$Path +) + +if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command Format-Markdown -ErrorAction SilentlyContinue)) { + throw "This requires EZOut. Install-Module EZOut -AllowClobber -Scope CurrentUser" +} + +Import-Excel $Path | Format-Markdown \ No newline at end of file diff --git a/Examples/FormatResults/GetAsYaml.ps1 b/Examples/FormatResults/GetAsYaml.ps1 new file mode 100644 index 00000000..162f1c5b --- /dev/null +++ b/Examples/FormatResults/GetAsYaml.ps1 @@ -0,0 +1,10 @@ +param( + [Alias('FullName')] + [String[]]$Path +) + +if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command Format-YAML -ErrorAction SilentlyContinue)) { + throw "This requires EZOut. Install-Module EZOut -AllowClobber -Scope CurrentUser" +} + +Import-Excel $Path | Format-YAML \ No newline at end of file diff --git a/Examples/FormatResults/Sample.csv b/Examples/FormatResults/Sample.csv new file mode 100644 index 00000000..37e40b8b --- /dev/null +++ b/Examples/FormatResults/Sample.csv @@ -0,0 +1,11 @@ +"OrderId","Category","Sales","Quantity","Discount" +"1","Cosmetics","744.01","7","0.7" +"2","Grocery","349.13","25","0.3" +"3","Apparels","535.11","88","0.2" +"4","Electronics","524.69","60","0.1" +"5","Electronics","439.1","41","0" +"6","Apparels","56.84","54","0.8" +"7","Electronics","326.66","97","0.7" +"8","Cosmetics","17.25","74","0.6" +"9","Grocery","199.96","39","0.4" +"10","Grocery","731.77","20","0.3" diff --git a/Examples/FormatResults/Sample.xlsx b/Examples/FormatResults/Sample.xlsx new file mode 100644 index 00000000..ecb09c10 Binary files /dev/null and b/Examples/FormatResults/Sample.xlsx differ diff --git a/Examples/Freeze/FreezePane.ps1 b/Examples/Freeze/FreezePane.ps1 new file mode 100644 index 00000000..6c15f963 --- /dev/null +++ b/Examples/Freeze/FreezePane.ps1 @@ -0,0 +1,54 @@ +# Freeze the columns/rows to left and above the cell + +$data = ConvertFrom-Csv @" +Region,State,Units,Price,Name,NA,EU,JP,Other +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +"@ + +$xlfilename = "test.xlsx" +Remove-Item $xlfilename -ErrorAction SilentlyContinue + +<# + Freezes the top two rows and the two leftmost column +#> + +$data | Export-Excel $xlfilename -Show -Title 'Sales Data' -FreezePane 3, 3 \ No newline at end of file diff --git a/Examples/GenerateData/GenDataForCustomReport.ps1 b/Examples/GenerateData/GenDataForCustomReport.ps1 index 86e6d4cf..d2b243f0 100644 --- a/Examples/GenerateData/GenDataForCustomReport.ps1 +++ b/Examples/GenerateData/GenDataForCustomReport.ps1 @@ -1,26 +1,26 @@ -if(!(gcm ig -ErrorAction SilentlyContinue)) { +if(!(Get-Command ig -ErrorAction SilentlyContinue)) { "Use ``Install-Module NameIT`` to get the needed module from the gallery to support running this script" return -} +} -$sign=@{sign=echo + -} -$location=@{location=echo Atlanta Newark Washington Chicago Philadelphia Houston Phoneix} +$sign=@{sign=@( "+", "-" )} +$location=@{location=@("Atlanta", "Newark", "Washington", "Chicago", "Philadelphia", "Houston", "Phoneix")} + +$(1..6 | Foreach-Object { -$(1..6 | % { - $from=$to="" while($from -eq $to) { $from=ig "[location]" -CustomData $location $to=ig "[location]" -CustomData $location - } + } [double]$a=ig "########" [double]$b=ig ".####" [double]$c=ig "#######" [double]$d=ig "[sign].##" -CustomData $sign - [double]$e=ig "###" + [double]$e=ig "###" [double]$f=ig "[sign]##" -CustomData $sign #"{0},{1},{2},{3},{4},{5},{6},{7}" -f $from, $to, $a, $b, $c, $d, $e, $f diff --git a/Examples/Grouping/First10Races.csv b/Examples/Grouping/First10Races.csv new file mode 100644 index 00000000..46b31804 --- /dev/null +++ b/Examples/Grouping/First10Races.csv @@ -0,0 +1,101 @@ +Race,Date,FinishPosition,Driver,GridPosition,Team,Points +Australian,25/03/2018,1,Sebastian Vettel,3,Ferrari,25 +Australian,25/03/2018,2,Lewis Hamilton,1,Mercedes,18 +Australian,25/03/2018,3,Kimi Räikkönen,2,Ferrari,15 +Australian,25/03/2018,4,Daniel Ricciardo,8,Red Bull Racing-TAG Heuer,12 +Australian,25/03/2018,5,Fernando Alonso,10,McLaren-Renault,10 +Australian,25/03/2018,6,Max Verstappen,4,Red Bull Racing-TAG Heuer,8 +Australian,25/03/2018,7,Nico Hülkenberg,7,Renault,6 +Australian,25/03/2018,8,Valtteri Bottas,15,Mercedes,4 +Australian,25/03/2018,9,Stoffel Vandoorne,11,McLaren-Renault,2 +Australian,25/03/2018,10,Carlos Sainz,9,Renault,1 +Bahrain,08/04/2018,1,Sebastian Vettel,1,Ferrari,25 +Bahrain,08/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Bahrain,08/04/2018,3,Lewis Hamilton,9,Mercedes,15 +Bahrain,08/04/2018,4,Pierre Gasly,5,STR-Honda,12 +Bahrain,08/04/2018,5,Kevin Magnussen,6,Haas-Ferrari,10 +Bahrain,08/04/2018,6,Nico Hülkenberg,7,Renault,8 +Bahrain,08/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Bahrain,08/04/2018,8,Stoffel Vandoorne,14,McLaren-Renault,4 +Bahrain,08/04/2018,9,Marcus Ericsson,17,Sauber-Ferrari,2 +Bahrain,08/04/2018,10,Esteban Ocon,8,Force India-Mercedes,1 +Chinese,15/04/2018,1,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,25 +Chinese,15/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Chinese,15/04/2018,3,Kimi Räikkönen,2,Ferrari,15 +Chinese,15/04/2018,4,Lewis Hamilton,4,Mercedes,12 +Chinese,15/04/2018,5,Max Verstappen,5,Red Bull Racing-TAG Heuer,10 +Chinese,15/04/2018,6,Nico Hülkenberg,7,Renault,8 +Chinese,15/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Chinese,15/04/2018,8,Sebastian Vettel,1,Ferrari,4 +Chinese,15/04/2018,9,Carlos Sainz,9,Renault,2 +Chinese,15/04/2018,10,Kevin Magnussen,11,Haas-Ferrari,1 +Azerbaijan,29/04/2018,1,Lewis Hamilton,2,Mercedes,25 +Azerbaijan,29/04/2018,2,Kimi Räikkönen,6,Ferrari,18 +Azerbaijan,29/04/2018,3,Sergio Pérez,8,Force India-Mercedes,15 +Azerbaijan,29/04/2018,4,Sebastian Vettel,1,Ferrari,12 +Azerbaijan,29/04/2018,5,Carlos Sainz,9,Renault,10 +Azerbaijan,29/04/2018,6,Charles Leclerc,13,Sauber-Ferrari,8 +Azerbaijan,29/04/2018,7,Fernando Alonso,12,McLaren-Renault,6 +Azerbaijan,29/04/2018,8,Lance Stroll,10,Williams-Mercedes,4 +Azerbaijan,29/04/2018,9,Stoffel Vandoorne,16,McLaren-Renault,2 +Azerbaijan,29/04/2018,10,Brendon Hartley,19,STR-Honda,1 +Spanish,13/05/2018,1,Lewis Hamilton,1,Mercedes,25 +Spanish,13/05/2018,2,Valtteri Bottas,2,Mercedes,18 +Spanish,13/05/2018,3,Max Verstappen,5,Red Bull Racing-TAG Heuer,15 +Spanish,13/05/2018,4,Sebastian Vettel,3,Ferrari,12 +Spanish,13/05/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +Spanish,13/05/2018,6,Kevin Magnussen,7,Haas-Ferrari,8 +Spanish,13/05/2018,7,Carlos Sainz,9,Renault,6 +Spanish,13/05/2018,8,Fernando Alonso,8,McLaren-Renault,4 +Spanish,13/05/2018,9,Sergio Pérez,15,Force India-Mercedes,2 +Spanish,13/05/2018,10,Charles Leclerc,14,Sauber-Ferrari,1 +Monaco,27/05/2018,1,Daniel Ricciardo,1,Red Bull Racing-TAG Heuer,25 +Monaco,27/05/2018,2,Sebastian Vettel,2,Ferrari,18 +Monaco,27/05/2018,3,Lewis Hamilton,3,Mercedes,15 +Monaco,27/05/2018,4,Kimi Räikkönen,4,Ferrari,12 +Monaco,27/05/2018,5,Valtteri Bottas,5,Mercedes,10 +Monaco,27/05/2018,6,Esteban Ocon,6,Force India-Mercedes,8 +Monaco,27/05/2018,7,Pierre Gasly,10,STR-Honda,6 +Monaco,27/05/2018,8,Nico Hülkenberg,11,Renault,4 +Monaco,27/05/2018,9,Max Verstappen,20,Red Bull Racing-TAG Heuer,2 +Monaco,27/05/2018,10,Carlos Sainz,8,Renault,1 +Canadian,10/06/2018,1,Sebastian Vettel,1,Ferrari,25 +Canadian,10/06/2018,2,Valtteri Bottas,2,Mercedes,18 +Canadian,10/06/2018,3,Max Verstappen,3,Red Bull Racing-TAG Heuer,15 +Canadian,10/06/2018,4,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,12 +Canadian,10/06/2018,5,Lewis Hamilton,4,Mercedes,10 +Canadian,10/06/2018,6,Kimi Räikkönen,5,Ferrari,8 +Canadian,10/06/2018,7,Nico Hülkenberg,7,Renault,6 +Canadian,10/06/2018,8,Carlos Sainz,9,Renault,4 +Canadian,10/06/2018,9,Esteban Ocon,8,Force India-Mercedes,2 +Canadian,10/06/2018,10,Charles Leclerc,13,Sauber-Ferrari,1 +French,24/06/2018,1,Lewis Hamilton,1,Mercedes,25 +French,24/06/2018,2,Max Verstappen,4,Red Bull Racing-TAG Heuer,18 +French,24/06/2018,3,Kimi Räikkönen,6,Ferrari,15 +French,24/06/2018,4,Daniel Ricciardo,5,Red Bull Racing-TAG Heuer,12 +French,24/06/2018,5,Sebastian Vettel,3,Ferrari,10 +French,24/06/2018,6,Kevin Magnussen,9,Haas-Ferrari,8 +French,24/06/2018,7,Valtteri Bottas,2,Mercedes,6 +French,24/06/2018,8,Carlos Sainz,7,Renault,4 +French,24/06/2018,9,Nico Hülkenberg,12,Renault,2 +French,24/06/2018,10,Charles Leclerc,8,Sauber-Ferrari,1 +Austrian,01/07/2018,1,Max Verstappen,4,Red Bull Racing-TAG Heuer,25 +Austrian,01/07/2018,2,Kimi Räikkönen,3,Ferrari,18 +Austrian,01/07/2018,3,Sebastian Vettel,6,Ferrari,15 +Austrian,01/07/2018,4,Romain Grosjean,5,Haas-Ferrari,12 +Austrian,01/07/2018,5,Kevin Magnussen,8,Haas-Ferrari,10 +Austrian,01/07/2018,6,Esteban Ocon,11,Force India-Mercedes,8 +Austrian,01/07/2018,7,Sergio Pérez,15,Force India-Mercedes,6 +Austrian,01/07/2018,8,Fernando Alonso,20,McLaren-Renault,4 +Austrian,01/07/2018,9,Charles Leclerc,17,Sauber-Ferrari,2 +Austrian,01/07/2018,10,Marcus Ericsson,18,Sauber-Ferrari,1 +British,08/07/2018,1,Sebastian Vettel,2,Ferrari,25 +British,08/07/2018,2,Lewis Hamilton,1,Mercedes,18 +British,08/07/2018,3,Kimi Räikkönen,3,Ferrari,15 +British,08/07/2018,4,Valtteri Bottas,4,Mercedes,12 +British,08/07/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +British,08/07/2018,6,Nico Hülkenberg,11,Renault,8 +British,08/07/2018,7,Esteban Ocon,10,Force India-Mercedes,6 +British,08/07/2018,8,Fernando Alonso,13,McLaren-Renault,4 +British,08/07/2018,9,Kevin Magnussen,7,Haas-Ferrari,2 +British,08/07/2018,10,Sergio Pérez,12,Force India-Mercedes,1 \ No newline at end of file diff --git a/Examples/Grouping/GroupDateColumn.ps1 b/Examples/Grouping/GroupDateColumn.ps1 new file mode 100644 index 00000000..6ee05cfe --- /dev/null +++ b/Examples/Grouping/GroupDateColumn.ps1 @@ -0,0 +1,13 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points ` + -PivotRows Driver -PivotColumns Date -PivotData @{Points = "SUM"} -GroupDateColumn Date -GroupDatePart Years, Months + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition \ No newline at end of file diff --git a/Examples/Grouping/GroupDateRow.ps1 b/Examples/Grouping/GroupDateRow.ps1 new file mode 100644 index 00000000..9429c1c2 --- /dev/null +++ b/Examples/Grouping/GroupDateRow.ps1 @@ -0,0 +1,13 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points ` + -PivotRows Driver, Date -PivotData @{Points = "SUM"} -GroupDateRow Date -GroupDatePart Years, Months + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition \ No newline at end of file diff --git a/Examples/Grouping/GroupNumericColumn.ps1 b/Examples/Grouping/GroupNumericColumn.ps1 new file mode 100644 index 00000000..4b973910 --- /dev/null +++ b/Examples/Grouping/GroupNumericColumn.ps1 @@ -0,0 +1,13 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places ` + -PivotRows Driver -PivotColumns FinishPosition -PivotData @{Date = "Count"} -GroupNumericColumn FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3 + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition \ No newline at end of file diff --git a/Examples/Grouping/GroupNumericRow.ps1 b/Examples/Grouping/GroupNumericRow.ps1 new file mode 100644 index 00000000..5d743e4c --- /dev/null +++ b/Examples/Grouping/GroupNumericRow.ps1 @@ -0,0 +1,13 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places ` + -PivotRows Driver, FinishPosition -PivotData @{Date = "Count"} -GroupNumericRow FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3 + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition \ No newline at end of file diff --git a/Examples/Grouping/TimestampBucket.ps1 b/Examples/Grouping/TimestampBucket.ps1 new file mode 100644 index 00000000..6ce88f63 --- /dev/null +++ b/Examples/Grouping/TimestampBucket.ps1 @@ -0,0 +1,42 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} +$data = ConvertFrom-Csv @" +Timestamp,Tenant +10/29/2018 3:00:00.123,1 +10/29/2018 3:00:10.456,1 +10/29/2018 3:01:20.389,1 +10/29/2018 3:00:30.222,1 +10/29/2018 3:00:40.143,1 +10/29/2018 3:00:50.809,1 +10/29/2018 3:01:00.193,1 +10/29/2018 3:01:10.555,1 +10/29/2018 3:01:20.739,1 +10/29/2018 3:01:30.912,1 +10/29/2018 3:01:40.989,1 +10/29/2018 3:01:50.545,1 +10/29/2018 3:02:00.999,1 +"@ | Select-Object @{n = 'Timestamp'; e = {Get-date $_.timestamp}}, tenant, @{n = 'Bucket'; e = { - (Get-date $_.timestamp).Second % 30}} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$pivotDefParams = @{ + PivotTableName = 'Timestamp Buckets' + PivotRows = @('Timestamp', 'Tenant') + PivotData = @{'Bucket' = 'count'} + GroupDateRow = 'TimeStamp' + GroupDatePart = @('Hours', 'Minutes') + Activate = $true +} + +$excelParams = @{ + PivotTableDefinition = New-PivotTableDefinition @pivotDefParams + Path = $xlSourcefile + WorkSheetname = "Log Data" + AutoSize = $true + AutoFilter = $true + Show = $true +} + +$data | Export-Excel @excelParams \ No newline at end of file diff --git a/Examples/HyperLinks/First10Races.csv b/Examples/HyperLinks/First10Races.csv new file mode 100644 index 00000000..46b31804 --- /dev/null +++ b/Examples/HyperLinks/First10Races.csv @@ -0,0 +1,101 @@ +Race,Date,FinishPosition,Driver,GridPosition,Team,Points +Australian,25/03/2018,1,Sebastian Vettel,3,Ferrari,25 +Australian,25/03/2018,2,Lewis Hamilton,1,Mercedes,18 +Australian,25/03/2018,3,Kimi Räikkönen,2,Ferrari,15 +Australian,25/03/2018,4,Daniel Ricciardo,8,Red Bull Racing-TAG Heuer,12 +Australian,25/03/2018,5,Fernando Alonso,10,McLaren-Renault,10 +Australian,25/03/2018,6,Max Verstappen,4,Red Bull Racing-TAG Heuer,8 +Australian,25/03/2018,7,Nico Hülkenberg,7,Renault,6 +Australian,25/03/2018,8,Valtteri Bottas,15,Mercedes,4 +Australian,25/03/2018,9,Stoffel Vandoorne,11,McLaren-Renault,2 +Australian,25/03/2018,10,Carlos Sainz,9,Renault,1 +Bahrain,08/04/2018,1,Sebastian Vettel,1,Ferrari,25 +Bahrain,08/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Bahrain,08/04/2018,3,Lewis Hamilton,9,Mercedes,15 +Bahrain,08/04/2018,4,Pierre Gasly,5,STR-Honda,12 +Bahrain,08/04/2018,5,Kevin Magnussen,6,Haas-Ferrari,10 +Bahrain,08/04/2018,6,Nico Hülkenberg,7,Renault,8 +Bahrain,08/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Bahrain,08/04/2018,8,Stoffel Vandoorne,14,McLaren-Renault,4 +Bahrain,08/04/2018,9,Marcus Ericsson,17,Sauber-Ferrari,2 +Bahrain,08/04/2018,10,Esteban Ocon,8,Force India-Mercedes,1 +Chinese,15/04/2018,1,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,25 +Chinese,15/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Chinese,15/04/2018,3,Kimi Räikkönen,2,Ferrari,15 +Chinese,15/04/2018,4,Lewis Hamilton,4,Mercedes,12 +Chinese,15/04/2018,5,Max Verstappen,5,Red Bull Racing-TAG Heuer,10 +Chinese,15/04/2018,6,Nico Hülkenberg,7,Renault,8 +Chinese,15/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Chinese,15/04/2018,8,Sebastian Vettel,1,Ferrari,4 +Chinese,15/04/2018,9,Carlos Sainz,9,Renault,2 +Chinese,15/04/2018,10,Kevin Magnussen,11,Haas-Ferrari,1 +Azerbaijan,29/04/2018,1,Lewis Hamilton,2,Mercedes,25 +Azerbaijan,29/04/2018,2,Kimi Räikkönen,6,Ferrari,18 +Azerbaijan,29/04/2018,3,Sergio Pérez,8,Force India-Mercedes,15 +Azerbaijan,29/04/2018,4,Sebastian Vettel,1,Ferrari,12 +Azerbaijan,29/04/2018,5,Carlos Sainz,9,Renault,10 +Azerbaijan,29/04/2018,6,Charles Leclerc,13,Sauber-Ferrari,8 +Azerbaijan,29/04/2018,7,Fernando Alonso,12,McLaren-Renault,6 +Azerbaijan,29/04/2018,8,Lance Stroll,10,Williams-Mercedes,4 +Azerbaijan,29/04/2018,9,Stoffel Vandoorne,16,McLaren-Renault,2 +Azerbaijan,29/04/2018,10,Brendon Hartley,19,STR-Honda,1 +Spanish,13/05/2018,1,Lewis Hamilton,1,Mercedes,25 +Spanish,13/05/2018,2,Valtteri Bottas,2,Mercedes,18 +Spanish,13/05/2018,3,Max Verstappen,5,Red Bull Racing-TAG Heuer,15 +Spanish,13/05/2018,4,Sebastian Vettel,3,Ferrari,12 +Spanish,13/05/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +Spanish,13/05/2018,6,Kevin Magnussen,7,Haas-Ferrari,8 +Spanish,13/05/2018,7,Carlos Sainz,9,Renault,6 +Spanish,13/05/2018,8,Fernando Alonso,8,McLaren-Renault,4 +Spanish,13/05/2018,9,Sergio Pérez,15,Force India-Mercedes,2 +Spanish,13/05/2018,10,Charles Leclerc,14,Sauber-Ferrari,1 +Monaco,27/05/2018,1,Daniel Ricciardo,1,Red Bull Racing-TAG Heuer,25 +Monaco,27/05/2018,2,Sebastian Vettel,2,Ferrari,18 +Monaco,27/05/2018,3,Lewis Hamilton,3,Mercedes,15 +Monaco,27/05/2018,4,Kimi Räikkönen,4,Ferrari,12 +Monaco,27/05/2018,5,Valtteri Bottas,5,Mercedes,10 +Monaco,27/05/2018,6,Esteban Ocon,6,Force India-Mercedes,8 +Monaco,27/05/2018,7,Pierre Gasly,10,STR-Honda,6 +Monaco,27/05/2018,8,Nico Hülkenberg,11,Renault,4 +Monaco,27/05/2018,9,Max Verstappen,20,Red Bull Racing-TAG Heuer,2 +Monaco,27/05/2018,10,Carlos Sainz,8,Renault,1 +Canadian,10/06/2018,1,Sebastian Vettel,1,Ferrari,25 +Canadian,10/06/2018,2,Valtteri Bottas,2,Mercedes,18 +Canadian,10/06/2018,3,Max Verstappen,3,Red Bull Racing-TAG Heuer,15 +Canadian,10/06/2018,4,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,12 +Canadian,10/06/2018,5,Lewis Hamilton,4,Mercedes,10 +Canadian,10/06/2018,6,Kimi Räikkönen,5,Ferrari,8 +Canadian,10/06/2018,7,Nico Hülkenberg,7,Renault,6 +Canadian,10/06/2018,8,Carlos Sainz,9,Renault,4 +Canadian,10/06/2018,9,Esteban Ocon,8,Force India-Mercedes,2 +Canadian,10/06/2018,10,Charles Leclerc,13,Sauber-Ferrari,1 +French,24/06/2018,1,Lewis Hamilton,1,Mercedes,25 +French,24/06/2018,2,Max Verstappen,4,Red Bull Racing-TAG Heuer,18 +French,24/06/2018,3,Kimi Räikkönen,6,Ferrari,15 +French,24/06/2018,4,Daniel Ricciardo,5,Red Bull Racing-TAG Heuer,12 +French,24/06/2018,5,Sebastian Vettel,3,Ferrari,10 +French,24/06/2018,6,Kevin Magnussen,9,Haas-Ferrari,8 +French,24/06/2018,7,Valtteri Bottas,2,Mercedes,6 +French,24/06/2018,8,Carlos Sainz,7,Renault,4 +French,24/06/2018,9,Nico Hülkenberg,12,Renault,2 +French,24/06/2018,10,Charles Leclerc,8,Sauber-Ferrari,1 +Austrian,01/07/2018,1,Max Verstappen,4,Red Bull Racing-TAG Heuer,25 +Austrian,01/07/2018,2,Kimi Räikkönen,3,Ferrari,18 +Austrian,01/07/2018,3,Sebastian Vettel,6,Ferrari,15 +Austrian,01/07/2018,4,Romain Grosjean,5,Haas-Ferrari,12 +Austrian,01/07/2018,5,Kevin Magnussen,8,Haas-Ferrari,10 +Austrian,01/07/2018,6,Esteban Ocon,11,Force India-Mercedes,8 +Austrian,01/07/2018,7,Sergio Pérez,15,Force India-Mercedes,6 +Austrian,01/07/2018,8,Fernando Alonso,20,McLaren-Renault,4 +Austrian,01/07/2018,9,Charles Leclerc,17,Sauber-Ferrari,2 +Austrian,01/07/2018,10,Marcus Ericsson,18,Sauber-Ferrari,1 +British,08/07/2018,1,Sebastian Vettel,2,Ferrari,25 +British,08/07/2018,2,Lewis Hamilton,1,Mercedes,18 +British,08/07/2018,3,Kimi Räikkönen,3,Ferrari,15 +British,08/07/2018,4,Valtteri Bottas,4,Mercedes,12 +British,08/07/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +British,08/07/2018,6,Nico Hülkenberg,11,Renault,8 +British,08/07/2018,7,Esteban Ocon,10,Force India-Mercedes,6 +British,08/07/2018,8,Fernando Alonso,13,McLaren-Renault,4 +British,08/07/2018,9,Kevin Magnussen,7,Haas-Ferrari,2 +British,08/07/2018,10,Sergio Pérez,12,Force India-Mercedes,1 \ No newline at end of file diff --git a/Examples/HyperLinks/Hyperlinks.ps1 b/Examples/HyperLinks/Hyperlinks.ps1 index 2356698a..4c5e627a 100644 --- a/Examples/HyperLinks/Hyperlinks.ps1 +++ b/Examples/HyperLinks/Hyperlinks.ps1 @@ -1,7 +1,8 @@ -#$( -# New-PSItem 'Every Man a King' http://orisonswettmarden.wwwhubs.com/ccount/click.php?id=2 -# New-PSItem 'Be Good to Yourself' http://orisonswettmarden.wwwhubs.com/ccount/click.php?id=3 -# New-PSItem 'Character : The Grandest Thing in the World' http://orisonswettmarden.wwwhubs.com/ccount/click.php?id=4 -# New-PSItem 'The Conquest of Worry' http://orisonswettmarden.wwwhubs.com/ccount/click.php?id=5 -# New-PSItem 'Success Nuggets' http://orisonswettmarden.wwwhubs.com/ccount/click.php?id=6 -#) | Export-Excel hyperlinks.xlsx -Show -AutoSize \ No newline at end of file +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +@" +site,link +google,http://www.google.com +stackoverflow,http://stackoverflow.com +microsoft,http://microsoft.com +"@ | ConvertFrom-Csv | Export-Excel diff --git a/Examples/HyperLinks/Races.ps1 b/Examples/HyperLinks/Races.ps1 new file mode 100644 index 00000000..05afe2ee --- /dev/null +++ b/Examples/HyperLinks/Races.ps1 @@ -0,0 +1,28 @@ + +#First 10 races is a CSV file containing the top 10 finishers for the first 10 Formula one races of 2018. Read this file and group the results by race +#We will create links to each race in the first 10 rows of the spreadSheet +#The next row will be column labels +#After that will come a block for each race. +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Read the data, and decide how much space to leave for the hyperlinks +$scriptPath = Split-Path -Path $MyInvocation.MyCommand.path -Parent +$dataPath = Join-Path -Path $scriptPath -ChildPath "First10Races.csv" +$results = Import-Csv -Path $dataPath | Group-Object -Property RACE +$topRow = $lastDataRow = 1 + $results.Count + +#Export the first row of the first group (race) with headers. +$path = "$env:TEMP\Results.xlsx" +Remove-Item -Path $path -ErrorAction SilentlyContinue +$excel = $results[0].Group[0] | Export-Excel -Path $path -StartRow $TopRow -BoldTopRow -PassThru + +#export each group (race) below the last one, without headers, and create a range for each using the group (Race) name +foreach ($r in $results) { + $excel = $R.Group | Export-Excel -ExcelPackage $excel -NoHeader -StartRow ($lastDataRow +1) -RangeName $R.Name -PassThru -AutoSize + $lastDataRow += $R.Group.Count +} + +#Create a hyperlink for each property with display text of "RaceNameGP" which links to the range created when the rows were exported a +$results | ForEach-Object {(New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP")} | + Export-Excel -ExcelPackage $excel -AutoSize -Show + diff --git a/Examples/Import-Excel/ImportMultipleSheetsAsArray.ps1 b/Examples/Import-Excel/ImportMultipleSheetsAsArray.ps1 new file mode 100644 index 00000000..31242b06 --- /dev/null +++ b/Examples/Import-Excel/ImportMultipleSheetsAsArray.ps1 @@ -0,0 +1,7 @@ +Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +$xlfile = "$PSScriptRoot\yearlySales.xlsx" + +$result = Import-Excel -Path $xlfile -WorksheetName * -Raw + +$result | Measure-Object \ No newline at end of file diff --git a/Examples/Import-Excel/ImportMultipleSheetsAsHashtable.ps1 b/Examples/Import-Excel/ImportMultipleSheetsAsHashtable.ps1 new file mode 100644 index 00000000..d4323493 --- /dev/null +++ b/Examples/Import-Excel/ImportMultipleSheetsAsHashtable.ps1 @@ -0,0 +1,9 @@ +Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +$xlfile = "$PSScriptRoot\yearlySales.xlsx" + +$result = Import-Excel -Path $xlfile -WorksheetName * + +foreach ($sheet in $result.Values) { + $sheet +} \ No newline at end of file diff --git a/Examples/Import-Excel/yearlySales.xlsx b/Examples/Import-Excel/yearlySales.xlsx new file mode 100644 index 00000000..d30993a1 Binary files /dev/null and b/Examples/Import-Excel/yearlySales.xlsx differ diff --git a/Examples/ImportByColumns/FruitCity.xlsx b/Examples/ImportByColumns/FruitCity.xlsx new file mode 100644 index 00000000..cb05fa17 Binary files /dev/null and b/Examples/ImportByColumns/FruitCity.xlsx differ diff --git a/Examples/ImportByColumns/VM_Build_Example.xlsx b/Examples/ImportByColumns/VM_Build_Example.xlsx new file mode 100644 index 00000000..33ae355a Binary files /dev/null and b/Examples/ImportByColumns/VM_Build_Example.xlsx differ diff --git a/Examples/ImportByColumns/import-by-columns.ps1 b/Examples/ImportByColumns/import-by-columns.ps1 new file mode 100644 index 00000000..e9bf1cc3 --- /dev/null +++ b/Examples/ImportByColumns/import-by-columns.ps1 @@ -0,0 +1,146 @@ +function Import-ByColumns { +<# + .synopsis + Works like Import-Excel but with data in columns instead of the conventional rows. + .Description. + Import-excel will read the sample file in this folder like this + > Import-excel FruitCity.xlsx | ft * + GroupAs Apple Orange Banana + ------- ----- ------ ------ + London 1 4 9 + Paris 2 4 10 + NewYork 6 5 11 + Munich 7 8 12 + Import-ByColumns transposes it + > Import-Bycolumns FruitCity.xlsx | ft * + GroupAs London Paris NewYork Munich + ------- ------ ----- ------- ------ + Apple 1 2 6 7 + Orange 4 4 5 8 + Banana 9 10 11 12 + .Example + C:\> Import-Bycolumns -path .\VM_Build_Example.xlsx -StartRow 7 -EndRow 21 -EndColumn 7 -HeaderName Desc,size,type, + cpu,ram,NetAcc,OS,OSDiskSize,DataDiskSize,LogDiskSize,TempDbDiskSize,BackupDiskSize,ImageDiskDize,AzureBackup,AzureReplication | ft -a * + + This reads a spreadsheet which has a block from row 7 to 21 containing 14 properties of virtual machines. + The properties names are in column A and the 6 VMS are in columns B-G + Because the property names are written for easy reading by the person completing the spreadsheet, they are replaced with new names. + All the parameters work as they would for Import-Excel +#> + + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + param( + [Alias('FullName')] + [Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [String]$Path, + + [Parameter(ParameterSetName = "PackageA", Mandatory)] + [Parameter(ParameterSetName = "PackageB", Mandatory)] + [Parameter(ParameterSetName = "PackageC", Mandatory)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + + [Alias('Sheet')] + [Parameter(Position = 1)] + [ValidateNotNullOrEmpty()] + [String]$WorksheetName, + + [Parameter(ParameterSetName = 'PathB' , Mandatory)] + [Parameter(ParameterSetName = 'PackageB', Mandatory)] + [String[]]$HeaderName , + [Parameter(ParameterSetName = 'PathC' , Mandatory)] + [Parameter(ParameterSetName = 'PackageC', Mandatory)] + [Switch]$NoHeader, + + [Alias('TopRow')] + [ValidateRange(1, 9999)] + [Int]$StartRow = 1, + + [Alias('StopRow', 'BottomRow')] + [Int]$EndRow , + + [Alias('LeftColumn','LabelColumn')] + [Int]$StartColumn = 1, + + [Int]$EndColumn, + [switch]$DataOnly, + [switch]$AsHash, + + [ValidateNotNullOrEmpty()] + [String]$Password + ) + function Get-PropertyNames { + <# + .SYNOPSIS + Create objects containing the row number and the row name for each of the different header types. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")] + param( + [Parameter(Mandatory)] + [Int[]]$Rows, + [Parameter(Mandatory)] + [Int]$StartColumn + ) + if ($HeaderName) { + $i = 0 + foreach ($h in $HeaderName) { + $h | Select-Object @{n='Row'; e={$rows[$i]}}, @{n='Value'; e={$h} } + $i++ + } + } + elseif ($NoHeader) { + $i = 0 + foreach ($r in $rows) { + $i++ + $r | Select-Object @{n='Row'; e={$_}}, @{n='Value'; e={"P$i"} } + } + } + else { + foreach ($r in $Rows) { + #allow "False" or "0" to be headings + $Worksheet.Cells[$r, $StartColumn] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{n='Row'; e={$r} }, Value + } + } + } + +#region open file if necessary, find worksheet and ensure we have start/end row/columns + if ($Path -and -not $ExcelPackage -and $Password) { + $ExcelPackage = Open-ExcelPackage -Path $Path -Password $Password + } + elseif ($Path -and -not $ExcelPackage ) { + $ExcelPackage = Open-ExcelPackage -Path $Path + } + if (-not $ExcelPackage) { + throw 'Could not get an Excel workbook to work on' ; return + } + + if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] } + elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) { + throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return + } + + if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row } + if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column } +#endregion + + $Rows = $Startrow .. $EndRow ; + $Columns = (1 + $StartColumn)..$EndColumn + + if ((-not $rows) -or (-not ($PropertyNames = Get-PropertyNames -Rows $Rows -StartColumn $StartColumn))) { + throw "No headers found in left coulmn '$Startcolumn'. "; return + } + if (-not $Columns) { + Write-Warning "Worksheet '$WorksheetName' in workbook contains no data in the rows after left column '$StartColumn'" + } + else { + foreach ($c in $Columns) { + $NewColumn = [Ordered]@{ } + foreach ($p in $PropertyNames) { + $NewColumn[$p.Value] = $Worksheet.Cells[$p.row,$c].text + } + if ($AsHash) {$NewColumn} + elseif (($NewColumn.Values -ne "") -or -not $dataonly) {[PSCustomObject]$NewColumn} + } + } +} diff --git a/Examples/ImportColumns/ImportColumns.ps1 b/Examples/ImportColumns/ImportColumns.ps1 new file mode 100644 index 00000000..c022b8a0 --- /dev/null +++ b/Examples/ImportColumns/ImportColumns.ps1 @@ -0,0 +1,9 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +# Create example file +$xlFile = "$PSScriptRoot\ImportColumns.xlsx" +Get-Process | Export-Excel -Path $xlFile +# -ImportColumns will also arrange columns +Import-Excel -Path $xlFile -ImportColumns @(1,3,2) -NoHeader -StartRow 1 +# Get only pm, npm, cpu, id, processname +Import-Excel -Path $xlFile -ImportColumns @(6,7,12,25,46) | Format-Table -AutoSize \ No newline at end of file diff --git a/Examples/ImportHtml/DemoGraphics.ps1 b/Examples/ImportHtml/DemoGraphics.ps1 index 011e104c..b017e701 100644 --- a/Examples/ImportHtml/DemoGraphics.ps1 +++ b/Examples/ImportHtml/DemoGraphics.ps1 @@ -1,2 +1,4 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + Import-Html "http://en.wikipedia.org/wiki/Demographics_of_India" 4 \ No newline at end of file diff --git a/Examples/ImportHtml/PeriodicElements.ps1 b/Examples/ImportHtml/PeriodicElements.ps1 index 50d7cbe0..b9dd4aee 100644 --- a/Examples/ImportHtml/PeriodicElements.ps1 +++ b/Examples/ImportHtml/PeriodicElements.ps1 @@ -1 +1,3 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + Import-Html "http://www.science.co.il/PTelements.asp" 1 \ No newline at end of file diff --git a/Examples/ImportHtml/StarTrek.ps1 b/Examples/ImportHtml/StarTrek.ps1 index a5ca93de..53ab0944 100644 --- a/Examples/ImportHtml/StarTrek.ps1 +++ b/Examples/ImportHtml/StarTrek.ps1 @@ -1 +1,3 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + Import-Html "https://en.wikipedia.org/wiki/List_of_Star_Trek:_The_Original_Series_episodes" 2 \ No newline at end of file diff --git a/Examples/Index - Music.ps1 b/Examples/Index - Music.ps1 new file mode 100644 index 00000000..7d83c305 --- /dev/null +++ b/Examples/Index - Music.ps1 @@ -0,0 +1,41 @@ +#requires -modules "Get-IndexedItem" +[CmdletBinding()] +Param() +Remove-Item ~\documents\music.xlsx -ErrorAction SilentlyContinue +[System.Diagnostics.Stopwatch]$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() + +#Query system index for .MP3 files in C:\Users, where album artist is non-blank. Leave sorted table with columns of interest in $Music. + +Get-IndexedItem "itemtype='.mp3'","AlbumArtist like '%'" -Recurse C:\Users -OutputVariable Music ` + -OrderBy AlbumArtist, AlbumTitle, TrackNumber, Title -NoFiles ` + -Property AlbumArtist, AlbumTitle, TrackNumber, Title, Duration, Size, SampleRate +Write-Verbose -Message ("Fetched " + $music.Rows.Count + " rows from index: " + $stopwatch.Elapsed.TotalSeconds) +#Send Table in $Music to Excel, format as a table, point $ws to the Worksheet +$excel = Send-SQLDataToExcel -Path ~\documents\music.xlsx -DataTable $music -WorkSheetname Music -TableName Music -Passthru +Write-Verbose -Message ("Inserted into Excel: " + $stopwatch.Elapsed.TotalSeconds) +$ws = $excel.Music + +#Strip "SYSTEM.", "SYSTEM.AUDIO", "SYSTEM.MEDIA", "SYSTEM.MUSIC" from the column headings +#Convert Duration (column 5) from 100ns ticks to days and format as minutes, seconds, decimal +#Format filesize and sample rate nicely +#Autofit the columns. +Set-ExcelRow -Worksheet $ws -Row 1 -Value {($worksheet.cells[$row,$column].value -replace '^SYSTEM\.','') -replace '^MEDIA\.|^AUDIO\.|^MUSIC\.','' } +Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'mm:ss.0' -StartRow 2 -Value {$worksheet.cells[$row,$column].value / 864000000000 } +Write-Verbose -Message ("Cells Reset: " + $stopwatch.Elapsed.TotalSeconds) +Set-ExcelColumn -Worksheet $ws -Column 6 -NumberFormat '#.#,,"MB"' +Set-ExcelColumn -Worksheet $ws -Column 7 -NumberFormat '0.0,"KHz"' +$ws.Cells[$ws.Dimension].AutoFitColumns() + +#Make a Pivot table for sum of space and count of tracks by artist. Sort by artist, apply formatting to space, give it nice titles. +$pt = Add-PivotTable -PassThru -PivotTableName SpaceUsedByMusic -ExcelPackage $excel -SourceWorkSheet $ws ` + -PivotRows ALBUMARTIST -PivotData ([ordered]@{"Size"="Sum"; "Duration"="Count"}) -PivotDataToColumn + +$pt.RowFields[0].Sort = [OfficeOpenXml.Table.PivotTable.eSortType]::Ascending +$pt.DataFields[0].Format = '#.0,,"MB"' +$pt.DataFields[0].Name = 'Space Used' +$pt.DataFields[1].Name = 'Tracks' + +#Save the file, and load it into Excel +$stopwatch.Stop() +Write-Verbose -Message ("Pivot Done: " + $stopwatch.Elapsed.TotalSeconds) +Close-ExcelPackage -show $excel diff --git a/Examples/InteractWithOtherModules/Pester/Analyze_that.ps1 b/Examples/InteractWithOtherModules/Pester/Analyze_that.ps1 new file mode 100644 index 00000000..69e46593 --- /dev/null +++ b/Examples/InteractWithOtherModules/Pester/Analyze_that.ps1 @@ -0,0 +1,26 @@ +param( + $PesterTestsPath = "$PSScriptRoot\..\..\..\__tests__\" +) + +$xlfile = "$env:Temp\testResults.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$xlparams = @{ + Path = $xlfile + InputObject = (Invoke-Pester -Script $PesterTestsPath -PassThru).TestResult | Sort-Object describe + WorksheetName = 'FullResults' + + IncludePivotTable = $true + PivotRows = 'Describe' + PivotColumns = 'Passed' + PivotData = @{'Passed' = 'Count' } + + IncludePivotChart = $true + ChartType = 'BarClustered' + + AutoSize = $true + AutoFilter = $true + Activate = $true +} + +Export-Excel -Show @xlparams \ No newline at end of file diff --git a/Examples/InteractWithOtherModules/ScriptAnalyzer/Analyze_this.ps1 b/Examples/InteractWithOtherModules/ScriptAnalyzer/Analyze_this.ps1 new file mode 100644 index 00000000..77aad5d2 --- /dev/null +++ b/Examples/InteractWithOtherModules/ScriptAnalyzer/Analyze_this.ps1 @@ -0,0 +1,62 @@ +<# + .Synopsis + Runs PsScriptAnalyzer against one or more folders and pivots the results to form a report. + + .Example + Analyze_this.ps1 + Invokes script analyzer on the current directory; creates a file in $env:temp and opens it in Excel + .Example + Analyze_this.ps1 -xlfile ..\mymodule.xlsx -quiet + Invokes script analyzer on the current directory; creates a file in the parent directory but does not open it + .Example + "." , (dir 'C:\Program Files\WindowsPowerShell\Modules\ImportExcel\') | .\examples\ScriptAnalyzer\Analyze_this.ps1 + run from a developemnt directory for importExcel it will produce a report for that directory compared against installed versions + this creates the file in the default location and opens it +#> +[CmdletBinding()] +param ( + [parameter(ValueFromPipeline = $true)] + $Path = $PWD, + $xlfile = "$env:TEMP\ScriptAnalyzer.xlsx", + $ChartType = 'BarClustered' , + $PivotColumns = 'Location', + [switch]$Quiet +) + +begin { + Remove-Item -Path $xlfile -ErrorAction SilentlyContinue + $xlparams = @{ + Path = $xlfile + WorksheetName = 'FullResults' + AutoSize = $true + AutoFilter = $true + Activate = $true + Show = (-not $Quiet) + } + $pivotParams = @{ + PivotTableName = 'BreakDown' + PivotData = @{RuleName = 'Count' } + PivotRows = 'Severity', 'RuleName' + PivotColumns = 'Location' + PivotTotals = 'Rows' + } + $dirsToProcess = @() +} +process { + if ($path.fullName) {$dirsToProcess += $path.fullName} + elseif ($path.path) {$dirsToProcess += $path.Path} + else {$dirsToProcess += $path} +} + +end { + $pivotParams['-PivotChartDefinition'] = New-ExcelChartDefinition -ChartType $chartType -Column (1 + $dirsToProcess.Count) -Title "Script analysis" -LegendBold + $xlparams['PivotTableDefinition'] = New-PivotTableDefinition @pivotParams + + $dirsToProcess | ForEach-Object { + $dirName = (Resolve-Path -Path $_) -replace "^.*\\(.*?)\\(.*?)$", '$1-$2' + Write-Progress -Activity "Running Script Analyzer" -CurrentOperation $dirName + Invoke-ScriptAnalyzer -Path $_ -ErrorAction SilentlyContinue | + Add-Member -MemberType NoteProperty -Name Location -Value $dirName -PassThru + } | Export-Excel @xlparams + Write-Progress -Activity "Running Script Analyzer" -Completed +} diff --git a/Examples/InvokeExcelQuery/Examples.ps1 b/Examples/InvokeExcelQuery/Examples.ps1 new file mode 100644 index 00000000..a42da76d --- /dev/null +++ b/Examples/InvokeExcelQuery/Examples.ps1 @@ -0,0 +1,14 @@ +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$queries = +'select * from [sheet1$A:A]', +'select * from [sheet1$]', +'select * from [sheet1$A2:E11]', +'select F2,F5 from [sheet1$A2:E11]', +'select * from [sheet1$A2:E11] where F2 = "Grocery"', +'select F2 as [Category], F5 as [Discount], F5*2 as [DiscountPlus] from [sheet1$A2:E11]' + +foreach ($query in $queries) { + "query: $($query)" + Invoke-ExcelQuery .\testOleDb.xlsx $query | Format-Table +} diff --git a/Examples/InvokeExcelQuery/testOleDb.xlsx b/Examples/InvokeExcelQuery/testOleDb.xlsx new file mode 100644 index 00000000..944751c9 Binary files /dev/null and b/Examples/InvokeExcelQuery/testOleDb.xlsx differ diff --git a/Examples/JoinWorksheet/EastSales.csv b/Examples/JoinWorksheet/EastSales.csv new file mode 100644 index 00000000..016be35d --- /dev/null +++ b/Examples/JoinWorksheet/EastSales.csv @@ -0,0 +1,6 @@ +"Region","Item","UnitSold","UnitCost" +"East","Banana","38","0.26" +"East","Kale","71","0.69" +"East","Apple","35","0.55" +"East","Potato","48","0.48" +"East","Kale","41","0.74" \ No newline at end of file diff --git a/Examples/JoinWorksheet/Join-Worksheet.sample.ps1 b/Examples/JoinWorksheet/Join-Worksheet.sample.ps1 new file mode 100644 index 00000000..6ba2f2ef --- /dev/null +++ b/Examples/JoinWorksheet/Join-Worksheet.sample.ps1 @@ -0,0 +1,46 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Create simple pages for 3 stores with product ID, Product Name, quanity price and total + +@" +ID,Product,Quantity,Price,Total +12001,Nails,37,3.99,147.63 +12002,Hammer,5,12.10,60.5 +12003,Saw,12,15.37,184.44 +12010,Drill,20,8,160 +12011,Crowbar,7,23.48,164.36 +"@ | ConvertFrom-Csv| Export-Excel -Path $xlSourcefile -WorkSheetname Oxford + +@" +ID,Product,Quantity,Price,Total +12001,Nails,53,3.99,211.47 +12002,Hammer,6,12.10,72.60 +12003,Saw,10,15.37,153.70 +12010,Drill,10,8,80 +12012,Pliers,2,14.99,29.98 +"@ | ConvertFrom-Csv| Export-Excel -Path $xlSourcefile -WorkSheetname Abingdon + + +@" +ID,Product,Quantity,Price,Total +12001,Nails,20,3.99,79.80 +12002,Hammer,2,12.10,24.20 +12010,Drill,11,8,88 +12012,Pliers,3,14.99,44.97 +"@ | ConvertFrom-Csv| Export-Excel -Path $xlSourcefile -WorkSheetname Banbury + +#define a pivot table with a chart to show a sales by store, broken down by product +$ptdef = New-PivotTableDefinition -PivotTableName "Summary" -PivotRows "Store" -PivotColumns "Product" -PivotData @{"Total"="SUM"} -IncludePivotChart -ChartTitle "Sales Breakdown" -ChartType ColumnStacked -ChartColumn 10 + +#Join the 3 worksheets. +#Name the combined page "Total" and Name the column with the sheet names "store" (as the sheets 'Oxford','Abingdon' and 'Banbury' are the names of the stores +#Format the data as a table named "Summary", using the style "Light1", put the column headers in bold +#Put in a title and freeze to top of the sheet including title and colmun headings +#Add the Pivot table. +#Show the result +Join-Worksheet -Path $xlSourcefile -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "Combined" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2,1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -PivotTableDefinition $ptdef -show diff --git a/Examples/JoinWorksheet/Join-worksheet-blocks.sample.ps1 b/Examples/JoinWorksheet/Join-worksheet-blocks.sample.ps1 new file mode 100644 index 00000000..66848c8b --- /dev/null +++ b/Examples/JoinWorksheet/Join-worksheet-blocks.sample.ps1 @@ -0,0 +1,17 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Export disk volume, and Network adapter to their own sheets. +Get-CimInstance -ClassName Win32_LogicalDisk | + Select-Object -Property DeviceId,VolumeName, Size,Freespace | + Export-Excel -Path $xlSourcefile -WorkSheetname Volumes -NumberFormat "0,000" +Get-NetAdapter | + Select-Object -Property Name,InterfaceDescription,MacAddress,LinkSpeed | + Export-Excel -Path $xlSourcefile -WorkSheetname NetAdapters + +#Create a summary page with a title of Summary, label the blocks with the name of the sheet they came from and hide the source sheets +Join-Worksheet -Path $xlSourcefile -HideSource -WorkSheetName Summary -NoHeader -LabelBlocks -AutoSize -Title "Summary" -TitleBold -TitleSize 22 -show diff --git a/Examples/JoinWorksheet/JoinSalesData.ps1 b/Examples/JoinWorksheet/JoinSalesData.ps1 new file mode 100644 index 00000000..a572e76d --- /dev/null +++ b/Examples/JoinWorksheet/JoinSalesData.ps1 @@ -0,0 +1,24 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$params = @{ + AutoSize = $true + AutoFilter = $true + AutoNameRange = $true + ExcelChartDefinition = New-ExcelChartDefinition -XRange Item -YRange UnitSold -Title 'Units Sold' + Path = $xlSourcefile +} +#Import 4 sets of sales data from 4 CSV files, using the parameters above. +Import-Csv $PSScriptRoot\NorthSales.csv | Export-Excel -WorkSheetname North @params +Import-Csv $PSScriptRoot\EastSales.csv | Export-Excel -WorkSheetname East @params +Import-Csv $PSScriptRoot\SouthSales.csv | Export-Excel -WorkSheetname South @params +Import-Csv $PSScriptRoot\WestSales.csv | Export-Excel -WorkSheetname West @params + +#Join the 4 worksheets together on a sheet named Allsales, use the same parameters, except for AutoNameRange and ExcelChartDefinition. +$params.Remove("AutoNameRange") +$params.Remove("ExcelChartDefinition") +Join-Worksheet -WorkSheetName AllSales -Show @params \ No newline at end of file diff --git a/Examples/JoinWorksheet/NorthSales.csv b/Examples/JoinWorksheet/NorthSales.csv new file mode 100644 index 00000000..361c9b20 --- /dev/null +++ b/Examples/JoinWorksheet/NorthSales.csv @@ -0,0 +1,5 @@ +"Region","Item","UnitSold","UnitCost" +"North","Apple","40","0.68" +"North","Kale","55","0.35" +"North","Banana","33","0.31" +"North","Pear","29","0.74" \ No newline at end of file diff --git a/Examples/JoinWorksheet/SouthSales.csv b/Examples/JoinWorksheet/SouthSales.csv new file mode 100644 index 00000000..a268248c --- /dev/null +++ b/Examples/JoinWorksheet/SouthSales.csv @@ -0,0 +1,6 @@ +"Region","Item","UnitSold","UnitCost" +"South","Banana","54","0.46" +"South","Pear","39","0.44" +"South","Potato","33","0.46" +"South","Banana","49","0.31" +"South","Apple","38","0.59" \ No newline at end of file diff --git a/Examples/JoinWorksheet/WestSales.csv b/Examples/JoinWorksheet/WestSales.csv new file mode 100644 index 00000000..26770ee5 --- /dev/null +++ b/Examples/JoinWorksheet/WestSales.csv @@ -0,0 +1,12 @@ +"Region","Item","UnitSold","UnitCost" +"West","Banana","74","0.56" +"West","Apple","26","0.7" +"West","Banana","59","0.49" +"West","Potato","56","0.62" +"West","Banana","60","0.64" +"West","Pear","32","0.29" +"West","Apple","73","0.26" +"West","Banana","49","0.59" +"West","Pear","65","0.35" +"West","Apple","60","0.34" +"West","Kale","67","0.38" \ No newline at end of file diff --git a/Examples/JustCharts/CentralLimitTheorem.ps1 b/Examples/JustCharts/CentralLimitTheorem.ps1 index 7696d374..6945647a 100644 --- a/Examples/JustCharts/CentralLimitTheorem.ps1 +++ b/Examples/JustCharts/CentralLimitTheorem.ps1 @@ -1,4 +1,6 @@ -ColumnChart -Title "Central Limit Theorem" -NoLegend ($( +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +ColumnChart -Title "Central Limit Theorem" -NoLegend ($( for ($i = 1; $i -le 500; $i++) { $s = 0 for ($j = 1; $j -le 100; $j++) { diff --git a/Examples/JustCharts/PieChartHandles.ps1 b/Examples/JustCharts/PieChartHandles.ps1 index 357eee91..12f54780 100644 --- a/Examples/JustCharts/PieChartHandles.ps1 +++ b/Examples/JustCharts/PieChartHandles.ps1 @@ -2,5 +2,7 @@ # Sum up handles by company # Show the Pie Chart +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + PieChart -Title "Total Handles by Company" ` - (Invoke-Sum (Get-Process|Where company) company handles) + (Invoke-Sum (Get-Process | Where-Object company) company handles) diff --git a/Examples/JustCharts/PieChartPM.ps1 b/Examples/JustCharts/PieChartPM.ps1 index 3a911cfc..1d245872 100644 --- a/Examples/JustCharts/PieChartPM.ps1 +++ b/Examples/JustCharts/PieChartPM.ps1 @@ -2,6 +2,8 @@ # Sum up PM by company # Show the Pie Chart +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + PieChart -Title "Total PM by Company" ` - (Invoke-Sum (Get-Process|Where company) company pm) + (Invoke-Sum (Get-Process|Where-Object company) company pm) diff --git a/Examples/JustCharts/TargetData.ps1 b/Examples/JustCharts/TargetData.ps1 index 26079200..23ff8e2c 100644 --- a/Examples/JustCharts/TargetData.ps1 +++ b/Examples/JustCharts/TargetData.ps1 @@ -1,4 +1,4 @@ -$PropertyNames = echo Cost Date Name +$PropertyNames = @("Cost", "Date", "Name") New-PSItem 1.1 1/1/2015 John $PropertyNames New-PSItem 2.1 1/2/2015 Tom diff --git a/Examples/JustCharts/TryBarChart.ps1 b/Examples/JustCharts/TryBarChart.ps1 index 11fec699..d007dcd7 100644 --- a/Examples/JustCharts/TryBarChart.ps1 +++ b/Examples/JustCharts/TryBarChart.ps1 @@ -1 +1,3 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + BarChart (.\TargetData.ps1) "A BarChart" \ No newline at end of file diff --git a/Examples/JustCharts/TryColumnChart.ps1 b/Examples/JustCharts/TryColumnChart.ps1 index a184db43..945647a5 100644 --- a/Examples/JustCharts/TryColumnChart.ps1 +++ b/Examples/JustCharts/TryColumnChart.ps1 @@ -1 +1,3 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + ColumnChart (.\TargetData.ps1) "A ColumnChart" diff --git a/Examples/JustCharts/TryPieChart.ps1 b/Examples/JustCharts/TryPieChart.ps1 index 236bc963..016abf7b 100644 --- a/Examples/JustCharts/TryPieChart.ps1 +++ b/Examples/JustCharts/TryPieChart.ps1 @@ -1 +1,3 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + PieChart (.\TargetData.ps1) "A PieChart" \ No newline at end of file diff --git a/Examples/MergeWorkSheet/MergeCSV.ps1 b/Examples/MergeWorkSheet/MergeCSV.ps1 new file mode 100644 index 00000000..bef07e30 --- /dev/null +++ b/Examples/MergeWorkSheet/MergeCSV.ps1 @@ -0,0 +1,20 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$leftCsv = @" +MyProp1,MyProp2,Length +a,b,10 +c,d,20 +"@ | ConvertFrom-Csv + +$rightCsv = @" +MyProp1,MyProp2,Length +a,b,10 +c,d,21 +"@ | ConvertFrom-Csv + +Merge-Worksheet -OutputFile $xlSourcefile -ReferenceObject $leftCsv -DifferenceObject $rightCsv -Key Length -Show \ No newline at end of file diff --git a/Examples/MergeWorkSheet/Merge_2_Servers_Services.ps1 b/Examples/MergeWorkSheet/Merge_2_Servers_Services.ps1 new file mode 100644 index 00000000..dc041162 --- /dev/null +++ b/Examples/MergeWorkSheet/Merge_2_Servers_Services.ps1 @@ -0,0 +1,23 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item -Path "$env:temp\server*.xlsx" , "$env:temp\Combined*.xlsx" -ErrorAction SilentlyContinue + +#Get a subset of services into $s and export them +[System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property * +$s | Export-Excel -Path $env:temp\server1.xlsx + +#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s. +#Change a row. Add a row. Delete a row. And export the changed $s to a second file. +$s[2].DisplayName = "Changed from the orginal" #This will be row 4 in Excel - this should be highlighted as a change + +$d = $s[-1] | Select-Object -Property * +$d.DisplayName = "Dummy Service" +$d.Name = "Dummy" +$s.Insert(3,$d) #This will be row 5 in Excel - this should be highlighted as a new item + +$s.RemoveAt(5) #This will be row 7 in Excel - this should be highlighted as deleted item + +$s | Export-Excel -Path $env:temp\server2.xlsx + +#This use of Merge-worksheet Assumes a default worksheet name, (sheet1) We will check and output Name (the key), DisplayName and StartType and ignore other properties. +Merge-Worksheet -Referencefile "$env:temp\server1.xlsx" -Differencefile "$env:temp\Server2.xlsx" -OutputFile "$env:temp\combined1.xlsx" -Property name,displayname,startType -Key name -Show \ No newline at end of file diff --git a/Examples/MergeWorkSheet/Merge_3_Servers_Services.ps1 b/Examples/MergeWorkSheet/Merge_3_Servers_Services.ps1 new file mode 100644 index 00000000..d2f31851 --- /dev/null +++ b/Examples/MergeWorkSheet/Merge_3_Servers_Services.ps1 @@ -0,0 +1,36 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item -Path "$env:temp\server*.xlsx" , "$env:temp\Combined*.xlsx" -ErrorAction SilentlyContinue + +#Get a subset of services into $s and export them +[System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property Name,DisplayName,StartType +$s | Export-Excel -Path $env:temp\server1.xlsx + +#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s. +#Change a row. Add a row. Delete a row. And export the changed $s to a second file. +$row4Displayname = $s[2].DisplayName +$s[2].DisplayName = "Changed from the orginal" #This will be excel row 4 and Server 2 will show as changed. + +$d = $s[-1] | Select-Object -Property * +$d.DisplayName = "Dummy Service" +$d.Name = "Dummy" +$s.Insert(3,$d) #This will be Excel row 5 and server 2 will show as changed - so will Server 3 + +$s.RemoveAt(5) #This will be Excel row 7 and Server 2 will show as missing. + +$s | Export-Excel -Path $env:temp\server2.xlsx + +#Make some more changes to $s and export it to a third file +$s[2].displayname = $row4Displayname #Server 3 row 4 will match server 1 so won't be highlighted + +$d = $s[-1] | Select-Object -Property * +$d.DisplayName = "Second Service" +$d.Name = "Service2" +$s.Insert(6,$d) #This will be an extra row in Server 3 at row 8. It will show as missing in Server 2. +$s.RemoveAt(8) #This will show as missing in Server 3 at row 11 () + +$s | Export-Excel -Path $env:temp\server3.xlsx + +#Now bring the three files together. + +Merge-MultipleSheets -Path "$env:temp\server1.xlsx", "$env:temp\Server2.xlsx","$env:temp\Server3.xlsx" -OutputFile "$env:temp\combined3.xlsx" -Property name,displayname,startType -Key name -Show \ No newline at end of file diff --git a/Examples/MortgageCalculator/MortgageCalculator.ps1 b/Examples/MortgageCalculator/MortgageCalculator.ps1 new file mode 100644 index 00000000..2b0f7d67 --- /dev/null +++ b/Examples/MortgageCalculator/MortgageCalculator.ps1 @@ -0,0 +1,56 @@ +<# + Fixed Rate Loan/Mortgage Calculator in Excel +#> + +param( + $Amount = 400000, + $InterestRate = .065, + $Term = 30 +) +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} +function New-CellData { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification='Does not change system state')] + param( + $Range, + $Value, + $Format + ) + + $setFormatParams = @{ + Worksheet = $ws + Range = $Range + NumberFormat = $Format + } + + if ($Value -is [string] -and $Value.StartsWith('=')) { + $setFormatParams.Formula = $Value + } + else { + $setFormatParams.Value = $Value + } + + Set-ExcelRange @setFormatParams +} + +$f = "$PSScriptRoot\mortgage.xlsx" +Remove-Item $f -ErrorAction SilentlyContinue + +$pkg = "" | Export-Excel $f -Title 'Fixed Rate Loan Payments' -PassThru -AutoSize +$ws = $pkg.Workbook.Worksheets["Sheet1"] + +New-CellData -Range A3 -Value 'Amount' +New-CellData -Range B3 -Value $Amount -Format '$#,##0' + +New-CellData -Range A4 -Value "Interest Rate" +New-CellData -Range B4 -Value $InterestRate -Format 'Percentage' + +New-CellData -Range A5 -Value "Term (Years)" +New-CellData -Range B5 -Value $Term + +New-CellData -Range D3 -Value "Monthly Payment" +New-CellData -Range F3 -Value "=-PMT(F4, B5*12, B3)" -Format '$#,##0.#0' + +New-CellData -Range D4 -Value "Monthly Rate" +New-CellData -Range F4 -Value "=((1+B4)^(1/12))-1" -Format 'Percentage' + +Close-ExcelPackage $pkg -Show \ No newline at end of file diff --git a/Examples/MoveSheets/MoveSheets.ps1 b/Examples/MoveSheets/MoveSheets.ps1 new file mode 100644 index 00000000..330746ac --- /dev/null +++ b/Examples/MoveSheets/MoveSheets.ps1 @@ -0,0 +1,9 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\testThis.xlsx" +Remove-Item $xlfile -ErrorAction Ignore + +1..10 | Export-Excel $xlfile -WorkSheetname First #'First' will be the only sheet +11..20 | Export-Excel $xlfile -WorkSheetname Second -MoveToStart #'Second' is moved before first so the order is 'Second', 'First' +21..30 | Export-Excel $xlfile -WorkSheetname Third -MoveBefore First #'Second' is moved before first so the order is 'Second', 'Third', 'First' +31..40 | Export-Excel $xlfile -WorkSheetname Fourth -MoveAfter Third -Show #'Fourth' is moved after third so the order is ' 'Second', 'Third', 'Fourth' First' \ No newline at end of file diff --git a/Examples/Nasa/FireBalls.ps1 b/Examples/Nasa/FireBalls.ps1 index b0582c4c..625aa873 100644 --- a/Examples/Nasa/FireBalls.ps1 +++ b/Examples/Nasa/FireBalls.ps1 @@ -1,19 +1,22 @@ -$header = echo ` - 'Date/Time - Peak Brightness (UT)' ` - 'Latitude (Deg)' ` - 'Longitude (Deg)' ` - 'Altitude (km)' ` - 'Velocity (km/s)' ` - 'Velocity Components (km/s) vx' ` - 'Velocity Components (km/s) vy' ` - 'Velocity Components (km/s) vz' ` - 'Total Radiated Energy (J)' ` +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$header = @( + 'Date/Time - Peak Brightness (UT)' , + 'Latitude (Deg)' , + 'Longitude (Deg)' , + 'Altitude (km)' , + 'Velocity (km/s)' , + 'Velocity Components (km/s) vx' , + 'Velocity Components (km/s) vy' , + 'Velocity Components (km/s) vz' , + 'Total Radiated Energy (J)' , 'Calculated Total Impact Energy (kt)' +) $splat=@{ url='http://neo.jpl.nasa.gov/fireballs/' - index=5 - Header=$header + index=5 + Header=$header FirstDataRow=1 } diff --git a/Examples/New-PSItem.ps1 b/Examples/New-PSItem.ps1 index b186dcc2..85a41c3d 100644 --- a/Examples/New-PSItem.ps1 +++ b/Examples/New-PSItem.ps1 @@ -1,5 +1,6 @@ function New-PSItem { - + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification='Does not change system state')] + param() $totalArgs = $args.Count if($args[-1] -is [array]) { diff --git a/Examples/NumberFormat/ColorizeNumbers.ps1 b/Examples/NumberFormat/ColorizeNumbers.ps1 index 7d80f520..0b6a026d 100644 --- a/Examples/NumberFormat/ColorizeNumbers.ps1 +++ b/Examples/NumberFormat/ColorizeNumbers.ps1 @@ -1,6 +1,8 @@ -$file = "disks.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $file -ErrorAction Ignore +$file = "$env:TEMP\disks.xlsx" + +Remove-Item $file -ErrorAction Ignore $data = $( New-PSItem 100 -100 @@ -9,5 +11,5 @@ $data = $( New-PSItem -3.2 -4.1 New-PSItem -5.2 6.1 ) - +#Set the numbers throughout the sheet to format as positive in blue with a + sign, negative in Red with a - sign. $data | Export-Excel -Path $file -Show -AutoSize -NumberFormat "[Blue]+0.#0;[Red]-0.#0" diff --git a/Examples/NumberFormat/CurrencyFormat.ps1 b/Examples/NumberFormat/CurrencyFormat.ps1 index 1d608cee..490b9d7a 100644 --- a/Examples/NumberFormat/CurrencyFormat.ps1 +++ b/Examples/NumberFormat/CurrencyFormat.ps1 @@ -1,6 +1,8 @@ -$file = "disks.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $file -ErrorAction Ignore +$file = "$env:temp\disks.xlsx" + +Remove-Item $file -ErrorAction Ignore $data = $( New-PSItem 100 -100 @@ -10,6 +12,5 @@ $data = $( New-PSItem -5.2 6.1 New-PSItem 1000 -2000 ) - -$data | Export-Excel -Path $file -Show -AutoSize -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' - +#Number format can expand terms like Currency, to the local currency format +$data | Export-Excel -Path $file -Show -AutoSize -NumberFormat 'Currency' diff --git a/Examples/NumberFormat/PercentagFormat.ps1 b/Examples/NumberFormat/PercentagFormat.ps1 index 95b156b6..bd5d5e3b 100644 --- a/Examples/NumberFormat/PercentagFormat.ps1 +++ b/Examples/NumberFormat/PercentagFormat.ps1 @@ -1,6 +1,8 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + $file = "disks.xlsx" -rm $file -ErrorAction Ignore +Remove-Item $file -ErrorAction Ignore $data = $( New-PSItem 1 diff --git a/Examples/NumberFormat/PosNegNumbers.ps1 b/Examples/NumberFormat/PosNegNumbers.ps1 index 43fbf51a..4103837d 100644 --- a/Examples/NumberFormat/PosNegNumbers.ps1 +++ b/Examples/NumberFormat/PosNegNumbers.ps1 @@ -1,6 +1,8 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + $file = "disks.xlsx" -rm $file -ErrorAction Ignore +Remove-Item $file -ErrorAction Ignore $data = $( New-PSItem 100 -100 diff --git a/Examples/NumberFormat/Win32LogicalDisk.ps1 b/Examples/NumberFormat/Win32LogicalDisk.ps1 index 6dc590ee..97b3176e 100644 --- a/Examples/NumberFormat/Win32LogicalDisk.ps1 +++ b/Examples/NumberFormat/Win32LogicalDisk.ps1 @@ -1,7 +1,9 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + $file = "disks.xlsx" -rm $file -ErrorAction Ignore +Remove-Item $file -ErrorAction Ignore -Get-CimInstance win32_logicaldisk -filter "drivetype=3" | - Select DeviceID,Volumename,Size,Freespace | +Get-CimInstance win32_logicaldisk -filter "drivetype=3" | + Select-Object DeviceID,Volumename,Size,Freespace | Export-Excel -Path $file -Show -AutoSize -NumberFormat "0" \ No newline at end of file diff --git a/Examples/NumberFormat/Win32LogicalDiskFormatted.ps1 b/Examples/NumberFormat/Win32LogicalDiskFormatted.ps1 index 4e3b3c15..dd14ae5e 100644 --- a/Examples/NumberFormat/Win32LogicalDiskFormatted.ps1 +++ b/Examples/NumberFormat/Win32LogicalDiskFormatted.ps1 @@ -1,7 +1,9 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + $file = "disks.xlsx" -rm $file -ErrorAction Ignore +Remove-Item $file -ErrorAction Ignore -Get-CimInstance win32_logicaldisk -filter "drivetype=3" | - Select DeviceID,Volumename,Size,Freespace | +Get-CimInstance win32_logicaldisk -filter "drivetype=3" | + Select-Object DeviceID,Volumename,Size,Freespace | Export-Excel -Path $file -Show -AutoSize \ No newline at end of file diff --git a/Examples/OpenExcelPackage/EnableFeatures.ps1 b/Examples/OpenExcelPackage/EnableFeatures.ps1 new file mode 100644 index 00000000..2d3d2634 --- /dev/null +++ b/Examples/OpenExcelPackage/EnableFeatures.ps1 @@ -0,0 +1,28 @@ +# How to use Enable-ExcelAutoFilter and Enable-ExcelAutofit + +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$data = ConvertFrom-Csv @" +RegionInfo,StateInfo,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + +$xlfile = "$PSScriptRoot\enableFeatures.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data | Export-Excel $xlfile + +$excel = Open-ExcelPackage $xlfile + +Enable-ExcelAutoFilter -Worksheet $excel.Sheet1 +Enable-ExcelAutofit -Worksheet $excel.Sheet1 + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/OutTabulator/demo.txt b/Examples/OutTabulator/demo.txt new file mode 100644 index 00000000..0060900d --- /dev/null +++ b/Examples/OutTabulator/demo.txt @@ -0,0 +1,23 @@ +# ConvertFrom-Excel +'' + +.\test.xlsx + +Import-Excel .\test.xlsx | ft + +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html + +# Create a column definition +$columnOptions = @() + +$columnOptions += New-ColumnOption -ColumnName Progress -formatter progress +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions + +$columnOptions += New-ColumnOption Activity -formatter lineFormatter +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions + +$columnOptions += New-ColumnOption -ColumnName Rating -formatter star +$columnOptions += New-ColumnOption Driver -formatter tickCross +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions + +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions -groupBy Gender \ No newline at end of file diff --git a/Examples/OutTabulator/start-demo.ps1 b/Examples/OutTabulator/start-demo.ps1 new file mode 100644 index 00000000..5211e0d6 --- /dev/null +++ b/Examples/OutTabulator/start-demo.ps1 @@ -0,0 +1,218 @@ +## Start-Demo.ps1 +################################################################################################## +## This is an overhaul of Jeffrey Snover's original Start-Demo script by Joel "Jaykul" Bennett +## +## I've switched it to using ReadKey instead of ReadLine (you don't have to hit Enter each time) +## As a result, I've changed the names and keys for a lot of the operations, so that they make +## sense with only a single letter to tell them apart (sorry if you had them memorized). +## +## I've also been adding features as I come across needs for them, and you'll contribute your +## improvements back to the PowerShell Script repository as well. +################################################################################################## +## Revision History (version 3.3) +## 3.3.3 Fixed: Script no longer says "unrecognized key" when you hit shift or ctrl, etc. +## Fixed: Blank lines in script were showing as errors (now printed like comments) +## 3.3.2 Fixed: Changed the "x" to match the "a" in the help text +## 3.3.1 Fixed: Added a missing bracket in the script +## 3.3 - Added: Added a "Clear Screen" option +## - Added: Added a "Rewind" function (which I'm not using much) +## 3.2 - Fixed: Put back the trap { continue; } +## 3.1 - Fixed: No Output when invoking Get-Member (and other cmdlets like it???) +## 3.0 - Fixed: Commands which set a variable, like: $files = ls +## - Fixed: Default action doesn't continue +## - Changed: Use ReadKey instead of ReadLine +## - Changed: Modified the option prompts (sorry if you had them memorized) +## - Changed: Various time and duration strings have better formatting +## - Enhance: Colors are settable: prompt, command, comment +## - Added: NoPauseAfterExecute switch removes the extra pause +## If you set this, the next command will be displayed immediately +## - Added: Auto Execute mode (FullAuto switch) runs the rest of the script +## at an automatic speed set by the AutoSpeed parameter (or manually) +## - Added: Automatically append an empty line to the end of the demo script +## so you have a chance to "go back" after the last line of you demo +################################################################################################## +## +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Correct and desirable usage')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '', Justification='Correct and desirable usage')] +param( + $file=".\demo.txt", + [int]$command=0, + [System.ConsoleColor]$promptColor="Yellow", + [System.ConsoleColor]$commandColor="White", + [System.ConsoleColor]$commentColor="Green", + [switch]$FullAuto, + [int]$AutoSpeed = 3, + [switch]$NoPauseAfterExecute +) + +$RawUI = $Host.UI.RawUI +$hostWidth = $RawUI.BufferSize.Width + +# A function for reading in a character +function Read-Char() { + $_OldColor = $RawUI.ForeGroundColor + $RawUI.ForeGroundColor = "Red" + $inChar=$RawUI.ReadKey("IncludeKeyUp") + # loop until they press a character, so Shift or Ctrl, etc don't terminate us + while($inChar.Character -eq 0){ + $inChar=$RawUI.ReadKey("IncludeKeyUp") + } + $RawUI.ForeGroundColor = $_OldColor + return $inChar.Character +} + +function Rewind($lines, $index, $steps = 1) { + $started = $index; + $index -= $steps; + while(($index -ge 0) -and ($lines[$index].Trim(" `t").StartsWith("#"))){ + $index-- + } + if( $index -lt 0 ) { $index = $started } + return $index +} + +$file = Resolve-Path $file +while(-not(Test-Path $file)) { + $file = Read-Host "Please enter the path of your demo script (Crtl+C to cancel)" + $file = Resolve-Path $file +} + +Clear-Host + +$_lines = Get-Content $file +# Append an extra (do nothing) line on the end so we can still go back after the last line. +$_lines += "Write-Host 'The End'" +$_starttime = [DateTime]::now +$FullAuto = $false + +Write-Host -nonew -back black -fore $promptColor $(" " * $hostWidth) +Write-Host -nonew -back black -fore $promptColor @" +$(' ' * ($hostWidth -(18 + $(split-path $file -leaf).Length))) +"@ +Write-Host -nonew -back black -fore $promptColor "Press" +Write-Host -nonew -back black -fore Red " ? " +Write-Host -nonew -back black -fore $promptColor "for help.$(' ' * ($hostWidth -17))" +Write-Host -nonew -back black -fore $promptColor $(" " * $hostWidth) + +# We use a FOR and an INDEX ($_i) instead of a FOREACH because +# it is possible to start at a different location and/or jump +# around in the order. +for ($_i = $Command; $_i -lt $_lines.count; $_i++) +{ + # Put the current command in the Window Title along with the demo duration + $Dur = [DateTime]::Now - $_StartTime + $RawUI.WindowTitle = "$(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s {3}" -f + $dur.Hours, $dur.Minutes, $dur.Seconds, $($_Lines[$_i]) + + # Echo out the commmand to the console with a prompt as though it were real + Write-Host -nonew -fore $promptColor "[$_i]$([char]0x2265) " + if ($_lines[$_i].Trim(" ").StartsWith("#") -or $_lines[$_i].Trim(" ").Length -le 0) { + Write-Host -fore $commentColor "$($_Lines[$_i]) " + continue + } else { + Write-Host -nonew -fore $commandColor "$($_Lines[$_i]) " + } + + if( $FullAuto ) { Start-Sleep $autoSpeed; $ch = [char]13 } else { $ch = Read-Char } + switch($ch) + { + "?" { + Write-Host -Fore $promptColor @" + +Running demo: $file +(n) Next (p) Previous +(q) Quit (s) Suspend +(t) Timecheck (v) View $(split-path $file -leaf) +(g) Go to line by number +(f) Find lines by string +(a) Auto Execute mode +(c) Clear Screen +"@ + $_i-- # back a line, we're gonna step forward when we loop + } + "n" { # Next (do nothing) + Write-Host -Fore $promptColor "" + } + "p" { # Previous + Write-Host -Fore $promptColor "" + while ($_lines[--$_i].Trim(" ").StartsWith("#")){} + $_i-- # back a line, we're gonna step forward when we loop + } + "a" { # EXECUTE (Go Faster) + $AutoSpeed = [int](Read-Host "Pause (seconds)") + $FullAuto = $true; + Write-Host -Fore $promptColor "" + $_i-- # Repeat this line, and then just blow through the rest + } + "q" { # Quit + Write-Host -Fore $promptColor "" + $_i = $_lines.count; + break; + } + "v" { # View Source + $lines[0..($_i-1)] | Write-Host -Fore Yellow + $lines[$_i] | Write-Host -Fore Green + $lines[($_i+1)..$lines.Count] | Write-Host -Fore Yellow + $_i-- # back a line, we're gonna step forward when we loop + } + "t" { # Time Check + $dur = [DateTime]::Now - $_StartTime + Write-Host -Fore $promptColor $( + "{3} -- $(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s" -f + $dur.Hours, $dur.Minutes, $dur.Seconds, ([DateTime]::Now.ToShortTimeString())) + $_i-- # back a line, we're gonna step forward when we loop + } + "s" { # Suspend (Enter Nested Prompt) + Write-Host -Fore $promptColor "" + $Host.EnterNestedPrompt() + $_i-- # back a line, we're gonna step forward when we loop + } + "g" { # GoTo Line Number + $i = [int](Read-Host "line number") + if($i -le $_lines.Count) { + if($i -gt 0) { + # extra line back because we're gonna step forward when we loop + $_i = Rewind -lines $_lines -index $_i -steps (($_i-$i)+1) + } else { + $_i = -1 # Start negative, because we step forward when we loop + } + } + } + "f" { # Find by pattern + $match = $_lines | Select-String (Read-Host "search string") + if($null -eq $match) { + Write-Host -Fore Red "Can't find a matching line" + } else { + $match | ForEach-Object { Write-Host -Fore $promptColor $("[{0,2}] {1}" -f ($_.LineNumber - 1), $_.Line) } + if($match.Count -lt 1) { + $_i = $match.lineNumber - 2 # back a line, we're gonna step forward when we loop + } else { + $_i-- # back a line, we're gonna step forward when we loop + } + } + } + "c" { + Clear-Host + $_i-- # back a line, we're gonna step forward when we loop + } + "$([char]13)" { # on enter + Write-Host + trap [System.Exception] {Write-Error $_; continue;} + Invoke-Expression ($_lines[$_i]) | out-default + if(-not $NoPauseAfterExecute -and -not $FullAuto) { + $null = $RawUI.ReadKey("NoEcho,IncludeKeyUp") # Pause after output for no apparent reason... ;) + } + } + default + { + Write-Host -Fore Green "`nKey not recognized. Press ? for help, or ENTER to execute the command." + $_i-- # back a line, we're gonna step forward when we loop + } + } +} +$dur = [DateTime]::Now - $_StartTime +Write-Host -Fore $promptColor $( + "" -f + $dur.Hours, $dur.Minutes, $dur.Seconds, [DateTime]::Now.ToLongTimeString()) +Write-Host -Fore $promptColor $([DateTime]::now) +Write-Host \ No newline at end of file diff --git a/Examples/OutTabulator/targetout.html b/Examples/OutTabulator/targetout.html new file mode 100644 index 00000000..7da2bd64 --- /dev/null +++ b/Examples/OutTabulator/targetout.html @@ -0,0 +1,80 @@ + + + + + + + + Out-TabulatorView + + + + + + + + + + + +
+ + + + diff --git a/Examples/OutTabulator/tryConvertFromExcel.ps1 b/Examples/OutTabulator/tryConvertFromExcel.ps1 new file mode 100644 index 00000000..4372ba0f --- /dev/null +++ b/Examples/OutTabulator/tryConvertFromExcel.ps1 @@ -0,0 +1,9 @@ +[CmdletBinding()] +param($outFile = "$PSScriptRoot\targetout.html") + +$columnOptions = @() + +$columnOptions += New-ColumnOption -ColumnName Progress -formatter progress +$columnOptions += New-ColumnOption -ColumnName Activity -formatter lineFormatter + +ConvertFrom-Excel -ExcelFile $PSScriptRoot\test.xlsx -outFile $PSScriptRoot\targetout.html -columnOptions $columnOptions \ No newline at end of file diff --git a/Examples/PassThru/TryPassThru.ps1 b/Examples/PassThru/TryPassThru.ps1 index 0a7591af..424ce871 100644 --- a/Examples/PassThru/TryPassThru.ps1 +++ b/Examples/PassThru/TryPassThru.ps1 @@ -1,23 +1,29 @@ -$file = "sales.xlsx" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm $file -ErrorAction Ignore +$file = "$env:Temp\sales.xlsx" +Remove-Item $file -ErrorAction Ignore + +#Using -Passthru with Export-Excel returns an Excel Package object. $xlPkg = Import-Csv .\sales.csv | Export-Excel $file -PassThru -$ws = $xlPkg.Workbook.WorkSheets[1] +#We add script properties to the package so $xlPkg.Sheet1 is equivalent to $xlPkg.Workbook.WorkSheets["Sheet1"] +$ws = $xlPkg.Sheet1 +#We can manipulate the cells ... $ws.Cells["E1"].Value = "TotalSold" $ws.Cells["F1"].Value = "Add 10%" -2..($ws.Dimension.Rows) | - ForEach { +#This is for illustration - there are more efficient ways to do this. +2..($ws.Dimension.Rows) | + ForEach-Object { $ws.Cells["E$_"].Formula = "=C$_+D$_" $ws.Cells["F$_"].Formula = "=E$_+(10%*(C$_+D$_))" } $ws.Cells.AutoFitColumns() +#You can call close-ExcelPackage $xlPkg -show, but here we will do the ssteps explicitly $xlPkg.Save() $xlPkg.Dispose() - Invoke-Item $file \ No newline at end of file diff --git a/Examples/Pester-To-XLSx.ps1 b/Examples/Pester-To-XLSx.ps1 new file mode 100644 index 00000000..167a90f6 --- /dev/null +++ b/Examples/Pester-To-XLSx.ps1 @@ -0,0 +1,147 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectComparisonWithNull', '', Justification = 'Intentional use to select non null array items')] +[CmdletBinding(DefaultParameterSetName = 'Default')] +param( + [Parameter(Position = 0)] + [string]$XLFile, + + [Parameter(ParameterSetName = 'Default', Position = 1)] + [Alias('Path', 'relative_path')] + [object[]]$Script = '.', + + [Parameter(ParameterSetName = 'Existing', Mandatory = $true)] + [switch] + $UseExisting, + + [Parameter(ParameterSetName = 'Default', Position = 2)] + [Parameter(ParameterSetName = 'Existing', Position = 2, Mandatory = $true)] + [string]$OutputFile, + + [Parameter(ParameterSetName = 'Default')] + [Alias("Name")] + [string[]]$TestName, + + [Parameter(ParameterSetName = 'Default')] + [switch]$EnableExit, + + [Parameter(ParameterSetName = 'Default')] + [Alias('Tags')] + [string[]]$Tag, + [string[]]$ExcludeTag, + + [Parameter(ParameterSetName = 'Default')] + [switch]$Strict, + + [string]$WorkSheetName = 'PesterResults', + [switch]$append, + [switch]$Show +) + +$InvokePesterParams = @{OutputFormat = 'NUnitXml' } + $PSBoundParameters +if (-not $InvokePesterParams['OutputFile']) { + $InvokePesterParams['OutputFile'] = Join-Path -ChildPath 'Pester.xml'-Path ([environment]::GetFolderPath([System.Environment+SpecialFolder]::MyDocuments)) +} +if ($InvokePesterParams['Show'] ) { } +if ($InvokePesterParams['XLFile']) { $InvokePesterParams.Remove('XLFile') } +else { $XLFile = $InvokePesterParams['OutputFile'] -replace '.xml$', '.xlsx' } +if (-not $UseExisting) { + $InvokePesterParams.Remove('Append') + $InvokePesterParams.Remove('UseExisting') + $InvokePesterParams.Remove('Show') + $InvokePesterParams.Remove('WorkSheetName') + Invoke-Pester @InvokePesterParams +} + +if (-not (Test-Path -Path $InvokePesterParams['OutputFile'])) { + throw "Could not output file $($InvokePesterParams['OutputFile'])"; return +} + +$resultXML = ([xml](Get-Content $InvokePesterParams['OutputFile'])).'test-results' +$startDate = [datetime]$resultXML.date +$startTime = $resultXML.time +$machine = $resultXML.environment.'machine-name' +#$user = $resultXML.environment.'user-domain' + '\' + $resultXML.environment.user +$os = $resultXML.environment.platform -replace '\|.*$', " $($resultXML.environment.'os-version')" +<#hierarchy goes + root, [date], start [time], [Name] (always "Pester"), test results broken down as [total],[errors],[failures],[not-run] etc. + Environment (user & machine info) + Culture-Info (current, and currentUi culture) + Test-Suite [name] = "Pester" [result], [time] to execute, etc. + Results + Test-Suite [name] = filename,[result], [Time] to Execute etc + Results + Test-Suite [Name] = Describe block Name, [result], [Time] to execute etc.. + Results + Test-Suite [Name] = Context block name [result], [Time] to execute etc. + Results + Test-Case [name] = Describe.Context.It block names [description]= it block name, result], [Time] to execute etc + or if the tests are parameterized + Test suite [description] - name in the the it block with not filled in + Results + Test-case [description] - name as rendered for display with filled in +#> +$testResults = foreach ($test in $resultXML.'test-suite'.results.'test-suite') { + $testPs1File = $test.name + #Test if there are context blocks in the hierarchy OR if we go straight from Describe to test-case + if ($test.results.'test-suite'.results.'test-suite' -ne $null) { + foreach ($suite in $test.results.'test-suite') { + $Describe = $suite.description + foreach ($subsuite in $suite.results.'test-suite') { + $Context = $subsuite.description + if ($subsuite.results.'test-suite'.results.'test-case') { + $testCases = $subsuite.results.'test-suite'.results.'test-case' + } + else { $testCases = $subsuite.results.'test-case' } + $testCases | ForEach-Object { + New-Object -TypeName psobject -Property ([ordered]@{ + Machine = $machine ; OS = $os + Date = $startDate ; Time = $startTime + Executed = $(if ($_.executed -eq 'True') { 1 }) + Success = $(if ($_.success -eq 'True') { 1 }) + Duration = $_.time + File = $testPs1File; Group = $Describe + SubGroup = $Context ; Name = ($_.Description -replace '\s{2,}', ' ') + Result = $_.result ; FullDesc = '=Group&" "&SubGroup&" "&Name' + }) + } + } + } + } + else { + $test.results.'test-suite' | ForEach-Object { + $Describe = $_.description + $_.results.'test-case' | ForEach-Object { + New-Object -TypeName psobject -Property ([ordered]@{ + Machine = $machine ; OS = $os + Date = $startDate ; Time = $startTime + Executed = $(if ($_.executed -eq 'True') { 1 }) + Success = $(if ($_.success -eq 'True') { 1 }) + Duration = $_.time + File = $testPs1File; Group = $Describe + SubGroup = $null ; Name = ($_.Description -replace '\s{2,}', ' ') + Result = $_.result ; FullDesc = '=Group&" "&Test' + }) + } + } + } +} +if (-not $testResults) { Write-Warning 'No Results found' ; return } +$clearSheet = -not $Append +$excel = $testResults | Export-Excel -Path $xlFile -WorkSheetname $WorkSheetName -ClearSheet:$clearSheet -Append:$append -PassThru -BoldTopRow -FreezeTopRow -AutoSize -AutoFilter -AutoNameRange +$ws = $excel.Workbook.Worksheets[$WorkSheetName] +<# Worksheet should look like .. + |A |B |C D |E |F |G |H |I |J |K |L |M + 1|Machine |OS |Date Time |Executed |Success |Duration |File |Group |SubGroup |Name |Result |FullDescription + 2|Flatfish |Name_Version |[run started] |Boolean |Boolean |In seconds |xx.ps1 |Describe |Context |It |Success |Desc_Context_It +#> + +#Display Date as a date, not a date time +Set-Column -Worksheet $ws -Column 3 -NumberFormat 'Short Date' # -AutoSize + +#Hide columns E to J (Executed, Success, Duration, File, Group and Subgroup) +(5..10) | ForEach-Object { Set-ExcelColumn -Worksheet $ws -Column $_ -Hide } + +#Use conditional formatting to make Failures red, and Successes green (skipped remains black ) ... and save +$endRow = $ws.Dimension.End.Row +Add-ConditionalFormatting -WorkSheet $ws -range "L2:L$endrow" -RuleType ContainsText -ConditionValue "Failure" -BackgroundPattern None -ForegroundColor Red -Bold +Add-ConditionalFormatting -WorkSheet $ws -range "L2:L$endRow" -RuleType ContainsText -ConditionValue "Success" -BackgroundPattern None -ForeGroundColor Green +Close-ExcelPackage -ExcelPackage $excel -Show:$show diff --git a/Examples/PesterTestReport/Pester test report.ps1 b/Examples/PesterTestReport/Pester test report.ps1 new file mode 100644 index 00000000..72fd1fbd --- /dev/null +++ b/Examples/PesterTestReport/Pester test report.ps1 @@ -0,0 +1,225 @@ +#Requires -Modules @{ ModuleName='Pester'; ModuleVersion='5.1' } + +<# +.SYNOPSIS + Run Pester tests and export the results to an Excel file. + +.DESCRIPTION + Use the `PesterConfigurationFile` to configure Pester to your requirements. + (Set the Path to the folder containing the tests, ...). Pester will be + invoked with the configuration you defined. + + Each Pester 'it' clause will be exported to a row in an Excel file + containing the details of the test (Path, Duration, Result, ...). + +.EXAMPLE + $params = @{ + PesterConfigurationFile = 'C:\TestResults\PesterConfiguration.json' + ExcelFilePath = 'C:\TestResults\Tests.xlsx' + WorkSheetName = 'Tests' + } + & 'Pester test report.ps1' @params + + # Content 'C:\TestResults\PesterConfiguration.json': + { + "Run": { + "Path": "C:\Scripts" + } + + Executing the script with this configuration file will generate 1 file: + - 'C:\TestResults\Tests.xlsx' created by this script with Export-Excel + +.EXAMPLE + $params = @{ + PesterConfigurationFile = 'C:\TestResults\PesterConfiguration.json' + ExcelFilePath = 'C:\TestResults\Tests.xlsx' + WorkSheetName = 'Tests' + } + & 'Pester test report.ps1' @params + + # Content 'C:\TestResults\PesterConfiguration.json': + { + "Run": { + "Path": "C:\Scripts" + }, + "TestResult": { + "Enabled": true, + "OutputFormat": "NUnitXml", + "OutputPath": "C:/TestResults/PesterTestResults.xml", + "OutputEncoding": "UTF8" + } + } + + Executing the script with this configuration file will generate 2 files: + - 'C:\TestResults\PesterTestResults.xml' created by Pester + - 'C:\TestResults\Tests.xlsx' created by this script with Export-Excel + +.LINK + https://pester-docs.netlify.app/docs/commands/Invoke-Pester#-configuration +#> + +[CmdletBinding()] +Param ( + [String]$PesterConfigurationFile = 'PesterConfiguration.json', + [String]$WorkSheetName = 'PesterTestResults', + [String]$ExcelFilePath = 'PesterTestResults.xlsx' +) + +Begin { + Function Get-PesterTests { + [CmdLetBinding()] + Param ( + $Container + ) + + if ($testCaseResults = $Container.Tests) { + foreach ($result in $testCaseResults) { + Write-Verbose "Result '$($result.result)' duration '$($result.time)' name '$($result.name)'" + $result + } + } + + if ($containerResults = $Container.Blocks) { + foreach ($result in $containerResults) { + Get-PesterTests -Container $result + } + } + } + + #region Import Pester configuration file + Try { + Write-Verbose 'Import Pester configuration file' + $getParams = @{ + Path = $PesterConfigurationFile + Raw = $true + } + [PesterConfiguration]$pesterConfiguration = Get-Content @getParams | + ConvertFrom-Json + } + Catch { + throw "Failed importing the Pester configuration file '$PesterConfigurationFile': $_" + } + #endregion +} + +Process { + #region Execute Pester tests + Try { + Write-Verbose 'Execute Pester tests' + $pesterConfiguration.Run.PassThru = $true + $invokePesterParams = @{ + Configuration = $pesterConfiguration + ErrorAction = 'Stop' + } + $invokePesterResult = Invoke-Pester @invokePesterParams + } + Catch { + throw "Failed to execute the Pester tests: $_ " + } + #endregion + + #region Get Pester test results for the it clauses + $pesterTestResults = foreach ( + $container in $invokePesterResult.Containers + ) { + Get-PesterTests -Container $container | + Select-Object -Property *, + @{name = 'Container'; expression = { $container } } + } + #endregion +} + +End { + if ($pesterTestResults) { + #region Export Pester test results to an Excel file + $exportExcelParams = @{ + Path = $ExcelFilePath + WorksheetName = $WorkSheetName + ClearSheet = $true + PassThru = $true + BoldTopRow = $true + FreezeTopRow = $true + AutoSize = $true + AutoFilter = $true + AutoNameRange = $true + } + + Write-Verbose "Export Pester test results to Excel file '$($exportExcelParams.Path)'" + + $excel = $pesterTestResults | Select-Object -Property @{ + name = 'FilePath'; expression = { $_.container.Item.FullName } + }, + @{name = 'FileName'; expression = { $_.container.Item.Name } }, + @{name = 'Path'; expression = { $_.ExpandedPath } }, + @{name = 'Name'; expression = { $_.ExpandedName } }, + @{name = 'Date'; expression = { $_.ExecutedAt } }, + @{name = 'Time'; expression = { $_.ExecutedAt } }, + Result, + Passed, + Skipped, + @{name = 'Duration'; expression = { $_.Duration.TotalSeconds } }, + @{name = 'TotalDuration'; expression = { $_.container.Duration } }, + @{name = 'Tag'; expression = { $_.Tag -join ', ' } }, + @{name = 'Error'; expression = { $_.ErrorRecord -join ', ' } } | + Export-Excel @exportExcelParams + #endregion + + #region Format the Excel worksheet + $ws = $excel.Workbook.Worksheets[$WorkSheetName] + + # Display ExecutedAt in Date and Time format + Set-Column -Worksheet $ws -Column 5 -NumberFormat 'Short Date' + Set-Column -Worksheet $ws -Column 6 -NumberFormat 'hh:mm:ss' + + # Display Duration in seconds with 3 decimals + Set-Column -Worksheet $ws -Column 10 -NumberFormat '0.000' + + # Add comment to Duration column title + $comment = $ws.Cells['J1:J1'].AddComment('Total seconds', $env:USERNAME) + $comment.AutoFit = $true + + # Set the width for column Path + $ws.Column(3) | Set-ExcelRange -Width 29 + + # Center the column titles + Set-ExcelRange -Address $ws.Row(1) -Bold -HorizontalAlignment Center + + # Hide columns FilePath, Name, Passed and Skipped + (1, 4, 8, 9) | ForEach-Object { + Set-ExcelColumn -Worksheet $ws -Column $_ -Hide + } + + # Set the color to red when 'Result' is 'Failed' + $endRow = $ws.Dimension.End.Row + $formattingParams = @{ + Worksheet = $ws + range = "G2:L$endRow" + RuleType = 'ContainsText' + ConditionValue = "Failed" + BackgroundPattern = 'None' + ForegroundColor = 'Red' + Bold = $true + } + Add-ConditionalFormatting @formattingParams + + # Set the color to green when 'Result' is 'Passed' + $endRow = $ws.Dimension.End.Row + $formattingParams = @{ + Worksheet = $ws + range = "G2:L$endRow" + RuleType = 'ContainsText' + ConditionValue = "Passed" + BackgroundPattern = 'None' + ForegroundColor = 'Green' + } + Add-ConditionalFormatting @formattingParams + #endregion + + #region Save the formatted Excel file + Close-ExcelPackage -ExcelPackage $excel + #endregion + } + else { + Write-Warning 'No Pester test results to export' + } +} \ No newline at end of file diff --git a/Examples/PesterTestReport/PesterConfiguration.json b/Examples/PesterTestReport/PesterConfiguration.json new file mode 100644 index 00000000..6475effa --- /dev/null +++ b/Examples/PesterTestReport/PesterConfiguration.json @@ -0,0 +1,11 @@ +{ + "Run": { + "Path": "." + }, + "TestResult": { + "Enabled": false, + "OutputFormat": "NUnitXml", + "OutputPath": "PesterTestResults.xml", + "OutputEncoding": "UTF8" + } +} diff --git a/Examples/PivotTable/MultiplePivotTables.ps1 b/Examples/PivotTable/MultiplePivotTables.ps1 new file mode 100644 index 00000000..9aac6c0e --- /dev/null +++ b/Examples/PivotTable/MultiplePivotTables.ps1 @@ -0,0 +1,55 @@ +$data = ConvertFrom-Csv @" +Region,Date,Fruit,Sold +North,1/1/2017,Pears,50 +South,1/1/2017,Pears,150 +East,4/1/2017,Grapes,100 +West,7/1/2017,Bananas,150 +South,10/1/2017,Apples,200 +North,1/1/2018,Pears,100 +East,4/1/2018,Grapes,200 +West,7/1/2018,Bananas,300 +South,10/1/2018,Apples,400 +"@ | Select-Object -Property Region, @{n = "Date"; e = {[datetime]::ParseExact($_.Date, "M/d/yyyy", (Get-Culture))}}, Fruit, Sold + +$xlfile = "$env:temp\multiplePivotTables.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$excel = $data | Export-Excel $xlfile -PassThru -AutoSize -TableName FruitData + +$pivotTableParams = @{ + PivotTableName = "ByRegion" + Address = $excel.Sheet1.cells["F1"] + SourceWorkSheet = $excel.Sheet1 + PivotRows = @("Region", "Fruit", "Date") + PivotData = @{'sold' = 'sum'} + PivotTableStyle = 'Light21' + GroupDateRow = "Date" + GroupDatePart = @("Years", "Quarters") +} + +$pt = Add-PivotTable @pivotTableParams -PassThru +#$pt.RowHeaderCaption ="By Region,Fruit,Date" +$pt.RowHeaderCaption = "By " + ($pivotTableParams.PivotRows -join ",") + +$pivotTableParams.PivotTableName = "ByFruit" +$pivotTableParams.Address = $excel.Sheet1.cells["J1"] +$pivotTableParams.PivotRows = @("Fruit", "Region", "Date") + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Fruit,Region" + +$pivotTableParams.PivotTableName = "ByDate" +$pivotTableParams.Address = $excel.Sheet1.cells["N1"] +$pivotTableParams.PivotRows = @("Date", "Region", "Fruit") + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Date,Region,Fruit" + +$pivotTableParams.PivotTableName = "ByYears" +$pivotTableParams.Address = $excel.Sheet1.cells["S1"] +$pivotTableParams.GroupDatePart = "Years" + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Years,Region" + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/PivotTable/PivotTableWithName.ps1 b/Examples/PivotTable/PivotTableWithName.ps1 new file mode 100644 index 00000000..9ce3f340 --- /dev/null +++ b/Examples/PivotTable/PivotTableWithName.ps1 @@ -0,0 +1,25 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$ExcelParams = @{ + Path = "$env:TEMP\test1.xlsx" + IncludePivotTable = $true + PivotRows = 'Company' + PivotTableName = 'MyTable' + PivotData = @{'Handles' = 'sum'} + Show = $true + Activate = $true +} +Remove-Item $ExcelParams.Path -ErrorAction Ignore +Get-Process | Select-Object Company, Handles | Export-Excel @ExcelParams + +<# Builds a pivot table that looks like this: + + Sum of Handles + Row Labels Total + Adobe Systems Incorporated 3100 + (blank) 214374 + Apple Inc. 215 + etc + etc + Grand Total 365625 +#> \ No newline at end of file diff --git a/Examples/PivotTable/TableAndPivotTable.ps1 b/Examples/PivotTable/TableAndPivotTable.ps1 new file mode 100644 index 00000000..468d247c --- /dev/null +++ b/Examples/PivotTable/TableAndPivotTable.ps1 @@ -0,0 +1,30 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Export some sales data to Excel, format it as a table and put a data-bar in. For this example we won't create the pivot table during the export +$excel = ConvertFrom-Csv @" +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 +"@ | Export-Excel -PassThru -Path $xlSourcefile -TableStyle Medium13 -tablename "RawData" -ConditionalFormat @{Range="C2:C7"; DataBarColor="Green"} + +#Add a pivot table, specify its address to put it on the same sheet, use the data that was just exported set the table style and number format. +#Use the "City" for the row names, and "Product" for the columnnames, and sum both the gross and net values for each City/Product combination; add grand totals to rows and columns. +# activate the sheet and add a pivot chart (defined in a hash table) +Add-PivotTable -Address $excel.Sheet1.Cells["F1"] -SourceWorkSheet $Excel.Sheet1 -SourceRange $Excel.Sheet1.Dimension.Address -PivotTableName "Sales" -PivotTableStyle "Medium12" -PivotNumberFormat "$#,##0.00" ` + -PivotRows "City" -PivotColumns "Product" -PivotData @{Gross="Sum";Net="Sum"}-PivotTotals "Both" -Activate -PivotChartDefinition @{ + Title="Gross and net by city and product"; + ChartType="ColumnClustered"; + Column=11; Width=500; Height=360; + YMajorUnit=500; YMinorUnit=100; YAxisNumberformat="$#,##0" + LegendPosition="Bottom"} +#Save and open in excel +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/PivotTableFilters/dashboard.xlsx b/Examples/PivotTableFilters/dashboard.xlsx deleted file mode 100644 index f6fa0fb9..00000000 Binary files a/Examples/PivotTableFilters/dashboard.xlsx and /dev/null differ diff --git a/Examples/PivotTableFilters/testPivot.xlsx b/Examples/PivotTableFilters/testPivot.xlsx deleted file mode 100644 index 23da3b1e..00000000 Binary files a/Examples/PivotTableFilters/testPivot.xlsx and /dev/null differ diff --git a/Examples/PivotTableFilters/testPivotFilter.ps1 b/Examples/PivotTableFilters/testPivotFilter.ps1 index f63b349b..9963beb5 100644 --- a/Examples/PivotTableFilters/testPivotFilter.ps1 +++ b/Examples/PivotTableFilters/testPivotFilter.ps1 @@ -1,6 +1,6 @@ -Import-Module ..\..\ImportExcel.psd1 -Force +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -$xlFile=".\testPivot.xlsx" +$xlFile="$env:TEMP\testPivot.xlsx" Remove-Item $xlFile -ErrorAction Ignore $data =@" @@ -18,4 +18,18 @@ $data | -AutoSize -AutoFilter ` -IncludePivotTable ` -PivotRows Product ` - -PivotData @{"Units"="sum"} -PivotFilter Region, Area + -PivotData @{"Units"="sum"} -PivotFilter Region, Area -Activate + +<# +Creates a Pivot table that looks like +Region All^ +Area All^ + +Sum of Units +Row Labels Total +Apple 100 +Pear 240 +Grape 280 +Banana 160 +Grand Total 780 +#> \ No newline at end of file diff --git a/Examples/Plot/PlotCos.ps1 b/Examples/Plot/PlotCos.ps1 index aec098aa..6c4c6b8e 100644 --- a/Examples/Plot/PlotCos.ps1 +++ b/Examples/Plot/PlotCos.ps1 @@ -1,4 +1,6 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + $plt = New-Plot -$plt.Plot((Get-Range 0 5 .02|%{[math]::Cos(2*[math]::pi*$_)})) +$plt.Plot((Get-Range 0 5 .02|Foreach-Object {[math]::Cos(2*[math]::pi*$_)})) $plt.SetChartSize(800,300) $plt.Show() \ No newline at end of file diff --git a/Examples/PsGallery.ps1 b/Examples/PsGallery.ps1 new file mode 100644 index 00000000..2e5c44b4 --- /dev/null +++ b/Examples/PsGallery.ps1 @@ -0,0 +1,21 @@ + +$top1000 = foreach ($p in 1..50) { + $c = Invoke-WebRequest -Uri "https://www.powershellgallery.com/packages" -method Post -Body "q=&sortOrder=package-download-count&page=$p" + [regex]::Matches($c.Content,'.*?
', [System.Text.RegularExpressions.RegexOptions]::Singleline) | foreach { + $name = [regex]::Match($_, "(?<=

).*(?=

)").value + $n = [regex]::replace($_,'^.*By:\s*
  • ','', [System.Text.RegularExpressions.RegexOptions]::Singleline) + $n = [regex]::replace($n,'.*$','', [System.Text.RegularExpressions.RegexOptions]::Singleline) + $by = [regex]::match($n,'(?<=">).*(?=)').value + $qty = [regex]::match($n,'\S*(?= downloads)').value + [PSCustomObject]@{ + Name = $name + by = $by + Downloads = $qty + } + } +} + +del "~\Documents\gallery.xlsx" +$pivotdef = New-PivotTableDefinition -PivotTableName 'Summary' -PivotRows by -PivotData @{name="Count" + Downloads="Sum"} -PivotDataToColumn -Activate -ChartType ColumnClustered -PivotNumberFormat '#,###' +$top1000 | export-excel -path '~\Documents\gallery.xlsx' -Numberformat '#,###' -PivotTableDefinition $pivotdef -TableName 'TopDownloads' -Show \ No newline at end of file diff --git a/Examples/ReadAllSheets/GenerateXlsx.ps1 b/Examples/ReadAllSheets/GenerateXlsx.ps1 new file mode 100644 index 00000000..7b42ea19 --- /dev/null +++ b/Examples/ReadAllSheets/GenerateXlsx.ps1 @@ -0,0 +1,54 @@ +param( + [Parameter(Mandatory)] + $path +) + +$sheet1 = ConvertFrom-Csv @" +Region,Item,TotalSold +West,melon,27 +North,avocado,21 +West,kiwi,84 +East,melon,23 +North,kiwi,8 +North,nail,29 +North,kiwi,46 +South,nail,83 +East,pear,10 +South,avocado,40 +"@ + +$sheet2 = ConvertFrom-Csv @" +Region,Item,TotalSold +West,lemon,24 +North,hammer,41 +East,nail,87 +West,lemon,68 +North,screwdriver,9 +North,drill,76 +West,lime,28 +West,pear,78 +North,apple,95 +South,melon,40 +"@ + +$sheet3 = ConvertFrom-Csv @" +Region,Item,TotalSold +South,drill,100 +East,saw,22 +North,saw,5 +West,orange,78 +East,saw,27 +North,screwdriver,57 +South,hammer,66 +East,saw,62 +West,nail,98 +West,nail,98 +"@ + +Remove-Item $path -ErrorAction SilentlyContinue + +$sheet1 | Export-Excel $path -WorksheetName Sheet1 +$sheet2 | Export-Excel $path -WorksheetName Sheet2 +$sheet3 | Export-Excel $xlfile -WorksheetName Sheet3 + +$path \ No newline at end of file diff --git a/Examples/ReadAllSheets/Get-ExcelSheets.ps1 b/Examples/ReadAllSheets/Get-ExcelSheets.ps1 new file mode 100644 index 00000000..3aacdc9c --- /dev/null +++ b/Examples/ReadAllSheets/Get-ExcelSheets.ps1 @@ -0,0 +1,19 @@ +# Get-ExcelSheets + +param( + [Parameter(Mandatory)] + $path +) + + +$hash = @{ } + +$e = Open-ExcelPackage $path + +foreach ($sheet in $e.workbook.worksheets) { + $hash[$sheet.name] = Import-Excel -ExcelPackage $e -WorksheetName $sheet.name +} + +Close-ExcelPackage $e -NoSave + +$hash \ No newline at end of file diff --git a/Examples/ReadAllSheets/ReadAllSheets.ps1 b/Examples/ReadAllSheets/ReadAllSheets.ps1 new file mode 100644 index 00000000..cf48ca5d --- /dev/null +++ b/Examples/ReadAllSheets/ReadAllSheets.ps1 @@ -0,0 +1,4 @@ +$xlfile = "$env:TEMP\MultipleSheets.xlsx" + +.\GenerateXlsx.ps1 $xlfile +.\Get-ExcelSheets.ps1 $xlfile \ No newline at end of file diff --git a/Examples/SQL+FillColumns+Pivot/Example.ps1 b/Examples/SQL+FillColumns+Pivot/Example.ps1 index 79b8e8ba..78a54d54 100644 --- a/Examples/SQL+FillColumns+Pivot/Example.ps1 +++ b/Examples/SQL+FillColumns+Pivot/Example.ps1 @@ -1,33 +1,33 @@ - ipmo C:\Users\mcp\Documents\GitHub\ImportExcel\ImportExcel.psd1 -Force -Verbose +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} $sql = @" - SELECT rootfile.baseName , rootfile.extension , Image.fileWidth AS width , image.fileHeight AS height , + SELECT rootfile.baseName , rootfile.extension , Image.fileWidth AS width , image.fileHeight AS height , metadata.dateDay , metadata.dateMonth , metadata.dateYear , Image.captureTime AS dateTaken, metadata.hasGPS , metadata.GPSLatitude , metadata.GPSLongitude , - metadata.focalLength , metadata.flashFired , metadata.ISOSpeedRating AS ISOSpeed, + metadata.focalLength , metadata.flashFired , metadata.ISOSpeedRating AS ISOSpeed, metadata.Aperture AS apertureValue , metadata.ShutterSpeed AS shutterSpeedValue, Image.bitdepth , image.colorLabels , - Camera.Value AS cameraModel , LensRef.value AS lensModel - FROM Adobe_images image - JOIN AgLibraryFile rootFile ON rootfile.id_local = image.rootFile - JOIN AgharvestedExifMetadata metadata ON image.id_local = metadata.image + Camera.Value AS cameraModel , LensRef.value AS lensModel + FROM Adobe_images image + JOIN AgLibraryFile rootFile ON rootfile.id_local = image.rootFile + JOIN AgharvestedExifMetadata metadata ON image.id_local = metadata.image LEFT JOIN AgInternedExifLens LensRef ON LensRef.id_Local = metadata.lensRef - LEFT JOIN AgInternedExifCameraModel Camera ON Camera.id_local = metadata.cameraModelRef -"@ -`` + LEFT JOIN AgInternedExifCameraModel Camera ON Camera.id_local = metadata.cameraModelRef +"@ + #Sql Statement gets 20 columns of data from Adobe lightroom database -#Define a pivot table and chart for total pictures with each lens. +#Define a pivot table and chart for total pictures with each lens. -$pt = @{"LensPivot" = @{ "PivotTableName" = "LensPivot"; +$pt = @{"LensPivot" = @{ "PivotTableName" = "LensPivot"; "SourceWorkSheet" = "Sheet1" ; "PivotRows" = "LensModel" ; "PivotData" = @{"basename" = "Count"} ; "IncludePivotChart" = $true ; "NoLegend" = $true ; - "ShowPercent" = $true ; + "ShowPercent" = $true ; "ChartType" = "Pie" ; "ChartTitle" = "Split by Lens" } -} +} #we want to add 3 columns, translate Apperture value and Shutter speed value into familar f/ and seconds notation, and use these and ISO to calculate EV level $Avalue = {"=IF(P$ROW>6.63,TEXT(ROUND(Sqrt(Power(2,O$ROW)),1),`"`"`"f/`"`"0.0`")," + @@ -37,52 +37,52 @@ $Svalue = {"=IF(P$ROW>2,TEXT(ROUND(POWER(2,P$ROW),0),`"`"`"1/`"`"0`"`"sec "TEXT(ROUND(1/POWER(2,P$ROW),2),`"0`"`"Sec`"`"`")))"} $evValue = {"=ROUND(P$Row+O$Row-(LOG(N$Row/100,2)),0)" } -#remove and recreate the file +#remove and recreate the file Remove-Item -Path "~\Documents\temp.xlsx" -ErrorAction SilentlyContinue -#Open a connection to the ODBC source "LR" (which points to the SQLLite DB for Lightroom), run the SQL query, and drop into Excel - in sheet1, autosizing columns. +#Open a connection to the ODBC source "LR" (which points to the SQLLite DB for Lightroom), run the SQL query, and drop into Excel - in sheet1, autosizing columns. $e = Send-SQLDataToExcel -Path "~\Documents\temp.xlsx" -WorkSheetname "Sheet1" -Connection "DSN=LR" -SQL $sql -AutoSize -Passthru -#Add columns, then format them and hide the ones which aren't of interest. -Set-Column -Worksheet $e.workbook.Worksheets["sheet1"] -Column 21 -Value $Avalue -Heading "Apperture" -Set-Column -Worksheet $e.workbook.Worksheets["sheet1"] -Column 22 -Value $Svalue -Heading "Shutter" -Set-Column -Worksheet $e.workbook.Worksheets["sheet1"] -Column 23 -Value $Evvalue -Heading "Ev" -Set-Format -Address $e.workbook.Worksheets["sheet1" ].Column(21) -HorizontalAlignment Left -AutoFit -Set-Format -Address $e.workbook.Worksheets["sheet1" ].Column(22) -HorizontalAlignment Right -AutoFit +#Add columns, then format them and hide the ones which aren't of interest. +Set-ExcelColumn -Worksheet $e.workbook.Worksheets["sheet1"] -Column 21 -Value $Avalue -Heading "Apperture" +Set-ExcelColumn -Worksheet $e.workbook.Worksheets["sheet1"] -Column 22 -Value $Svalue -Heading "Shutter" +Set-ExcelColumn -Worksheet $e.workbook.Worksheets["sheet1"] -Column 23 -Value $Evvalue -Heading "Ev" +Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Column(21) -HorizontalAlignment Left -AutoFit +Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Column(22) -HorizontalAlignment Right -AutoFit @(5,6,7,13,15,16,17,18) | ForEach-Object { - Set-Format -Address $e.workbook.Worksheets["sheet1" ].Column($_) -Hidden + Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Column($_) -Hidden } -#Center the column labels. -Set-Format -Address $e.workbook.Worksheets["sheet1" ].Row(1) -HorizontalAlignment Center +#Center the column labels. +Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Row(1) -HorizontalAlignment Center -#Format the data as a nice Table, Create the pivot table & chart defined above, show the file in Excel in excel after saving. -Export-Excel -ExcelPackage $e -WorkSheetname "sheet1" -TableName "Table" -PivotTableDefinition $pt -Show +#Format the data as a nice Table, Create the pivot table & chart defined above, show the file in Excel in excel after saving. +Export-Excel -ExcelPackage $e -WorkSheetname "sheet1" -TableName "Table" -PivotTableDefinition $pt -Show ############################################################ Remove-Item .\demo3.xlsx #Database query to get race wins, Poles and fastest lapes for the 25 best drivers; we already have a connection to the DB in $dbSessions -$session = $DbSessions["f1"] +$session = $DbSessions["f1"] $SQL = @" - SELECT TOP 25 DriverName, + SELECT TOP 25 DriverName, Count(RaceDate) AS Races, - Count(Win) AS Wins, - Count(Pole) AS Poles, - Count(FastestLap) AS Fastlaps - FROM Results - GROUP BY DriverName + Count(Win) AS Wins, + Count(Pole) AS Poles, + Count(FastestLap) AS Fastlaps + FROM Results + GROUP BY DriverName ORDER BY (Count(win)) DESC -"@ +"@ -#Run the query and put the results in workshet "Winners", autosize the columns and hold on to the ExcelPackage object +#Run the query and put the results in workshet "Winners", autosize the columns and hold on to the ExcelPackage object $Excel = Send-SQLDataToExcel -SQL $sql -Session $session -path .\demo3.xlsx -WorkSheetname "Winners" -AutoSize -Passthru -#Create and format columns for the ratio of Wins to poles and fast laps. -Set-Column -ExcelPackage $Excel -WorkSheetname "Winners" -column 6 -Heading "WinsToPoles" -Value {"=D$row/C$row"} -Set-Column -ExcelPackage $Excel -WorkSheetname "Winners" -column 7 -Heading "WinsToFast" -Value {"=E$row/C$row"} +#Create and format columns for the ratio of Wins to poles and fast laps. +Set-ExcelColumn -ExcelPackage $Excel -WorkSheetname "Winners" -column 6 -Heading "WinsToPoles" -Value {"=D$row/C$row"} +Set-ExcelColumn -ExcelPackage $Excel -WorkSheetname "Winners" -column 7 -Heading "WinsToFast" -Value {"=E$row/C$row"} 6..7 | ForEach-Object { - Set-Format -Address $Excel.Workbook.Worksheets["Winners"].column($_) -NumberFormat "0.0%" -AutoFit } -#Define a chart to show the relationship of lest on an XY Grid, create the ranges required in the, add the chart and show the file in Excel in excel after saving. -$chart = New-ExcelChart -NoLegend -ChartType XYScatter -XRange WinsToFast -YRange WinsToPoles -ShowCategory -Column 7 -Width 2000 -Height 700 -Export-Excel -ExcelPackage $Excel -WorkSheetname "Winners" -AutoNameRange -ExcelChartDefinition $chart -Show + Set-ExcelRange -Address $Excel.Workbook.Worksheets["Winners"].column($_) -NumberFormat "0.0%" -AutoFit } +#Define a chart to show the relationship of lest on an XY Grid, create the ranges required in the, add the chart and show the file in Excel in excel after saving. +$chart = New-ExcelChartDefinition -NoLegend -ChartType XYScatter -XRange WinsToFast -YRange WinsToPoles -ShowCategory -Column 7 -Width 2000 -Height 700 +Export-Excel -ExcelPackage $Excel -WorkSheetname "Winners" -AutoNameRange -ExcelChartDefinition $chart -Show diff --git a/Examples/SQL+FillColumns+Pivot/Example2.ps1 b/Examples/SQL+FillColumns+Pivot/Example2.ps1 index c1e73228..65b8acc0 100644 --- a/Examples/SQL+FillColumns+Pivot/Example2.ps1 +++ b/Examples/SQL+FillColumns+Pivot/Example2.ps1 @@ -1,22 +1,24 @@ -ipmo C:\Users\mcp\Documents\GitHub\ImportExcel\ImportExcel.psd1 -Force +#requires -modules "getSql" +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} +#download f1Results from https://1drv.ms/f/s!AhfYu7-CJv4egbt5FD7Cdxi8jSz3aQ and update the path below Get-SQL -Session f1 -Excel -Connection C:\Users\mcp\OneDrive\Public\F1\f1Results.xlsx -showtables -Verbose -del .\demo3.xlsx +Remove-Item .\demo3.xlsx $session = $DbSessions["f1"] -$SQL = "SELECT top 25 DriverName, Count(RaceDate) as Races , - Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps - FROM Results GROUP BY DriverName - order by (count(win)) desc" -$Excel = Send-SQLDataToExcel -SQL $sql -Session $session -path .\demo3.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange -BoldTopRow -FreezeTopRow -Passthru +$SQL = "SELECT top 25 DriverName, Count(RaceDate) as Races , + Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps + FROM Results GROUP BY DriverName + order by (count(win)) desc" +$Excel = Send-SQLDataToExcel -SQL $sql -Session $session -path .\demo3.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange -BoldTopRow -FreezeTopRow -Passthru -$ws = $Excel.Workbook.Worksheets["Winners"] +$ws = $Excel.Workbook.Worksheets["Winners"] -Set-Row -Worksheet $ws -Heading "Average" -Value {"=Average($columnName`2:$columnName$endrow)"} -NumberFormat "0.0" -Bold -Set-Column -Worksheet $ws -Heading "WinsToPoles" -Value {"=D$row/C$row"} -Column 6 -AutoSize -AutoNameRange -Set-Column -Worksheet $ws -Heading "WinsToFast" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange +Set-ExcelRow -Worksheet $ws -Heading "Average" -Value {"=Average($columnName`2:$columnName$endrow)"} -NumberFormat "0.0" -Bold +Set-ExcelColumn -Worksheet $ws -Heading "WinsToPoles" -Value {"=D$row/C$row"} -Column 6 -AutoSize -AutoNameRange +Set-ExcelColumn -Worksheet $ws -Heading "WinsToFast" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange -Set-Format -WorkSheet $ws -Range "F2:G50" -NumberFormat "0.0%" -$chart = New-ExcelChart -NoLegend -ChartType XYScatter -XRange WinsToFast -YRange WinsToPoles -Column 7 -Width 2000 -Height 700 -Title "Poles vs fastlaps" +Set-ExcelRange -Worksheet $ws -Range "F2:G50" -NumberFormat "0.0%" +$chart = New-ExcelChartDefinition -NoLegend -ChartType XYScatter -XRange WinsToFast -YRange WinsToPoles -Column 7 -Width 2000 -Height 700 -Title "Poles vs fastlaps" Export-Excel -ExcelPackage $Excel -WorkSheetname "Winners" -ExcelChartDefinition $chart -Show \ No newline at end of file diff --git a/Examples/SetColumnBackgroundColor/SetColumnBackgroundColor.ps1 b/Examples/SetColumnBackgroundColor/SetColumnBackgroundColor.ps1 index 67d37381..28542d05 100644 --- a/Examples/SetColumnBackgroundColor/SetColumnBackgroundColor.ps1 +++ b/Examples/SetColumnBackgroundColor/SetColumnBackgroundColor.ps1 @@ -1,9 +1,13 @@ - -$p = ps | select Company, Handles | Export-Excel c:\temp\testBackgroundColor.xlsx -ClearSheet -KillExcel -PassThru +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$path = "$env:TEMP\testBackgroundColor.xlsx" + +$p = Get-Process | Select-Object Company, Handles | Export-Excel $path -ClearSheet -PassThru $ws = $p.Workbook.WorkSheets[1] $totalRows = $ws.Dimension.Rows -Set-Format -Address $ws.Cells["B2:B$($totalRows)"] -BackgroundColor LightBlue +#Set the range from B2 to the last active row. s +Set-ExcelRange -Range $ws.Cells["B2:B$($totalRows)"] -BackgroundColor LightBlue -Export-Excel -ExcelPackage $p -show \ No newline at end of file +Export-Excel -ExcelPackage $p -show -AutoSize \ No newline at end of file diff --git a/Examples/Sparklines/SalesByQuarter.ps1 b/Examples/Sparklines/SalesByQuarter.ps1 new file mode 100644 index 00000000..57ebe289 --- /dev/null +++ b/Examples/Sparklines/SalesByQuarter.ps1 @@ -0,0 +1,25 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\SalesByQuarter.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data = ConvertFrom-Csv @" +Region,Q1,Q2,Q3,Q4,YTDPerformance +Asia,1400,7200,5700,6900 +Europe,3400,2300,9400,7300 +Midwest,4700,9300,3700,8600 +Northeast,2300,4300,4600,5600 +"@ + +$excel = $data | Export-Excel $xlfile -Passthru -AutoSize -TableName SalesByQuarter + +$ws = $excel.Sheet1 + +Set-ExcelRange -Worksheet $ws -Range "B2:E5" -NumberFormat "$#,##0" -AutoSize +$sparkLineType = "line" +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F2"], $ws.Cells["B2:E2"] ) +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F3"], $ws.Cells["B3:E3"] ) +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F4"], $ws.Cells["B4:E4"] ) +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F5"], $ws.Cells["B5:E5"] ) + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/Sparklines/Sparklines.ps1 b/Examples/Sparklines/Sparklines.ps1 new file mode 100644 index 00000000..46718ed6 --- /dev/null +++ b/Examples/Sparklines/Sparklines.ps1 @@ -0,0 +1,99 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +class data { + [datetime]$Date + [Double]$AUD + [Double]$CAD + [Double]$CHF + [Double]$DKK + [Double]$EUR + [Double]$GBP + [Double]$HKD + [Double]$JPY + [Double]$MYR + [Double]$NOK + [Double]$NZD + [Double]$RUB + [Double]$SEK + [Double]$THB + [Double]$TRY + [Double]$USD +} + +[data[]]$data = ConvertFrom-Csv @" +Date,AUD,CAD,CHF,DKK,EUR,GBP,HKD,JPY,MYR,NOK,NZD,RUB,SEK,THB,TRY,USD +2016-03-01,6.17350,6.42084,8.64785,1.25668,9.37376,12.01683,1.11067,0.07599,2.06900,0.99522,5.69227,0.11665,1.00000,0.24233,2.93017,8.63185 +2016-03-02,6.27223,6.42345,8.63480,1.25404,9.35350,12.14970,1.11099,0.07582,2.07401,0.99311,5.73277,0.11757,1.00000,0.24306,2.94083,8.63825 +2016-03-07,6.33778,6.38403,8.50245,1.24980,9.32373,12.05756,1.09314,0.07478,2.07171,0.99751,5.77539,0.11842,1.00000,0.23973,2.91088,8.48885 +2016-03-08,6.30268,6.31774,8.54066,1.25471,9.36254,12.03361,1.09046,0.07531,2.05625,0.99225,5.72501,0.11619,1.00000,0.23948,2.91067,8.47020 +2016-03-09,6.32630,6.33698,8.46118,1.24399,9.28125,11.98879,1.08544,0.07467,2.04128,0.98960,5.71601,0.11863,1.00000,0.23893,2.91349,8.42945 +2016-03-10,6.24241,6.28817,8.48684,1.25260,9.34350,11.99193,1.07956,0.07392,2.04500,0.98267,5.58145,0.11769,1.00000,0.23780,2.89150,8.38245 +2016-03-11,6.30180,6.30152,8.48295,1.24848,9.31230,12.01194,1.07545,0.07352,2.04112,0.98934,5.62335,0.11914,1.00000,0.23809,2.90310,8.34510 +2016-03-15,6.19790,6.21615,8.42931,1.23754,9.22896,11.76418,1.07026,0.07359,2.00929,0.97129,5.49278,0.11694,1.00000,0.23642,2.86487,8.30540 +2016-03-16,6.18508,6.22493,8.41792,1.23543,9.21149,11.72470,1.07152,0.07318,2.01179,0.96907,5.49138,0.11836,1.00000,0.23724,2.84767,8.31775 +2016-03-17,6.25214,6.30642,8.45981,1.24327,9.26623,11.86396,1.05571,0.07356,2.01706,0.98159,5.59544,0.12024,1.00000,0.23543,2.87595,8.18825 +2016-03-18,6.25359,6.32400,8.47826,1.24381,9.26976,11.91322,1.05881,0.07370,2.02554,0.98439,5.59067,0.12063,1.00000,0.23538,2.86880,8.20950 +"@ + +$xlfile = "$env:TEMP\sparklines.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$excel = $data | Export-Excel $xlfile -WorksheetName SEKRates -AutoSize -PassThru + +# Add a column sparkline for all currencies +Set-ExcelRange -Worksheet $excel.SEKRates -Range "A2:A12" -NumberFormat "yyyy-mm-dd" -AutoSize +Set-ExcelRange -Worksheet $excel.SEKRates -Range A15 -Value Column -AutoSize + +$sparklineCol = $excel.SEKRates.SparklineGroups.Add( + "Column", + $excel.SEKRates.Cells["B15:Q15"], + $excel.SEKRates.Cells["B2:Q12"] +) + +$sparklineCol.High = $true +$sparklineCol.ColorHigh.SetColor("Red") + +# Add a line sparkline for all currencies +Set-ExcelRange -Worksheet $excel.SEKRates -Range A16 -Value Line -AutoSize +$sparklineLine = $excel.SEKRates.SparklineGroups.Add( + "Line", + $excel.SEKRates.Cells["B16:Q16"], + $excel.SEKRates.Cells["B2:Q12"] +) + +$sparklineLine.DateAxisRange = $excel.SEKRates.Cells["A2:A12"] + +# Add some more random values and add a stacked sparkline. +Set-ExcelRange -Worksheet $excel.SEKRates -Range A17 -Value Stacked -AutoSize + +$numbers = 2, -1, 3, -4, 8, 5, -12, 18, 99, 1, -4, 12, -8, 9, 0, -8 + +$col = 2 # Column B +foreach ($n in $numbers) { + $excel.SEKRates.Cells[17, $col++].Value = $n +} + +$sparklineStacked = $excel.SEKRates.SparklineGroups.Add( + "Stacked", + $excel.SEKRates.Cells["R17"], + $excel.SEKRates.Cells["B17:Q17"] +) + +$sparklineStacked.High = $true +$sparklineStacked.ColorHigh.SetColor("Red") +$sparklineStacked.Low = $true +$sparklineStacked.ColorLow.SetColor("Green") +$sparklineStacked.Negative = $true +$sparklineStacked.ColorNegative.SetColor("Blue") + +Set-ExcelRange -Worksheet $excel.SEKRates -Range "A15:A17" -Bold -Height 50 -AutoSize + +$v = @" +High - Red +Low - Green +Negative - Blue +"@ + +Set-ExcelRange -Worksheet $excel.SEKRates -Range S17 -Value $v -WrapText -Width 20 -HorizontalAlignment Center -VerticalAlignment Center + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/SpreadsheetCells/CalculatedFields.ps1 b/Examples/SpreadsheetCells/CalculatedFields.ps1 index eb44b549..f03b3178 100644 --- a/Examples/SpreadsheetCells/CalculatedFields.ps1 +++ b/Examples/SpreadsheetCells/CalculatedFields.ps1 @@ -1,11 +1,14 @@ -. ..\New-PSItem.ps1 +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm *.xlsx + +#. ..\New-PSItem.ps1 + +Remove-Item "$env:temp\functions.xlsx" -ErrorAction SilentlyContinue $( - New-PSItem 12001 Nails 37 3.99 =C2*D2 (echo ID Product Quantity Price Total) + New-PSItem 12001 Nails 37 3.99 =C2*D2 @("ID", "Product", "Quantity", "Price", "Total") New-PSItem 12002 Hammer 5 12.10 =C3*D3 New-PSItem 12003 Saw 12 15.37 =C4*D4 New-PSItem 12010 Drill 20 8 =C5*D5 - New-PSItem 12011 Crowbar 7 23.48 =C6*D6 -) | Export-Excel functions.xlsx -AutoSize -Show + New-PSItem 12011 Crowbar 7 23.48 =C6*D6 +) | Export-Excel "$env:temp\functions.xlsx"-AutoSize -Show diff --git a/Examples/SpreadsheetCells/ExcelFormulasUsingAddMember.ps1 b/Examples/SpreadsheetCells/ExcelFormulasUsingAddMember.ps1 new file mode 100644 index 00000000..e55fab3c --- /dev/null +++ b/Examples/SpreadsheetCells/ExcelFormulasUsingAddMember.ps1 @@ -0,0 +1,14 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item .\testFormula.xlsx -ErrorAction Ignore + +@" +id,item,units,cost +12001,Nails,37,3.99 +12002,Hammer,5,12.10 +12003,Saw,12,15.37 +12010,Drill,20,8 +12011,Crowbar,7,23.48 +"@ | ConvertFrom-Csv | + Add-Member -PassThru -MemberType NoteProperty -Name Total -Value "=units*cost" | + Export-Excel -Path .\testFormula.xlsx -Show -AutoSize -AutoNameRange \ No newline at end of file diff --git a/Examples/SpreadsheetCells/ExcelFunctions.ps1 b/Examples/SpreadsheetCells/ExcelFunctions.ps1 index 4760e512..49ec3964 100644 --- a/Examples/SpreadsheetCells/ExcelFunctions.ps1 +++ b/Examples/SpreadsheetCells/ExcelFunctions.ps1 @@ -1,12 +1,12 @@ -. ..\New-PSItem.ps1 +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -rm *.xlsx +Remove-Item "$env:temp\functions.xlsx" -ErrorAction SilentlyContinue $( - New-PSItem =2%/12 60 500000 "=pmt(rate,nper,pv)" (echo rate nper pv pmt) - New-PSItem =3%/12 60 500000 "=pmt(rate,nper,pv)" - New-PSItem =4%/12 60 500000 "=pmt(rate,nper,pv)" - New-PSItem =5%/12 60 500000 "=pmt(rate,nper,pv)" - New-PSItem =6%/12 60 500000 "=pmt(rate,nper,pv)" - New-PSItem =7%/12 60 500000 "=pmt(rate,nper,pv)" -) | Export-Excel functions.xlsx -AutoNameRange -AutoSize -Show \ No newline at end of file + New-PSItem =2%/12 60 500000 "=pmt(rate,nper,pv)" @("rate", "nper", "pv", "pmt") + New-PSItem =3%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =4%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =5%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =6%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =7%/12 60 500000 "=pmt(rate,nper,pv)" +) | Export-Excel "$env:temp\functions.xlsx" -AutoNameRange -AutoSize -Show \ No newline at end of file diff --git a/Examples/SpreadsheetCells/HyperLink.ps1 b/Examples/SpreadsheetCells/HyperLink.ps1 index 2cf36c7b..3f4a1115 100644 --- a/Examples/SpreadsheetCells/HyperLink.ps1 +++ b/Examples/SpreadsheetCells/HyperLink.ps1 @@ -1,8 +1,10 @@ -rm *.xlsx +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item "$env:temp\hyperlink.xlsx" -ErrorAction SilentlyContinue $( New-PSItem '=Hyperlink("http://dougfinke.com/blog","Doug Finke")' @("Link") New-PSItem '=Hyperlink("http://blogs.msdn.com/b/powershell/","PowerShell Blog")' New-PSItem '=Hyperlink("http://blogs.technet.com/b/heyscriptingguy/","Hey, Scripting Guy")' - -) | Export-Excel hyperlink.xlsx -AutoSize -Show + +) | Export-Excel "$env:temp\hyperlink.xlsx" -AutoSize -Show diff --git a/Examples/Stocks/Get-StockInfo.ps1 b/Examples/Stocks/Get-StockInfo.ps1 index fff9c38a..b5a5fde4 100644 --- a/Examples/Stocks/Get-StockInfo.ps1 +++ b/Examples/Stocks/Get-StockInfo.ps1 @@ -1,21 +1,21 @@ function Get-StockInfo { param( - $stock, - [datetime]$startDate, - [datetime]$endDate + [Parameter(Mandatory)] + $symbols, + [ValidateSet('open', 'close', 'high', 'low', 'avgTotalVolume')] + $dataPlot = "close" ) - Process { + $xlfile = "$env:TEMP\stocks.xlsx" + Remove-Item -Path $xlfile -ErrorAction Ignore - if(!$endDate) { $endDate = $startDate} + $result = Invoke-RestMethod "https://api.iextrading.com/1.0/stock/market/batch?symbols=$($symbols)&types=quote&last=1" - $baseUrl = "http://query.yahooapis.com/v1/public/yql?q=" - $q = @" -select * from yahoo.finance.historicaldata where symbol = "$($stock)" and startDate = "$($startDate.ToString('yyyy-MM-dd'))" and endDate = "$($endDate.ToString('yyyy-MM-dd'))" -"@ - $suffix = "&env=store://datatables.org/alltableswithkeys&format=json" - $r=Invoke-RestMethod ($baseUrl + $q + $suffix) - $r.query.results.quote + $ecd = New-ExcelChartDefinition -Row 1 -Column 1 -SeriesHeader $dataPlot ` + -XRange symbol -YRange $dataPlot ` + -Title "$($dataPlot)`r`n As Of $((Get-Date).ToShortDateString())" - } -} \ No newline at end of file + $(foreach ($name in $result.psobject.Properties.name) { + $result.$name.quote + }) | Export-Excel $xlfile -AutoNameRange -AutoSize -Show -ExcelChartDefinition $ecd -StartRow 21 -StartColumn 2 +} diff --git a/Examples/Stocks/GetMSFT.ps1 b/Examples/Stocks/GetMSFT.ps1 deleted file mode 100644 index 3d91b319..00000000 --- a/Examples/Stocks/GetMSFT.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -$Symbol = "MSFT" - -. .\Get-StockInfo.ps1 - -rm *.xlsx - -$chart = New-ExcelChart -XRange Date -YRange Volume ` - -ChartType ColumnStacked ` - -Column 9 -Title "$Symbol Volume" - -Get-StockInfo $Symbol 11/2 11/30 | - Export-Excel .\stocks.xlsx -Show ` - -AutoSize -AutoNameRange ` - -ExcelChartDefinition $chart \ No newline at end of file diff --git a/Examples/Stocks/GetStocksAvgTotVol.ps1 b/Examples/Stocks/GetStocksAvgTotVol.ps1 new file mode 100644 index 00000000..665e7768 --- /dev/null +++ b/Examples/Stocks/GetStocksAvgTotVol.ps1 @@ -0,0 +1,3 @@ +. $PSScriptRoot\Get-StockInfo.ps1 + +Get-StockInfo -symbols "msft,ibm,ge,xom,aapl" -dataPlot avgTotalVolume \ No newline at end of file diff --git a/Examples/Styles/MultipleStyles.ps1 b/Examples/Styles/MultipleStyles.ps1 new file mode 100644 index 00000000..70b57ffb --- /dev/null +++ b/Examples/Styles/MultipleStyles.ps1 @@ -0,0 +1,35 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\test.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data = ConvertFrom-Csv @" +Region,Item,TotalSold +North,melon,38 +South,screwdriver,21 +South,peach,33 +South,saw,81 +South,kiwi,70 +North,orange,59 +North,avocado,25 +South,lime,48 +South,nail,83 +North,apple,2 +"@ + +$styleParams = @{ + FontSize = 13 + Bold = $true +} + +$styles = $( + New-ExcelStyle -BackgroundColor LightBlue -FontSize 14 -Bold -Range "A1:H1" -HorizontalAlignment Center -Merge + + New-ExcelStyle -BackgroundColor LimeGreen -Range "B10" @styleParams + New-ExcelStyle -BackgroundColor PeachPuff -Range "B5" @styleParams + New-ExcelStyle -BackgroundColor Orange -Range "B8" @styleParams + New-ExcelStyle -BackgroundColor Red -Range "B12" @styleParams +) + +$reportTitle = "This is a report Title" +$data | Export-Excel $xlfile -Show -AutoSize -AutoFilter -Title $reportTitle -Style $styles \ No newline at end of file diff --git a/Examples/Styles/NewExcelStyle.ps1 b/Examples/Styles/NewExcelStyle.ps1 new file mode 100644 index 00000000..77286f0f --- /dev/null +++ b/Examples/Styles/NewExcelStyle.ps1 @@ -0,0 +1,23 @@ +# https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/NewExcelStyle.png +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\test.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data = ConvertFrom-Csv @" +Region,Item,TotalSold +North,melon,38 +South,screwdriver,21 +South,peach,33 +South,saw,81 +South,kiwi,70 +North,orange,59 +North,avocado,25 +South,lime,48 +South,nail,83 +North,apple,2 +"@ + +$reportTitle = "This is a report Title" +$style = New-ExcelStyle -BackgroundColor LightBlue -FontSize 14 -Bold -Range "A1:H1" -HorizontalAlignment Center -Merge +$data | Export-Excel $xlfile -Show -AutoSize -AutoFilter -Title $reportTitle -Style $style \ No newline at end of file diff --git a/Examples/Subtotals.ps1 b/Examples/Subtotals.ps1 new file mode 100644 index 00000000..1e6bf0d4 --- /dev/null +++ b/Examples/Subtotals.ps1 @@ -0,0 +1,78 @@ +$Data = ConvertFrom-Csv @' +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Grape, Munich, 100, 100 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 +'@ +$ExcelPath = "$env:temp\subtotal.xlsx" +$SheetName = 'Sheet1' +Remove-Item -Path $ExcelPath -ErrorAction SilentlyContinue + + +$GroupByFieldName = 'City' +$TotalSingleRows = $false +$GrandTotal = $false +$SubtotalRowHeight = 0 #If non zero will set subtotals to this height +$Subtotals =@{ 'Net' = {"=SUBTOTAL(3,D{0}:D{1})" -f $from, $to} + + +} +$SubtotalFieldName = 'Net' + +$SubtotalFormula = '=SUBTOTAL(3,D{0}:D{1})' # {0} and {1} are placeholders for the first and last row. D is the column to total in + # 1=AVERAGE; 2=COUNT; 3=COUNTA; 4=MAX; 5=MIN; 6=PRODUCT; 7=STDEV; 8=STDEVP; 9=SUM; 10=VAR; 11=VARP add 100 to ignore hidden values + +#at each change in the Group by field, insert a subtotal (count) formula in the title column & send to excel - list those rows and make them half height after export +$currentRow = 2 +$lastChangeRow = 2 +$insertedRows = @() +#$hideRows = @() +$lastValue = $Data[0].$GroupByFieldName +$excel = $Data | ForEach-Object -Process { + if ($_.$GroupByFieldName -ne $lastvalue) { + if ($lastChangeRow -lt ($currentrow - 1) -or $totalSingleRows) { + $formula = $SubtotalFormula -f $lastChangeRow, ($currentrow - 1) + $insertedRows += $currentRow + [pscustomobject]@{$SubtotalFieldName = $formula} + $currentRow += 1 + } + $lastChangeRow = $currentRow + $lastValue = $_.$GroupByFieldName + } + $_ + $currentRow += 1 +} -end { + $formula = $SubtotalFormula -f $lastChangeRow, ($currentrow - 1) + [pscustomobject]@{$SubtotalFieldName=$formula} + if ($GrandTotal) { + $formula = $SubtotalFormula -f $lastChangeRow, ($currentrow - 1) + [pscustomobject]@{$SubtotalFieldName=$formula} + } +} | Export-Excel -Path $ExcelPath -PassThru -AutoSize -AutoFilter -BoldTopRow -WorksheetName $sheetName + +#We kept a lists of the total rows. Since single rows won't get expanded/collapsed hide them. +if ($subtotalrowHeight) { + foreach ($r in $insertedrows) { $excel.WorkItems.Row($r).Height = $SubtotalRowHeight} +} +#foreach ($r in $hideRows) { $excel.$SheetName.Row($r).hidden = $true} +$range = $excel.$SheetName.Dimension.Address +$sheetIndex = $excel.Sheet1.Index +Close-ExcelPackage -ExcelPackage $excel + +try { $excelApp = New-Object -ComObject "Excel.Application" } +catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return } + +try { $excelWorkBook = $excelApp.Workbooks.Open($ExcelPath) } +catch { Write-Warning -Message "Could not Open $ExcelPath." ; return } +$ws = $excelWorkBook.Worksheets.Item($sheetIndex) +$null = $ws.Range($range).Select() +$null = $excelapp.Selection.AutoOutline() +$excelWorkBook.Save() +$excelWorkBook.Close() +$excelApp.Quit() + +Start-Process $ExcelPath \ No newline at end of file diff --git a/Examples/Tables/MultipleTables.ps1 b/Examples/Tables/MultipleTables.ps1 index 8e5cf73b..d2c0188b 100644 --- a/Examples/Tables/MultipleTables.ps1 +++ b/Examples/Tables/MultipleTables.ps1 @@ -1,38 +1,43 @@ -$xlfile = "testData.xlsx" -rm *.xlsx +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} -$r = dir C:\WINDOWS\system32 +$xlfile = "$env:Temp\testData.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$r = Get-ChildItem C:\WINDOWS\system32 $BySize=@{} -$r | ForEach{ $BySize.($_.extension)+=$_.length } +$r | ForEach-Object{ $BySize.($_.extension)+=$_.length } + +$top10BySize = $BySize.GetEnumerator() | + ForEach-Object{ [PSCustomObject]@{Name=$_.key;Size=[double]$_.value} } | + Sort-Object size -Descending | + Select-Object -First 10 -$top10BySize = $BySize.GetEnumerator() | - ForEach{ [PSCustomObject]@{Name=$_.key;Size=[double]$_.value} } | - Sort size -Descending | - Select -First 10 +$top10ByCount = $r.extension | + Group-Object | + Sort-Object count -Descending | + Select-Object -First 10 Name, count -$top10ByCount = $r.extension | - Group | - Sort count -Descending | - Select -First 10 Name, count +$top10ByFileSize = $r | + Sort-Object length -Descending | + Select-Object -First 10 Name, @{n="Size";e={$_.Length}} #,Extension,Path -$top10ByFileSize = $r | - Sort length -Descending | - Select -First 10 Name, @{n="Size";e={$_.Length}} #,Extension,Path +$xlPkg = $top10BySize | Export-Excel -path $xlfile -WorkSheetname FileInfo -TableName ExtSize -PassThru +$xlPkg = $top10ByCount | Export-Excel -ExcelPackage $xlPkg -WorkSheetname FileInfo -StartRow 13 -TableName ExtCount -PassThru +$xlPkg = $top10ByFileSize | Export-Excel -ExcelPackage $xlPkg -WorkSheetname FileInfo -StartRow 25 -TableName FileSize -PassThru -AutoSize -$top10BySize | Export-Excel $xlfile -WorkSheetname FileInfo -TableName ExtSize -$top10ByCount | Export-Excel $xlfile -WorkSheetname FileInfo -StartRow 13 -TableName ExtCount -$top10ByFileSize | Export-Excel $xlfile -WorkSheetname FileInfo -StartRow 25 -AutoSize -TableName FileSize +#worksheets.tables["Name1","Name2"] returns 2 tables. Set-ExcelRange can process those and will set the number format over both +Set-ExcelRange -Range $xlpkg.Workbook.Worksheets[1].Tables["ExtSize","FileSize"] -NumberFormat '0,,"MB"' -$ps = ps | ? Company +$ps = Get-Process | Where-Object Company -$ps | - sort handles -Descending | - select -First 10 company, handles | - Export-Excel $xlfile -WorkSheetname Handles -AutoSize -TableName Handles +$ps | + Sort-Object handles -Descending | + Select-Object -First 10 company, handles | + Export-Excel -ExcelPackage $xlPkg -WorkSheetname Handles -AutoSize -TableName Handles -$ps | - sort PM -Descending | - select -First 10 company, PM | +$ps | + Sort-Object PM -Descending | + Select-Object -First 10 company, PM | Export-Excel $xlfile -WorkSheetname Handles -AutoSize -TableName PM -StartRow 13 -Show diff --git a/Examples/Tables/SalesData-WithTotalRow.ps1 b/Examples/Tables/SalesData-WithTotalRow.ps1 new file mode 100644 index 00000000..c7b7e0b8 --- /dev/null +++ b/Examples/Tables/SalesData-WithTotalRow.ps1 @@ -0,0 +1,29 @@ +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$data = ConvertFrom-Csv @" +OrderId,Category,Sales,Quantity,Discount +1,Cosmetics,744.01,07,0.7 +2,Grocery,349.13,25,0.3 +3,Apparels,535.11,88,0.2 +4,Electronics,524.69,60,0.1 +5,Electronics,439.10,41,0.0 +6,Apparels,56.84,54,0.8 +7,Electronics,326.66,97,0.7 +8,Cosmetics,17.25,74,0.6 +9,Grocery,199.96,39,0.4 +10,Grocery,731.77,20,0.3 +"@ + +$xlfile = "$PSScriptRoot\TotalsRow.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$TableTotalSettings = @{ + Quantity = 'Sum' + Category = '=COUNTIF([Category],"<>Electronics")' # Count the number of categories not equal to Electronics + Sales = @{ + Function = '=SUMIF([Category],"<>Electronics",[Sales])' + Comment = "Sum of sales for everything that is NOT Electronics" + } +} + +$data | Export-Excel -Path $xlfile -TableName Sales -TableStyle Medium10 -TableTotalSettings $TableTotalSettings -AutoSize -Show \ No newline at end of file diff --git a/Examples/Tables/TotalsRow.ps1 b/Examples/Tables/TotalsRow.ps1 new file mode 100644 index 00000000..bf8e5f74 --- /dev/null +++ b/Examples/Tables/TotalsRow.ps1 @@ -0,0 +1,16 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$r = Get-ChildItem C:\WINDOWS\system32 -File + +$TotalSettings = @{ + Name = "Count" + # You can create the formula in an Excel workbook first and copy-paste it here + # This syntax can only be used for the Custom type + Extension = "=COUNTIF([Extension];`".exe`")" + Length = @{ + Function = "=SUMIF([Extension];`".exe`";[Length])" + Comment = "Sum of all exe sizes" + } +} + +$r | Export-Excel -TableName system32files -TableStyle Medium10 -TableTotalSettings $TotalSettings -Show \ No newline at end of file diff --git a/Examples/TestRestAPI/PSExcelPester.psm1 b/Examples/TestRestAPI/PSExcelPester.psm1 new file mode 100644 index 00000000..9456c621 --- /dev/null +++ b/Examples/TestRestAPI/PSExcelPester.psm1 @@ -0,0 +1,90 @@ +function ConvertTo-PesterTest { + param( + [parameter(Mandatory)] + $XlFilename, + $WorksheetName = 'Sheet1' + ) + + $testFileName = "{0}.tests.ps1" -f (Get-date).ToString("yyyyMMddHHmmss") + + $records = Import-Excel $XlFilename + + $params = @{} + + $blocks = $(foreach ($record in $records) { + foreach ($propertyName in $record.psobject.properties.name) { + if ($propertyName -notmatch 'ExpectedResult|QueryString') { + $params.$propertyName = $record.$propertyName + } + } + + if ($record.QueryString) { + $params.Uri += "?{0}" -f $record.QueryString + } + + @" + + it "Should have the expected result '$($record.ExpectedResult)'" { + `$target = '$($params | ConvertTo-Json -compress)' | ConvertFrom-Json + + `$target.psobject.Properties.name | ForEach-Object {`$p=@{}} {`$p.`$_=`$(`$target.`$_)} + + Invoke-RestMethod @p | Should -Be '$($record.ExpectedResult)' + } + +"@ + }) + + @" +Describe "Tests from $($XlFilename) in $($WorksheetName)" { +$($blocks) +} +"@ | Set-Content -Encoding Ascii $testFileName + + [PSCustomObject]@{ + TestFileName = (Get-ChildItem $testFileName).FullName + } +} + +function Show-PesterResult { + param( + [Parameter(ValueFromPipelineByPropertyName, Mandatory)] + $TestFileName + ) + + Begin { + $xlfilename = ".\test.xlsx" + Remove-Item $xlfilename -ErrorAction SilentlyContinue + + $ConditionalText = @() + $ConditionalText += New-ConditionalText -Range "Result" -Text failed -BackgroundColor red -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text passed -BackgroundColor green -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text pending -BackgroundColor gray -ConditionalTextColor black + + $xlParams = @{ + Path = $xlfilename + WorkSheetname = 'PesterTests' + ConditionalText = $ConditionalText + PivotRows = 'Result', 'Name' + PivotData = @{'Result' = 'Count'} + IncludePivotTable = $true + AutoSize = $true + AutoNameRange = $true + AutoFilter = $true + Show = $true + } + } + + End { + + $(foreach ($result in (Invoke-Pester -Script $TestFileName -PassThru -Show None).TestResult) { + [PSCustomObject][Ordered]@{ + Description = $result.Describe + Name = $result.Name + Result = $result.Result + Messge = $result.FailureMessage + StackTrace = $result.StackTrace + } + }) | Export-Excel @xlParams + } +} \ No newline at end of file diff --git a/Examples/TestRestAPI/RunAndShowUnitTests.ps1 b/Examples/TestRestAPI/RunAndShowUnitTests.ps1 new file mode 100644 index 00000000..084033ad --- /dev/null +++ b/Examples/TestRestAPI/RunAndShowUnitTests.ps1 @@ -0,0 +1,37 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfilename=".\test.xlsx" +Remove-Item $xlfilename -ErrorAction Ignore + +$ConditionalText = @() +$ConditionalText += New-ConditionalText -Range "C:C" -Text failed -BackgroundColor red -ConditionalTextColor black +$ConditionalText += New-ConditionalText -Range "C:C" -Text passed -BackgroundColor green -ConditionalTextColor black + +$r = .\TryIt.ps1 + +$xlPkg = $(foreach($result in $r.TestResult) { + + [PSCustomObject]@{ + Name = $result.Name + #Time = $result.Time + Result = $result.Result + Messge = $result.FailureMessage + StackTrace = $result.StackTrace + } + +}) | Export-Excel -Path $xlfilename -AutoSize -ConditionalText $ConditionalText -PassThru + +$sheet1 = $xlPkg.Workbook.Worksheets["sheet1"] + +$sheet1.View.ShowGridLines = $false +$sheet1.View.ShowHeaders = $false + +Set-ExcelRange -Address $sheet1.Cells["A:A"] -AutoSize +Set-ExcelRange -Address $sheet1.Cells["B:D"] -WrapText + +$sheet1.InsertColumn(1, 1) +Set-ExcelRange -Address $sheet1.Cells["A:A"] -Width 5 + +Set-ExcelRange -Address $sheet1.Cells["B1:E1"] -HorizontalAlignment Center -BorderBottom Thick -BorderColor Cyan + +Close-ExcelPackage $xlPkg -Show \ No newline at end of file diff --git a/Examples/TestRestAPI/ShowPesterResults.ps1 b/Examples/TestRestAPI/ShowPesterResults.ps1 new file mode 100644 index 00000000..55e8e166 --- /dev/null +++ b/Examples/TestRestAPI/ShowPesterResults.ps1 @@ -0,0 +1,34 @@ +function Show-PesterResults { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="No suitable singular")] + Param() + $xlfilename = ".\test.xlsx" + Remove-Item $xlfilename -ErrorAction Ignore + + $ConditionalText = @() + $ConditionalText += New-ConditionalText -Range "Result" -Text failed -BackgroundColor red -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text passed -BackgroundColor green -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text pending -BackgroundColor gray -ConditionalTextColor black + + $xlParams = @{ + Path = $xlfilename + WorkSheetname = 'PesterTests' + ConditionalText = $ConditionalText + PivotRows = 'Result', 'Name' + PivotData = @{'Result' = 'Count'} + IncludePivotTable = $true + AutoSize = $true + AutoNameRange = $true + AutoFilter = $true + Show = $true + } + + $(foreach ($result in (Invoke-Pester -PassThru -Show None).TestResult) { + [PSCustomObject]@{ + Description = $result.Describe + Name = $result.Name + Result = $result.Result + Messge = $result.FailureMessage + StackTrace = $result.StackTrace + } + }) | Sort-Object Description | Export-Excel @xlParams +} \ No newline at end of file diff --git a/Examples/TestRestAPI/TestAPIReadXls.ps1 b/Examples/TestRestAPI/TestAPIReadXls.ps1 new file mode 100644 index 00000000..42c73600 --- /dev/null +++ b/Examples/TestRestAPI/TestAPIReadXls.ps1 @@ -0,0 +1,46 @@ +function Test-APIReadXls { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="False Positive")] + param( + [parameter(Mandatory)] + $XlFilename, + $WorksheetName = 'Sheet1' + ) + + $testFileName = "{0}.tests.ps1" -f (Get-date).ToString("yyyyMMddHHmmss") + + $records = Import-Excel $XlFilename + + $params = @{} + + $blocks = $(foreach ($record in $records) { + foreach ($propertyName in $record.psobject.properties.name) { + if ($propertyName -notmatch 'ExpectedResult|QueryString') { + $params.$propertyName = $record.$propertyName + } + } + + if ($record.QueryString) { + $params.Uri += "?{0}" -f $record.QueryString + } + + @" + + it "Should have the expected result '$($record.ExpectedResult)'" { + `$target = '$($params | ConvertTo-Json -compress)' | ConvertFrom-Json + + `$target.psobject.Properties.name | ForEach-Object {`$p=@{}} {`$p.`$_=`$(`$target.`$_)} + + Invoke-RestMethod @p | Should -Be '$($record.ExpectedResult)' + } + +"@ + }) + + @" +Describe "Tests from $($XlFilename) in $($WorksheetName)" { +$($blocks) +} +"@ | Set-Content -Encoding Ascii $testFileName + + (Get-ChildItem $testFileName).FullName +} \ No newline at end of file diff --git a/Examples/TestRestAPI/TryIt.ps1 b/Examples/TestRestAPI/TryIt.ps1 new file mode 100644 index 00000000..d6d6eae6 --- /dev/null +++ b/Examples/TestRestAPI/TryIt.ps1 @@ -0,0 +1,7 @@ +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +. $PSScriptRoot\TestAPIReadXls.ps1 + +Test-APIReadXls $PSScriptRoot\testlist.xlsx | Foreach-Object { + Invoke-Pester -Script $_.fullname -PassThru -Show None +} \ No newline at end of file diff --git a/Examples/TestRestAPI/testlist.xlsx b/Examples/TestRestAPI/testlist.xlsx new file mode 100644 index 00000000..b6daf82f Binary files /dev/null and b/Examples/TestRestAPI/testlist.xlsx differ diff --git a/Examples/TryMultiplePivotTables.ps1 b/Examples/TryMultiplePivotTables.ps1 index f53338fb..6b5c3320 100644 --- a/Examples/TryMultiplePivotTables.ps1 +++ b/Examples/TryMultiplePivotTables.ps1 @@ -1,12 +1,12 @@ -# To ship, is to choose +# To ship, is to choose #ipmo .\ImportExcel.psd1 -Force $pt=[ordered]@{} -$pt.ServiceInfo=@{ +$pt.ServiceInfo=@{ SourceWorkSheet='Services' - PivotRows = "Status" + PivotRows = "Status" PivotData= @{'Status'='count'} IncludePivotChart=$true ChartType='BarClustered3D' @@ -14,7 +14,7 @@ $pt.ServiceInfo=@{ $pt.ProcessInfo=@{ SourceWorkSheet='Processes' - PivotRows = "Company" + PivotRows = "Company" PivotData= @{'Company'='count'} IncludePivotChart=$true ChartType='PieExploded3D' @@ -24,7 +24,7 @@ $gsv=Get-Service | Select-Object status, Name, displayName, starttype $ps=Get-Process | Select-Object Name,Company, Handles $file = "c:\temp\testPT.xlsx" -rm $file -ErrorAction Ignore +Remove-Item $file -ErrorAction Ignore $gsv| Export-Excel -Path $file -AutoSize -WorkSheetname Services -$ps | Export-Excel -Path $file -AutoSize -WorkSheetname Processes -PivotTableDefinition $pt -Show +$ps | Export-Excel -Path $file -AutoSize -WorkSheetname Processes -PivotTableDefinition $pt -Show diff --git a/Examples/TryMultiplePivotTablesFromOneSheet.ps1 b/Examples/TryMultiplePivotTablesFromOneSheet.ps1 index 3993ebcf..eb76f8c8 100644 --- a/Examples/TryMultiplePivotTablesFromOneSheet.ps1 +++ b/Examples/TryMultiplePivotTablesFromOneSheet.ps1 @@ -1,4 +1,4 @@ -Import-Module ..\ImportExcel.psd1 -Force +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} $file = "C:\Temp\test.xlsx" diff --git a/Examples/VBA/AddModuleMultipleWorksheetVBA.ps1 b/Examples/VBA/AddModuleMultipleWorksheetVBA.ps1 new file mode 100644 index 00000000..456a9edf --- /dev/null +++ b/Examples/VBA/AddModuleMultipleWorksheetVBA.ps1 @@ -0,0 +1,64 @@ +$xlfile = "$env:temp\test.xlsm" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +ConvertFrom-Csv @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize + +$Excel = ConvertFrom-Csv @" +Supplier,Item,TotalBought +Hardware,screwdriver,98 +Groceries,kiwi,19 +Hardware,screws,48 +Groceries,avocado,52 +Hardware,drill,61 +Groceries,orange,92 +Hardware,drill,29 +HArdware,saw,36 +"@ | Export-Excel $xlfile -TableName 'Purchases' -WorksheetName 'Purchases' -PassThru -AutoSize + +$wb = $Excel.Workbook +$wb.CreateVBAProject() + +# Create a module with a sub to highlight the selected row & column of the active table. +# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column +$codeModule = @" +Public Sub HighlightSelection(ByVal Target As Range) + ' Clear the color of all the cells + Cells.Interior.ColorIndex = 0 + If Target.Cells.Count > 1 Then Exit Sub + Application.ScreenUpdating = False + With ActiveCell + ' Highlight the row and column that contain the active cell, within the current region + Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38 + Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24 + End With + Application.ScreenUpdating = True +End Sub +"@ + +$module = $wb.VbaProject.Modules.AddModule("PSExcelModule") +$module.Code = $codeModule + +# Add a call to the row & column highlight sub on each worksheet. +$codeSheet = @" +Private Sub Worksheet_SelectionChange(ByVal Target As Range) + HighlightSelection Target +End Sub +"@ + +foreach ($sheet in $wb.Worksheets) { + $sheet.CodeModule.Code = $codeSheet +} + +Close-ExcelPackage $Excel -Show \ No newline at end of file diff --git a/Examples/VBA/AddWorksheetVBA.ps1 b/Examples/VBA/AddWorksheetVBA.ps1 new file mode 100644 index 00000000..3068c41a --- /dev/null +++ b/Examples/VBA/AddWorksheetVBA.ps1 @@ -0,0 +1,41 @@ +$xlfile = "$env:temp\test.xlsm" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$Excel = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize -PassThru + +$wb = $Excel.Workbook +$sheet = $wb.Worksheets["Sales"] +$wb.CreateVBAProject() + +# Add a sub to the 'Worksheet_SelectionChange' event of the worksheet to highlight the selected row & column of the active table. +# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column +$code = @" +Private Sub Worksheet_SelectionChange(ByVal Target As Range) + ' Clear the color of all the cells + Cells.Interior.ColorIndex = 0 + If Target.Cells.Count > 1 Then Exit Sub + Application.ScreenUpdating = False + With ActiveCell + ' Highlight the row and column that contain the active cell, within the current region + Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38 + Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24 + End With + Application.ScreenUpdating = True +End Sub +"@ + +$sheet.CodeModule.Code = $code + +Close-ExcelPackage $Excel -Show \ No newline at end of file diff --git a/Examples/VBA/ChangePivotTablesVBA.ps1 b/Examples/VBA/ChangePivotTablesVBA.ps1 new file mode 100644 index 00000000..b61d4a66 --- /dev/null +++ b/Examples/VBA/ChangePivotTablesVBA.ps1 @@ -0,0 +1,62 @@ +<# +Excel VBA macro which changes all PivotTables in the workbook to Tabular form, disables subtotals and repeats item labels. +https://github.com/dfinke/ImportExcel/issues/1196#issuecomment-1156320581 +#> +$ExcelFile = "$ENV:TEMP\test.xlsm" +Remove-Item -Path $ExcelFile -ErrorAction SilentlyContinue + +$Macro = @" +Private Sub Workbook_Open() +' +' ChangePivotTables Macro +' Runs when the Excel workbook is opened. +' +' Changes all PivotTables in the workbook to Tabular form, repeats labels +' and disables Subtotals. +' + ' Declare variables + Dim Ws As Worksheet + Dim Pt As PivotTable + Dim Pf As PivotField + ' Disable screen updates + Application.ScreenUpdating = False + ' Continue even if an error occurs + On Error Resume Next + For Each Ws In ActiveWorkbook.Worksheets + For Each Pt In Ws.PivotTables + Pt.RowAxisLayout xlTabularRow + Pt.RepeatAllLabels xlRepeatLabels + For Each Pf In Pt.PivotFields + Pf.Subtotals(1) = False + Next + Next + Next + Application.ScreenUpdating = True +End Sub +"@ + +$Data = ConvertFrom-Csv -InputObject @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ + +$ExcelPackage = $Data | Export-Excel -Path $ExcelFile -TableName "Sales" -WorksheetName "Sales" -AutoSize -PassThru +# Add Macro to the ThisWorkbook module +$ExcelPackage.Workbook.CreateVBAProject() +$VBAThisWorkbookModule = $ExcelPackage.Workbook.VbaProject.Modules | Where-Object -FilterScript { $_.Name -eq "ThisWorkbook" } +$VBAThisWorkbookModule.Code = $Macro + +# Create PivotTable example +Add-PivotTable -PivotTableName "SalesPivot" -Address $ExcelPackage.Sales.Cells["E1"] -SourceWorksheet $ExcelPackage.Sales ` + -SourceRange $ExcelPackage.Sales.Tables[0].Address -PivotRows "Region", "Item" -PivotData @{ "TotalSold" = "Sum" } + +Close-ExcelPackage -ExcelPackage $ExcelPackage -Show \ No newline at end of file diff --git a/Examples/VBA/HelloWorldVBA.ps1 b/Examples/VBA/HelloWorldVBA.ps1 new file mode 100644 index 00000000..dc511b57 --- /dev/null +++ b/Examples/VBA/HelloWorldVBA.ps1 @@ -0,0 +1,38 @@ +$xlfile = "$env:temp\test.xlsm" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$Excel = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ | Export-Excel $xlfile -PassThru -AutoSize + +$wb = $Excel.Workbook +$sheet = $wb.Worksheets["Sheet1"] +$wb.CreateVBAProject() + +$code = @" +Public Function HelloWorld() As String + HelloWorld = "Hello World" +End Function + +Public Function DoSum() As Integer + DoSum = Application.Sum(Range("C:C")) +End Function +"@ + +$module = $wb.VbaProject.Modules.AddModule("PSExcelModule") +$module.Code = $code + +Set-ExcelRange -Worksheet $sheet -Range "h7" -Formula "HelloWorld()" -AutoSize +Set-ExcelRange -Worksheet $sheet -Range "h8" -Formula "DoSum()" -AutoSize + +Close-ExcelPackage $Excel -Show \ No newline at end of file diff --git a/Examples/XlRangeToImage/XlRangeToImage.ps1 b/Examples/XlRangeToImage/XlRangeToImage.ps1 index c7afbcad..de9fec59 100644 --- a/Examples/XlRangeToImage/XlRangeToImage.ps1 +++ b/Examples/XlRangeToImage/XlRangeToImage.ps1 @@ -1,10 +1,11 @@ -ipmo .\ImportExcel.psd1 -Force +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + . .\ConvertExcelToImageFile.ps1 $xlFileName = "C:\Temp\testPNG.xlsx" -rm C:\Temp\testPNG.xlsx -ErrorAction Ignore +Remove-Item C:\Temp\testPNG.xlsx -ErrorAction Ignore $range = @" Region,Item,Cost @@ -16,8 +17,8 @@ North,Pear,1 South,Apple,2 East,Grapes,3 West,Berry,4 -"@ | ConvertFrom-Csv | +"@ | ConvertFrom-Csv | Export-Excel $xlFileName -ReturnRange ` - -ConditionalText (New-ConditionalText Apple), (New-ConditionalText Berry -ConditionalTextColor White -BackgroundColor Purple) + -ConditionalText (New-ConditionalText Apple), (New-ConditionalText Berry -ConditionalTextColor White -BackgroundColor Purple) -Convert-XlRangeToImage -Path $xlFileName -workSheetname sheet1 -range $range -Show +Convert-ExcelXlRangeToImage -Path $xlFileName -workSheetname sheet1 -range $range -Show diff --git a/Export-Excel.Tests.ps1 b/Export-Excel.Tests.ps1 deleted file mode 100644 index c59ae7fd..00000000 --- a/Export-Excel.Tests.ps1 +++ /dev/null @@ -1,94 +0,0 @@ -#Requires -Modules Pester -#Requires -Modules Assert - -$here = Split-Path -Parent $MyInvocation.MyCommand.Path -$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' - -Import-Module $here -Force - -$WarningPreference = 'SilentlyContinue' -$ProgressPreference = 'SilentlyContinue' - -Function Test-isNumeric { - Param ( - [Parameter(ValueFromPipeline)]$x - ) - - Return $x -is [byte] -or $x -is [int16] -or $x -is [int32] -or $x -is [int64] ` - -or $x -is [sbyte] -or $x -is [uint16] -or $x -is [uint32] -or $x -is [uint64] ` - -or $x -is [float] -or $x -is [double] -or $x -is [decimal] -} - -$fakeData = [PSCustOmobject]@{ - Property_1_Date = (Get-Date).ToString('d') # US '10/16/2017' BE '16/10/2107' - Property_2_Formula = '=SUM(G2:H2)' - Property_3_String = 'My String' - Property_4_String = 'a' - Property_5_IPAddress = '10.10.25.5' - Property_6_Number = '0' - Property_7_Number = '5' - Property_8_Number = '007' - Property_9_Number = (33).ToString('F2') # US '33.00' BE '33,00' - Property_10_Number = (5/3).ToString('F2') # US '1.67' BE '1,67' - Property_11_Number = (15999998/3).ToString('N2') # US '5,333,332.67' BE '5.333.332,67' - Property_12_Number = '1.555,83' - Property_13_PhoneNr = '+32 44' - Property_14_PhoneNr = '+32 4 4444 444' - Property_15_PhoneNr = '+3244444444' -} - -$Path = 'Test.xlsx' - -Describe 'Export-Excel' { - in $TestDrive { - Describe 'Number conversion' { - Context 'numerical values expected' { - #region Create test file - $fakeData | Export-Excel -Path $Path - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Worksheet = $Excel.Workbook.WorkSheets[1] - #endregion - - it 'zero' { - $fakeData.Property_6_Number | Should -BeExactly '0' - $Worksheet.Cells[2, 6].Text | Should -BeExactly $fakeData.Property_6_Number - $Worksheet.Cells[2, 6].Value | Test-isNumeric | Should -Be $true - } - - It 'regular number' { - $fakeData.Property_7_Number | Should -BeExactly '5' - $Worksheet.Cells[2, 7].Text | Should -BeExactly $fakeData.Property_7_Number - $Worksheet.Cells[2, 7].Value | Test-isNumeric | Should -Be $true - } - - It 'number starting with zero' { - $fakeData.Property_8_Number | Should -BeExactly '007' - $Worksheet.Cells[2, 8].Text | Should -BeExactly '7' - $Worksheet.Cells[2, 8].Value | Test-isNumeric | Should -Be $true - } - - It 'decimal number' { - # US '33.00' BE '33,00' - $fakeData.Property_9_Number | Should -BeExactly (33).ToString('F2') - $Worksheet.Cells[2, 9].Text | Should -BeExactly '33' - $Worksheet.Cells[2, 9].Value | Test-isNumeric | Should -Be $true - - # US '1.67' BE '1,67' - $fakeData.Property_10_Number | Should -BeExactly (5/3).ToString('F2') - $Worksheet.Cells[2, 10].Text | Should -BeExactly $fakeData.Property_10_Number - $Worksheet.Cells[2, 10].Value | Test-isNumeric | Should -Be $true - } - - It 'thousand seperator and decimal number' { - # US '5,333,332.67' BE '5.333.332,67' - # Excel BE '5333332,67' - $fakeData.Property_11_Number | Should -BeExactly (15999998/3).ToString('N2') - $Worksheet.Cells[2, 11].Text | Should -BeExactly $fakeData.Property_11_Number - $Worksheet.Cells[2, 11].Value | Test-isNumeric | Should -Be $true - } - } - } - } -} \ No newline at end of file diff --git a/Export-Excel.ps1 b/Export-Excel.ps1 deleted file mode 100644 index bbf3c3a8..00000000 --- a/Export-Excel.ps1 +++ /dev/null @@ -1,1059 +0,0 @@ -Function Export-Excel { - <# - .SYNOPSIS - 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 Path - Path to a new or existing .XLSX file - .PARAMETER ExcelPackage - An object representing an Excel Package - usually this is returned by specifying -Passthru allowing multiple commands to work on the same Workbook without saving and reloading each time. - .PARAMETER WorkSheetName - The name of a sheet within the workbook - "Sheet1" by default - .PARAMETER ClearSheet - If specified Export-Excel will remove any existing worksheet with the selected name. The Default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place) - .PARAMETER Append - If specified data will be added to the end of an existing sheet, using the same column headings. - .PARAMETER TargetData - Data to insert onto the worksheet - this is often provided from the pipeline. - .PARAMETER ExcludeProperty - Specifies properties which may exist in the target data but should not be placed on the worksheet - .PARAMETER Title - Text of a title to be placed in Cell A1 - .PARAMETER TitleBold - Sets the title in boldface type - .PARAMETER TitleSize - Sets the point size for the title - .PARAMETER TitleBackgroundColor - Sets the cell background to solid and the chose colour for the title cell - .PARAMETER Password - Sets password protection on the workbook - .PARAMETER IncludePivotTable - Adds a Pivot table using the data in the worksheet - .PARAMETER PivotRows - Name(s) columns from the spreadhseet which will provide the row name(s) in the pivot table - .PARAMETER PivotColumns - Name(s) columns from the spreadhseet which will provide the Column name(s) in the pivot table - .PARAMETER PivotData - Hash table in the form ColumnName = Average|Count|CountNums|Max|Min|Product|None|StdDev|StdDevP|Sum|Var|VarP to provide the data in the Pivot table - .PARAMETER PivotTableDefinition, - HashTable(s) with Sheet PivotTows, PivotColumns, PivotData, IncludePivotChart and ChartType values to make it easier to specify a definition or multiple Pivots. - .PARAMETER IncludePivotChart, - Include a chart with the Pivot table - implies Include Pivot Table. - .PARAMETER NoLegend - Exclude the legend from the pivot chart - .PARAMETER ShowCategory - Add category labels to the pivot chart - .PARAMETER ShowPercent - Add Percentage labels to the pivot chart - .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 BoldTopRow - Makes the top Row boldface. - .PARAMETER NoHeader - Does not put field names at the top of columns - .PARAMETER RangeName - Makes the data in the worksheet a named range - .PARAMETER TableName - Makes the data in the worksheet a table with a name applies a style to it. Name must not contain spaces - .PARAMETER TableStyle - Selects the style for the named table - defaults to 'Medium6' - .PARAMETER ExcelChartDefinition - A hash table containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts - .PARAMETER HideSheet - Name(s) of Sheet(s) to hide in the workbook - .PARAMETER KillExcel - Closes Excel - prevents errors writing to the file because Excel has it open - .PARAMETER AutoNameRange - Makes each column a named range - .PARAMETER StartRow - Row to start adding data. 1 by default. Row 1 will contain the title if any. Then headers will appear (Unless -No header is specified) then the data appears - .PARAMETER StartColumn - Column to start adding data - 1 by default - - .PARAMETER FreezeTopRow - Freezes headers etc. in the top row - .PARAMETER FreezeFirstColumn - Freezes titles etc. in the left column - .PARAMETER FreezeTopRowFirstColumn - Freezes top row and left column (equivalent to Freeze pane 2,2 ) - .PARAMETER FreezePane - Freezes panes at specified coordinates (in the form RowNumber , ColumnNumber) - .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 - '€#,##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. - .PARAMETER PassThru - If specified, Export-Excel returns an object representing the Excel package without saving the package first. To save it you need to call the save or Saveas method or send it back to Export-Excel - - .EXAMPLE - Get-Process | Export-Excel .\Test.xlsx -show - Export all the processes to the Excel file 'Test.xlsx' and open the file immediately. - - .EXAMPLE - $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 - $ExcelParams = @{ - Path = $env:TEMP + '\Excel.xlsx' - Show = $true - Verbose = $true - } - Remove-Item -Path $ExcelParams.Path -Force -EA Ignore - - $Array = @() - - $Obj1 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - } - - $Obj2 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - Member3 = 'Third' - } - - $Obj3 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - Member3 = 'Third' - Member4 = 'Fourth' - } - - $Array = $Obj1, $Obj2, $Obj3 - $Array | Out-GridView -Title 'Not showing Member3 and Member4' - $Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorkSheetname Numbers - - Updates the first object of the array by adding property 'Member3' and 'Member4'. Afterwards. all objects are exported to an Excel file and all column headers are visible. - - .EXAMPLE - Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM - - .EXAMPLE - Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -ChartType PieExploded3D -IncludePivotChart -IncludePivotTable -Show -PivotRows Company -PivotData PM - - .EXAMPLE - Get-Service | Export-Excel 'c:\temp\test.xlsx' -Show -IncludePivotTable -PivotRows status -PivotData @{status='count'} - - .EXAMPLE - $pt = [ordered]@{} - $pt.pt1=@{ SourceWorkSheet = 'Sheet1'; - PivotRows = 'Status' - PivotData = @{'Status'='count'} - IncludePivotChart = $true - ChartType = 'BarClustered3D' - } - $pt.pt2=@{ SourceWorkSheet = 'Sheet2'; - PivotRows = 'Company' - PivotData = @{'Company'='count'} - IncludePivotChart = $true - ChartType = 'PieExploded3D' - } - Remove-Item -Path .\test.xlsx - Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -AutoSize - Get-Process | Select-Object -Property Name,Company,Handles,CPU,VM | Export-Excel -Path .\test.xlsx -AutoSize -WorkSheetname 'sheet2' - Export-Excel -Path .\test.xlsx -PivotTableDefinition $pt -Show - - This example defines two pivot tables. Then it puts Service data on Sheet1 with one call to Export-Excel and Process Data on sheet2 with a second call to Export-Excel - The thrid and final call adds the two pivot tables and opens the spreadsheet in Excel - - - .EXAMPLE - Remove-Item -Path .\test.xlsx - $excel = Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -PassThru - $excel.Workbook.Worksheets["Sheet1"].Row(1).style.font.bold = $true - $excel.Workbook.Worksheets["Sheet1"].Column(3 ).width = 29 - $excel.Workbook.Worksheets["Sheet1"].Column(3 ).Style.wraptext = $true - $excel.Save() - $excel.Dispose() - Start-Process .\test.xlsx - - This example uses -passthrough - put service information into sheet1 of the work book and saves the excelPackageObject in $Excel - It then uses the package object to apply formatting, and then saves the workbook and disposes of the object before loading the document in Excel. - - .EXAMPLE - $excel = Get-Process | Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | Export-Excel -Path .\test.xlsx -ClearSheet -WorkSheetname "Processes" -PassThru - $sheet = $excel.Workbook.Worksheets["Processes"] - $sheet.Column(1) | Set-Format -Bold -AutoFit - $sheet.Column(2) | Set-Format -Width 29 -WrapText - $sheet.Column(3) | Set-Format -HorizontalAlignment Right -NFormat "#,###" - Set-Format -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" - Set-Format -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold - Set-Format -Address $sheet.Row(1) -Bold -HorizontalAlignment Center - Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red - Add-ConditionalFormatting -WorkSheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red - foreach ($c in 5..9) {Set-Format $sheet.Column($c) -AutoFit } - Export-Excel -ExcelPackage $excel -WorkSheetname "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show - - This a more sophisticated version of the previous example showing different ways of using Set-Format, and also adding conditional formatting. - In the final command a Pivot chart is added and the workbook is opened in Excel. - - .LINK - https://github.com/dfinke/ImportExcel - #> - - [CmdletBinding(DefaultParameterSetName = 'Default')] - Param( - [Parameter(ParameterSetName = "Default", Position = 0)] - [Parameter(ParameterSetName = "Table" , Position = 0)] - [String]$Path, - [Parameter(Mandatory = $true, ParameterSetName = "PackageDefault")] - [Parameter(Mandatory = $true, ParameterSetName = "PackageTable")] - [OfficeOpenXml.ExcelPackage]$ExcelPackage, - [Parameter(ValueFromPipeline = $true)] - $TargetData, - [String]$Password, - [String]$WorkSheetname = 'Sheet1', - [switch]$ClearSheet, - [switch]$Append, - [String]$Title, - [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None', - [Switch]$TitleBold, - [Int]$TitleSize = 22, - [System.Drawing.Color]$TitleBackgroundColor, - [Switch]$IncludePivotTable, - [String[]]$PivotRows, - [String[]]$PivotColumns, - $PivotData, - [String[]]$PivotFilter, - [Switch]$PivotDataToColumn, - [Hashtable]$PivotTableDefinition, - [Switch]$IncludePivotChart, - [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie', - [Switch]$NoLegend, - [Switch]$ShowCategory, - [Switch]$ShowPercent, - [Switch]$AutoSize, - [Switch]$Show, - [Switch]$NoClobber, - [Switch]$FreezeTopRow, - [Switch]$FreezeFirstColumn, - [Switch]$FreezeTopRowFirstColumn, - [Int[]]$FreezePane, - [Parameter(ParameterSetName = 'Default')] - [Parameter(ParameterSetName = 'PackageDefault')] - [Switch]$AutoFilter, - [Switch]$BoldTopRow, - [Switch]$NoHeader, - [String]$RangeName, - [ValidateScript( { - if ($_.Contains(' ')) { - throw 'Tablename has spaces.' - } - elseif (-not $_) { - throw 'Tablename is null or empty.' - } - elseif ($_[0] -notmatch '[a-z]') { - throw 'Tablename starts with an invalid character.' - } - else { - $true - } - })] - [Parameter(ParameterSetName = 'Table' , Mandatory = $true)] - [Parameter(ParameterSetName = 'PackageTable' , Mandatory = $true)] - [String]$TableName, - [Parameter(ParameterSetName = 'Table')] - [Parameter(ParameterSetName = 'PackageTable')] - [OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6', - [Object[]]$ExcelChartDefinition, - [String[]]$HideSheet, - [Switch]$KillExcel, - [Switch]$AutoNameRange, - [Int]$StartRow = 1, - [Int]$StartColumn = 1, - [Switch]$PassThru, - [String]$Numberformat = 'General', - [string[]]$ExcludeProperty, - [String[]]$NoNumberConversion, - [Object[]]$ConditionalFormat, - [Object[]]$ConditionalText, - [ScriptBlock]$CellStyleSB, - [Parameter(ParameterSetName = 'Now')] - # [Parameter(ParameterSetName = 'TableNow')] - [Switch]$Now, - [Switch]$ReturnRange, - [Switch]$NoTotalsInPivot, - [Switch]$ReZip - ) - - Begin { - function Find-WorkSheet { - param ( - $WorkSheetName - ) - - $pkg.Workbook.Worksheets | Where-Object {$_.name -match $WorkSheetName} - } - - 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' # This is not a custom format, but a preset recognized as date and localized. - 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 $_) -ne $null) { - $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) - } - elseif ($TitleBackgroundColor) { - 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 ($append -and $clearSheet) {throw "You can't use -Append AND -ClearSheet."} - if ($KillExcel) { - Stop-ExcelProcess - } - - if ($PSBoundParameters.Keys.Count -eq 0 -Or $Now) { - $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' - $Show = $true - $AutoSize = $true - if (!$TableName) { - $AutoFilter = $true - } - } - - if ($ExcelPackage) { - $pkg = $ExcelPackage - $Path = $pkg.File - } - Else { - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - - $targetPath = Split-Path $Path - if (!(Test-Path $targetPath)) { - Write-Debug "Base path $($targetPath) does not exist, creating" - $null = mkdir $targetPath -ErrorAction Ignore - } - elseif (Test-Path $Path) { - Write-Debug "Path '$Path' already exists" - } - - $pkg = New-Object OfficeOpenXml.ExcelPackage $Path - } - - [OfficeOpenXml.ExcelWorksheet]$ws = $pkg | Add-WorkSheet -WorkSheetname $WorkSheetname -NoClobber:$NoClobber -ClearSheet:$ClearSheet #Add worksheet doesn't take any action for -noClobber - foreach ($format in $ConditionalFormat ) { - $target = "Add$($format.Formatter)" - $rule = ($ws.ConditionalFormatting).PSObject.Methods[$target].Invoke($format.Range, $format.IconType) - $rule.Reverse = $format.Reverse - } - - if ($append) { - $headerRange = $ws.Dimension.Address -replace "\d+$", "1" - #if there is a title or anything else above the header row, specifying StartRow will skip it. - if ($StartRow -ne 1) {$headerRange = $headerRange -replace "1", "$StartRow"} - #$script:Header = $ws.Cells[$headerrange].Value - #using a slightly odd syntax otherwise header ends up as a 2D array - $ws.Cells[$headerRange].Value | foreach -Begin {$Script:header = @()} -Process {$Script:header += $_ } - $row = $ws.Dimension.Rows - Write-Debug -Message ("Appending: headers are " + ($script:Header -join ", ") + "Start row $row") - } - elseif ($Title) { - #Can only add a title if not appending - $Row = $StartRow - Add-Title - $Row ++ ; $startRow ++ - } - else { - $Row = $StartRow - - } - $ColumnIndex = $StartColumn - $firstTimeThru = $true - $isDataTypeValueType = $false - $pattern = 'string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort' - } - Catch { - if ($AlreadyExists) { - #Is this set anywhere ? - throw "Failed exporting worksheet '$WorkSheetname' to '$Path': The worksheet '$WorkSheetname' already exists." - } - else { - throw "Failed exporting worksheet '$WorkSheetname' to '$Path': $_" - } - } - } - - Process { - if ($TargetData) { - Try { - if ($firstTimeThru) { - $firstTimeThru = $false - $isDataTypeValueType = $TargetData.GetType().name -match $pattern - Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" - } - - if ($isDataTypeValueType) { - $ColumnIndex = $StartColumn - - Add-CellValue -TargetCell $ws.Cells[$Row, $ColumnIndex] -CellValue $TargetData - - $ColumnIndex += 1 - $Row += 1 - } - else { - #region Add headers - if (-not $script:Header) { - $ColumnIndex = $StartColumn - $script:Header = $TargetData.PSObject.Properties.Name | Where-Object {$_ -notin $ExcludeProperty} - - if ($NoHeader) { - # Don't push the headers to the spread sheet - $Row -= 1 - } - else { - foreach ($Name in $script:Header) { - $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) { - #region Add non header values - Add-CellValue -TargetCell $ws.Cells[$Row, $ColumnIndex] -CellValue $TargetData.$Name - - $ColumnIndex += 1 - #endregion - } - } - } - Catch { - throw "Failed exporting worksheet '$WorkSheetname' to '$Path': $_" - } - } - } - - End { - Try { - if ($AutoNameRange) { - if (-not $script:header) { - $headerRange = $ws.Dimension.Address -replace "\d+$", "1" - #if there is a title or anything else above the header row, specifying StartRow will skip it. - if ($StartRow -ne 1) {$headerRange = $headerRange -replace "1", "$StartRow"} - #using a slightly odd syntax otherwise header ends up as a 2D array - $ws.Cells[$headerRange].Value | foreach -Begin {$Script:header = @()} -Process {$Script:header += $_ } - } - $totalRows = $ws.Dimension.End.Row - $totalColumns = $ws.Dimension.Columns - foreach ($c in 0..($totalColumns - 1)) { - $targetRangeName = "$($script:Header[$c])" - $targetColumn = $c + $StartColumn - $theCell = $ws.Cells[($startrow + 1), $targetColumn, $totalRows , $targetColumn ] - $ws.Names.Add($targetRangeName, $theCell) | Out-Null - - if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress($targetRangeName)) { - Write-Warning "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property name." - } - } - } - - if ($Title) { - $startAddress = $ws.Dimension.Start.address -replace "$($ws.Dimension.Start.row)`$", "$($ws.Dimension.Start.row + 1)" - } - else { - $startAddress = $ws.Dimension.Start.Address - } - - $dataRange = "{0}:{1}" -f $startAddress, $ws.Dimension.End.Address - - Write-Debug "Data Range '$dataRange'" - - if (-not [String]::IsNullOrEmpty($RangeName)) { - $ws.Names.Add($RangeName, $ws.Cells[$dataRange]) | Out-Null - } - - if (-not [String]::IsNullOrEmpty($TableName)) { - $csr = $StartRow - - $csc = $StartColumn - $cer = $ws.Dimension.End.Row - $cec = $ws.Dimension.End.Column # was $script:Header.Count - - $targetRange = $ws.Cells[$csr, $csc, $cer, $cec] - #if we're appending data the table may already exist: but excel doesn't like the result if I put - # if ($ws.Tables[$TableName]) {$ws.Tables.Delete($TableName) } - $tbl = $ws.Tables.Add($targetRange, $TableName) - $tbl.TableStyle = $TableStyle - } - - $PivotTableStartCell = "A1" - if($PivotFilter) {$PivotTableStartCell = "A3"} - - if ($PivotTableDefinition) { - foreach ($item in $PivotTableDefinition.GetEnumerator()) { - $targetName = $item.Key - $pivotTableName = $targetName #+ 'PivotTable' - #Make sure the Pivot table sheet doesn't already exist - try { $pkg.Workbook.Worksheets.Delete( $pivotTableName) } catch {} - $wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber - $pivotTableDataName = $targetName + 'PivotTableData' - - if (!$item.Value.SourceWorkSheet) { - $pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells[$PivotTableStartCell], $ws.Cells[$dataRange], $pivotTableDataName) - } - else { - $workSheet = Find-WorkSheet $item.Value.SourceWorkSheet - - if ($workSheet) { - $targetStartAddress = $workSheet.Dimension.Start.Address - $targetDataRange = "{0}:{1}" -f $targetStartAddress, $workSheet.Dimension.End.Address - - $pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells[$PivotTableStartCell], $workSheet.Cells[$targetDataRange], $pivotTableDataName) - } - } - - switch ($item.Value.Keys) { - "PivotRows" { - foreach ($Row in $item.Value.PivotRows) { - $null = $pivotTable.RowFields.Add($pivotTable.Fields[$Row]) - } - } - - "PivotColumns" { - foreach ($Column in $item.Value.PivotColumns) { - $null = $pivotTable.ColumnFields.Add($pivotTable.Fields[$Column]) - } - } - - "PivotData" { - $pivotData = $item.Value.PivotData - 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 { - foreach ($Item in $PivotData) { - $df = $pivotTable.DataFields.Add($pivotTable.Fields[$Item]) - $df.Function = 'Count' - } - } - - if ($PivotDataToColumn) { - $pivotTable.DataOnRows = $false - } - } - - "IncludePivotChart" { - $ChartType = "Pie" - if ($item.Value.ChartType) { - $ChartType = $item.Value.ChartType - } - - $chart = $wsPivot.Drawings.AddChart('PivotChart', $ChartType, $pivotTable) - $chart.SetPosition(0, 0, 4, 0) #Changed position to top row, next to a chart which doesn't pivot on columns - $chart.SetSize(600, 400) - if ($chart.DataLabel) { - $chart.DataLabel.ShowCategory = [boolean]$item.value.ShowCategory - $chart.DataLabel.ShowPercent = [boolean]$item.value.ShowPercent - } - if ([boolean]$item.value.NoLegend) {$chart.Legend.Remove()} - if ($item.value.ChartTitle) {$chart.Title.Text = $item.value.chartTitle} - } - } - - if($item.Value.NoTotalsInPivot) { - $pivotTable.RowGrandTotals = $false - } - } - } - - if ($IncludePivotTable -or $IncludePivotChart) { - #changed so -includePivotChart Implies -includePivotTable. - $pivotTableName = $WorkSheetname + 'PivotTable' - #Make sure the Pivot table sheet doesn't already exist - try { $pkg.Workbook.Worksheets.Delete( $pivotTableName) } catch {} - $wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber - - $wsPivot.View.TabSelected = $true - - $pivotTableDataName = $WorkSheetname + 'PivotTableData' - - $pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells[$PivotTableStartCell], $ws.Cells[$dataRange], $pivotTableDataName) - - if ($PivotRows) { - foreach ($Row in $PivotRows) { - $null = $pivotTable.RowFields.Add($pivotTable.Fields[$Row]) - } - } - - if ($PivotColumns) { - foreach ($Column in $PivotColumns) { - $null = $pivotTable.ColumnFields.Add($pivotTable.Fields[$Column]) - } - } - - if ($PivotData) { - 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 { - foreach ($Item in $PivotData) { - $df = $pivotTable.DataFields.Add($pivotTable.Fields[$Item]) - $df.Function = 'Count' - } - } - if ($PivotDataToColumn) { - $pivotTable.DataOnRows = $false - } - } - - if($NoTotalsInPivot) { - $pivotTable.RowGrandTotals = $false - } - - if ($IncludePivotChart) { - $chart = $wsPivot.Drawings.AddChart('PivotChart', $ChartType, $pivotTable) - if ($chart.DataLabel) { - $chart.DataLabel.ShowCategory = $ShowCategory - $chart.DataLabel.ShowPercent = $ShowPercent - } - $chart.SetPosition(0, 26, 2, 26) # if Pivot table is rows+data only it will be 2 columns wide if has pivot columns we don't know how wide it will be - if ($NoLegend) { - $chart.Legend.Remove() - } - - } - } - - if($pivotTable -and $PivotFilter) { - - foreach($pFilter in $PivotFilter) { - $null = $pivotTable.PageFields.Add($pivotTable.Fields[$pFilter]) - } - } - - - 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 ($FreezePane) { - $freezeRow, $freezeColumn = $FreezePane - if (-not $freezeColumn -or $freezeColumn -eq 0) { - $freezeColumn = 1 - } - - if ($freezeRow -gt 1) { - $ws.View.FreezePanes($freezeRow, $freezeColumn) - } - } - if ($BoldTopRow) { - if ($Title) { - $range = $ws.Dimension.Address -replace '\d+', '2' - } - else { - $range = $ws.Dimension.Address -replace '\d+', '1' - } - - $ws.Cells[$range].Style.Font.Bold = $true - } - if ($AutoSize) { - $ws.Cells.AutoFitColumns() - } - - foreach ($Sheet in $HideSheet) { - $pkg.Workbook.WorkSheets[$Sheet].Hidden = 'Hidden' - } - - $chartCount = 0 - foreach ($chartDef in $ExcelChartDefinition) { - $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() - } - - if ($chart.Datalabel -ne $null) { - $chart.Datalabel.ShowCategory = $chartDef.ShowCategory - $chart.Datalabel.ShowPercent = $chartDef.ShowPercent - } - - $chart.SetPosition($chartDef.Row, $chartDef.RowOffsetPixels, $chartDef.Column, $chartDef.ColumnOffsetPixels) - $chart.SetSize($chartDef.Width, $chartDef.Height) - - $chartDefCount = @($chartDef.YRange).Count - if ($chartDefCount -eq 1) { - $Series = $chart.Series.Add($chartDef.YRange, $chartDef.XRange) - - $SeriesHeader = $chartDef.SeriesHeader - if (-not $SeriesHeader) { - $SeriesHeader = 'Series 1' - } - - $Series.Header = $SeriesHeader - } - else { - 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] - } - - if (-not $SeriesHeader) { - $SeriesHeader = "Series $($idx)" - } - - $Series.Header = $SeriesHeader - $SeriesHeader = $null - } - } - } - - if ($ConditionalText) { - foreach ($targetConditionalText in $ConditionalText) { - $target = "Add$($targetConditionalText.ConditionalType)" - - $Range = $targetConditionalText.Range - 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 { - $rule.Text = $targetConditionalText.Text - } - } - - $rule.Style.Font.Color.Color = $targetConditionalText.ConditionalTextColor - $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 - & $CellStyleSB $ws $TotalRows $LastColumn - } - - if ($PassThru) { - $pkg - } - else { - if ($ReturnRange) { - $ws.Dimension.Address - } - - - - $pkg.Save() - - if ($ReZip) { - write-verbose "Re-Zipping $($pkg.file) using .NET ZIP library" - $zipAssembly = "System.IO.Compression.Filesystem" - try { - Add-Type -assembly $zipAssembly -ErrorAction stop - } catch { - write-error "The -ReZip parameter requires .NET Framework 4.5 or later to be installed. Recommend to install Powershell v4+" - continue - } - - $TempZipPath = Join-Path -path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName()) - [io.compression.zipfile]::ExtractToDirectory($pkg.File,$TempZipPath) | Out-Null - Remove-Item $pkg.File -Force - [io.compression.zipfile]::CreateFromDirectory($TempZipPath,$pkg.File) | Out-Null - } - - $pkg.Dispose() - - if ($Show) { - Invoke-Item $Path - } - } - } - Catch { - throw "Failed exporting worksheet '$WorkSheetname' to '$Path': $_" - } - } -} - -function New-PivotTableDefinition { - param( - [Parameter(Mandatory)] - [Alias("PivtoTableName")]#Previous typo - use alias to avoid breaking scripts - $PivotTableName, - $SourceWorkSheet, - $PivotRows, - [hashtable]$PivotData, - $PivotColumns, - [Switch]$IncludePivotChart, - [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie', - [Switch]$NoLegend, - [Switch]$ShowCategory, - [Switch]$ShowPercent, - [String]$ChartTitle, - [Switch]$NoTotalsInPivot - ) - - $parameters = @{} + $PSBoundParameters - $parameters.Remove('PivotTableName') - - @{$PivotTableName = $parameters} -} diff --git a/Export-ExcelSheet.ps1 b/Export-ExcelSheet.ps1 deleted file mode 100644 index fc095e74..00000000 --- a/Export-ExcelSheet.ps1 +++ /dev/null @@ -1,40 +0,0 @@ -function Export-ExcelSheet { - - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [String]$Path, - [String]$OutputPath = '.\', - [String]$SheetName, - [ValidateSet('ASCII', 'BigEndianUniCode','Default','OEM','UniCode','UTF32','UTF7','UTF8')] - [string]$Encoding = 'UTF8', - [ValidateSet('.txt', '.log','.csv')] - [string]$Extension = '.csv', - [ValidateSet(';', ',')] - [string]$Delimiter = ';' - ) - - $Path = (Resolve-Path $Path).Path - $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path - $workbook = $xl.Workbook - - $targetSheets = $workbook.Worksheets | Where {$_.Name -Match $SheetName} - - $params = @{} + $PSBoundParameters - $params.Remove("OutputPath") - $params.Remove("SheetName") - $params.Remove('Extension') - $params.NoTypeInformation = $true - - Foreach ($sheet in $targetSheets) - { - Write-Verbose "Exporting sheet: $($sheet.Name)" - - $params.Path = "$OutputPath\$($Sheet.Name)$Extension" - - Import-Excel $Path -Sheet $($sheet.Name) | Export-Csv @params - } - - $xl.Dispose() -} diff --git a/Export-StocksToExcel.ps1 b/Export-StocksToExcel.ps1 new file mode 100644 index 00000000..4785e0b7 --- /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 = Join-Path ([IO.Path]::GetTempPath()) '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/Export-charts.ps1 b/Export-charts.ps1 index 196d8e57..96c64965 100644 --- a/Export-charts.ps1 +++ b/Export-charts.ps1 @@ -1,51 +1,51 @@ <# .Synopsis - Exports the charts in an Excel spreadSheet + Exports the charts in an Excel spreadSheet .Example - Export-Charts .\test,xlsx + Export-Charts .\test.xlsx Exports the charts in test.xlsx to JPEG files in the current directory. .Example - Export-Charts -path .\test,xlsx -destination [System.Environment+SpecialFolder]::MyDocuments -outputType PNG -passthrough - Exports the charts to PNG files in MyDocuments , and returns file objects representing the newly created files + Export-Charts -path .\test,xlsx -destination [System.Environment+SpecialFolder]::MyDocuments -outputType PNG -passthrough + Exports the charts to PNG files in MyDocuments , and returns file objects representing the newly created files #> -Param ( - #Path to the Excel file whose chars we will export. - $Path = "C:\Users\public\Documents\stats.xlsx", - #If specified, output file objects representing the image files. - [switch]$passthru, - #Format to write - JPG by default +param( + #Path to the Excel file whose chars we will export. + $Path = "C:\Users\public\Documents\stats.xlsx", + #If specified, output file objects representing the image files + [switch]$Passthru, + #Format to write - JPG by default [ValidateSet("JPG","PNG","GIF")] - $OutputType = "JPG", - #Folder to write image files to (defaults to same one as the Excel file is in) + $OutputType = "JPG", + #Folder to write image files to (defaults to same one as the Excel file is in) $Destination ) -#if no output folder was specified, set destination to the folder where the Excel file came from -if (-not $Destination) {$Destination = Split-Path -Path $path -Parent } +#if no output folder was specified, set destination to the folder where the Excel file came from +if (-not $Destination) {$Destination = Split-Path -Path $Path -Parent } -#Call up Excel and tell it to open the file. -try { $excelApp = New-Object -ComObject "Excel.Application" } -catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return } +#Call up Excel and tell it to open the file. +try { $excelApp = New-Object -ComObject "Excel.Application" } +catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return } -try { $excelWorkBook = $excelApp.Workbooks.Open($path) } -catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return } +try { $excelWorkBook = $excelApp.Workbooks.Open($Path) } +catch { Write-Warning -Message "Could not Open $Path." ; return } - -#For each worksheet, for each chart, jump to the chart, create a filename of "WorksheetName_ChartTitle.jpg", and export the file. +#For each worksheet, for each chart, jump to the chart, create a filename of "WorksheetName_ChartTitle.jpg", and export the file. foreach ($excelWorkSheet in $excelWorkBook.Worksheets) { - #note somewhat unusual way of telling excel we want all the charts. + #note somewhat unusual way of telling excel we want all the charts. foreach ($excelchart in $excelWorkSheet.ChartObjects([System.Type]::Missing)) { - #if you don't go to the chart the image will be zero size ! + #if you don't go to the chart the image will be zero size ! $excelApp.Goto($excelchart.TopLeftCell,$true) $imagePath = Join-Path -Path $Destination -ChildPath ($excelWorkSheet.Name + "_" + ($excelchart.Chart.ChartTitle.Text -split "\s\d\d:\d\d,")[0] + ".$OutputType") - if ( $excelchart.Chart.Export($imagePath, $OutputType, $false) ) { # Export returs true/false for success/failure - if ($passThru) {Get-Item -Path $imagePath } # when succesful return a file object (-passthru) or print a verbose message, write warning for any failures + if ( $excelchart.Chart.Export($imagePath, $OutputType, $false) ) { # Export returs true/false for success/failure + if ($Passthru) {Get-Item -Path $imagePath } # when succesful return a file object (-Passthru) or print a verbose message, write warning for any failures else {Write-Verbose -Message "Exported $imagePath"} - } - else {Write-Warning -Message "Failure exporting $imagePath" } + } + else {Write-Warning -Message "Failure exporting $imagePath" } } } - -$excelApp.Quit() \ No newline at end of file +$excelApp.DisplayAlerts = $false +$excelWorkBook.Close($false,$null,$null) +$excelApp.Quit() diff --git a/FAQ/How to Create an Empty Excel File.md b/FAQ/How to Create an Empty Excel File.md new file mode 100644 index 00000000..33b63ce4 --- /dev/null +++ b/FAQ/How to Create an Empty Excel File.md @@ -0,0 +1,6 @@ +# Create an Empty Excel File +Use an empty string to export to an excel file. +```powershell +#Build an Excel file named: "file.xlsx" containing a worksheet: "MyWorksheet" +"" | Export-Excel -Path "C:\Test\file.xlsx" -WorksheetName "MyWorksheet" +``` diff --git a/FAQ/How to Read an Existing Excel File.md b/FAQ/How to Read an Existing Excel File.md new file mode 100644 index 00000000..bb869ca3 --- /dev/null +++ b/FAQ/How to Read an Existing Excel File.md @@ -0,0 +1,41 @@ +# How to Read an Existing Excel File +## Enumerate the Excel File Contents +```powershell +#Load the Excel file into a PSCustomObject +$ExcelFile = Import-Excel "C:\Test\file.xlsx" -WorksheetName "Sheet1" +``` + +## Visual of Data Structure +The File C:\Test\file.xlsx contains +![ExcelFileContents](/images/FAQ_Images/ExcelFileContents.png) + +After loading this data into ```$ExcelFile``` the data is stored like: +![ExcelFileDebugImg](/images/FAQ_Images/ExcelFileDebugImg.jpg) + +## Other Common Operations + +### Load a Column +```powershell +$SpecificColumn = $ExcelFile."anotherHeader" #loads column with the header "anotherHeader" -- data stored in an array +``` + +### Load a Row +```powershell +$SpecificRow = $ExcelFile[1] #Loads row at index 1. Index 1 is the first row instead of 0. +``` + +### Map Contents to Hashtable to Interpret Data +Sometimes mapping to a Hashtable is more convenient to have access to common Hashtable operations. Enumerate a Hashtable with the row's data by: +```powershell +$HashTable = @{} +$SpecificRow= $ExcelFile[2] +$SpecificRow.psobject.properties | ForEach-Object { + $HashTable[$_.Name] = $_.Value +} +``` +To then iterate through the enumerated Hashtable: +```powershell +ForEach ($Key in ($HashTable.GetEnumerator()) | Where-Object {$_.Value -eq "x"}){ #Only grabs a key where the value is "x" + #values accessible with $Key.Name or $Key.Value +} +``` diff --git a/FAQ/How to Write to an Existing Excel File.md b/FAQ/How to Write to an Existing Excel File.md new file mode 100644 index 00000000..ce796ddb --- /dev/null +++ b/FAQ/How to Write to an Existing Excel File.md @@ -0,0 +1,34 @@ +# Write to an Existing Excel File +### Enumerate the Excel File +The cmdlets ```Open-ExcelPackage``` and ```Close-ExcelPackage``` allow for direct modification to Excel file contents. +```powershell +$ExcelPkg = Open-ExcelPackage -Path "C:\Test\file.xlsx" +``` +Contents of file.xlsx: +![ExcelFileContents](/images/FAQ_Images/ExcelFileContents.png) +### Enumerate the Worksheet to View or Modify the Data +```powershell +$WorkSheet = $ExcelPkg.Workbook.Worksheets["sheet1"].Cells #open excel worksheet cells from worksheet "sheet1" +``` +Visual of data structure: +![DataStructureExcelPkg](/images/FAQ_Images/DataStructureExcelPkg.png) +A1 contains "someHeader", A2 contains "data1" etc. +### Modify a Specific Value in a File +Values can be accessed by row, column. Similar to a 2D array. +```powershell +$WorkSheet[1,4].Value = "New Column Header" #Starts at index 1 not 0 +``` +Contents of file.xlsx after modifying: +![ExcelFileContentsPostAdd](/images/FAQ_Images/ExcelFileContentsPostAdd.png) +### Load Value at Specific Index +```powershell +$ValueAtIndex = $WorkSheet[2,1].Value #Loads the value at row 2, column A +``` +```$ValueAtIndex``` now contains: ![ValueAtIndexData](/images/FAQ_Images/ValueAtIndexData.png) +### Save File After Modifying +The changes will not display in the Excel file until Close-ExcelPackage is called. +```powershell +Close-ExcelPackage $ExcelPkg #close and save changes made to the Excel file. +``` +**Note**: If the file is currently in use, Close-ExcelPackage will return an error and will not save the information. + diff --git a/Get-ExcelWorkbookInfo.ps1 b/Get-ExcelWorkbookInfo.ps1 deleted file mode 100644 index acd2e920..00000000 --- a/Get-ExcelWorkbookInfo.ps1 +++ /dev/null @@ -1,68 +0,0 @@ -Function Get-ExcelWorkbookInfo { - <# - .SYNOPSIS - Retrieve information of an Excel workbook. - - .DESCRIPTION - The Get-ExcelWorkbookInfo cmdlet retrieves information (LastModifiedBy, LastPrinted, Created, Modified, ...) fron an Excel workbook. These are the same details that are visible in Windows Explorer when right clicking the Excel file, selecting Properties and check the Details tabpage. - - .PARAMETER Path - Specifies the path to the Excel file. This parameter is required. - - .EXAMPLE - Get-ExcelWorkbookInfo .\Test.xlsx - - CorePropertiesXml : #document - Title : - Subject : - Author : Konica Minolta User - Comments : - Keywords : - LastModifiedBy : Bond, James (London) GBR - LastPrinted : 2017-01-21T12:36:11Z - Created : 17/01/2017 13:51:32 - Category : - Status : - ExtendedPropertiesXml : #document - Application : Microsoft Excel - HyperlinkBase : - AppVersion : 14.0300 - Company : Secret Service - Manager : - Modified : 10/02/2017 12:45:37 - CustomPropertiesXml : #document - - .NOTES - CHANGELOG - 2016/01/07 Added Created by Johan Akerstrom (https://github.com/CosmosKey) - - .LINK - https://github.com/dfinke/ImportExcel - #> - - [CmdletBinding()] - Param ( - [Alias('FullName')] - [Parameter(ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, Mandatory=$true)] - [String]$Path - ) - - Process { - Try { - $Path = (Resolve-Path $Path).ProviderPath - - $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path,'Open','Read','ReadWrite' - $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream - $workbook = $xl.Workbook - $workbook.Properties - - $stream.Close() - $stream.Dispose() - $xl.Dispose() - $xl = $null - } - Catch { - throw "Failed retrieving Excel workbook information for '$Path': $_" - } - } -} diff --git a/Get-HtmlTable.ps1 b/Get-HtmlTable.ps1 deleted file mode 100644 index df7f54c4..00000000 --- a/Get-HtmlTable.ps1 +++ /dev/null @@ -1,42 +0,0 @@ -function Get-HtmlTable { - param( - [Parameter(Mandatory=$true)] - $url, - $tableIndex=0, - $Header, - [int]$FirstDataRow=0, - [Switch]$UseDefaultCredentials - ) - - $r = Invoke-WebRequest $url -UseDefaultCredentials: $UseDefaultCredentials - - $table = $r.ParsedHtml.getElementsByTagName("table")[$tableIndex] - $propertyNames=$Header - $totalRows=@($table.rows).count - - for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) { - - $row = $table.rows[$idx] - $cells = @($row.cells) - - if(!$propertyNames) { - if($cells[0].tagName -eq 'th') { - $propertyNames = @($cells | foreach {$_.innertext -replace ' ',''}) - } else { - $propertyNames = @(1..($cells.Count + 2) | % { "P$_" }) - } - continue - } - - $result = [ordered]@{} - - for($counter = 0; $counter -lt $cells.Count; $counter++) { - $propertyName = $propertyNames[$counter] - - if(!$propertyName) { $propertyName= '[missing]'} - $result.$propertyName= $cells[$counter].InnerText - } - - [PSCustomObject]$result - } -} \ No newline at end of file diff --git a/Get-Range.ps1 b/Get-Range.ps1 deleted file mode 100644 index e25db9c7..00000000 --- a/Get-Range.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -function Get-Range ($start=0,$stop,$step=1) { - for ($idx = $start; $idx -lt $stop; $idx+=$step) {$idx} -} \ No newline at end of file diff --git a/GetExcelTable.ps1 b/GetExcelTable.ps1 index e1aacc0a..109f2d6d 100644 --- a/GetExcelTable.ps1 +++ b/GetExcelTable.ps1 @@ -1,5 +1,5 @@ -Function Get-ExcelTableName { - Param ( +function Get-ExcelTableName { + param( $Path, $WorksheetName ) @@ -25,11 +25,11 @@ Function Get-ExcelTableName { $Stream.Close() $Stream.Dispose() $Excel.Dispose() - $Excel = $null + $Excel = $null } -Function Get-ExcelTable { - Param ( +function Get-ExcelTable { + param( $Path, $TableName, $WorksheetName @@ -66,7 +66,7 @@ Function Get-ExcelTable { $propertyNames = for($col=$startCol; $col -lt ($startCol+$colCount); $col+= 1) { $Worksheet.Cells[$startRow, $col].value } - + $startRow++ for($row=$startRow; $row -lt ($startRow+$rowCount); $row += 1) { $nr=[ordered]@{} @@ -89,16 +89,14 @@ function ConvertFrom-ExcelColumnName { $sum=0 $columnName.ToCharArray() | - ForEach { + ForEach-Object { $sum*=26 $sum+=[char]$_.tostring().toupper()-[char]'A'+1 - } + } $sum } -cls - -ipmo .\ImportExcel.psd1 -Force +Import-Module .\ImportExcel.psd1 -Force -#Get-ExcelTableName .\testTable.xlsx | Get-ExcelTable .\testTable.xlsx +#Get-ExcelTableName .\testTable.xlsx | Get-ExcelTable .\testTable.xlsx Get-ExcelTable .\testTable.xlsx Table3 \ No newline at end of file diff --git a/ImportExcel.Tests.ps1 b/ImportExcel.Tests.ps1 deleted file mode 100644 index faacee7c..00000000 --- a/ImportExcel.Tests.ps1 +++ /dev/null @@ -1,2084 +0,0 @@ -#Requires -Modules Pester -#Requires -Modules Assert - -$here = Split-Path -Parent $MyInvocation.MyCommand.Path -$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' - -Import-Module $here -Force - -$WarningPreference = 'SilentlyContinue' -# $WarningPreference = 'Continue' -$ProgressPreference = 'SilentlyContinue' - -$Path = 'Test.xlsx' -#<# -Context 'input' { - in $TestDrive { - Describe 'parameters' { - BeforeEach { - Remove-Item ./* -Force - } - Context 'mandatory in sets' { - it 'Path' { - (Get-Command Import-Excel).Parameters['Path'].Attributes.Mandatory | Should be $true - } - it 'HeaderName' { - (Get-Command Import-Excel).Parameters['HeaderName'].Attributes.Mandatory | Should be $true - } - it 'NoHeader' { - (Get-Command Import-Excel).Parameters['NoHeader'].Attributes.Mandatory | Should be $true - } - } - Context 'optional' { - it 'DataOnly' { - (Get-Command Import-Excel).Parameters['DataOnly'].Attributes.Mandatory | Should be $false - } - it 'StartRow' { - (Get-Command Import-Excel).Parameters['StartRow'].Attributes.Mandatory | Should be $false - } - it 'WorksheetName' { - (Get-Command Import-Excel).Parameters['WorksheetName'].Attributes.Mandatory | Should be $false - } - it 'Password' { - (Get-Command Import-Excel).Parameters['Password'].Attributes.Mandatory | Should be $false - } - } - Context 'aliases' { - it 'Path' { - (Get-Command Import-Excel).Parameters['Path'].Attributes.AliasNames | Should be 'FullName' - } - it 'WorksheetName' { - (Get-Command Import-Excel).Parameters['WorksheetName'].Attributes.AliasNames | Should be 'Sheet' - } - it 'StartRow' { - (Get-Command Import-Excel).Parameters['StartRow'].Attributes.AliasNames | Should be @('HeaderRow','TopRow') - } - } - Context 'illegal' { - it 'NoHeader combined with HeaderName' { - 'Kiwi'| Export-Excel -Path $Path -WorkSheetname Fruit - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName A -NoHeader} | Should Throw 'Parameter set cannot be resolved' - } - it 'HeaderName with blanks' { - 'Kiwi'| Export-Excel -Path $Path -WorkSheetname Fruit - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName A, $null, C} | Should Throw "Cannot bind argument to parameter 'HeaderName'" - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName $null, C} | Should Throw "Cannot bind argument to parameter 'HeaderName'" - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName $null} | Should Throw "Cannot bind argument to parameter 'HeaderName'" - - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName A, '', C} | Should Throw "Cannot bind argument to parameter 'HeaderName'" - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName '', C} | Should Throw "Cannot bind argument to parameter 'HeaderName'" - {Import-Excel -Path $Path -WorksheetName Fruit -HeaderName ''} | Should Throw "Cannot bind argument to parameter 'HeaderName'" - } - it 'Path does not exist' { - {Import-Excel -Path D:\DontExist -WorksheetName Fruit} | Should Throw "Cannot validate argument on parameter 'Path'" - } - it 'Path exists but does not have extension .xlsx or .xls' { - 'Kiwi' | Out-File NotAnExcelFile.txt - Test-Path -Path NotAnExcelFile.txt -PathType Leaf | Should be $true - {Import-Excel -Path NotAnExcelFile.txt -WorksheetName Fruit} | Should Throw "Cannot validate argument on parameter 'Path'" - } - it 'WorksheetName left blank' { - 'Kiwi'| Export-Excel -Path $Path -WorkSheetname Fruit - {Import-Excel -Path $Path -WorksheetName $null} | Should Throw "Cannot validate argument on parameter 'WorksheetName'. The argument is null or empty" - {Import-Excel -Path $Path -WorksheetName ''} | Should Throw "Cannot validate argument on parameter 'WorksheetName'. The argument is null or empty" - } - it 'Password left blank' { - 'Kiwi'| Export-Excel -Path $Path -WorkSheetname Fruit - {Import-Excel -Path $Path -WorksheetName Fruit -Password $null} | Should Throw "Cannot validate argument on parameter 'Password'. The argument is null or empty" - {Import-Excel -Path $Path -WorksheetName Fruit -Password ''} | Should Throw "Cannot validate argument on parameter 'Password'. The argument is null or empty" - } - } - Context 'omit parameter name' { - it 'Path' { - [PSCustomObject]@{ - Number = 1 - } | Export-Excel -Path $Path -WorkSheetname Test - - $ExpectedResult = [PSCustomObject]@{ - 'Number' = '1' - } - - $Result = Import-Excel $Path - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Path and WorksheetName' { - [PSCustomObject]@{ - Number = 1 - } | Export-Excel -Path $Path -WorkSheetname Test - - $ExpectedResult = [PSCustomObject]@{ - 'Number' = '1' - } - - $Result = Import-Excel $Path Test - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Path and WorksheetName with NoHeader' { - 'Kiwi' | Export-Excel -Path $Path -WorkSheetname Fruit - - $ExpectedResult = [PSCustomObject]@{ - P1 = 'Kiwi' - } - - $Result = Import-Excel $Path Fruit -NoHeader - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Path and WorksheetName with HeaderName' { - 'Kiwi' | Export-Excel -Path $Path -WorkSheetname Fruit - - $ExpectedResult = [PSCustomObject]@{ - Fruits = 'Kiwi' - } - - $Result = Import-Excel $Path Fruit -HeaderName Fruits - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - } - } - Describe 'worksheet' { - #region Create test file - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Excel | Add-WorkSheet -WorkSheetname Test - $Excel.Save() - $Excel.Dispose() - #endregion - - it 'not found' { - {Import-Excel -Path $Path -WorksheetName NotExisting} | Should Throw 'not found' - } - it 'empty' { - Import-Excel -Path $Path -WorksheetName Test -NoHeader | Should BeNullOrEmpty - } - it 'select first worksheet by default' { - Remove-Item ./* -Force - #region Create test file - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - - - # ---------------------------------------------- - # | A B C | - # |1 First Name Address | - # |2 Chuck Norris California | - # |3 Jean-Claude Vandamme Brussels | - # ---------------------------------------------- - - # Row, Column - $WorksheetActors = $Excel | Add-WorkSheet -WorkSheetname Actors - $WorksheetActors.Cells[1, 1].Value = 'First Name' - $WorksheetActors.Cells[1, 3].Value = 'Address' - $WorksheetActors.Cells[2, 1].Value = 'Chuck' - $WorksheetActors.Cells[2, 2].Value = 'Norris' - $WorksheetActors.Cells[2, 3].Value = 'California' - $WorksheetActors.Cells[3, 1].Value = 'Jean-Claude' - $WorksheetActors.Cells[3, 2].Value = 'Vandamme' - $WorksheetActors.Cells[3, 3].Value = 'Brussels' - - # --------------------------------------------------------------------- - # | A B C D E | - # |1 Movie name Year Rating Genre | - # |2 The Bodyguard 1992 9 Thriller | - # |3 The Matrix 1999 8 Sci-Fi | - # |4 | - # |5 Skyfall 2012 9 Thriller | - # --------------------------------------------------------------------- - - # Row, Column - $WorksheetMovies = $Excel | Add-WorkSheet -WorkSheetname Movies - $WorksheetMovies.Cells[1, 1].Value = 'Movie name' - $WorksheetMovies.Cells[1, 2].Value = 'Year' - $WorksheetMovies.Cells[1, 3].Value = 'Rating' - $WorksheetMovies.Cells[1, 5].Value = 'Genre' - $WorksheetMovies.Cells[2, 1].Value = 'The Bodyguard' - $WorksheetMovies.Cells[2, 2].Value = '1982' - $WorksheetMovies.Cells[2, 3].Value = '9' - $WorksheetMovies.Cells[2, 5].Value = 'Thriller' - $WorksheetMovies.Cells[3, 1].Value = 'The Matrix' - $WorksheetMovies.Cells[3, 2].Value = '1999' - $WorksheetMovies.Cells[3, 3].Value = '8' - $WorksheetMovies.Cells[3, 5].Value = 'Sci-Fi' - $WorksheetMovies.Cells[5, 1].Value = 'Skyfall' - $WorksheetMovies.Cells[5, 2].Value = '2012' - $WorksheetMovies.Cells[5, 3].Value = '9' - $WorksheetMovies.Cells[5, 5].Value = 'Thriller' - - $Excel.Save() - $Excel.Dispose() - #endregion - - $ExpectedResult = @( - [PSCustomObject]@{ - 'First Name' = 'Chuck' - 'Address' = 'California' - } - [PSCustomObject]@{ - 'First Name' = 'Jean-Claude' - 'Address' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Remove-Item ./* -Force - - #region Create test file - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - - # --------------------------------------------------------------------- - # | A B C D E | - # |1 Movie name Year Rating Genre | - # |2 The Bodyguard 1992 9 Thriller | - # |3 The Matrix 1999 8 Sci-Fi | - # |4 | - # |5 Skyfall 2012 9 Thriller | - # --------------------------------------------------------------------- - - # Row, Column - $WorksheetMovies = $Excel | Add-WorkSheet -WorkSheetname Movies - $WorksheetMovies.Cells[1, 1].Value = 'Movie name' - $WorksheetMovies.Cells[1, 2].Value = 'Year' - $WorksheetMovies.Cells[1, 3].Value = 'Rating' - $WorksheetMovies.Cells[1, 5].Value = 'Genre' - $WorksheetMovies.Cells[2, 1].Value = 'The Bodyguard' - $WorksheetMovies.Cells[2, 2].Value = '1982' - $WorksheetMovies.Cells[2, 3].Value = '9' - $WorksheetMovies.Cells[2, 5].Value = 'Thriller' - $WorksheetMovies.Cells[3, 1].Value = 'The Matrix' - $WorksheetMovies.Cells[3, 2].Value = '1999' - $WorksheetMovies.Cells[3, 3].Value = '8' - $WorksheetMovies.Cells[3, 5].Value = 'Sci-Fi' - $WorksheetMovies.Cells[5, 1].Value = 'Skyfall' - $WorksheetMovies.Cells[5, 2].Value = '2012' - $WorksheetMovies.Cells[5, 3].Value = '9' - $WorksheetMovies.Cells[5, 5].Value = 'Thriller' - - # ---------------------------------------------- - # | A B C | - # |1 First Name Address | - # |2 Chuck Norris California | - # |3 Jean-Claude Vandamme Brussels | - # ---------------------------------------------- - - # Row, Column - $WorksheetActors = $Excel | Add-WorkSheet -WorkSheetname Actors - $WorksheetActors.Cells[1, 1].Value = 'First Name' - $WorksheetActors.Cells[1, 3].Value = 'Address' - $WorksheetActors.Cells[2, 1].Value = 'Chuck' - $WorksheetActors.Cells[2, 2].Value = 'Norris' - $WorksheetActors.Cells[2, 3].Value = 'California' - $WorksheetActors.Cells[3, 1].Value = 'Jean-Claude' - $WorksheetActors.Cells[3, 2].Value = 'Vandamme' - $WorksheetActors.Cells[3, 3].Value = 'Brussels' - - $Excel.Save() - $Excel.Dispose() - #endregion - - $ExpectedResult = @( - [PSCustomObject]@{ - 'Movie name' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'Movie name' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'Movie name' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - } - [PSCustomObject]@{ - 'Movie name' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - } - } -} - -Context 'output' { - in $TestDrive { - Describe 'missing column header' { - - #region Create test file - - # ---------------------------------------------- - # | A B C | - # |1 First Name Address | - # |2 Chuck Norris California | - # |3 Jean-Claude Vandamme Brussels | - # ---------------------------------------------- - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Worksheet = $Excel | Add-WorkSheet -WorkSheetname Test - - # Row, Column - $Worksheet.Cells[1, 1].Value = 'First Name' - $Worksheet.Cells[1, 3].Value = 'Address' - $Worksheet.Cells[2, 1].Value = 'Chuck' - $Worksheet.Cells[2, 2].Value = 'Norris' - $Worksheet.Cells[2, 3].Value = 'California' - $Worksheet.Cells[3, 1].Value = 'Jean-Claude' - $Worksheet.Cells[3, 2].Value = 'Vandamme' - $Worksheet.Cells[3, 3].Value = 'Brussels' - - $Excel.Save() - $Excel.Dispose() - #endregion - - it 'Default' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'First Name' = 'Chuck' - 'Address' = 'California' - } - [PSCustomObject]@{ - 'First Name' = 'Jean-Claude' - 'Address' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default and StartRow' { - $ExpectedResult = [PSCustomObject]@{ - 'Chuck' = 'Jean-Claude' - 'Norris' = 'Vandamme' - 'California' = 'Brussels' - } - - $Result = Import-Excel -Path $Path -WorksheetName Test -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -StartRow 4 | Should BeNullOrEmpty - } - it 'Default and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'First Name' = 'Chuck' - 'Address' = 'California' - } - [PSCustomObject]@{ - 'First Name' = 'Jean-Claude' - 'Address' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default, DataOnly and StartRow' { - $ExpectedResult = [PSCustomObject]@{ - 'Chuck' = 'Jean-Claude' - 'Norris' = 'Vandamme' - 'California' = 'Brussels' - } - - $Result = Import-Excel -Path $Path -WorksheetName Test -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -DataOnly -StartRow 4 | Should BeNullOrEmpty - } - it 'NoHeader' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'First Name' - 'P2' = $null - 'P3' = 'Address' - } - [PSCustomObject]@{ - 'P1' = 'Chuck' - 'P2' = 'Norris' - 'P3' = 'California' - } - [PSCustomObject]@{ - 'P1' = 'Jean-Claude' - 'P2' = 'Vandamme' - 'P3' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'Chuck' - 'P2' = 'Norris' - 'P3' = 'California' - } - [PSCustomObject]@{ - 'P1' = 'Jean-Claude' - 'P2' = 'Vandamme' - 'P3' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 4 | Should BeNullOrEmpty - } - it 'NoHeader and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'First Name' - 'P2' = $null - 'P3' = 'Address' - } - [PSCustomObject]@{ - 'P1' = 'Chuck' - 'P2' = 'Norris' - 'P3' = 'California' - } - [PSCustomObject]@{ - 'P1' = 'Jean-Claude' - 'P2' = 'Vandamme' - 'P3' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'Chuck' - 'P2' = 'Norris' - 'P3' = 'California' - } - [PSCustomObject]@{ - 'P1' = 'Jean-Claude' - 'P2' = 'Vandamme' - 'P3' = 'Brussels' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 4 | Should BeNullOrEmpty - } - it 'HeaderName' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'First Name' - 'SecondName' = $null - 'City' = 'Address' - 'Rating' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'First Name' - 'SecondName' = $null - 'City' = 'Address' - 'Rating' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating, Country - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating, Country -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating, Country -StartRow 4 | Should BeNullOrEmpty - } - it 'HeaderName and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'First Name' - 'SecondName' = $null - 'City' = 'Address' - 'Rating' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'First Name' - 'SecondName' = $null - 'City' = 'Address' - 'Rating' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating, Country -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'FirstName' = 'Chuck' - 'SecondName' = 'Norris' - 'City' = 'California' - 'Rating' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'FirstName' = 'Jean-Claude' - 'SecondName' = 'Vandamme' - 'City' = 'Brussels' - 'Rating' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating, Country -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -HeaderName FirstName, SecondName, City, Rating, Country -DataOnly -StartRow 4 | Should BeNullOrEmpty - } - } - Describe 'blank rows and columns' { - - #region Create test file - - # --------------------------------------------------------------------- - # | A B C D E | - # |1 Movie name Year Rating Genre | - # |2 The Bodyguard 1992 9 Thriller | - # |3 The Matrix 1999 8 Sci-Fi | - # |4 | - # |5 Skyfall 2012 9 Thriller | - # --------------------------------------------------------------------- - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Worksheet = $Excel | Add-WorkSheet -WorkSheetname Test - - # Row, Column - $Worksheet.Cells[1, 1].Value = 'Movie name' - $Worksheet.Cells[1, 2].Value = 'Year' - $Worksheet.Cells[1, 3].Value = 'Rating' - $Worksheet.Cells[1, 5].Value = 'Genre' - $Worksheet.Cells[2, 1].Value = 'The Bodyguard' - $Worksheet.Cells[2, 2].Value = '1982' - $Worksheet.Cells[2, 3].Value = '9' - $Worksheet.Cells[2, 5].Value = 'Thriller' - $Worksheet.Cells[3, 1].Value = 'The Matrix' - $Worksheet.Cells[3, 2].Value = '1999' - $Worksheet.Cells[3, 3].Value = '8' - $Worksheet.Cells[3, 5].Value = 'Sci-Fi' - $Worksheet.Cells[5, 1].Value = 'Skyfall' - $Worksheet.Cells[5, 2].Value = '2012' - $Worksheet.Cells[5, 3].Value = '9' - $Worksheet.Cells[5, 5].Value = 'Thriller' - - $Excel.Save() - $Excel.Dispose() - #endregion - - it 'Default' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'Movie name' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'Movie name' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'Movie name' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - } - [PSCustomObject]@{ - 'Movie name' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'The Bodyguard' = 'The Matrix' - '1982' = '1999' - '9' = '8' - 'Thriller' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'The Bodyguard' = $null - '1982' = $null - '9' = $null - 'Thriller' = $null - } - [PSCustomObject]@{ - 'The Bodyguard' = 'Skyfall' - '1982' = '2012' - '9' = '9' - 'Thriller' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - {Import-Excel -Path $Path -WorksheetName Test -StartRow 4} | Should Throw 'No column headers found' - Import-Excel -Path $Path -WorksheetName Test -StartRow 5 | Should BeNullOrEmpty - } - it 'Default and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'Movie name' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'Movie name' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'Movie name' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'The Bodyguard' = 'The Matrix' - '1982' = '1999' - '9' = '8' - 'Thriller' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'The Bodyguard' = 'Skyfall' - '1982' = '2012' - '9' = '9' - 'Thriller' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - {Import-Excel -Path $Path -WorksheetName Test -DataOnly -StartRow 4} | Should Throw 'No column headers found' - - Import-Excel -Path $Path -WorksheetName Test -DataOnly -StartRow 5 | Should BeNullOrEmpty - } - it 'HeaderName' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = 'Year' - 'Rating' = 'Rating' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = 'Year' - 'Rating' = 'Rating' - 'Genre' = $null - 'Country' = 'Genre' - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - 'Country' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - 'Country' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -StartRow 4 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -StartRow 5 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -StartRow 6 | Should BeNullOrEmpty - } - it 'HeaderName and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = 'Year' - 'Rating' = 'Rating' - 'Genre' = 'Genre' - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - } - - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = 'Year' - 'Rating' = 'Rating' - 'Genre' = 'Genre' - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - 'Country' = $null - } - - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - } - - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = '1982' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = 'Sci-Fi' - 'Country' = $null - } - - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = $null - } - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly -StartRow 4 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly -StartRow 5 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly -StartRow 6 | Should BeNullOrEmpty - } - it 'NoHeader' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'Movie name' - 'P2' = 'Year' - 'P3' = 'Rating' - 'P4' = $null - 'P5' = 'Genre' - } - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = '1982' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = $null - 'P5' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = $null - 'P4' = $null - 'P5' = $null - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = '1982' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = $null - 'P5' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = $null - 'P4' = $null - 'P5' = $null - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = $null - 'P4' = $null - 'P5' = $null - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - } - ) - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 4 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - } - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 5 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 6 | Should BeNullOrEmpty - } - it 'NoHeader and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'Movie name' - 'P2' = 'Year' - 'P3' = 'Rating' - 'P4' = 'Genre' - } - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = '1982' - 'P3' = '9' - 'P4' = 'Thriller' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = '1982' - 'P3' = '9' - 'P4' = 'Thriller' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = 'Sci-Fi' - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = 'Thriller' - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = 'Thriller' - } - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 4 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 5 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 6 | Should BeNullOrEmpty - } - } - Describe 'blank rows and columns with missing headers' { - - #region Create test file - - # --------------------------------------------------------------------------------------------------- - # | A B C D E F G | - # |1 Movie name Rating Director | - # |2 The Bodyguard 9 Thriller Mick Jackson | - # |3 The Matrix 1999 8 Wachowski | - # |4 | - # |5 Skyfall 2012 9 Thriller Sam Mendes | - # |6 10 | - # --------------------------------------------------------------------------------------------------- - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Worksheet = $Excel | Add-WorkSheet -WorkSheetname Test - - # Row, Column - $Worksheet.Cells[1, 1].Value = 'Movie name' - $Worksheet.Cells[1, 3].Value = 'Rating' - $Worksheet.Cells[1, 7].Value = 'Director' - $Worksheet.Cells[2, 1].Value = 'The Bodyguard' - $Worksheet.Cells[2, 3].Value = '9' - $Worksheet.Cells[2, 5].Value = 'Thriller' - $Worksheet.Cells[2, 7].Value = 'Mick Jackson' - $Worksheet.Cells[3, 1].Value = 'The Matrix' - $Worksheet.Cells[3, 2].Value = '1999' - $Worksheet.Cells[3, 3].Value = '8' - $Worksheet.Cells[3, 7].Value = 'Wachowski' - $Worksheet.Cells[5, 1].Value = 'Skyfall' - $Worksheet.Cells[5, 2].Value = '2012' - $Worksheet.Cells[5, 3].Value = '9' - $Worksheet.Cells[5, 5].Value = 'Thriller' - $Worksheet.Cells[5, 7].Value = 'Sam Mendes' - $Worksheet.Cells[6, 3].Value = '10' - - $Excel.Save() - $Excel.Dispose() - #endregion - - it 'Default' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'Movie name' = 'The Bodyguard' - 'Rating' = '9' - 'Director' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'Movie name' = 'The Matrix' - 'Rating' = '8' - 'Director' = 'Wachowski' - } - [PSCustomObject]@{ - 'Movie name' = $null - 'Rating' = $null - 'Director' = $null - } - [PSCustomObject]@{ - 'Movie name' = 'Skyfall' - 'Rating' = '9' - 'Director' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'Movie name' = $null - 'Rating' = '10' - 'Director' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'The Bodyguard' = 'The Matrix' - '9' = '8' - 'Thriller' = $null - 'Mick Jackson' = 'Wachowski' - } - [PSCustomObject]@{ - 'The Bodyguard' = $null - '9' = $null - 'Thriller' = $null - 'Mick Jackson' = $null - } - [PSCustomObject]@{ - 'The Bodyguard' = 'Skyfall' - '9' = '9' - 'Thriller' = 'Thriller' - 'Mick Jackson' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'The Bodyguard' = $null - '9' = '10' - 'Thriller' = $null - 'Mick Jackson' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'Movie name' = 'The Bodyguard' - 'Rating' = '9' - 'Director' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'Movie name' = 'The Matrix' - 'Rating' = '8' - 'Director' = 'Wachowski' - } - [PSCustomObject]@{ - 'Movie name' = 'Skyfall' - 'Rating' = '9' - 'Director' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'Movie name' = $null - 'Rating' = '10' - 'Director' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'Default, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'The Bodyguard' = 'The Matrix' - '9' = '8' - 'Thriller' = $null - 'Mick Jackson' = 'Wachowski' - } - [PSCustomObject]@{ - 'The Bodyguard' = 'Skyfall' - '9' = '9' - 'Thriller' = 'Thriller' - 'Mick Jackson' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'The Bodyguard' = $null - '9' = '10' - 'Thriller' = $null - 'Mick Jackson' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = $null - 'Rating' = 'Rating' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = $null - 'Rating' = 'Rating' - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = $null - 'Genre' = $null - 'Country' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = $null - 'Country' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = $null - 'Rating' = 'Rating' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'Movie name' - 'Year' = $null - 'Rating' = 'Rating' - 'Genre' = $null - 'Country' = 'Director' - } - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - 'Country' = 'Wachowski' - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'HeaderName, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - - $ExpectedResult = @( - [PSCustomObject]@{ - 'MovieName' = 'The Bodyguard' - 'Year' = $null - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'MovieName' = 'The Matrix' - 'Year' = '1999' - 'Rating' = '8' - 'Genre' = $null - 'Country' = 'Wachowski' - } - [PSCustomObject]@{ - 'MovieName' = 'Skyfall' - 'Year' = '2012' - 'Rating' = '9' - 'Genre' = 'Thriller' - 'Country' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'MovieName' = $null - 'Year' = $null - 'Rating' = '10' - 'Genre' = $null - 'Country' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -HeaderName MovieName, Year, Rating, Genre, Country -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'Movie name' - 'P2' = $null - 'P3' = 'Rating' - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = 'Director' - } - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = $null - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - 'P6' = $null - 'P7' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = 'Wachowski' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = $null - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = $null - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - 'P6' = $null - 'P7' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = '10' - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = $null - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - 'P6' = $null - 'P7' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = 'Wachowski' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = $null - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = $null - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = $null - 'P5' = 'Thriller' - 'P6' = $null - 'P7' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = '10' - 'P4' = $null - 'P5' = $null - 'P6' = $null - 'P7' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader and DataOnly' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'Movie name' - 'P2' = $null - 'P3' = 'Rating' - 'P4' = $null - 'P5' = 'Director' - } - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = $null - 'P3' = '9' - 'P4' = 'Thriller' - 'P5' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = $null - 'P5' = 'Wachowski' - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = 'Thriller' - 'P5' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = '10' - 'P4' = $null - 'P5' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'NoHeader, DataOnly and StartRow' { - $ExpectedResult = @( - [PSCustomObject]@{ - 'P1' = 'The Bodyguard' - 'P2' = $null - 'P3' = '9' - 'P4' = 'Thriller' - 'P5' = 'Mick Jackson' - } - [PSCustomObject]@{ - 'P1' = 'The Matrix' - 'P2' = '1999' - 'P3' = '8' - 'P4' = $null - 'P5' = 'Wachowski' - } - [PSCustomObject]@{ - 'P1' = 'Skyfall' - 'P2' = '2012' - 'P3' = '9' - 'P4' = 'Thriller' - 'P5' = 'Sam Mendes' - } - [PSCustomObject]@{ - 'P1' = $null - 'P2' = $null - 'P3' = '10' - 'P4' = $null - 'P5' = $null - } - ) - - $Result = Import-Excel -Path $Path -WorksheetName Test -NoHeader -DataOnly -StartRow 2 - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - } - } -} -#> -Context 'special cases' { - in $TestDrive { - #<# - Describe 'duplicate column headers' { - it 'worksheet' { - #region Create test file - - # ---------------------------------------------- - # | A B C | - # |1 First Name first name Address | - # |2 Chuck Norris California | - # |3 Jean-Claude Vandamme Brussels | - # ---------------------------------------------- - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Worksheet = $Excel | Add-WorkSheet -WorkSheetname Test - - # Row, Column - $Worksheet.Cells[1, 1].Value = 'First Name' - $Worksheet.Cells[1, 2].Value = 'first name' - $Worksheet.Cells[1, 3].Value = 'Address' - $Worksheet.Cells[2, 1].Value = 'Chuck' - $Worksheet.Cells[2, 2].Value = 'Norris' - $Worksheet.Cells[2, 3].Value = 'California' - $Worksheet.Cells[3, 1].Value = 'Jean-Claude' - $Worksheet.Cells[3, 2].Value = 'Vandamme' - $Worksheet.Cells[3, 3].Value = 'Brussels' - - $Excel.Save() - $Excel.Dispose() - #endregion - - {Import-Excel -Path $Path -WorksheetName Test} | Should Throw 'Duplicate column headers found' - - #region Create test file - Remove-Item .\* -Force - - # ---------------------------------------------- - # | A B C | - # |1 | - # |2 Fruit Fruit Color | - # |3 Kiwi Green | - # ---------------------------------------------- - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - $Worksheet = $Excel | Add-WorkSheet -WorkSheetname Test - - # Row, Column - $Worksheet.Cells[2, 1].Value = 'Fruit' - $Worksheet.Cells[2, 2].Value = 'Fruit' - $Worksheet.Cells[2, 3].Value = 'Color' - $Worksheet.Cells[3, 1].Value = 'Kiwi' - $Worksheet.Cells[3, 3].Value = 'Green' - - $Excel.Save() - $Excel.Dispose() - #endregion - - {Import-Excel -Path $Path -WorksheetName Test -StartRow 2} | Should Throw 'Duplicate column headers found' - } - it 'HeaderName parameter' { - {Import-Excel -Path $Path -WorksheetName Test -HeaderName Apples, Apples, Kiwi} | Should Throw 'Duplicate column headers found' - } - } - #> - Describe 'open password protected files' { - $Password = 'P@ssw0rd' - - #region Create password protected file - - # ---------------- - # | A | - # |1 Type | - # |2 Sensitive | - # ---------------- - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - $Excel = New-Object OfficeOpenXml.ExcelPackage $Path - - # Row, Column - $Worksheet = $Excel | Add-WorkSheet -WorkSheetname Test - $Worksheet.Cells[1, 1].Value = 'Type' - $Worksheet.Cells[2, 1].Value = 'Sensitive' - - $Excel.Save($Password) - $Excel.Dispose() - #endregion - - it 'password correct' { - $Result = Import-Excel -Path $Path -WorksheetName Test -Password $Password - - $ExpectedResult = [PSCustomObject]@{ - Type = 'Sensitive' - } - Assert-Equivalent -Actual $Result -Expected $ExpectedResult - } - it 'password wrong' { - {Import-Excel -Path $Path -WorksheetName Test -Password WrongPassword} | Should Throw 'Password' - } - } - } -} - -Context 'General Tests' { - in $TestDrive { - Describe 'Get Help' { - it 'New-Plot' { - #Get-Help : Unable to find type [PSPlot]. - {Help New-Plot} | Should -Not -Throw - } - } - } -} \ No newline at end of file diff --git a/ImportExcel.psd1 b/ImportExcel.psd1 index 169f557f..b9a6148c 100644 --- a/ImportExcel.psd1 +++ b/ImportExcel.psd1 @@ -1,120 +1,218 @@ @{ + # Assemblies that must be loaded prior to importing this module + RequiredAssemblies = @('.\EPPlus.dll') -# Script module or binary module file associated with this manifest. -RootModule = 'ImportExcel.psm1' + # Script module or binary module file associated with this manifest. + RootModule = 'ImportExcel.psm1' -# Version number of this module. -ModuleVersion = '4.0.14' + # Version number of this module. + ModuleVersion = '7.8.10' -# ID used to uniquely identify this module -GUID = '60dd4136-feff-401a-ba27-a84458c57ede' + # ID used to uniquely identify this module + GUID = '60dd4136-feff-401a-ba27-a84458c57ede' -# Author of this module -Author = 'Douglas Finke' + # Author of this module + Author = 'Douglas Finke' -# Company or vendor of this module -CompanyName = 'Doug Finke' + # Company or vendor of this module + CompanyName = 'Doug Finke' -# Copyright statement for this module -Copyright = 'c 2015 All rights reserved.' + # Copyright statement for this module + Copyright = 'c 2020 All rights reserved.' -# Description of the functionality provided by this module - Description = @' + # Description of the functionality provided by this module + Description = @' PowerShell module to import/export Excel spreadsheets, without Excel. Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq '@ -# Minimum version of the Windows PowerShell engine required by this module -# PowerShellVersion = '' -# Name of the Windows PowerShell host required by this module -# PowerShellHostName = '' -# Minimum version of the Windows PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module -# DotNetFrameworkVersion = '' - -# Minimum version of the common language runtime (CLR) required by this module -# CLRVersion = '' - -# Processor architecture (None, X86, Amd64) required by this module -# ProcessorArchitecture = '' - -# Modules that must be imported into the global environment prior to importing this module -# RequiredModules = @() - -# Assemblies that must be loaded prior to importing this module -# RequiredAssemblies = @() - -# Script files (.ps1) that are run in the caller's environment prior to importing this module. -# ScriptsToProcess = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() + # Functions to export from this module + FunctionsToExport = @( + 'Add-ConditionalFormatting', + 'Add-ExcelChart', + 'Add-ExcelDataValidationRule', + 'Add-ExcelName', + 'Add-ExcelTable', + 'Add-PivotTable', + 'Add-Worksheet', + 'BarChart', + 'Close-ExcelPackage', + 'ColumnChart', + 'Compare-Worksheet', + 'Convert-ExcelRangeToImage', + 'ConvertFrom-ExcelData', + 'ConvertFrom-ExcelSheet', + 'ConvertFrom-ExcelToSQLInsert', + 'ConvertTo-ExcelXlsx', + 'Copy-ExcelWorksheet', + 'DoChart', + 'Enable-ExcelAutoFilter', + 'Enable-ExcelAutofit', + 'Expand-NumberFormat', + 'Export-Excel', + 'Export-ExcelSheet', + 'Get-ExcelColumnName', + 'Get-ExcelFileSchema', + 'Get-ExcelFileSummary', + 'Get-ExcelSheetDimensionAddress', + 'Get-ExcelSheetInfo', + 'Get-ExcelWorkbookInfo', + 'Get-HtmlTable', + 'Get-Range', + 'Get-XYRange', + 'Import-Excel', + 'Import-Html', + 'Import-UPS', + 'Import-USPS', + 'Invoke-AllTests', + 'Invoke-ExcelQuery', + 'Invoke-Sum', + 'Join-Worksheet', + 'LineChart', + 'Merge-MultipleSheets', + 'Merge-Worksheet', + 'New-ConditionalFormattingIconSet', + 'New-ConditionalText', + 'New-ExcelChartDefinition', + 'New-ExcelStyle', + 'New-PivotTableDefinition', + 'New-Plot', + 'New-PSItem', + 'Open-ExcelPackage', + 'PieChart', + 'Pivot', + 'Read-Clipboard', + 'Read-OleDbData', + 'ReadClipboardImpl', + 'Remove-Worksheet', + 'Select-Worksheet', + 'Send-SQLDataToExcel', + 'Set-CellComment', + 'Set-CellStyle', + 'Set-ExcelColumn', + 'Set-ExcelRange', + 'Set-ExcelRow', + 'Set-WorksheetProtection', + 'Test-Boolean', + 'Test-Date', + 'Test-Integer', + 'Test-Number', + 'Test-String', + 'Update-FirstObjectProperties' + ) + + # Aliases to export from this module + AliasesToExport = @( + 'Convert-XlRangeToImage', + 'Export-ExcelSheet', + 'New-ExcelChart', + 'Set-Column', + 'Set-Format', + 'Set-Row', + 'Use-ExcelData' + ) + + # Cmdlets to export from this module + CmdletsToExport = @() + + FileList = @( + '.\EPPlus.dll', + '.\Export-charts.ps1', + '.\GetExcelTable.ps1', + '.\ImportExcel.psd1', + '.\ImportExcel.psm1', + '.\LICENSE.txt', + '.\Plot.ps1', + '.\Private', + '.\Public', + '.\en\ImportExcel-help.xml', + '.\en\Strings.psd1', + '.\Charting\Charting.ps1', + '.\InferData\InferData.ps1', + '.\Pivot\Pivot.ps1', + '.\Examples', + '.\Testimonials' + ) + + # Private data to pass to the module specified in RootModule/ModuleToProcess + PrivateData = @{ + # PSData is module packaging and gallery metadata embedded in PrivateData + # It's for rebuilding PowerShellGet (and PoshCode) NuGet-style packages + # We had to do this because it's the only place we're allowed to extend the manifest + # https://connect.microsoft.com/PowerShell/feedback/details/421837 + PSData = @{ + # The primary categorization of this module (from the TechNet Gallery tech tree). + Category = "Scripting Excel" + + # Keyword tags to help users find this module via navigations and search. + Tags = @("Excel", "EPPlus", "Export", "Import") + + # The web address of an icon which can be used in galleries to represent this module + #IconUri = + + # The web address of this module's project or support homepage. + ProjectUri = "https://github.com/dfinke/ImportExcel" + + # The web address of this module's license. Points to a page that's embeddable and linkable. + LicenseUri = "https://github.com/dfinke/ImportExcel/blob/master/LICENSE.txt" + + # Release notes for this particular version of the module + #ReleaseNotes = $True + + # If true, the LicenseUrl points to an end-user license (not just a source license) which requires the user agreement before use. + # RequireLicenseAcceptance = "" + + # Indicates this is a pre-release/testing version of the module. + IsPrerelease = 'False' + } + } -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() + # Minimum version of the Windows PowerShell engine required by this module + # PowerShellVersion = '' -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -# NestedModules = @() + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' -# Functions to export from this module -FunctionsToExport = '*' + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' -# Cmdlets to export from this module -CmdletsToExport = '*' + # Minimum version of Microsoft .NET Framework required by this module + # DotNetFrameworkVersion = '' -# Variables to export from this module -VariablesToExport = '*' + # Minimum version of the common language runtime (CLR) required by this module + # CLRVersion = '' -# Aliases to export from this module -AliasesToExport = '*' + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' -# List of all modules packaged with this module -# ModuleList = @() + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() -# List of all files packaged with this module -# FileList = @() + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() -# Private data to pass to the module specified in RootModule/ModuleToProcess -PrivateData = @{ - # PSData is module packaging and gallery metadata embedded in PrivateData - # It's for rebuilding PowerShellGet (and PoshCode) NuGet-style packages - # We had to do this because it's the only place we're allowed to extend the manifest - # https://connect.microsoft.com/PowerShell/feedback/details/421837 - PSData = @{ - # The primary categorization of this module (from the TechNet Gallery tech tree). - Category = "Scripting Excel" + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() - # Keyword tags to help users find this module via navigations and search. - Tags = @("Excel","EPPlus","Export","Import") + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() - # The web address of an icon which can be used in galleries to represent this module - #IconUri = "http://pesterbdd.com/images/Pester.png" + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() - # The web address of this module's project or support homepage. - ProjectUri = "https://github.com/dfinke/ImportExcel" + # List of all modules packaged with this module + # ModuleList = @() - # The web address of this module's license. Points to a page that's embeddable and linkable. - LicenseUri = "https://github.com/dfinke/ImportExcel/blob/master/LICENSE.txt" + # List of all files packaged with this module + # Variables to export from this module + #VariablesToExport = '*' - # Release notes for this particular version of the module - #ReleaseNotes = $True + # HelpInfo URI of this module + # HelpInfoURI = '' - # If true, the LicenseUrl points to an end-user license (not just a source license) which requires the user agreement before use. - # RequireLicenseAcceptance = "" + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' - # Indicates this is a pre-release/testing version of the module. - IsPrerelease = 'False' - } } - -# HelpInfo URI of this module -# HelpInfoURI = '' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} \ No newline at end of file diff --git a/ImportExcel.psm1 b/ImportExcel.psm1 index 8b2b3554..8ea51803 100644 --- a/ImportExcel.psm1 +++ b/ImportExcel.psm1 @@ -1,549 +1,60 @@ -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\New-ConditionalFormattingIconSet.ps1 -. $PSScriptRoot\New-ConditionalText.ps1 -. $PSScriptRoot\New-ExcelChart.ps1 -. $PSScriptRoot\New-PSItem.ps1 -. $PSScriptRoot\Open-ExcelPackage.ps1 -. $PSScriptRoot\Pivot.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 - +#region import everything we need +$culture = $host.CurrentCulture.Name -replace '-\w*$', '' +Import-LocalizedData -UICulture $culture -BindingVariable Strings -FileName Strings -ErrorAction Ignore +if (-not $Strings) { + Import-LocalizedData -UICulture "en" -BindingVariable Strings -FileName Strings -ErrorAction Ignore +} +try { [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") } +catch { Write-Warning -Message $Strings.SystemDrawingAvailable } -New-Alias -Name Use-ExcelData -Value "ConvertFrom-ExcelData" -Force +foreach ($directory in @('Private', 'Public', 'Charting', 'InferData', 'Pivot')) { + Get-ChildItem -Path "$PSScriptRoot\$directory\*.ps1" | ForEach-Object { . $_.FullName } +} if ($PSVersionTable.PSVersion.Major -ge 5) { . $PSScriptRoot\Plot.ps1 - Function New-Plot { - Param() + function New-Plot { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingfunctions', '', Justification = 'New-Plot does not change system state')] + param() [PSPlot]::new() } } else { - Write-Warning 'PowerShell 5 is required for plot.ps1' - Write-Warning 'PowerShell Excel is ready, except for that functionality' + Write-Warning $Strings.PS5NeededForPlot + Write-Warning $Strings.ModuleReadyExceptPlot } -Function Import-Excel { - <# - .SYNOPSIS - Create custom objects from the rows in an Excel worksheet. - - .DESCRIPTION - The Import-Excel cmdlet creates custom objects from the rows in an Excel worksheet. Each row represents one object. All of this is possible without installing Microsoft Excel and by using the .NET library ‘EPPLus.dll’. - - By default, the property names of the objects are retrieved from the column headers. Because an object cannot have a blanc property name, only columns with column headers will be imported. - - If the default behavior is not desired and you want to import the complete worksheet ‘as is’, the parameter ‘-NoHeader’ can be used. In case you want to provide your own property names, you can use the parameter ‘-HeaderName’. - - .PARAMETER Path - Specifies the path to the Excel file. - - .PARAMETER WorksheetName - Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. - - .PARAMETER DataOnly - Import only rows and columns that contain data, empty rows and empty columns are not imported. - - .PARAMETER HeaderName - Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. - - In case you provide less header names than there is data in the worksheet, then only the data with a corresponding header name will be imported and the data without header name will be disregarded. - - In case you provide more header names than there is data in the worksheet, then all data will be imported and all objects will have all the property names you defined in the header names. As such, the last properties will be blanc as there is no data for them. - - .PARAMETER NoHeader - Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. - - This switch is best used when you want to import the complete worksheet ‘as is’ and are not concerned with the property names. - - .PARAMETER StartRow - The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. - - When the parameters ‘-NoHeader’ and ‘-HeaderName’ are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data. - - .PARAMETER Password - Accepts a string that will be used to open a password protected Excel file. - - .EXAMPLE - Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the column names defined in the first row. In case a column doesn’t have a column header (usually in row 1 when ‘-StartRow’ is not used), then the unnamed columns will be skipped and the data in those columns will not be imported. - - ---------------------------------------------- - | File: Movies.xlsx - Sheet: Actors | - ---------------------------------------------- - | A B C | - |1 First Name Address | - |2 Chuck Norris California | - |3 Jean-Claude Vandamme Brussels | - ---------------------------------------------- - - PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors - - First Name: Chuck - Address : California - - First Name: Jean-Claude - Address : Brussels - - Notice that column 'B' is not imported because there's no value in cell 'B1' that can be used as property name for the objects. - - .EXAMPLE - Import the complete Excel worksheet ‘as is’ by using the ‘-NoHeader’ switch. One object is created for each row. The property names of the objects will be automatically generated (P1, P2, P3, ..). - - ---------------------------------------------- - | File: Movies.xlsx - Sheet: Actors | - ---------------------------------------------- - | A B C | - |1 First Name Address | - |2 Chuck Norris California | - |3 Jean-Claude Vandamme Brussels | - ---------------------------------------------- - - PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors -NoHeader - - P1: First Name - P2: - P3: Address - - P1: Chuck - P2: Norris - P3: California - - P1: Jean-Claude - P2: Vandamme - P3: Brussels - - Notice that the column header (row 1) is imported as an object too. - - .EXAMPLE - Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the names defined in the parameter ‘-HeaderName’. The properties are named starting from the most left column (A) to the right. In case no value is present in one of the columns, that property will have an empty value. - - ---------------------------------------------------------- - | File: Movies.xlsx - Sheet: Movies | - ---------------------------------------------------------- - | A B C D | - |1 The Bodyguard 1992 9 | - |2 The Matrix 1999 8 | - |3 | - |4 Skyfall 2012 9 | - ---------------------------------------------------------- - - PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Movies -HeaderName 'Movie name', 'Year', 'Rating', 'Genre' - - Movie name: The Bodyguard - Year : 1992 - Rating : 9 - Genre : - - Movie name: The Matrix - Year : 1999 - Rating : 8 - Genre : - - Movie name: - Year : - Rating : - Genre : - - Movie name: Skyfall - Year : 2012 - Rating : 9 - Genre : - - Notice that empty rows are imported and that data for the property 'Genre' is not present in the worksheet. As such, the 'Genre' property will be blanc for all objects. - - .EXAMPLE - Import data from an Excel worksheet. One object is created for each row. The property names of the objects are automatically generated by using the switch ‘-NoHeader’ (P1, P@, P#, ..). The switch ‘-DataOnly’ will speed up the import because empty rows and empty columns are not imported. - - ---------------------------------------------------------- - | File: Movies.xlsx - Sheet: Movies | - ---------------------------------------------------------- - | A B C D | - |1 The Bodyguard 1992 9 | - |2 The Matrix 1999 8 | - |3 | - |4 Skyfall 2012 9 | - ---------------------------------------------------------- - - PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Movies –NoHeader -DataOnly - - P1: The Bodyguard - P2: 1992 - P3: 9 - - P1: The Matrix - P2: 1999 - P3: 8 - - P1: Skyfall - P2: 2012 - P3: 9 - - Notice that empty rows and empty columns are not imported. - - .EXAMPLE - Import data from an Excel worksheet. One object is created for each row. The property names are provided with the ‘-HeaderName’ parameter. The import will start from row 2 and empty columns and rows are not imported. - - ---------------------------------------------------------- - | File: Movies.xlsx - Sheet: Actors | - ---------------------------------------------------------- - | A B C D | - |1 Chuck Norris California | - |2 | - |3 Jean-Claude Vandamme Brussels | - ---------------------------------------------------------- - - PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors -DataOnly -HeaderName 'FirstName', 'SecondName', 'City' –StartRow 2 - - FirstName : Jean-Claude - SecondName: Vandamme - City : Brussels - - Notice that only 1 object is imported with only 3 properties. Column B and row 2 are empty and have been disregarded by using the switch '-DataOnly'. The property names have been named with the values provided with the parameter '-HeaderName'. Row number 1 with ‘Chuck Norris’ has not been imported, because we started the import from row 2 with the parameter ‘-StartRow 2’. - - .LINK - https://github.com/dfinke/ImportExcel +#endregion - .NOTES - #> - - [CmdLetBinding(DefaultParameterSetName)] - Param ( - [Alias('FullName')] - [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline, Position=0, Mandatory)] - [ValidateScript( {(Test-Path -Path $_ -PathType Leaf) -and ($_ -match '.xls$|.xlsx$|.xlsm$')})] - [String]$Path, - [Alias('Sheet')] - [Parameter(Position=1)] - [ValidateNotNullOrEmpty()] - [String]$WorksheetName, - [Parameter(ParameterSetName='B', Mandatory)] - [String[]]$HeaderName, - [Parameter(ParameterSetName='C', Mandatory)] - [Switch]$NoHeader, - [Alias('HeaderRow','TopRow')] - [ValidateRange(1, 9999)] - [Int]$StartRow, - [Switch]$DataOnly, - [ValidateNotNullOrEmpty()] - [String]$Password - ) - - Begin { - Function Add-Property { - <# - .SYNOPSIS - Add the property name and value to the hashtable that will create a new object for each row. - #> - - Param ( - [Parameter(Mandatory)] - [String]$Name, - $Value - ) - - Try { - $NewRow.$Name = $Value - Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$Name' and value '$Value'" - } - Catch { - throw "Failed adding the property name '$Name' with value '$Value': $_" - } - } - - Function Get-PropertyNames { - <# - .SYNOPSIS - Create objects containing the column number and the column name for each of the different header types. - #> - - Param ( - [Parameter(Mandatory)] - [Int[]]$Columns, - [Parameter(Mandatory)] - [Int]$StartRow - ) - - Try { - if ($NoHeader) { - $i = 0 - foreach ($C in $Columns) { - $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}} - $i++ - } - } - else { - if ($StartRow -eq 0) { - throw 'The top row can never be equal to 0 when we need to retrieve headers from the worksheet.' - } - - foreach ($C in $Columns) { - $Worksheet.Cells[$StartRow,$C] | where {$_.Value} | Select-Object @{N='Column'; E={$C}}, Value - } - } - } - Catch { - throw "Failed creating property names: $_" - } - } +if (($IsLinux -or $IsMacOS) -or $env:NoAutoSize) { + $ExcelPackage = [OfficeOpenXml.ExcelPackage]::new() + $Cells = ($ExcelPackage | Add-Worksheet).Cells['A1'] + $Cells.Value = 'Test' + try { + $Cells.AutoFitColumns() + if ($env:NoAutoSize) { Remove-Item Env:\NoAutoSize } } - - Process { - Try { - #region Open file - $Path = (Resolve-Path $Path).ProviderPath - Write-Verbose "Import Excel workbook '$Path' with worksheet '$Worksheetname'" - - $Stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, 'Open', 'Read', 'ReadWrite' - - if ($Password) { - $Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage - - Try { - $Excel.Load($Stream,$Password) - } - Catch { - throw "Password '$Password' is not correct." - } - } - else { - $Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream - } - #endregion - - #region Select worksheet - if ($WorksheetName) { - if (-not ($Worksheet = $Excel.Workbook.Worksheets[$WorkSheetName])) { - throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($Excel.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." - } - } - else { - $Worksheet = $Excel.Workbook.Worksheets | Select-Object -First 1 - } - #endregion - - #region Set the top row - if (((-not ($NoHeader -or $HeaderName)) -and ($StartRow -eq 0))) { - $StartRow = 1 - } - #endregion - - if (-not ($AllCells = $Worksheet.Cells | where {($_.Start.Row -ge $StartRow)})) { - Write-Warning "Worksheet '$WorksheetName' in workbook '$Path' is empty after StartRow '$StartRow'" - } - else { - #region Get rows and columns - if ($DataOnly) { - $CellsWithValues = $AllCells | where {$_.Value} - - $Columns = $CellsWithValues.Start.Column | Sort-Object -Unique - $Rows = $CellsWithValues.Start.Row | Sort-Object -Unique - } - else { - $LastColumn = $AllCells.Start.Column | Sort-Object -Unique | Select-Object -Last 1 - $Columns = 1..$LastColumn - - $LastRow = $AllCells.Start.Row | Sort-Object -Unique | Select-Object -Last 1 - $Rows = $StartRow..$LastRow | where {($_ -ge $StartRow) -and ($_ -gt 0)} - } - #endregion - - #region Create property names - if ((-not $Columns) -or (-not ($PropertyNames = Get-PropertyNames -Columns $Columns -StartRow $StartRow))) { - throw "No column headers found on top row '$StartRow'. If column headers in the worksheet are not a requirement then please use the '-NoHeader' or '-HeaderName' parameter." - } - - if ($Duplicates = $PropertyNames | Group-Object Value | where Count -GE 2) { - throw "Duplicate column headers found on row '$StartRow' in columns '$($Duplicates.Group.Column)'. Column headers must be unique, if this is not a requirement please use the '-NoHeader' or '-HeaderName' parameter." - } - #endregion - - #region Filter out rows with data in columns that don't have a column header - if ($DataOnly -and (-not $NoHeader)) { - $Rows = $CellsWithValues.Start | where {$PropertyNames.Column -contains $_.Column} | - Sort-Object Row -Unique | Select-Object -ExpandProperty Row - } - #endregion - - #region Filter out the top row when it contains column headers - if (-not ($NoHeader -or $HeaderName)) { - $Rows = $Rows | where {$_ -gt $StartRow} - } - #endregion - - if (-not $Rows) { - Write-Warning "Worksheet '$WorksheetName' in workbook '$Path' contains no data in the rows after top row '$StartRow'" - } - else { - #region Create one object per row - foreach ($R in $Rows) { - Write-Verbose "Import row '$R'" - $NewRow = [Ordered]@{} - - foreach ($P in $PropertyNames) { - Add-Property -Name $P.Value -Value $Worksheet.Cells[$R, $P.Column].Value - } - - [PSCustomObject]$NewRow - } - #endregion - } - } + catch { + $env:NoAutoSize = $true + if ($IsLinux) { + $msg = @" +ImportExcel Module Cannot Autosize. Please run the following command to install dependencies: +apt-get -y update && apt-get install -y --no-install-recommends libgdiplus libc6-dev +"@ + Write-Warning -Message $msg } - Catch { - throw "Failed importing the Excel workbook '$Path' with worksheet '$Worksheetname': $_" + if ($IsMacOS) { + $msg = @" +ImportExcel Module Cannot Autosize. Please run the following command to install dependencies: +brew install mono-libgdiplus +"@ + Write-Warning -Message $msg } - Finally { - $Stream.Close() - $Stream.Dispose() - $Excel.Dispose() - $Excel = $null - } - } -} - -function Add-WorkSheet { - param( - #TODO Use parametersets to allow a workbook to be passed instead of a package - [Parameter(Mandatory=$true, ValueFromPipeline=$true)] - [OfficeOpenXml.ExcelPackage] $ExcelPackage, - [Parameter(Mandatory=$true)] - [string] $WorkSheetname, - [switch] $ClearSheet, - [Switch] $NoClobber - ) - - $ws = $ExcelPackage.Workbook.Worksheets[$WorkSheetname] - if($ClearSheet -and $ws) {$ExcelPackage.Workbook.Worksheets.Delete($WorkSheetname) ; $ws = $null } - if(!$ws) { - Write-Verbose "Add worksheet '$WorkSheetname'" - $ws=$ExcelPackage.Workbook.Worksheets.Add($WorkSheetname) - } - - return $ws -} - -function ConvertFrom-ExcelSheet { - <# - .Synopsis - Reads an Excel file an converts the data to a delimited text file - - .Example - ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data - Reads each sheet in TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt - - .Example - ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data sheet?0 - Reads and outputs sheets like Sheet10 and Sheet20 form TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt - #> - - [CmdletBinding()] - param - ( - [Alias("FullName")] - [Parameter(Mandatory = $true)] - [String] - $Path, - [String] - $OutputPath = '.\', - [String] - $SheetName="*", - [ValidateSet('ASCII', 'BigEndianUniCode','Default','OEM','UniCode','UTF32','UTF7','UTF8')] - [string] - $Encoding = 'UTF8', - [ValidateSet('.txt', '.log','.csv')] - [string] - $Extension = '.csv', - [ValidateSet(';', ',')] - [string] - $Delimiter = ';' - ) - - $Path = (Resolve-Path $Path).Path - $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path,"Open","Read","ReadWrite" - $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream - $workbook = $xl.Workbook - - $targetSheets = $workbook.Worksheets | Where {$_.Name -like $SheetName} - - $params = @{} + $PSBoundParameters - $params.Remove("OutputPath") - $params.Remove("SheetName") - $params.Remove('Extension') - $params.NoTypeInformation = $true - - Foreach ($sheet in $targetSheets) - { - Write-Verbose "Exporting sheet: $($sheet.Name)" - - $params.Path = "$OutputPath\$($Sheet.Name)$Extension" - - Import-Excel $Path -Sheet $($sheet.Name) | Export-Csv @params } - - $stream.Close() - $stream.Dispose() - $xl.Dispose() -} - -function Export-MultipleExcelSheets { - param( - [Parameter(Mandatory=$true)] - $Path, - [Parameter(Mandatory=$true)] - [hashtable]$InfoMap, - [string]$Password, - [Switch]$Show, - [Switch]$AutoSize - ) - - $parameters = @{}+$PSBoundParameters - $parameters.Remove("InfoMap") - $parameters.Remove("Show") - - $parameters.Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - - foreach ($entry in $InfoMap.GetEnumerator()) { - Write-Progress -Activity "Exporting" -Status "$($entry.Key)" - $parameters.WorkSheetname=$entry.Key - - & $entry.Value | Export-Excel @parameters + finally { + $ExcelPackage | Close-ExcelPackage -NoSave } - - if($Show) {Invoke-Item $Path} } diff --git a/InferData.ps1 b/InferData/InferData.ps1 similarity index 94% rename from InferData.ps1 rename to InferData/InferData.ps1 index add8f040..06bf3df4 100644 --- a/InferData.ps1 +++ b/InferData/InferData.ps1 @@ -60,7 +60,8 @@ $tests = [ordered]@{ TestString = Get-Command Test-String } -function Invoke-AllTests { +function Invoke-TestSet { + [alias("Invoke-AllTests")] param( $target, [Switch]$OnlyPassing, @@ -68,7 +69,7 @@ function Invoke-AllTests { ) $resultCount=0 - $tests.GetEnumerator() | ForEach { + $tests.GetEnumerator() | ForEach-Object { $result=& $_.Value $target diff --git a/Install.ps1 b/Install.ps1 deleted file mode 100644 index 66f70898..00000000 --- a/Install.ps1 +++ /dev/null @@ -1,104 +0,0 @@ -<# - .SYNOPSIS - Download the module files from GitHub. - - .DESCRIPTION - Download the module files from GitHub to the local client in the module folder. -#> - -[CmdLetBinding()] -Param ( - [ValidateNotNullOrEmpty()] - [String]$ModuleName = 'ImportExcel', - [String]$InstallDirectory, - [ValidateNotNullOrEmpty()] - [String]$GitPath = 'https://raw.github.com/dfinke/ImportExcel/master' -) - -Begin { - Try { - Write-Verbose "$ModuleName module installation started" - - $Files = @( - 'AddConditionalFormatting.ps1', - 'Charting.ps1', - 'ColorCompletion.ps1', - 'ConvertFromExcelData.ps1', - 'ConvertFromExcelToSQLInsert.ps1', - 'ConvertExcelToImageFile.ps1', - 'ConvertToExcelXlsx.ps1', - 'Copy-ExcelWorkSheet.ps1', - 'EPPlus.dll', - 'Export-charts.ps1', - 'Export-Excel.ps1', - 'Export-ExcelSheet.ps1', - 'formatting.ps1', - 'Get-ExcelColumnName.ps1', - 'Get-ExcelSheetInfo.ps1', - 'Get-ExcelWorkbookInfo.ps1', - 'Get-HtmlTable.ps1', - 'Get-Range.ps1', - 'Get-XYRange.ps1', - 'Import-Html.ps1', - 'ImportExcel.psd1', - 'ImportExcel.psm1', - 'InferData.ps1', - 'Invoke-Sum.ps1', - 'New-ConditionalFormattingIconSet.ps1', - 'New-ConditionalText.ps1', - 'New-ExcelChart.ps1', - 'New-PSItem.ps1', - 'Open-ExcelPackage.ps1', - 'Pivot.ps1', - 'plot.ps1', - 'Send-SqlDataToExcel.ps1', - 'Set-CellStyle.ps1', - 'Set-Column.ps1', - 'Set-Row.ps1', - 'SetFormat.ps1', - 'TrackingUtils.ps1', - 'Update-FirstObjectProperties.ps1' - ) - } - Catch { - throw "Failed installing the module in the install directory '$InstallDirectory': $_" - } -} - -Process { - Try { - if (-not $InstallDirectory) { - Write-Verbose "$ModuleName no installation directory provided" - - $PersonalModules = Join-Path -Path ([Environment]::GetFolderPath('MyDocuments')) -ChildPath WindowsPowerShell\Modules - - if (($env:PSModulePath -split ';') -notcontains $PersonalModules) { - Write-Warning "$ModuleName personal module path '$PersonalModules' not found in '`$env:PSModulePath'" - } - - if (-not (Test-Path $PersonalModules)) { - Write-Error "$ModuleName path '$PersonalModules' does not exist" - } - - $InstallDirectory = Join-Path -Path $PersonalModules -ChildPath $ModuleName - Write-Verbose "$ModuleName default installation directory is '$InstallDirectory'" - } - - if (-not (Test-Path $InstallDirectory)) { - New-Item -Path $InstallDirectory -ItemType Directory -EA Stop | Out-Null - Write-Verbose "$ModuleName created module folder '$InstallDirectory'" - } - - $WebClient = New-Object System.Net.WebClient - - $Files | ForEach-Object { - $WebClient.DownloadFile("$GitPath/$_","$installDirectory\$_") - Write-Verbose "$ModuleName installed module file '$_'" - } - - Write-Verbose "$ModuleName module installation successful" - } - Catch { - throw "Failed installing the module in the install directory '$InstallDirectory': $_" - } -} \ No newline at end of file diff --git a/InstallModule.ps1 b/InstallModule.ps1 index 6dce7a91..0e006b17 100644 --- a/InstallModule.ps1 +++ b/InstallModule.ps1 @@ -1,87 +1,11 @@ -<# - .SYNOPSIS - Install the module in the PowerShell module folder. - - .DESCRIPTION - Install the module in the PowerShell module folder by copying all the files. -#> - -[CmdLetBinding()] -Param ( - [ValidateNotNullOrEmpty()] - [String]$ModuleName = 'ImportExcel', - [ValidateScript({Test-Path -Path $_ -Type Container})] - [String]$ModulePath = 'C:\Program Files\WindowsPowerShell\Modules' -) - -Begin { - Try { - Write-Verbose "$ModuleName module installation started" - - $Files = @( - '*.dll', - '*.psd1', - '*.psm1', - 'AddConditionalFormatting.ps1', - 'Charting.ps1', - 'ColorCompletion.ps1', - 'compare-Worksheet.ps1', - 'ConvertFromExcelData.ps1', - 'ConvertFromExcelToSQLInsert.ps1', - 'ConvertExcelToImageFile.ps1', - 'ConvertToExcelXlsx.ps1', - 'Copy-ExcelWorkSheet.ps1', - 'Export-Charts.ps1', - 'Export-Excel.ps1', - 'Export-ExcelSheet.ps1', - 'formatting.ps1', - 'Get-ExcelColumnName.ps1', - 'Get-ExcelSheetInfo.ps1', - 'Get-ExcelWorkbookInfo.ps1', - 'Get-HtmlTable.ps1', - 'Get-Range.ps1', - 'Get-XYRange.ps1', - 'Import-Html.ps1', - 'InferData.ps1', - 'Invoke-Sum.ps1', - 'New-ConditionalFormattingIconSet.ps1', - 'New-ConditionalText.ps1', - 'New-ExcelChart.ps1', - 'New-PSItem.ps1', - 'Open-ExcelPackage.ps1', - 'Pivot.ps1', - 'Plot.ps1', - 'Send-SQLDataToExcel.ps1', - 'Set-CellStyle.ps1', - 'Set-Column.ps1', - 'Set-Row.ps1', - 'SetFormat.ps1', - 'TrackingUtils.ps1', - 'Update-FirstObjectProperties.ps1' - ) - } - Catch { - throw "Failed installing the module '$ModuleName': $_" - } +param ($fullPath) +#$fullPath = 'C:\Program Files\WindowsPowerShell\Modules\ImportExcel' +if (-not $fullPath) { + $fullpath = $env:PSModulePath -split ":(?!\\)|;|," | + Where-Object {$_ -notlike ([System.Environment]::GetFolderPath("UserProfile")+"*") -and $_ -notlike "$pshome*"} | + Select-Object -First 1 + $fullPath = Join-Path $fullPath -ChildPath "ImportExcel" } - -Process { - Try { - $TargetPath = Join-Path -Path $ModulePath -ChildPath $ModuleName - - if (-not (Test-Path $TargetPath)) { - New-Item -Path $TargetPath -ItemType Directory -EA Stop | Out-Null - Write-Verbose "$ModuleName created module folder '$TargetPath'" - } - - Get-ChildItem $Files | ForEach-Object { - Copy-Item -Path $_.FullName -Destination "$($TargetPath)\$($_.Name)" - Write-Verbose "$ModuleName installed module file '$($_.Name)'" - } - - Write-Verbose "$ModuleName module installation successful" - } - Catch { - throw "Failed installing the module '$ModuleName': $_" - } -} \ No newline at end of file +Push-location $PSScriptRoot +Robocopy . $fullPath /mir /XD .vscode images .git .github CI __tests__ data mdHelp spikes /XF README.md README.original.md appveyor.yml azure-pipelines.yml .gitattributes .gitignore filelist.txt install.ps1 InstallModule.ps1 PublishToGallery.ps1 +Pop-Location \ No newline at end of file diff --git a/New-ConditionalText.ps1 b/New-ConditionalText.ps1 deleted file mode 100644 index a842245e..00000000 --- a/New-ConditionalText.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -function New-ConditionalText { - param( - #[Parameter(Mandatory=$true)] - $Text, - [System.Drawing.Color]$ConditionalTextColor="DarkRed", - [System.Drawing.Color]$BackgroundColor="LightPink", - [String]$Range, - [OfficeOpenXml.Style.ExcelFillStyle]$PatternType=[OfficeOpenXml.Style.ExcelFillStyle]::Solid, - [ValidateSet( - "LessThan","LessThanOrEqual","GreaterThan","GreaterThanOrEqual", - "NotEqual","Equal","ContainsText","NotContainsText","BeginsWith","EndsWith", - "Last7Days","LastMonth","LastWeek", - "NextMonth","NextWeek", - "ThisMonth","ThisWeek", - "Today","Tomorrow","Yesterday", - "DuplicateValues", - "AboveOrEqualAverage","BelowAverage","AboveAverage", - "Top", "TopPercent", "ContainsBlanks" - )] - $ConditionalType="ContainsText" - ) - - $obj = [PSCustomObject]@{ - Text = $Text - ConditionalTextColor = $ConditionalTextColor - ConditionalType = $ConditionalType - PatternType = $PatternType - Range = $Range - BackgroundColor = $BackgroundColor - } - - $obj.pstypenames.Clear() - $obj.pstypenames.Add("ConditionalText") - $obj -} \ No newline at end of file diff --git a/New-ExcelChart.ps1 b/New-ExcelChart.ps1 deleted file mode 100644 index 2d950557..00000000 --- a/New-ExcelChart.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -function New-ExcelChart { - param( - $Title="Chart Title", - $Header, - [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType="ColumnStacked", - $XRange, - $YRange, - $Width=500, - $Height=350, - $Row=0, - $RowOffSetPixels=10, - $Column=6, - $ColumnOffSetPixels=5, - [Switch]$NoLegend, - [Switch]$ShowCategory, - [Switch]$ShowPercent, - $SeriesHeader - ) - - [PSCustomObject]@{ - Title=$Title - Header=$Header - ChartType=$ChartType - XRange=$XRange - YRange=$YRange - Width=$Width - Height=$Height - Row=$Row - RowOffSetPixels=$RowOffSetPixels - Column=$Column - ColumnOffSetPixels=$ColumnOffSetPixels - NoLegend = if($NoLegend) {$true} else {$false} - ShowCategory = if($ShowCategory) {$true} else {$false} - ShowPercent = if($ShowPercent) {$true} else {$false} - SeriesHeader=$SeriesHeader - } -} \ No newline at end of file diff --git a/Open-ExcelPackage.ps1 b/Open-ExcelPackage.ps1 deleted file mode 100644 index 6789dfd5..00000000 --- a/Open-ExcelPackage.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -Function Open-ExcelPackage { -<# -.Synopsis - Returns an Excel Package Object with for the specified XLSX ile -.Example - $excel = Open-ExcelPackage -path $xlPath - $sheet1 = $excel.Workbook.Worksheets["sheet1"] - set-Format -Address $sheet1.Cells["E1:S1048576"], $sheet1.Cells["V1:V1048576"] -NFormat ([cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern) - close-ExcelPackage $excel -Show - - This will open the file at $xlPath, select sheet1 apply formatting to two blocks of the sheet and close the package -#> - [OutputType([OfficeOpenXml.ExcelPackage])] - Param ([Parameter(Mandatory=$true)]$Path, - [switch]$KillExcel) - - if($KillExcel) { - Get-Process -Name "excel" -ErrorAction Ignore | Stop-Process - while (Get-Process -Name "excel" -ErrorAction Ignore) {} - } - - $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) - if (Test-Path $path) {New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path } - Else {Write-Warning "Could not find $path" } - } - -Function Close-ExcelPackage { -<# -.Synopsis - Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file as required -#> - Param ( - #File to close - [parameter(Mandatory=$true, ValueFromPipeline=$true)] - [OfficeOpenXml.ExcelPackage]$ExcelPackage, - #Open the file - [switch]$Show, - #Abandon the file without saving - [Switch]$NoSave, - #Save file with a new name (ignored if -NoSaveSpecified) - $SaveAs - ) - if ( $NoSave) {$ExcelPackage.Dispose()} - else { - if ($SaveAs) {$ExcelPackage.SaveAs( $SaveAs ) } - Else {$ExcelPackage.Save(); $SaveAs = $ExcelPackage.File.FullName } - $ExcelPackage.Dispose() - if ($show) {Start-Process -FilePath $SaveAs } - } -} \ No newline at end of file diff --git a/Pivot.ps1 b/Pivot/Pivot.ps1 similarity index 100% rename from Pivot.ps1 rename to Pivot/Pivot.ps1 diff --git a/Pivot/README.md b/Pivot/README.md new file mode 100644 index 00000000..3a539717 --- /dev/null +++ b/Pivot/README.md @@ -0,0 +1,2 @@ +# Pivot + diff --git a/Pivot/pivot.md b/Pivot/pivot.md new file mode 100644 index 00000000..d90f983f --- /dev/null +++ b/Pivot/pivot.md @@ -0,0 +1,103 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Pivot + +## SYNOPSIS + +## SYNTAX + +```text +Pivot [[-targetData] ] [[-pivotRows] ] [[-pivotData] ] [[-ChartType] ] + [] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -ChartType + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -pivotData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -pivotRows + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -targetData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/plot.ps1 b/Plot.ps1 similarity index 86% rename from plot.ps1 rename to Plot.ps1 index 05b193c7..4a54ea14 100644 --- a/plot.ps1 +++ b/Plot.ps1 @@ -1,6 +1,8 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification="False positives")] +param() class PSPlot { hidden $path - hidden $pkg + hidden $pkg hidden $ws hidden $chart @@ -11,62 +13,62 @@ class PSPlot { } [PSPlot] Plot($yValues) { - + $this.NewChart() - + $xValues = 0..$yValues.Count $xCol = 'A' $yCol = 'B' - $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) + $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) $this.AddSeries($xCol,$yCol,$yValues) $this.SetChartPosition($yCol) - + return $this } [PSPlot] Plot($yValues,[string]$options) { $this.NewChart() - + $xValues = 0..$yValues.Count $xCol = 'A' $yCol = 'B' - $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) + $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) $this.AddSeries($xCol,$yCol,$yValues) - $this.SetMarkerInfo($options) + $this.SetMarkerInfo($options) $this.SetChartPosition($yCol) return $this } [PSPlot] Plot($xValues,$yValues) { - - $this.NewChart() + + $this.NewChart() $xCol = 'A' $yCol = 'B' - $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) + $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) $this.AddSeries($xCol,$yCol,$yValues) $this.SetChartPosition($yCol) return $this } - + [PSPlot] Plot($xValues,$yValues,[string]$options) { - $this.NewChart() + $this.NewChart() $xCol = 'A' $yCol = 'B' - $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) + $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) $this.AddSeries($xCol,$yCol,$yValues) - + $this.SetMarkerInfo($options) $this.SetChartPosition($yCol) @@ -75,19 +77,19 @@ class PSPlot { } [PSPlot] Plot($xValues,$yValues,$x1Values,$y1Values) { - - $this.NewChart() + + $this.NewChart() $xCol = 'A' $yCol = 'B' - $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) + $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) $this.AddSeries($xCol,$yCol,$yValues) $xCol=$this.GetNextColumnName($yCol) $yCol=$this.GetNextColumnName($xCol) - $this.AddDataToSheet($xCol,$yCol,'x1','y1',$x1Values,$y1Values) + $this.AddDataToSheet($xCol,$yCol,'x1','y1',$x1Values,$y1Values) $this.AddSeries($xCol,$yCol,$y1Values) $this.SetChartPosition($yCol) @@ -96,32 +98,32 @@ class PSPlot { } [PSPlot] Plot($xValues,$yValues,$x1Values,$y1Values,$x2Values,$y2Values) { - - $this.NewChart() + + $this.NewChart() $xCol = 'A' $yCol = 'B' - $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) + $this.AddDataToSheet($xCol,$yCol,'x','y',$xValues,$yValues) $this.AddSeries($xCol,$yCol,$yValues) $xCol=$this.GetNextColumnName($yCol) $yCol=$this.GetNextColumnName($xCol) - $this.AddDataToSheet($xCol,$yCol,'x1','y1',$x1Values,$y1Values) + $this.AddDataToSheet($xCol,$yCol,'x1','y1',$x1Values,$y1Values) $this.AddSeries($xCol,$yCol,$y1Values) $xCol=$this.GetNextColumnName($yCol) $yCol=$this.GetNextColumnName($xCol) - $this.AddDataToSheet($xCol,$yCol,'x2','y2',$x2Values,$y2Values) + $this.AddDataToSheet($xCol,$yCol,'x2','y2',$x2Values,$y2Values) $this.AddSeries($xCol,$yCol,$y2Values) $this.SetChartPosition($yCol) return $this } - + [PSPLot] SetChartPosition($yCol) { $columnNumber = $this.GetColumnNumber($yCol)+1 $this.chart.SetPosition(1,0,$columnNumber,0) @@ -131,31 +133,31 @@ class PSPlot { AddSeries($xCol,$yCol,$yValues) { $yRange = "{0}2:{0}{1}" -f $yCol,($yValues.Count+1) - $xRange = "{0}2:{0}{1}" -f $xCol,($yValues.Count+1) - $Series=$this.chart.Series.Add($yRange,$xRange) + $xRange = "{0}2:{0}{1}" -f $xCol,($yValues.Count+1) + $Series=$this.chart.Series.Add($yRange,$xRange) } hidden SetMarkerInfo([string]$options) { $c=$options.Substring(0,1) $m=$options.Substring(1) - + $cmap=@{r='red';g='green';b='blue';i='indigo';v='violet';c='cyan'} $mmap=@{Ci='Circle';Da='Dash';di='diamond';do='dot';pl='plus';sq='square';tr='triangle'} - + $this.chart.Series[0].Marker = $mmap.$m $this.chart.Series[0].MarkerColor = $cmap.$c $this.chart.Series[0].MarkerLineColor = $cmap.$c } hidden [string]GetNextColumnName($columnName) { - return $this.GetColumnName($this.GetColumnNumber($columnName)+1) + return $this.GetColumnName($this.GetColumnNumber($columnName)+1) } hidden [int]GetColumnNumber($columnName) { $sum=0 - + $columnName.ToCharArray() | - ForEach { + ForEach-Object { $sum*=26 $sum+=[char]$_.tostring().toupper()-[char]'A'+1 } @@ -179,20 +181,20 @@ class PSPlot { $count=$yValues.Count $this.ws.Cells["$($xColumn)1"].Value=$xHeader $this.ws.Cells["$($yColumn)1"].Value=$yHeader - - for ($idx= 0; $idx-lt $count; $idx++) { - $row=$idx+2 + + for ($idx= 0; $idx-lt $count; $idx++) { + $row=$idx+2 $this.ws.Cells["$($xColumn)$($row)"].Value=$xValues[$idx] $this.ws.Cells["$($yColumn)$($row)"].Value=$yValues[$idx] } } - hidden NewChart() { + hidden NewChart() { $chartType="XYScatter" #$chartType="line" $this.chart=$this.ws.Drawings.AddChart("plot", $chartType) $this.chart.Title.Text = 'Plot' - $this.chart.Legend.Remove() + $this.chart.Legend.Remove() $this.SetChartSize(300,300) } diff --git a/Private/ArgumentCompletion.ps1 b/Private/ArgumentCompletion.ps1 new file mode 100644 index 00000000..ceaefe87 --- /dev/null +++ b/Private/ArgumentCompletion.ps1 @@ -0,0 +1,132 @@ +function ColorCompletion { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) + [System.Drawing.KnownColor].GetFields() | Where-Object {$_.IsStatic -and $_.name -like "$wordToComplete*" } | + Sort-Object name | ForEach-Object {New-CompletionResult $_.name $_.name + } +} + +function ListFonts { + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingEmptyCatchBlock", "")] + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) + if (-not $script:FontFamilies) { + $script:FontFamilies = @("","") + try { + $script:FontFamilies = (New-Object System.Drawing.Text.InstalledFontCollection).Families.Name + } + catch {} + } + $script:FontFamilies.where({$_ -Gt "" -and $_ -like "$wordToComplete*"} ) | ForEach-Object { + New-Object -TypeName System.Management.Automation.CompletionResult -ArgumentList "'$_'" , $_ , + ([System.Management.Automation.CompletionResultType]::ParameterValue) , $_ + } +} + +function NumberFormatCompletion { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) + $numformats = [ordered]@{ + "General" = "General" # format ID 0 + "Number" = "0.00" # format ID 2 + "Percentage" = "0.00%" # format ID 10 + "Scientific" = "0.00E+00" # format ID 11 + "Fraction" = "# ?/?" # format ID 12 + "Short Date" = "Localized" # format ID 14 - will be translated to "mm-dd-yy" which is localized on load by Excel. + "Short Time" = "Localized" # format ID 20 - will be translated to "h:mm" which is localized on load by Excel. + "Long Time" = "Localized" # format ID 21 - will be translated to "h:mm:ss" which is localized on load by Excel. + "Date-Time" = "Localized" # format ID 22 - will be translated to "m/d/yy h:mm" which is localized on load by Excel. + "Currency" = [cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol + "#,##0.00" + "Text" = "@" # format ID 49 + "h:mm AM/PM" = "h:mm AM/PM" # format ID 18 + "h:mm:ss AM/PM" = "h:mm:ss AM/PM" # format ID 19 + "mm:ss" = "mm:ss" # format ID 45 + "[h]:mm:ss" = "Elapsed hours" # format ID 46 + "mm:ss.0" = "mm:ss.0" # format ID 47 + "d-mmm-yy" = "Localized" # format ID 15 which is localized on load by Excel. + "d-mmm" = "Localized" # format ID 16 which is localized on load by Excel. + "mmm-yy" = "mmm-yy" # format ID 17 which is localized on load by Excel. + "0" = "Whole number" # format ID 1 + "0.00" = "Number, 2 decimals" # format ID 2 or "number" + "#,##0" = "Thousand separators" # format ID 3 + "#,##0.00" = "Thousand separators and 2 decimals" # format ID 4 + "#," = "Whole thousands" + "#.0,," = "Millions, 1 Decimal" + "0%" = "Nearest whole percentage" # format ID 9 + "0.00%" = "Percentage with decimals" # format ID 10 or "Percentage" + "00E+00" = "Scientific" # format ID 11 or "Scientific" + "# ?/?" = "One Digit fraction" # format ID 12 or "Fraction" + "# ??/??" = "Two Digit fraction" # format ID 13 + "@" = "Text" # format ID 49 or "Text" + } + $numformats.keys.where({$_ -like "$wordToComplete*"} ) | ForEach-Object { + New-Object -TypeName System.Management.Automation.CompletionResult -ArgumentList "'$_'" , $_ , + ([System.Management.Automation.CompletionResultType]::ParameterValue) , $numformats[$_] + } +} + +function WorksheetArgumentCompleter { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) + $xlPath = $fakeBoundParameter['Path'] + if (Test-Path -Path $xlPath) { + $xlSheet = Get-ExcelSheetInfo -Path $xlPath + $WorksheetNames = $xlSheet.Name + $WorksheetNames.where( { $_ -like "*$wordToComplete*" }) | foreach-object { + New-Object -TypeName System.Management.Automation.CompletionResult -ArgumentList "'$_'", + $_ , ([System.Management.Automation.CompletionResultType]::ParameterValue) , $_ + } + } +} + +if (Get-Command -ErrorAction SilentlyContinue -name Register-ArgumentCompleter) { + Register-ArgumentCompleter -CommandName Export-Excel -ParameterName TitleBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName DataBarColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName ForeGroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName AllDataBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName FontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName TabColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Join-Worksheet -ParameterName TitleBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName AddBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName ChangeBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-Worksheet ` -ParameterName DeleteBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-MulipleSheets -ParameterName KeyFontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-MulipleSheets -ParameterName AddBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-MulipleSheets -ParameterName ChangeBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-MulipleSheets ` -ParameterName DeleteBackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Merge-MulipleSheets -ParameterName KeyFontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ConditionalText -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ConditionalText -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ConditionalText -ParameterName ConditionalTextColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ExcelStyle -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ExcelStyle -ParameterName FontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ExcelStyle -ParameterName BorderColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ExcelStyle -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName FontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName BorderColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelColumn -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelColumn -ParameterName FontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelColumn -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName FontColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName New-ExcelStyle -ParameterName FontName -ScriptBlock $Function:ListFonts + Register-ArgumentCompleter -CommandName Set-ExcelColumn -ParameterName FontName -ScriptBlock $Function:ListFonts + Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName FontName -ScriptBlock $Function:ListFonts + Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName FontName -ScriptBlock $Function:ListFonts + Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName NumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Export-Excel -ParameterName NumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName New-ExcelStyle -ParameterName NumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName NumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Set-ExcelColumn -ParameterName NumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName NumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Add-PivotTable -ParameterName PivotNumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName New-PivotTableDefinition -ParameterName PivotNumberFormat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName New-ExcelChartDefinition -ParameterName XAxisNumberformat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName New-ExcelChartDefinition -ParameterName YAxisNumberformat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Add-ExcelChart -ParameterName XAxisNumberformat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Add-ExcelChart -ParameterName YAxisNumberformat -ScriptBlock $Function:NumberFormatCompletion + Register-ArgumentCompleter -CommandName Import-Excel -ParameterName WorksheetName -ScriptBlock $Function:WorksheetArgumentCompleter +} diff --git a/Private/Invoke-ExcelReZipFile.ps1 b/Private/Invoke-ExcelReZipFile.ps1 new file mode 100644 index 00000000..0c949689 --- /dev/null +++ b/Private/Invoke-ExcelReZipFile.ps1 @@ -0,0 +1,25 @@ +function Invoke-ExcelReZipFile { + <# + #> + param( + [Parameter(Mandatory)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage + ) + + Write-Verbose -Message "Re-Zipping $($ExcelPackage.file) using .NET ZIP library" + try { + Add-Type -AssemblyName 'System.IO.Compression.Filesystem' -ErrorAction stop + } + catch { + Write-Error "The -ReZip parameter requires .NET Framework 4.5 or later to be installed. Recommend to install Powershell v4+" + continue + } + try { + $TempZipPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName()) + $null = [io.compression.zipfile]::ExtractToDirectory($ExcelPackage.File, $TempZipPath) + Remove-Item $ExcelPackage.File -Force + $null = [io.compression.zipfile]::CreateFromDirectory($TempZipPath, $ExcelPackage.File) + Remove-Item $TempZipPath -Recurse -Force + } + catch { throw "Error resizipping $path : $_" } +} \ No newline at end of file diff --git a/Public/Add-ConditionalFormatting.ps1 b/Public/Add-ConditionalFormatting.ps1 new file mode 100644 index 00000000..bab408c5 --- /dev/null +++ b/Public/Add-ConditionalFormatting.ps1 @@ -0,0 +1,158 @@ +function Add-ConditionalFormatting { + param ( + [Parameter(Mandatory = $true, Position = 0)] + [Alias("Range")] + $Address , + [OfficeOpenXml.ExcelWorksheet]$Worksheet , + [Parameter(Mandatory = $true, ParameterSetName = "NamedRule", Position = 1)] + [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType]$RuleType , + [Parameter(ParameterSetName = "NamedRule")] + [Alias("ForegroundColour","FontColor")] + $ForegroundColor, + [Parameter(Mandatory = $true, ParameterSetName = "DataBar")] + [Alias("DataBarColour")] + $DataBarColor, + [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSet")] + [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting3IconsSetType]$ThreeIconsSet, + [Parameter(Mandatory = $true, ParameterSetName = "FourIconSet")] + [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting4IconsSetType]$FourIconsSet, + [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSet")] + [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting5IconsSetType]$FiveIconsSet, + [Parameter(ParameterSetName = "NamedRule")] + [Parameter(ParameterSetName = "ThreeIconSet")] + [Parameter(ParameterSetName = "FourIconSet")] + [Parameter(ParameterSetName = "FiveIconSet")] + [switch]$Reverse, + [switch]$ShowIconOnly, + [Parameter(ParameterSetName = "NamedRule",Position = 2)] + $ConditionValue, + [Parameter(ParameterSetName = "NamedRule",Position = 3)] + $ConditionValue2, + [Parameter(ParameterSetName = "NamedRule")] + $BackgroundColor, + [Parameter(ParameterSetName = "NamedRule")] + [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::None , + [Parameter(ParameterSetName = "NamedRule")] + $PatternColor, + [Parameter(ParameterSetName = "NamedRule")] + $NumberFormat, + [Parameter(ParameterSetName = "NamedRule")] + [switch]$Bold, + [Parameter(ParameterSetName = "NamedRule")] + [switch]$Italic, + [Parameter(ParameterSetName = "NamedRule")] + [switch]$Underline, + [Parameter(ParameterSetName = "NamedRule")] + [switch]$StrikeThru, + [Parameter(ParameterSetName = "NamedRule")] + [switch]$StopIfTrue, + [int]$Priority, + [switch]$PassThru + ) + + #Allow conditional formatting to work like Set-ExcelRange (with single ADDRESS parameter), split it to get worksheet and range of cells. + if ($Address -is [OfficeOpenXml.Table.ExcelTable]) { + $Worksheet = $Address.Address.Worksheet + $Address = $Address.Address.Address + } + elseif ($Address.Address -and $Address.Worksheet -and -not $Worksheet) { #Address is a rangebase or similar + $Worksheet = $Address.Worksheet[0] + $Address = $Address.Address + } + elseif ($Address -is [String] -and $Worksheet -and $Worksheet.Names[$Address] ) { #Address is the name of a named range. + $Address = $Worksheet.Names[$Address].Address + } + if (($Address -is [OfficeOpenXml.ExcelRow] -and -not $Worksheet) -or + ($Address -is [OfficeOpenXml.ExcelColumn] -and -not $Worksheet) ){ #EPPLUs Can't get the worksheet object from a row or column object, so bail if that was tried + Write-Warning -Message "Add-ConditionalFormatting does not support Row or Column objects as an address; use a worksheet and/or specify 'R:R' or 'C:C' instead. "; return + } + elseif ($Address -is [OfficeOpenXml.ExcelRow]) { #But if we have a column or row object and a worksheet (I don't know *why*) turn them into a string for the range + $Address = "$($Address.Row):$($Address.Row)" + } + elseif ($Address -is [OfficeOpenXml.ExcelColumn]) { + $Address = (New-Object 'OfficeOpenXml.ExcelAddress' @(1, $address.ColumnMin, 1, $address.ColumnMax)).Address -replace '1','' + if ($Address -notmatch ':') {$Address = "$Address`:$Address"} + } + if ( $Address -is [string] -and $Address -match "!") {$Address = $Address -replace '^.*!',''} + #By this point we should have a worksheet object whose ConditionalFormatting collection we will add to. If not, bail. + if (-not $worksheet -or $Worksheet -isnot [OfficeOpenXml.ExcelWorksheet]) {write-warning "You need to provide a worksheet object." ; return} + #region create a rule of the right type + if ($RuleType -match 'IconSet$') {Write-warning -Message "You cannot configure a Icon-Set rule in this way; please use -$RuleType ." ; return} + if ($PSBoundParameters.ContainsKey("DataBarColor" ) ) {if ($DataBarColor -is [string]) {$DataBarColor = [System.Drawing.Color]::$DataBarColor } + $rule = $Worksheet.ConditionalFormatting.AddDatabar( $Address , $DataBarColor ) + } + elseif ($PSBoundParameters.ContainsKey("ThreeIconsSet" ) ) {$rule = $Worksheet.ConditionalFormatting.AddThreeIconSet($Address , $ThreeIconsSet)} + elseif ($PSBoundParameters.ContainsKey("FourIconsSet" ) ) {$rule = $Worksheet.ConditionalFormatting.AddFourIconSet( $Address , $FourIconsSet )} + elseif ($PSBoundParameters.ContainsKey("FiveIconsSet" ) ) {$rule = $Worksheet.ConditionalFormatting.AddFiveIconSet( $Address , $FiveIconsSet )} + else {$rule = ($Worksheet.ConditionalFormatting)."Add$RuleType"($Address ) } + If($ShowIconOnly) { + $rule.ShowValue = $false + } + if ($Reverse) { + if ($rule.type -match 'IconSet$' ) {$rule.reverse = $true} + elseif ($rule.type -match 'ColorScale$') {$temp =$rule.LowValue.Color ; $rule.LowValue.Color = $rule.HighValue.Color; $rule.HighValue.Color = $temp} + else {Write-Warning -Message "-Reverse was ignored because $RuleType does not support it."} + } + #endregion + #region set the rule conditions + #for lessThan/GreaterThan/Equal/Between conditions make sure that strings are wrapped in quotes. Formulas should be passed with = which will be stripped. + if ($RuleType -match "Than|Equal|Between" ) { + if ($PSBoundParameters.ContainsKey("ConditionValue" )) { + $number = $Null + #if the condition type is not a value type, but parses as a number, make it the number + if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) { + $ConditionValue = $number + } #else if it is not a value type, or a formula, or wrapped in quotes, wrap it in quotes. + elseif (($ConditionValue -isnot [System.ValueType])-and ($ConditionValue -notmatch '^=') -and ($ConditionValue -notmatch '^".*"$') ) { + $ConditionValue = '"' + $ConditionValue +'"' + } + } + if ($PSBoundParameters.ContainsKey("ConditionValue2")) { + $number = $Null + if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue2, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) { + $ConditionValue2 = $number + } + elseif (($ConditionValue -isnot [System.ValueType]) -and ($ConditionValue2 -notmatch '^=') -and ($ConditionValue2 -notmatch '^".*"$') ) { + $ConditionValue2 = '"' + $ConditionValue2 + '"' + } + } + } + #But we don't usually want quotes round containstext | beginswith type rules. Can't be Certain they need to be removed, so warn the user their condition might be wrong + if ($RuleType -match "Text|With" -and $ConditionValue -match '^".*"$' ) { + Write-Warning -Message "The condition will look for the quotes at the start and end." + } + if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and + $RuleType -match "Top|Bottom" ) {$rule.Rank = $ConditionValue } + if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and + $RuleType -match "StdDev" ) {$rule.StdDev = $ConditionValue } + if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and + $RuleType -match "Than|Equal|Expression" ) {$rule.Formula = ($ConditionValue -replace '^=','') } + if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and + $RuleType -match "Text|With" ) {$rule.Text = ($ConditionValue -replace '^=','') } + if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and + $PSBoundParameters.ContainsKey("ConditionValue2") -and + $RuleType -match "Between" ) { + $rule.Formula = ($ConditionValue -replace '^=',''); + $rule.Formula2 = ($ConditionValue2 -replace '^=','') + } + if ($PSBoundParameters.ContainsKey("StopIfTrue") ) {$rule.StopIfTrue = $StopIfTrue } + if ($PSBoundParameters.ContainsKey("Priority") ) {$rule.Priority = $Priority } + #endregion + #region set the rule format + if ($PSBoundParameters.ContainsKey("NumberFormat" ) ) {$rule.Style.NumberFormat.Format = (Expand-NumberFormat $NumberFormat) } + if ($Underline ) {$rule.Style.Font.Underline = [OfficeOpenXml.Style.ExcelUnderLineType]::Single } + elseif ($PSBoundParameters.ContainsKey("Underline" ) ) {$rule.Style.Font.Underline = [OfficeOpenXml.Style.ExcelUnderLineType]::None } + if ($PSBoundParameters.ContainsKey("Bold" ) ) {$rule.Style.Font.Bold = [boolean]$Bold } + if ($PSBoundParameters.ContainsKey("Italic" ) ) {$rule.Style.Font.Italic = [boolean]$Italic } + if ($PSBoundParameters.ContainsKey("StrikeThru" ) ) {$rule.Style.Font.Strike = [boolean]$StrikeThru } + if ($PSBoundParameters.ContainsKey("ForeGroundColor" ) ) {if ($ForeGroundColor -is [string]) {$ForeGroundColor = [System.Drawing.Color]::$ForeGroundColor } + $rule.Style.Font.Color.color = $ForeGroundColor } + if ($PSBoundParameters.ContainsKey("BackgroundColor" ) ) {if ($BackgroundColor -is [string]) {$BackgroundColor = [System.Drawing.Color]::$BackgroundColor } + $rule.Style.Fill.BackgroundColor.color = $BackgroundColor } + if ($PSBoundParameters.ContainsKey("BackgroundPattern") ) {$rule.Style.Fill.PatternType = $BackgroundPattern } + if ($PSBoundParameters.ContainsKey("PatternColor" ) ) {if ($PatternColor -is [string]) {$PatternColor = [System.Drawing.Color]::$PatternColor } + $rule.Style.Fill.PatternColor.color = $PatternColor } + #endregion + #Allow further tweaking by returning the rule, if passthru specified + if ($Passthru) {$rule} +} \ No newline at end of file diff --git a/Public/Add-ExcelChart.ps1 b/Public/Add-ExcelChart.ps1 new file mode 100644 index 00000000..88a0d460 --- /dev/null +++ b/Public/Add-ExcelChart.ps1 @@ -0,0 +1,142 @@ + +function Add-ExcelChart { + [CmdletBinding(DefaultParameterSetName = 'Worksheet')] + [OutputType([OfficeOpenXml.Drawing.Chart.ExcelChart])] + param( + [Parameter(ParameterSetName = 'Worksheet', Mandatory = $true)] + [OfficeOpenXml.ExcelWorksheet]$Worksheet, + [Parameter(ParameterSetName = 'PivotTable', Mandatory = $true)] + [OfficeOpenXml.Table.PivotTable.ExcelPivotTable]$PivotTable , + [String]$Title, + [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = "ColumnStacked", + [OfficeOpenXml.Drawing.Chart.eTrendLine[]]$ChartTrendLine, + $XRange, + $YRange, + [int]$Width = 500, + [int]$Height = 350, + [int]$Row = 0, + [int]$RowOffSetPixels = 10, + [int]$Column = 6, + [int]$ColumnOffSetPixels = 5, + [OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPosition, + $LegendSize, + [Switch]$LegendBold, + [Switch]$NoLegend, + [Switch]$ShowCategory, + [Switch]$ShowPercent, + [String[]]$SeriesHeader, + [Switch]$TitleBold, + [Int]$TitleSize , + [String]$XAxisTitleText, + [Switch]$XAxisTitleBold, + $XAxisTitleSize , + [string]$XAxisNumberformat, + $XMajorUnit, + $XMinorUnit, + $XMaxValue, + $XMinValue, + [OfficeOpenXml.Drawing.Chart.eAxisPosition]$XAxisPosition , + [String]$YAxisTitleText, + [Switch]$YAxisTitleBold, + $YAxisTitleSize, + [string]$YAxisNumberformat, + $YMajorUnit, + $YMinorUnit, + $YMaxValue, + $YMinValue, + [OfficeOpenXml.Drawing.Chart.eAxisPosition]$YAxisPosition, + [Switch]$PassThru + ) + try { + if ($PivotTable) { + $Worksheet = $PivotTable.Worksheet + $chart = $Worksheet.Drawings.AddChart(("Chart" + $PivotTable.Name ), $ChartType, $PivotTable) + } + else { + $ChartName = 'Chart' + (Split-Path -Leaf ([System.IO.path]::GetTempFileName())) -replace 'tmp|\.', '' + $chart = $Worksheet.Drawings.AddChart($ChartName, $ChartType) + $chartDefCount = @($YRange).Count + if ($chartDefCount -eq 1) { + $Series = $chart.Series.Add($YRange, $XRange) + if ($ChartTrendLine) { + if ($ChartType -notmatch "stacked|3D$|pie|Doughnut|Cone|Cylinder|Pyramid") { + foreach ($trendLine in $ChartTrendLine) { + $null = $Series.TrendLines.Add($trendLine) + } + } + else { + Write-Warning "Chart trend line is not supported for chart type: $ChartType" + } + } + if ($SeriesHeader) { $Series.Header = $SeriesHeader } + else { $Series.Header = 'Series 1' } + } + else { + for ($idx = 0; $idx -lt $chartDefCount; $idx += 1) { + if ($Yrange.count -eq $xrange.count) { + $Series = $chart.Series.Add($YRange[$idx], $XRange[$idx]) + } + else { + $Series = $chart.Series.Add($YRange[$idx], $XRange) + } + if ($SeriesHeader.Count -gt 0) { + if ($SeriesHeader[$idx] -match '^=') { $Series.HeaderAddress = $SeriesHeader[$idx] -replace '^=', '' } + else { $Series.Header = $SeriesHeader[$idx] } + } + else { $Series.Header = "Series $($idx)" } + } + } + } + if ($Title) { + $chart.Title.Text = $Title + if ($TitleBold) { $chart.Title.Font.Bold = $true } + if ($TitleSize) { $chart.Title.Font.Size = $TitleSize } + } + if ($NoLegend) { $chart.Legend.Remove() } + else { + if ($PSBoundParameters.ContainsKey('LegendPosition')) { $chart.Legend.Position = $LegendPosition } + if ($PSBoundParameters.ContainsKey('LegendBold')) { $chart.Legend.Font.Bold = [boolean]$LegendBold } + if ($LegendSize) { $chart.Legend.Font.Size = $LegendSize } + } + + if ($XAxisTitleText) { + $chart.XAxis.Title.Text = $XAxisTitleText + if ($PSBoundParameters.ContainsKey('XAxisTitleBold')) { + $chart.XAxis.Title.Font.Bold = [boolean]$XAxisTitleBold + } + if ($XAxisTitleSize) { $chart.XAxis.Title.Font.Size = $XAxisTitleSize } + } + if ($XAxisPosition) { Write-Warning "X-axis position is not being set propertly at the moment, parameter ignored" } + #$chart.ChartXml.chartSpace.chart.plotArea.catAx.axPos.val = $XAxisPosition.ToString().substring(0,1)} + if ($XMajorUnit) { $chart.XAxis.MajorUnit = $XMajorUnit } + if ($XMinorUnit) { $chart.XAxis.MinorUnit = $XMinorUnit } + if ($null -ne $XMinValue) { $chart.XAxis.MinValue = $XMinValue } + if ($null -ne $XMaxValue) { $chart.XAxis.MaxValue = $XMaxValue } + if ($XAxisNumberformat) { $chart.XAxis.Format = (Expand-NumberFormat $XAxisNumberformat) } + + if ($YAxisTitleText) { + $chart.YAxis.Title.Text = $YAxisTitleText + if ($PSBoundParameters.ContainsKey('YAxisTitleBold')) { + $chart.YAxis.Title.Font.Bold = [boolean]$YAxisTitleBold + } + if ($YAxisTitleSize) { $chart.YAxis.Title.Font.Size = $YAxisTitleSize } + } + if ($YAxisPosition) { Write-Warning "Y-axis position is not being set propertly at the moment, parameter ignored" } + #$chart.ChartXml.chartSpace.chart.plotArea.valAx.axPos.val= $YAxisPosition.ToString().substring(0,1)} + if ($YMajorUnit) { $chart.YAxis.MajorUnit = $YMajorUnit } + if ($YMinorUnit) { $chart.YAxis.MinorUnit = $YMinorUnit } + if ($null -ne $YMinValue) { $chart.YAxis.MinValue = $YMinValue } + if ($null -ne $YMaxValue) { $chart.YAxis.MaxValue = $YMaxValue } + if ($YAxisNumberformat) { $chart.YAxis.Format = (Expand-NumberFormat $YAxisNumberformat) } + if ($null -ne $chart.Datalabel) { + $chart.Datalabel.ShowCategory = [boolean]$ShowCategory + $chart.Datalabel.ShowPercent = [boolean]$ShowPercent + } + + $chart.SetPosition($Row, $RowOffsetPixels, $Column, $ColumnOffsetPixels) + $chart.SetSize($Width, $Height) + + if ($PassThru) { return $chart } + } + catch { Write-Warning -Message "Failed adding Chart to worksheet '$($Worksheet).name': $_" } +} diff --git a/Public/Add-ExcelDataValidationRule.ps1 b/Public/Add-ExcelDataValidationRule.ps1 new file mode 100644 index 00000000..cd3f7324 --- /dev/null +++ b/Public/Add-ExcelDataValidationRule.ps1 @@ -0,0 +1,58 @@ +function Add-ExcelDataValidationRule { + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline = $true,Position=0)] + [Alias("Address")] + $Range , + [OfficeOpenXml.ExcelWorksheet]$Worksheet , + [ValidateSet('Any','Custom','DateTime','Decimal','Integer','List','TextLength','Time')] + $ValidationType, + [OfficeOpenXml.DataValidation.ExcelDataValidationOperator]$Operator = [OfficeOpenXml.DataValidation.ExcelDataValidationOperator]::equal , + $Value, + $Value2, + $Formula, + $Formula2, + $ValueSet, + [switch]$ShowErrorMessage, + [OfficeOpenXml.DataValidation.ExcelDataValidationWarningStyle]$ErrorStyle, + [String]$ErrorTitle, + [String]$ErrorBody, + [switch]$ShowPromptMessage, + [String]$PromptBody, + [String]$PromptTitle, + [String]$NoBlank + ) + if ($Range -is [Array]) { + $null = $PSBoundParameters.Remove("Range") + $Range | Add-ExcelDataValidationRule @PSBoundParameters + } + else { + #We should accept, a worksheet and a name of a range or a cell address; a table; the address of a table; a named range; a row, a column or .Cells[ ] + if (-not $Worksheet -and $Range.worksheet) {$Worksheet = $Range.worksheet} + if ($Range.Address) {$Range = $Range.Address} + + if ($Range -isnot [string] -or -not $Worksheet) {Write-Warning -Message "You need to provide a worksheet and range of cells." ;return} + #else we assume Range is a range. + + $validation = $Worksheet.DataValidations."Add$ValidationType`Validation"($Range) + if ($validation.AllowsOperator) {$validation.Operator = $Operator} + if ($PSBoundParameters.ContainsKey('value')) { + $validation.Formula.Value = $Value + } + elseif ($Formula) {$validation.Formula.ExcelFormula = $Formula} + elseif ($ValueSet) {Foreach ($v in $ValueSet) {$validation.Formula.Values.Add($V)}} + if ($PSBoundParameters.ContainsKey('Value2')) { + $validation.Formula2.Value = $Value2 + } + elseif ($Formula2) {$validation.Formula2.ExcelFormula = $Formula} + $validation.ShowErrorMessage = [bool]$ShowErrorMessage + $validation.ShowInputMessage = [bool]$ShowPromptMessage + $validation.AllowBlank = -not $NoBlank + + if ($PromptTitle) {$validation.PromptTitle = $PromptTitle} + if ($ErrorTitle) {$validation.ErrorTitle = $ErrorTitle} + if ($PromptBody) {$validation.Prompt = $PromptBody} + if ($ErrorBody) {$validation.Error = $ErrorBody} + if ($ErrorStyle) {$validation.ErrorStyle = $ErrorStyle} + } + } diff --git a/Public/Add-ExcelName.ps1 b/Public/Add-ExcelName.ps1 new file mode 100644 index 00000000..03241808 --- /dev/null +++ b/Public/Add-ExcelName.ps1 @@ -0,0 +1,30 @@ +function Add-ExcelName { + [CmdletBinding()] + param( + #The range of cells to assign as a name. + [Parameter(Mandatory=$true)] + [OfficeOpenXml.ExcelRange]$Range, + #The name to assign to the range. If the name exists it will be updated to the new range. If no name is specified, the first cell in the range will be used as the name. + [String]$RangeName + ) + try { + $ws = $Range.Worksheet + if (-not $RangeName) { + $RangeName = $ws.Cells[$Range.Start.Address].Value + $Range = ($Range.Worksheet.cells[($Range.start.row +1), $Range.start.Column , $Range.end.row, $Range.end.column]) + } + if ($RangeName -match '\W') { + Write-Warning -Message "Range name '$RangeName' contains illegal characters, they will be replaced with '_'." + $RangeName = $RangeName -replace '\W','_' + } + if ($ws.names[$RangeName]) { + Write-verbose -Message "Updating Named range '$RangeName' to $($Range.FullAddressAbsolute)." + $ws.Names[$RangeName].Address = $Range.FullAddressAbsolute + } + else { + Write-verbose -Message "Creating Named range '$RangeName' as $($Range.FullAddressAbsolute)." + $null = $ws.Names.Add($RangeName, $Range) + } + } + catch {Write-Warning -Message "Failed adding named range '$RangeName' to worksheet '$($ws.Name)': $_" } +} diff --git a/Public/Add-ExcelTable.ps1 b/Public/Add-ExcelTable.ps1 new file mode 100644 index 00000000..232efaf6 --- /dev/null +++ b/Public/Add-ExcelTable.ps1 @@ -0,0 +1,126 @@ +function Add-ExcelTable { + [CmdletBinding()] + [OutputType([OfficeOpenXml.Table.ExcelTable])] + param ( + [Parameter(Mandatory=$true)] + [OfficeOpenXml.ExcelRange]$Range, + [String]$TableName = "", + [OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6', + [Switch]$ShowHeader , + [Switch]$ShowFilter, + [Switch]$ShowTotal, + [hashtable]$TableTotalSettings, + [Switch]$ShowFirstColumn, + [Switch]$ShowLastColumn, + [Switch]$ShowRowStripes, + [Switch]$ShowColumnStripes, + [Switch]$PassThru + ) + try { + if ($TableName -eq "" -or $null -eq $TableName) { + $tbl = $Range.Worksheet.Tables.Add($Range, "") + } + else { + if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress($TableName)) { + Write-Warning -Message "$TableName reads as an Excel address, and so is not allowed as a table name." + return + } + if ($TableName -notMatch '^[A-Z]') { + Write-Warning -Message "$TableName is not allowed as a table name because it does not begin with a letter." + return + } + if ($TableName -match "\W") { + Write-Warning -Message "At least one character in $TableName is illegal in a table name and will be replaced with '_' . " + $TableName = $TableName -replace '\W', '_' + } + $ws = $Range.Worksheet + #if the table exists in this worksheet, update it. + if ($ws.Tables[$TableName]) { + $tbl =$ws.Tables[$TableName] + $tbl.TableXml.table.ref = $Range.Address + Write-Verbose -Message "Re-defined table '$TableName', now at $($Range.Address)." + } + elseif ($ws.Workbook.Worksheets.Tables.Name -contains $TableName) { + Write-Warning -Message "The Table name '$TableName' is already used on a different worksheet." + return + } + else { + $tbl = $ws.Tables.Add($Range, $TableName) + Write-Verbose -Message "Defined table '$($tbl.Name)' at $($Range.Address)" + } + } + #it seems that show total changes some of the others, so the sequence matters. + if ($PSBoundParameters.ContainsKey('ShowHeader')) {$tbl.ShowHeader = [bool]$ShowHeader} + if ($PSBoundParameters.ContainsKey('TableTotalSettings') -And $Null -ne $TableTotalSettings) { + $tbl.ShowTotal = $true + foreach ($k in $TableTotalSettings.keys) { + + # Get the Function to be added in the totals row + if ($TableTotalSettings[$k] -is [HashTable]) { + If ($TableTotalSettings[$k].Keys -contains "Function") { + $TotalFunction = $TableTotalSettings[$k]["Function"] + } + Else { Write-Warning -Message "TableTotalSettings parameter for column '$k' needs a key 'Function'" } + } + else { + $TotalFunction = [String]($TableTotalSettings[$k]) + } + + # Add the totals row + if (-not $tbl.Columns[$k]) {Write-Warning -Message "Table does not have a Column '$k'."} + elseif ($TotalFunction -match "^=") { + ### A function in Excel uses ";" between parameters but the OpenXML parameter separator is "," + ### Only replace semicolon when it's NOT somewhere between quotes quotes. + # Get all text between quotes + $QuoteMatches = [Regex]::Matches($TotalFunction,"`"[^`"]*`"|'[^']*'") + # Create array with all indexes of characters between quotes (and the quotes themselves) + $QuoteCharIndexes = $( + Foreach ($QuoteMatch in $QuoteMatches) { + (($QuoteMatch.Index)..($QuoteMatch.Index + $QuoteMatch.Length - 1)) + } + ) + + # Get all semicolons + $SemiColonMatches = [Regex]::Matches($TotalFunction, ";") + # Replace the semicolons of which the index is not in the list of quote-text indexes + Foreach ($SemiColonMatch in $SemiColonMatches.Index) { + If ($QuoteCharIndexes -notcontains $SemiColonMatch) { + $TotalFunction = $TotalFunction.remove($SemiColonMatch,1).Insert($SemiColonMatch,",") + } + } + + # Configure the formula. The TotalsRowFunction is automatically set to "Custom" when the TotalsRowFormula is set. + $tbl.Columns[$k].TotalsRowFormula = $TotalFunction + } + elseif ($TotalFunction -notin @("Average", "Count", "CountNums", "Max", "Min", "None", "StdDev", "Sum", "Var") ) { + Write-Warning -Message "'$($TotalFunction)' is not a valid total function." + } + else {$tbl.Columns[$k].TotalsRowFunction = $TotalFunction} + + # Set comment on totals row + If ($TableTotalSettings[$k] -is [HashTable] -and $TableTotalSettings[$k].Keys -contains "Comment" -and ![String]::IsNullOrEmpty($TableTotalSettings[$k]["Comment"])) { + $ColumnLetter = [officeOpenXml.ExcelAddress]::GetAddressCol(($tbl.columns | ? { $_.name -eq $k }).Id, $False) + $CommentRange = "{0}{1}" -f $ColumnLetter, $tbl.Address.End.Row + + $CellCommentParams = @{ + Worksheet = $tbl.WorkSheet + Range = $CommentRange + Text = $TableTotalSettings[$k]["Comment"] + } + + Set-CellComment @CellCommentParams + } + } + } + elseif ($PSBoundParameters.ContainsKey('ShowTotal')) {$tbl.ShowTotal = [bool]$ShowTotal} + if ($PSBoundParameters.ContainsKey('ShowFilter')) {$tbl.ShowFilter = [bool]$ShowFilter} + if ($PSBoundParameters.ContainsKey('ShowFirstColumn')) {$tbl.ShowFirstColumn = [bool]$ShowFirstColumn} + if ($PSBoundParameters.ContainsKey('ShowLastColumn')) {$tbl.ShowLastColumn = [bool]$ShowLastColumn} + if ($PSBoundParameters.ContainsKey('ShowRowStripes')) {$tbl.ShowRowStripes = [bool]$ShowRowStripes} + if ($PSBoundParameters.ContainsKey('ShowColumnStripes')) {$tbl.ShowColumnStripes = [bool]$ShowColumnStripes} + $tbl.TableStyle = $TableStyle + + if ($PassThru) {return $tbl} + } + catch {Write-Warning -Message "Failed adding table '$TableName' to worksheet '$WorksheetName': $_"} +} diff --git a/Public/Add-PivotTable.ps1 b/Public/Add-PivotTable.ps1 new file mode 100644 index 00000000..ebeea210 --- /dev/null +++ b/Public/Add-PivotTable.ps1 @@ -0,0 +1,188 @@ +function Add-PivotTable { + [CmdletBinding(defaultParameterSetName = 'ChartbyParams')] + [OutputType([OfficeOpenXml.Table.PivotTable.ExcelPivotTable])] + param ( + [Parameter(Mandatory = $true)] + [string]$PivotTableName, + [OfficeOpenXml.ExcelAddressBase] + $Address, + $ExcelPackage, + $SourceWorksheet, + $SourceRange, + $PivotRows, + $PivotData, + $PivotColumns, + $PivotFilter, + [Switch]$PivotDataToColumn, + [ValidateSet("Both", "Columns", "Rows", "None")] + [String]$PivotTotals = "Both", + [Switch]$NoTotalsInPivot, + [String]$GroupDateRow, + [String]$GroupDateColumn, + [OfficeOpenXml.Table.PivotTable.eDateGroupBy[]]$GroupDatePart, + [String]$GroupNumericRow, + [String]$GroupNumericColumn, + [double]$GroupNumericMin = 0 , + [double]$GroupNumericMax = [Double]::MaxValue , + [double]$GroupNumericInterval = 100 , + [string]$PivotNumberFormat, + [OfficeOpenXml.Table.TableStyles]$PivotTableStyle, + [Parameter(ParameterSetName = 'ChartbyDef', Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + $PivotChartDefinition, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$IncludePivotChart, + [Parameter(ParameterSetName = 'ChartbyParams')] + [String]$ChartTitle = "", + [Parameter(ParameterSetName = 'ChartbyParams')] + [int]$ChartHeight = 400 , + [Parameter(ParameterSetName = 'ChartbyParams')] + [int]$ChartWidth = 600, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartRow = 0 , + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartColumn = 4, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartRowOffSetPixels = 0 , + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartColumnOffSetPixels = 0, + [Parameter(ParameterSetName = 'ChartbyParams')] + [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie', + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$NoLegend, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$ShowCategory, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$ShowPercent, + [switch]$Activate, + [Switch]$PassThru + ) + if ($PivotTableName.length -gt 250) { + Write-warning -Message "PivotTable name will be truncated" + $PivotTableName = $PivotTableName.Substring(0, 250) + } + if ($Address) { + [OfficeOpenXml.ExcelWorksheet]$wsPivot = $address.Worksheet + } + else { + try { + if (-not $ExcelPackage) {Write-Warning -message "This combination of Parameters needs to include the ExcelPackage." ; return } + [OfficeOpenXml.ExcelWorksheet]$wsPivot = Add-Worksheet -ExcelPackage $ExcelPackage -WorksheetName $pivotTableName -Activate:$Activate + if ($wsPivot.Name -ne $PivotTableName) {Write-Warning -Message "The Worksheet name for the PivotTable does not match the table name '$PivotTableName'; probably because excess or illegal characters were removed." } + if ($PivotFilter) {$Address = $wsPivot.Cells["A3"]} else { $Address = $wsPivot.Cells["A1"]} + } + catch {throw "Could not create the sheet for the PivotTable. $_" } + } + #if the pivot doesn't exist, create it. + if (-not $wsPivot) {throw "There was a problem getting the worksheet for the PivotTable"} + if (-not $wsPivot.PivotTables[$pivotTableName] ) { + try { + #Accept a string or a worksheet object as $SourceWorksheet - we don't need a worksheet if we have a Rangebase . + if ( $SourceWorksheet -is [string]) { + $SourceWorksheet = $ExcelPackage.Workbook.Worksheets.where( {$_.name -Like $SourceWorksheet})[0] + } + elseif ( $SourceWorksheet -is [int] ) { + $SourceWorksheet = $ExcelPackage.Workbook.Worksheets[$SourceWorksheet] + } + if ( $SourceRange -is [OfficeOpenXml.Table.ExcelTable]) {$SourceRange = $SourceRange.Address } + if ( $sourceRange -is [OfficeOpenXml.ExcelRange] -or + $SourceRange -is [OfficeOpenXml.ExcelAddress]) { + $pivotTable = $wsPivot.PivotTables.Add($Address, $SourceRange, $pivotTableName) + } + elseif (-not $SourceRange) { + $pivotTable = $wsPivot.PivotTables.Add($Address, $SourceWorksheet.cells[$SourceWorksheet.Dimension.Address], $pivotTableName) + } + elseif ($SourceWorksheet -isnot [OfficeOpenXml.ExcelWorksheet] ) { + Write-Warning -Message "Could not find source Worksheet for pivot-table '$pivotTableName'." ; return + } + elseif ( $SourceRange -is [String] -or $SourceRange -is [OfficeOpenXml.ExcelAddress]) { + $pivotTable = $wsPivot.PivotTables.Add($Address, $SourceWorksheet.Cells[$SourceRange], $pivotTableName) + } + else {Write-warning "Could not create a PivotTable with the Source Range provided."; return} + foreach ($row in $PivotRows) { + try {$null = $pivotTable.RowFields.Add($pivotTable.Fields[$row]) } + catch {Write-Warning -message "Could not add '$row' to Rows in PivotTable $pivotTableName." } + } + foreach ($Column in $PivotColumns) { + try {$null = $pivotTable.ColumnFields.Add($pivotTable.Fields[$Column])} + catch {Write-Warning -message "Could not add '$Column' to Columns in PivotTable $pivotTableName." } + } + if ($PivotData -is [HashTable] -or $PivotData -is [System.Collections.Specialized.OrderedDictionary]) { + $PivotData.Keys | ForEach-Object { + try { + $df = $pivotTable.DataFields.Add($pivotTable.Fields[$_]) + $df.Function = $PivotData.$_ + if ($PivotNumberFormat) {$df.Format = (Expand-NumberFormat -NumberFormat $PivotNumberFormat)} + } + catch {Write-Warning -message "Problem adding data fields to PivotTable $pivotTableName." } + } + } + else { + foreach ($field in $PivotData) { + try { + $df = $pivotTable.DataFields.Add($pivotTable.Fields[$field]) + $df.Function = 'Count' + } + catch {Write-Warning -message "Problem adding data field '$field' to PivotTable $pivotTableName." } + } + } + foreach ( $pFilter in $PivotFilter) { + try { $null = $pivotTable.PageFields.Add($pivotTable.Fields[$pFilter])} + catch {Write-Warning -message "Could not add '$pFilter' to Filter/Page fields in PivotTable $pivotTableName." } + } + if ($NoTotalsInPivot) {$PivotTotals = "None" } + if ($PivotTotals -eq "None" -or $PivotTotals -eq "Columns") { $pivotTable.RowGrandTotals = $false } + elseif ($PivotTotals -eq "Both" -or $PivotTotals -eq "Rows") { $pivotTable.RowGrandTotals = $true } + if ($PivotTotals -eq "None" -or $PivotTotals -eq "Rows") { $pivotTable.ColumGrandTotals = $false } # Epplus spelling mistake, not mine! + elseif ($PivotTotals -eq "Both" -or $PivotTotals -eq "Columns") { $pivotTable.ColumGrandTotals = $true } + if ($PivotDataToColumn ) { $pivotTable.DataOnRows = $false } + if ($PivotTableStyle) { $pivotTable.TableStyle = $PivotTableStyle} + if ($GroupNumericRow) { + $r = $pivotTable.RowFields.Where( {$_.name -eq $GroupNumericRow }) + if (-not $r ) {Write-Warning -Message "Could not find a Row field named '$GroupNumericRow'; no numeric grouping will be done."} + else {$r.AddNumericGrouping($GroupNumericMin, $GroupNumericMax, $GroupNumericInterval)} + } + elseif ($GroupNumericColumn) { + $c = $pivotTable.ColumnFields.Where( {$_.name -eq $GroupNumericColumn }) + if (-not $c ) {Write-Warning -Message "Could not find a Column field named '$GroupNumericColumn'; no numeric grouping will be done."} + else {$c.AddNumericGrouping($GroupNumericMin, $GroupNumericMax, $GroupNumericInterval)} + } + if ($GroupDateRow -and $PSBoundParameters.ContainsKey("GroupDatePart")) { + $r = $pivotTable.RowFields.Where( {$_.name -eq $GroupDateRow }) + if (-not $r ) {Write-Warning -Message "Could not find a Row field named '$GroupDateRow'; no date grouping will be done."} + else {$r.AddDateGrouping($GroupDatePart)} + } + elseif ($GroupDateColumn -and $PSBoundParameters.ContainsKey("GroupDatePart")) { + $c = $pivotTable.ColumnFields.Where( {$_.name -eq $GroupDateColumn }) + if (-not $c ) {Write-Warning -Message "Could not find a Column field named '$GroupDateColumn'; no date grouping will be done."} + else {$c.AddDateGrouping($GroupDatePart)} + } + } + catch {Write-Warning -Message "Failed adding PivotTable '$pivotTableName': $_"} + } + else { + Write-Warning -Message "PivotTable defined in $($pivotTableName) already exists, only the data range will be changed." + $pivotTable = $wsPivot.PivotTables[$pivotTableName] + if (-not $SourceRange) { $SourceRange = $SourceWorksheet.Dimension.Address} + $pivotTable.CacheDefinition.SourceRange = $SourceWorksheet.cells[$SourceRange] + #change for epPlus 4.5 - Previously needed to hack the xml + # $pivotTable.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref = $SourceRange + + } + + #Create the chart if it doesn't exist, leave alone if it does. + if ($IncludePivotChart -and -not $wsPivot.Drawings["Chart$pivotTableName"] ) { + try {Add-ExcelChart -PivotTable $pivotTable -ChartType $ChartType -Width $ChartWidth -Height $ChartHeight -Row $ChartRow -Column $ChartColumn -RowOffSetPixels $ChartRowOffSetPixels -ColumnOffSetPixels $ChartColumnOffSetPixels -Title $ChartTitle -NoLegend:$NoLegend -ShowCategory:$ShowCategory -ShowPercent:$ShowPercent } + catch {Write-Warning -Message "Failed adding chart for pivotable '$pivotTableName': $_"} + } + elseif ($PivotChartDefinition -and -not $wsPivot.Drawings["Chart$pivotTableName"]) { + if ($PivotChartDefinition -is [System.Management.Automation.PSCustomObject]) { + $params = @{PivotTable = $pivotTable } + $PivotChartDefinition.PSObject.Properties | ForEach-Object {if ( $null -ne $_.value) {$params[$_.name] = $_.value}} + Add-ExcelChart @params + } + elseif ($PivotChartDefinition -is [hashtable] -or $PivotChartDefinition -is [System.Collections.Specialized.OrderedDictionary]) { + Add-ExcelChart -PivotTable $pivotTable @PivotChartDefinition + } + } + if ($PassThru) {return $pivotTable} +} diff --git a/Public/Add-Worksheet.ps1 b/Public/Add-Worksheet.ps1 new file mode 100644 index 00000000..0a9e9849 --- /dev/null +++ b/Public/Add-Worksheet.ps1 @@ -0,0 +1,80 @@ +function Add-Worksheet { + [cmdletBinding()] + [OutputType([OfficeOpenXml.ExcelWorksheet])] + param( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = "Package", Position = 0)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Parameter(Mandatory = $true, ParameterSetName = "Workbook")] + [OfficeOpenXml.ExcelWorkbook]$ExcelWorkbook, + [string]$WorksheetName , + [switch]$ClearSheet, + [Switch]$MoveToStart, + [Switch]$MoveToEnd, + $MoveBefore , + $MoveAfter , + [switch]$Activate, + [OfficeOpenXml.ExcelWorksheet]$CopySource, + [parameter(DontShow=$true)] + [Switch] $NoClobber + ) + #if we were given a workbook use it, if we were given a package, use its workbook + if ($ExcelPackage -and -not $ExcelWorkbook) {$ExcelWorkbook = $ExcelPackage.Workbook} + + # If WorksheetName was given, try to use that worksheet. If it wasn't, and we are copying an existing sheet, try to use the sheet name + # If we are not copying a sheet, and have no name, use the name "SheetX" where X is the number of the new sheet + if (-not $WorksheetName -and $CopySource -and -not $ExcelWorkbook[$CopySource.Name]) {$WorksheetName = $CopySource.Name} + elseif (-not $WorksheetName) {$WorksheetName = "Sheet" + (1 + $ExcelWorkbook.Worksheets.Count)} + else {$ws = $ExcelWorkbook.Worksheets[$WorksheetName]} + + #If -clearsheet was specified and the named sheet exists, delete it + if ($ws -and $ClearSheet) { $ExcelWorkbook.Worksheets.Delete($WorksheetName) ; $ws = $null } + + #Copy or create new sheet as needed + if (-not $ws -and $CopySource) { + Write-Verbose -Message "Copying into worksheet '$WorksheetName'." + $ws = $ExcelWorkbook.Worksheets.Add($WorksheetName, $CopySource) + } + elseif (-not $ws) { + $ws = $ExcelWorkbook.Worksheets.Add($WorksheetName) + Write-Verbose -Message "Adding worksheet '$WorksheetName'." + } + else {Write-Verbose -Message "Worksheet '$WorksheetName' already existed."} + #region Move sheet if needed + if ($MoveToStart) {$ExcelWorkbook.Worksheets.MoveToStart($WorksheetName) } + elseif ($MoveToEnd ) {$ExcelWorkbook.Worksheets.MoveToEnd($WorksheetName) } + elseif ($MoveBefore ) { + if ($ExcelWorkbook.Worksheets[$MoveBefore]) { + if ($MoveBefore -is [int]) { + $ExcelWorkbook.Worksheets.MoveBefore($ws.Index, $MoveBefore) + } + else {$ExcelWorkbook.Worksheets.MoveBefore($WorksheetName, $MoveBefore)} + } + else {Write-Warning "Can't find worksheet '$MoveBefore'; worksheet '$WorksheetName' will not be moved."} + } + elseif ($MoveAfter ) { + if ($MoveAfter -eq "*") { + if ($WorksheetName -lt $ExcelWorkbook.Worksheets[1].Name) {$ExcelWorkbook.Worksheets.MoveToStart($WorksheetName)} + else { + $i = 1 + While ($i -lt $ExcelWorkbook.Worksheets.Count -and ($ExcelWorkbook.Worksheets[$i + 1].Name -le $WorksheetName) ) { $i++} + $ExcelWorkbook.Worksheets.MoveAfter($ws.Index, $i) + } + } + elseif ($ExcelWorkbook.Worksheets[$MoveAfter]) { + if ($MoveAfter -is [int]) { + $ExcelWorkbook.Worksheets.MoveAfter($ws.Index, $MoveAfter) + } + else { + $ExcelWorkbook.Worksheets.MoveAfter($WorksheetName, $MoveAfter) + } + } + else {Write-Warning "Can't find worksheet '$MoveAfter'; worksheet '$WorksheetName' will not be moved."} + } + #endregion + if ($Activate) {Select-Worksheet -ExcelWorksheet $ws } + if ($ExcelPackage -and -not (Get-Member -InputObject $ExcelPackage -Name $ws.Name)) { + $sb = [scriptblock]::Create(('$this.workbook.Worksheets["{0}"]' -f $ws.name)) + Add-Member -InputObject $ExcelPackage -MemberType ScriptProperty -Name $ws.name -Value $sb + } + return $ws +} diff --git a/Public/Close-ExcelPackage.ps1 b/Public/Close-ExcelPackage.ps1 new file mode 100644 index 00000000..ee64bc05 --- /dev/null +++ b/Public/Close-ExcelPackage.ps1 @@ -0,0 +1,38 @@ +function Close-ExcelPackage { + [CmdLetBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + param ( + [parameter(Mandatory = $true, ValueFromPipeline = $true)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Switch]$Show, + [Switch]$NoSave, + $SaveAs, + [ValidateNotNullOrEmpty()] + [String]$Password, + [Switch]$Calculate, + [Switch]$ReZip + ) + + if ( $NoSave) { $ExcelPackage.Dispose() } + else { + if ($Calculate) { + try { [OfficeOpenXml.CalculationExtension]::Calculate($ExcelPackage.Workbook) } + catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook." } + } + if ($SaveAs) { + $SaveAs = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($SaveAs) + if ($Password) { $ExcelPackage.SaveAs( $SaveAs, $Password ) } + else { $ExcelPackage.SaveAs( $SaveAs) } + } + else { + if ($Password) { $ExcelPackage.Save($Password) } + else { $ExcelPackage.Save() } + $SaveAs = $ExcelPackage.File.FullName + } + if ($ReZip) { + Invoke-ExcelReZipFile -ExcelPackage $ExcelPackage + } + $ExcelPackage.Dispose() + if ($Show) { Start-Process -FilePath $SaveAs } + } +} diff --git a/Public/Compare-Worksheet.ps1 b/Public/Compare-Worksheet.ps1 new file mode 100644 index 00000000..214e0f6b --- /dev/null +++ b/Public/Compare-Worksheet.ps1 @@ -0,0 +1,199 @@ +function Compare-Worksheet { + [CmdletBinding(DefaultParameterSetName)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification="Write host used for sub-warning level message to operator which does not form output")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification="False positives when initializing variable in begin block")] + param( + [parameter(Mandatory=$true,Position=0)] + $Referencefile , + [parameter(Mandatory=$true,Position=1)] + $Differencefile , + $WorksheetName = "Sheet1", + $Property = "*" , + $ExcludeProperty , + [Parameter(ParameterSetName='B', Mandatory)] + [String[]]$Headername, + [Parameter(ParameterSetName='C', Mandatory)] + [switch]$NoHeader, + [int]$Startrow = 1, + $AllDataBackgroundColor, + $BackgroundColor, + $TabColor, + $Key = "Name" , + $FontColor, + [Switch]$Show, + [switch]$GridView, + [Switch]$PassThru, + [Switch]$IncludeEqual, + [Switch]$ExcludeDifferent + ) + + #if the filenames don't resolve, give up now. + try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)} + catch { Write-Warning -Message "Could not Resolve the filenames." ; return } + + #If we have one file , we must have two different worksheet names. If we have two files we can have a single string or two strings. + if ($onefile -and ( ($WorksheetName.count -ne 2) -or $WorksheetName[0] -eq $WorksheetName[1] ) ) { + Write-Warning -Message "If both the Reference and difference file are the same then worksheet name must provide 2 different names" + return + } + if ($WorksheetName.count -eq 2) {$worksheet1 = $WorksheetName[0] ; $worksheet2 = $WorksheetName[1]} + elseif ($WorksheetName -is [string]) {$worksheet1 = $worksheet2 = $WorksheetName} + else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return } + + $params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop } + foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}} + try { + $sheet1 = Import-Excel -Path $Referencefile -WorksheetName $worksheet1 @params + $sheet2 = Import-Excel -Path $Differencefile -WorksheetName $worksheet2 @Params + } + catch {Write-Warning -Message "Could not read the worksheet from $Referencefile and/or $Differencefile." ; return } + + #Get Column headings and create a hash table of Name to column letter. + $headings = $Sheet1[-1].psobject.Properties.name # This preserves the sequence - using Get-member would sort them alphabetically! + $headings | ForEach-Object -Begin {$columns = @{} ; $i= 1 } -Process {$Columns[$_] = [OfficeOpenXml.ExcelAddress]::GetAddress(1,($i ++)) -replace "\d","" } + + #Make a list of property headings using the Property (default "*") and ExcludeProperty parameters + if ($Key -eq "Name" -and $NoHeader) {$Key = "p1"} + $propList = @() + foreach ($p in $Property) {$propList += ($headings.where({$_ -like $p}) )} + foreach ($p in $ExcludeProperty) {$propList = $propList.where({$_ -notlike $p}) } + if (($headings -contains $Key) -and ($propList -notcontains $Key)) {$propList += $Key} + $propList = $propList | Select-Object -Unique + if ($propList.Count -eq 0) {Write-Warning -Message "No Columns are selected with -Property = '$Property' and -excludeProperty = '$ExcludeProperty'." ; return} + + #Add RowNumber, Sheetname and file name to every row + $firstDataRow = $startRow + 1 + if ($Headername -or $NoHeader) {$firstDataRow -- } + $i = $firstDataRow ; foreach ($row in $Sheet1) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++) + Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet1 + Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Referencefile} + $i = $firstDataRow ; foreach ($row in $Sheet2) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++) + Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet2 + Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Differencefile} + + if ($ExcludeDifferent -and -not $IncludeEqual) {$IncludeEqual = $true} + #Do the comparison and add file,sheet and row to the result - these are prefixed with "_" to show they are added the addition will fail if the sheet has these properties so split the operations + [PSCustomObject[]]$diff = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual:$IncludeEqual -ExcludeDifferent:$ExcludeDifferent | + Sort-Object -Property "_Row","File" + + #if BackgroundColor was specified, set it on extra or extra or changed rows + if ($diff -and $BackgroundColor) { + #Differences may only exist in one file. So gather the changes for each file; open the file, update each impacted row in the shee, save the file + $updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property "_File" + foreach ($file in $updates) { + try {$xl = Open-ExcelPackage -Path $file.name } + catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return} + if ($PSBoundParameters.ContainsKey("AllDataBackgroundColor")) { + $file.Group._sheet | Sort-Object -Unique | ForEach-Object { + $ws = $xl.Workbook.Worksheets[$_] + if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address} + else {$range = "A" + ($startrow + 1) + ":" + $ws.dimension.end.address} + Set-ExcelRange -Worksheet $ws -BackgroundColor $AllDataBackgroundColor -Range $Range + } + } + foreach ($row in $file.group) { + $ws = $xl.Workbook.Worksheets[$row._Sheet] + $range = $ws.Dimension -replace "\d+",$row._row + Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $BackgroundColor + } + if ($PSBoundParameters.ContainsKey("TabColor")) { + if ($TabColor -is [string]) {$TabColor = [System.Drawing.Color]::$TabColor } + foreach ($tab in ($file.group._sheet | Select-Object -Unique)) { + $xl.Workbook.Worksheets[$tab].TabColor = $TabColor + } + } + $xl.save() ; $xl.Stream.Close() ; $xl.Dispose() + } + } + #if font color was specified, set it on changed properties where the same key appears in both sheets. + if ($diff -and $FontColor -and (($propList -contains $Key) -or ($Key -is [hashtable])) ) { + $updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | Where-Object {$_.count -eq 2} + if ($updates) { + $XL1 = Open-ExcelPackage -path $Referencefile + if ($oneFile ) {$xl2 = $xl1} + else {$xl2 = Open-ExcelPackage -path $Differencefile } + foreach ($u in $updates) { + foreach ($p in $propList) { + if ($u.group[0]._file -eq $Referencefile) { + $ws1 = $xl1.Workbook.Worksheets[$u.Group[0]._sheet] + $ws2 = $xl2.Workbook.Worksheets[$u.Group[1]._sheet] + } + else { + $ws1 = $xl2.Workbook.Worksheets[$u.Group[0]._sheet] + $ws2 = $xl1.Workbook.Worksheets[$u.Group[1]._sheet] + } + if($u.Group[0].$p -ne $u.Group[1].$p ) { + Set-ExcelRange -Worksheet $ws1 -Range ($Columns[$p] + $u.Group[0]._Row) -FontColor $FontColor + Set-ExcelRange -Worksheet $ws2 -Range ($Columns[$p] + $u.Group[1]._Row) -FontColor $FontColor + } + } + } + $xl1.Save() ; $xl1.Stream.Close() ; $xl1.Dispose() + if (-not $oneFile) {$xl2.Save() ; $xl2.Stream.Close() ; $xl2.Dispose()} + } + } + elseif ($diff -and $FontColor) {Write-Warning -Message "To match rows to set changed cells, you must specify -Key and it must match one of the included properties." } + + #if nothing was found write a message which will not be redirected + if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$worksheet2 returned no results." } + + if ($Show) { + Start-Process -FilePath $Referencefile + if (-not $oneFile) { Start-Process -FilePath $Differencefile } + if ($GridView) { Write-Warning -Message "-GridView is ignored when -Show is specified" } + } + elseif ($GridView -and $propList -contains $Key) { + + + if ($IncludeEqual -and -not $ExcludeDifferent) { + $GroupedRows = $diff | Group-Object -Property $Key + } + else { #to get the right now numbers on the grid we need to have all the rows. + $GroupedRows = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual | + Group-Object -Property $Key + } + #Additions, deletions and unchanged rows will give a group of 1; changes will give a group of 2 . + + #If one sheet has extra rows we can get a single "==" result from compare, but with the row from the reference sheet + #but the row in the other sheet might so we will look up the row number from the key field build a hash table for that + $Sheet2 | ForEach-Object -Begin {$rowHash = @{} } -Process {$rowHash[$_.$Key] = $_._row } + + $ExpandedDiff = ForEach ($g in $GroupedRows) { + #we're going to create a custom object from a hash table. We want the fields to be ordered + $hash = [ordered]@{} + foreach ($result IN $g.Group) { + # if result indicates equal or "in Reference" set the reference side row. If we did that on a previous result keep it. Otherwise set to "blank" + if ($result.sideindicator -ne "=>") {$hash["Row"] = $rowHash[$g.Name] + #position the key as the next field (only appears once) + $Hash[$Key] = $g.Name + #For all the other fields we care about create <=FieldName and/or =>FieldName + foreach ($p in $propList.Where({$_ -ne $Key})) { + if ($result.SideIndicator -eq "==") {$hash[("=>$P")] = $hash[("<=$P")] =$result.$P} + else {$hash[($result.SideIndicator+$P)] =$result.$P} + } + } + [Pscustomobject]$hash + } + + #Sort by reference row number, and fill in any blanks in the difference-row column + $ExpandedDiff = $ExpandedDiff | Sort-Object -Property "row") {$ExpandedDiff[$i].">row" = $ExpandedDiff[$i-1].">row" } } + #Sort by difference row number, and fill in any blanks in the reference-row column + $ExpandedDiff = $ExpandedDiff | Sort-Object -Property ">row" + for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i]."row" } + elseif ( $IncludeEqual) {$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "row" } + else {$ExpandedDiff = $ExpandedDiff.where({$_.side -ne "=="}) | Sort-Object -Property "row" } + $ExpandedDiff | Update-FirstObjectProperties | Out-GridView -Title "Comparing $Referencefile::$worksheet1 (<=) with $Differencefile::$worksheet2 (=>)" + } + elseif ($GridView ) {Write-Warning -Message "To use -GridView you must specify -Key and it must match one of the included properties." } + elseif (-not $PassThru) {return ($diff | Select-Object -Property (@(@{n="_Side";e={$_.SideIndicator}},"_File" ,"_Sheet","_Row") + $propList))} + if ( $PassThru) {return $diff } +} diff --git a/Public/Convert-ExcelRangeToImage.ps1 b/Public/Convert-ExcelRangeToImage.ps1 new file mode 100644 index 00000000..71be2512 --- /dev/null +++ b/Public/Convert-ExcelRangeToImage.ps1 @@ -0,0 +1,58 @@ +function Convert-ExcelRangeToImage { + [alias("Convert-XlRangeToImage")] + param ( + [parameter(Mandatory=$true)] + $Path, + $WorksheetName = "Sheet1" , + [parameter(Mandatory=$true)] + $Range, + $Destination = "$pwd\temp.png", + [switch]$Show + ) + $extension = $Destination -replace '^.*\.(\w+)$' ,'$1' + if ($extension -in @('JPEG','BMP','PNG')) { + $Format = [system.Drawing.Imaging.ImageFormat]$extension + } #if we don't recognise the extension OR if it is JPG with an E, use JPEG format + else { $Format = [system.Drawing.Imaging.ImageFormat]::Jpeg} + Write-Progress -Activity "Exporting $Range of $WorksheetName in $Path" -Status "Starting Excel" + $xlApp = New-Object -ComObject "Excel.Application" + Write-Progress -Activity "Exporting $Range of $WorksheetName in $Path" -Status "Opening Workbook and copying data" + $xlWbk = $xlApp.Workbooks.Open($Path) + $xlWbk.Worksheets($WorksheetName).Select() + $null = $xlWbk.ActiveSheet.Range($Range).Select() + $null = $xlApp.Selection.Copy() + Write-Progress -Activity "Exporting $Range of $WorksheetName in $Path" -Status "Saving copied data" + # Get-Clipboard came in with PS5. Older versions can use [System.Windows.Clipboard] but it is ugly. + $image = Get-Clipboard -Format Image + $image.Save($Destination, $Format) + Write-Progress -Activity "Exporting $Range of $WorksheetName in $Path" -Status "Closing Excel" + $null = $xlWbk.ActiveSheet.Range("a1").Select() + $null = $xlApp.Selection.Copy() + $xlApp.Quit() + Write-Progress -Activity "Exporting $Range of $WorksheetName in $Path" -Completed + if ($Show) {Start-Process -FilePath $Destination} + else {Get-Item -Path $Destination} +} +<# +del demo*.xlsx + +$worksheetName = 'Processes' +$Path = "$pwd\demo.xlsx" +$myData = Get-Process | Select-Object -Property Name,WS,CPU,Description,company,startTime + +$excelPackage = $myData | Export-Excel -KillExcel -Path $Path -WorksheetName $worksheetName -ClearSheet -AutoSize -AutoFilter -BoldTopRow -FreezeTopRow -PassThru +$worksheet = $excelPackage.Workbook.Worksheets[$worksheetName] +$range = $worksheet.Dimension.Address +Set-ExcelRange -Worksheet $worksheet -Range "b:b" -NumberFormat "#,###" -AutoFit +Set-ExcelRange -Worksheet $worksheet -Range "C:C" -NumberFormat "#,##0.00" -AutoFit +Set-ExcelRange -Worksheet $worksheet -Range "F:F" -NumberFormat "dd MMMM HH:mm:ss" -AutoFit +Add-ConditionalFormatting -Worksheet $worksheet -Range "c2:c1000" -DataBarColor Blue +Add-ConditionalFormatting -Worksheet $worksheet -Range "b2:B1000" -RuleType GreaterThan -ConditionValue '104857600' -ForeGroundColor "Red" -Bold + +Export-Excel -ExcelPackage $excelPackage -WorksheetName $worksheetName + +Convert-ExcelRangeToImage -Path $Path -WorksheetName $worksheetName -range $range -destination "$pwd\temp.png" -show +#> + + +#Convert-ExcelRangeToImage -Path $Path -WorksheetName $worksheetName -range $range -destination "$pwd\temp.png" -show \ No newline at end of file diff --git a/Public/ConvertFrom-ExcelData.ps1 b/Public/ConvertFrom-ExcelData.ps1 new file mode 100644 index 00000000..3014434e --- /dev/null +++ b/Public/ConvertFrom-ExcelData.ps1 @@ -0,0 +1,30 @@ +function ConvertFrom-ExcelData { + [alias("Use-ExcelData")] + param( + [Alias("FullName")] + [Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true)] + [ValidateScript( { Test-Path $_ -PathType Leaf })] + $Path, + [ScriptBlock]$ScriptBlock, + [Alias("Sheet")] + $WorksheetName = 1, + [Alias('HeaderRow', 'TopRow')] + [int]$StartRow = 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 + } +} \ No newline at end of file diff --git a/Public/ConvertFrom-ExcelSheet.ps1 b/Public/ConvertFrom-ExcelSheet.ps1 new file mode 100644 index 00000000..afa1061b --- /dev/null +++ b/Public/ConvertFrom-ExcelSheet.ps1 @@ -0,0 +1,43 @@ +function ConvertFrom-ExcelSheet { + [CmdletBinding()] + [Alias("Export-ExcelSheet")] + param ( + [Parameter(Mandatory = $true)] + [String]$Path, + [String]$OutputPath = '.\', + [String]$SheetName = "*", + [ValidateSet('ASCII', 'BigEndianUniCode','Default','OEM','UniCode','UTF32','UTF7','UTF8')] + [string]$Encoding = 'UTF8', + [ValidateSet('.txt', '.log','.csv')] + [string]$Extension = '.csv', + [ValidateSet(';', ',')] + [string]$Delimiter , + $Property = "*", + $ExcludeProperty = @(), + [switch]$Append, + [string[]]$AsText = @(), + [string[]]$AsDate = @() + ) + + $Path = (Resolve-Path $Path).ProviderPath + $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path + $workbook = $xl.Workbook + + $targetSheets = $workbook.Worksheets | Where-Object {$_.Name -Like $SheetName} + + $csvParams = @{NoTypeInformation = $true} + $PSBoundParameters + foreach ($p in 'OutputPath', 'SheetName', 'Extension', 'Property','ExcludeProperty', 'AsText','AsDate') { + $csvParams.Remove($p) + } + + Foreach ($sheet in $targetSheets) { + Write-Verbose "Exporting sheet: $($sheet.Name)" + + $csvParams.Path = "$OutputPath\$($Sheet.Name)$Extension" + + Import-Excel -ExcelPackage $xl -Sheet $($sheet.Name) -AsText:$AsText -AsDate:$AsDate | + Select-Object -Property $Property | Export-Csv @csvparams + } + + $xl.Dispose() +} diff --git a/Public/ConvertFrom-ExcelToSQLInsert.ps1 b/Public/ConvertFrom-ExcelToSQLInsert.ps1 new file mode 100644 index 00000000..858544eb --- /dev/null +++ b/Public/ConvertFrom-ExcelToSQLInsert.ps1 @@ -0,0 +1,56 @@ +function ConvertFrom-ExcelToSQLInsert { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + $TableName, + [Alias("FullName")] + [Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true)] + [ValidateScript( { Test-Path $_ -PathType Leaf })] + $Path, + [Alias("Sheet")] + $WorksheetName = 1, + [Alias('HeaderRow', 'TopRow')] + [ValidateRange(1, 9999)] + [Int]$StartRow, + [string[]]$Header, + [switch]$NoHeader, + [switch]$DataOnly, + [switch]$ConvertEmptyStringsToNull, + [switch]$UseMsSqlSyntax, + [Parameter(Mandatory = $false)] + $SingleQuoteStyle + ) + + $null = $PSBoundParameters.Remove('TableName') + $null = $PSBoundParameters.Remove('ConvertEmptyStringsToNull') + $null = $PSBoundParameters.Remove('UseMsSqlSyntax') + $null = $PSBoundParameters.Remove('SingleQuoteStyle') + + $params = @{} + $PSBoundParameters + + ConvertFrom-ExcelData @params { + param($propertyNames, $record) + + $ColumnNames = "'" + ($PropertyNames -join "', '") + "'" + if($UseMsSqlSyntax) { + $ColumnNames = "[" + ($PropertyNames -join "], [") + "]" + } + + $values = foreach ($propertyName in $PropertyNames) { + if ($ConvertEmptyStringsToNull.IsPresent -and [string]::IsNullOrEmpty($record.$propertyName)) { + 'NULL' + } + else { + if ( $SingleQuoteStyle ) { + "'" + $record.$propertyName.ToString().Replace("'",${SingleQuoteStyle}) + "'" + } + else { + "'" + $record.$propertyName + "'" + } + } + } + $targetValues = ($values -join ", ") + + "INSERT INTO {0} ({1}) Values({2});" -f $TableName, $ColumnNames, $targetValues + } +} diff --git a/Public/ConvertTo-ExcelXlsx.ps1 b/Public/ConvertTo-ExcelXlsx.ps1 new file mode 100644 index 00000000..578445e0 --- /dev/null +++ b/Public/ConvertTo-ExcelXlsx.ps1 @@ -0,0 +1,62 @@ +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." + } + + try { + $Excel.Visible = $false + $null = $Excel.Workbooks.Open($xlsFile.FullName, $null, $true) + $Excel.ActiveWorkbook.SaveAs($xlsxPath, $xlFixedFormat) + } + finally { + if ($null -ne $Excel.ActiveWorkbook) { + $Excel.ActiveWorkbook.Close() + } + + $Excel.Quit() + } + } +} + diff --git a/Public/Copy-ExcelWorksheet.ps1 b/Public/Copy-ExcelWorksheet.ps1 new file mode 100644 index 00000000..91634985 --- /dev/null +++ b/Public/Copy-ExcelWorksheet.ps1 @@ -0,0 +1,95 @@ +function Copy-ExcelWorksheet { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true,ValueFromPipeline=$true)] + [Alias('SourceWorkbook')] + $SourceObject, + $SourceWorksheet = 1 , + [Parameter(Mandatory = $true)] + $DestinationWorkbook, + $DestinationWorksheet, + [Switch]$Show + ) + begin { + #For the case where we are piped multiple sheets, we want to open the destination in the begin and close it in the end. + if ($DestinationWorkbook -is [OfficeOpenXml.ExcelPackage] ) { + if ($Show) {$package2 = $DestinationWorkbook} + $DestinationWorkbook = $DestinationWorkbook.Workbook + } + elseif ($DestinationWorkbook -is [string] -and ($DestinationWorkbook -ne $SourceObject)) { + $package2 = Open-ExcelPackage -Create -Path $DestinationWorkbook + $DestinationWorkbook = $package2.Workbook + } + } + process { + #Special case - given the same path for source and destination worksheet + if ($SourceObject -is [System.String] -and $SourceObject -eq $DestinationWorkbook) { + if (-not $DestinationWorksheet) {Write-Warning -Message "You must specify a destination worksheet name if copying within the same workbook."; return} + else { + Write-Verbose -Message "Copying " + $excel = Open-ExcelPackage -Path $SourceObject + if (-not $excel.Workbook.Worksheets[$Sourceworksheet]) { + Write-Warning -Message "Could not find Worksheet $sourceWorksheet in $SourceObject" + Close-ExcelPackage -ExcelPackage $excel -NoSave + return + } + elseif ($excel.Workbook.Worksheets[$Sourceworksheet].name -eq $DestinationWorksheet) { + Write-Warning -Message "The destination worksheet name is the same as the source. " + Close-ExcelPackage -ExcelPackage $excel -NoSave + return + } + else { + $null = Add-Worksheet -ExcelPackage $excel -WorksheetName $DestinationWorksheet -CopySource ($excel.Workbook.Worksheets[$SourceWorksheet]) + Close-ExcelPackage -ExcelPackage $excel -Show:$Show + return + } + } + } + else { + if ($SourceObject -is [OfficeOpenXml.ExcelWorksheet]) {$sourceWs = $SourceObject} + elseif ($SourceObject -is [OfficeOpenXml.ExcelWorkbook]) {$sourceWs = $SourceObject.Worksheets[$SourceWorksheet]} + elseif ($SourceObject -is [OfficeOpenXml.ExcelPackage] ) {$sourceWs = $SourceObject.Workbook.Worksheets[$SourceWorksheet]} + else { + $SourceObject = (Resolve-Path $SourceObject).ProviderPath + try { + Write-Verbose "Opening worksheet '$WorksheetName' in Excel workbook '$SourceObject'." + $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $SourceObject, 'Open', 'Read' , 'ReadWrite' + $package1 = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream + $sourceWs = $Package1.Workbook.Worksheets[$SourceWorksheet] + } + catch {Write-Warning -Message "Could not open $SourceObject - the error was '$($_.exception.message)' " ; return} + } + if (-not $sourceWs) {Write-Warning -Message "Could not find worksheet '$Sourceworksheet' in the source workbook." ; return} + else { + try { + if ($DestinationWorkbook -isnot [OfficeOpenXml.ExcelWorkbook]) { + Write-Warning "Not a valid workbook" ; return + } + #check if we have a destination sheet name and set one if not. Because we might loop round check $psBoundParameters, not the variable. + if (-not $PSBoundParameters['DestinationWorksheet']) { + #if we are piped files, use the file name without the extension as the destination sheet name, Otherwise use the source sheet name + if ($_ -is [System.IO.FileInfo]) {$DestinationWorksheet = $_.name -replace '\.xlsx$', '' } + else { $DestinationWorksheet = $sourceWs.Name} + } + if ($DestinationWorkbook.Worksheets[$DestinationWorksheet]) { + Write-Verbose "Destination workbook already has a sheet named '$DestinationWorksheet', deleting it." + $DestinationWorkbook.Worksheets.Delete($DestinationWorksheet) + } + Write-Verbose "Copying '$($sourcews.name)' from $($SourceObject) to '$($DestinationWorksheet)' in $($PSBoundParameters['DestinationWorkbook'])" + $null = Add-Worksheet -ExcelWorkbook $DestinationWorkbook -WorksheetName $DestinationWorksheet -CopySource $sourceWs + #Leave the destination open but close the source - if we're copying more than one sheet we'll re-open it and live with the inefficiency + if ($stream) {$stream.Close() } + if ($package1) {Close-ExcelPackage -ExcelPackage $package1 -NoSave } + } + catch {Write-Warning -Message "Could not write to sheet '$DestinationWorksheet' in the destination workbook. Error was '$($_.exception.message)'" ; return} + } + } + } + end { + #OK Now we can close the destination package + if ($package2) {Close-ExcelPackage -ExcelPackage $package2 -Show:$Show } + if ($Show -and -not $package2) { + Write-Warning -Message "-Show only works if the Destination workbook is given as a file path or an ExcelPackage object." + } + } +} \ No newline at end of file diff --git a/Public/Enable-ExcelAutoFilter.ps1 b/Public/Enable-ExcelAutoFilter.ps1 new file mode 100644 index 00000000..0c4a3d58 --- /dev/null +++ b/Public/Enable-ExcelAutoFilter.ps1 @@ -0,0 +1,16 @@ +function Enable-ExcelAutoFilter { + <# + .SYNOPSIS + Enable the Excel AutoFilter + + .EXAMPLE + Enable-ExcelAutoFilter $targetSheet + #> + param( + [Parameter(Mandatory)] + [OfficeOpenXml.ExcelWorksheet]$Worksheet + ) + + $range = Get-ExcelSheetDimensionAddress $Worksheet + $Worksheet.Cells[$range].AutoFilter = $true +} \ No newline at end of file diff --git a/Public/Enable-ExcelAutofit.ps1 b/Public/Enable-ExcelAutofit.ps1 new file mode 100644 index 00000000..0d117d4a --- /dev/null +++ b/Public/Enable-ExcelAutofit.ps1 @@ -0,0 +1,16 @@ +function Enable-ExcelAutofit { + <# + .SYNOPSIS + Make all text fit the cells + + .EXAMPLE + Enable-ExcelAutofit $excel.Sheet1 + #> + param( + [Parameter(Mandatory)] + [OfficeOpenXml.ExcelWorksheet]$Worksheet + ) + + $range = Get-ExcelSheetDimensionAddress $Worksheet + $Worksheet.Cells[$range].AutoFitColumns() +} \ No newline at end of file diff --git a/Public/Expand-NumberFormat.ps1 b/Public/Expand-NumberFormat.ps1 new file mode 100644 index 00000000..650a1b67 --- /dev/null +++ b/Public/Expand-NumberFormat.ps1 @@ -0,0 +1,48 @@ +function Expand-NumberFormat { + [CmdletBinding()] + [OutputType([String])] + param ( + #the format string to Expand + $NumberFormat + ) + switch ($NumberFormat) { + "Currency" { + #https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.currencynegativepattern(v=vs.110).aspx + $sign = [cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol + switch ([cultureinfo]::CurrentCulture.NumberFormat.CurrencyPositivePattern) { + 0 {$pos = "$Sign#,##0.00" ; break } + 1 {$pos = "#,##0.00$Sign" ; break } + 2 {$pos = "$Sign #,##0.00" ; break } + 3 {$pos = "#,##0.00 $Sign" ; break } + } + switch ([cultureinfo]::CurrentCulture.NumberFormat.CurrencyPositivePattern) { + 0 {return "$pos;($Sign#,##0.00)" } + 1 {return "$pos;-$Sign#,##0.00" } + 2 {return "$pos;$Sign-#,##0.00" } + 3 {return "$pos;$Sign#,##0.00-" } + 4 {return "$pos;(#,##0.00$Sign)" } + 5 {return "$pos;-#,##0.00$Sign" } + 6 {return "$pos;#,##0.00-$Sign" } + 7 {return "$pos;#,##0.00$Sign-" } + 8 {return "$pos;-#,##0.00 $Sign" } + 9 {return "$pos;-$Sign #,##0.00" } + 10 {return "$pos;#,##0.00 $Sign-" } + 11 {return "$pos;$Sign #,##0.00-" } + 12 {return "$pos;$Sign -#,##0.00" } + 13 {return "$pos;#,##0.00- $Sign" } + 14 {return "$pos;($Sign #,##0.00)" } + 15 {return "$pos;(#,##0.00 $Sign)" } + } + } + "Number" {return "0.00" } # format id 2 + "Percentage" {return "0.00%" } # format id 10 + "Scientific" {return "0.00E+00" } # format id 11 + "Fraction" {return "# ?/?" } # format id 12 + "Short Date" {return "mm-dd-yy" } # format id 14 localized on load by Excel. + "Short Time" {return "h:mm" } # format id 20 localized on load by Excel. + "Long Time" {return "h:mm:ss" } # format id 21 localized on load by Excel. + "Date-Time" {return "m/d/yy h:mm"} # format id 22 localized on load by Excel. + "Text" {return "@" } # format ID 49 + Default {return $NumberFormat} + } +} diff --git a/Public/Export-Excel.ps1 b/Public/Export-Excel.ps1 new file mode 100644 index 00000000..5c08b208 --- /dev/null +++ b/Public/Export-Excel.ps1 @@ -0,0 +1,697 @@ +function Export-Excel { + [CmdletBinding(DefaultParameterSetName = 'Default')] + [OutputType([OfficeOpenXml.ExcelPackage])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + param( + [Parameter(ParameterSetName = 'Default', Position = 0)] + [String]$Path, + [Parameter(Mandatory = $true, ParameterSetName = "Package")] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Parameter(ValueFromPipeline = $true)] + [Alias('TargetData')] + $InputObject, + [Switch]$Calculate, + [Switch]$Show, + [String]$WorksheetName = 'Sheet1', + [Alias("PW")] + [String]$Password, + [switch]$ClearSheet, + [switch]$Append, + [String]$Title, + [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'Solid', + [Switch]$TitleBold, + [Int]$TitleSize = 22, + $TitleBackgroundColor, + [parameter(DontShow = $true)] + [Switch]$IncludePivotTable, + [String]$PivotTableName, + [String[]]$PivotRows, + [String[]]$PivotColumns, + $PivotData, + [String[]]$PivotFilter, + [Switch]$PivotDataToColumn, + [Hashtable]$PivotTableDefinition, + [Switch]$IncludePivotChart, + [Alias('ChartType')] + [OfficeOpenXml.Drawing.Chart.eChartType]$PivotChartType = 'Pie', + [Switch]$NoLegend, + [Switch]$ShowCategory, + [Switch]$ShowPercent, + [Switch]$AutoSize, + $MaxAutoSizeRows = 1000, + [Switch]$NoClobber, + [Switch]$FreezeTopRow, + [Switch]$FreezeFirstColumn, + [Switch]$FreezeTopRowFirstColumn, + [Int[]]$FreezePane, + [Switch]$AutoFilter, + [Switch]$BoldTopRow, + [Switch]$NoHeader, + [ValidateScript( { + if (-not $_) { throw 'RangeName is null or empty.' } + elseif ($_[0] -notmatch '[a-z]') { throw 'RangeName starts with an invalid character.' } + else { $true } + })] + [String]$RangeName, + [Alias('Table')] + $TableName, + [OfficeOpenXml.Table.TableStyles]$TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium6, + [HashTable]$TableTotalSettings, + [Switch]$BarChart, + [Switch]$PieChart, + [Switch]$LineChart , + [Switch]$ColumnChart , + [Object[]]$ExcelChartDefinition, + [String[]]$HideSheet, + [String[]]$UnHideSheet, + [Switch]$MoveToStart, + [Switch]$MoveToEnd, + $MoveBefore , + $MoveAfter , + [Switch]$KillExcel, + [Switch]$AutoNameRange, + [Int]$StartRow = 1, + [Int]$StartColumn = 1, + [alias('PT')] + [Switch]$PassThru, + [String]$Numberformat = 'General', + [string[]]$ExcludeProperty, + [Switch]$NoAliasOrScriptPropeties, + [Switch]$DisplayPropertySet, + [String[]]$NoNumberConversion, + [String[]]$NoHyperLinkConversion, + [Object[]]$ConditionalFormat, + [Object[]]$ConditionalText, + [Object[]]$Style, + [ScriptBlock]$CellStyleSB, + #If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified + [switch]$Activate, + [Parameter(ParameterSetName = 'Default')] + [Switch]$Now, + [Switch]$ReturnRange, + #By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + [ValidateSet("Both", "Columns", "Rows", "None")] + [String]$PivotTotals = "Both", + #Included for compatibility - equivalent to -PivotTotals "None" + [Switch]$NoTotalsInPivot, + [Switch]$ReZip + ) + + begin { + $numberRegex = [Regex]'\d' + $isDataTypeValueType = $false + if ($NoClobber) { Write-Warning -Message "-NoClobber parameter is no longer used" } + #Open the file, get the worksheet, and decide where in the sheet we are writing, and if there is a number format to apply. + try { + $script:Header = $null + if ($Append -and $ClearSheet) { throw "You can't use -Append AND -ClearSheet." ; return } + #To force -Now not to format as a table, allow $false in -TableName to be "No table" + $TableName = if ($null -eq $TableName -or ($TableName -is [bool] -and $false -eq $TableName)) { $null } else { [String]$TableName } + if ($Now -or (-not $Path -and -not $ExcelPackage) ) { + if (-not $PSBoundParameters.ContainsKey("Path")) { $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' } + if (-not $PSBoundParameters.ContainsKey("Show")) { $Show = $true } + if (-not $PSBoundParameters.ContainsKey("AutoSize")) { $AutoSize = $true } + #"Now" option will create a table, unless something passed in TableName/Table Style. False in TableName will block autocreation + if (-not $PSBoundParameters.ContainsKey("TableName") -and + -not $PSBoundParameters.ContainsKey("TableStyle") -and + -not $AutoFilter) { + $TableName = '' # later rely on distinction between NULL and "" + } + } + if ($ExcelPackage) { + $pkg = $ExcelPackage + $Path = $pkg.File + } + Else { $pkg = Open-ExcelPackage -Path $Path -Create -KillExcel:$KillExcel -Password:$Password } + } + catch { throw "Could not open Excel Package $path" } + try { + $params = @{WorksheetName = $WorksheetName } + foreach ($p in @("ClearSheet", "MoveToStart", "MoveToEnd", "MoveBefore", "MoveAfter", "Activate")) { if ($PSBoundParameters[$p]) { $params[$p] = $PSBoundParameters[$p] } } + $ws = $pkg | Add-Worksheet @params + if ($ws.Name -ne $WorksheetName) { + Write-Warning -Message "The Worksheet name has been changed from $WorksheetName to $($ws.Name), this may cause errors later." + $WorksheetName = $ws.Name + } + } + catch { throw "Could not get worksheet $WorksheetName" } + try { + if ($Append -and $ws.Dimension) { + #if there is a title or anything else above the header row, append needs to be combined wih a suitable startrow parameter + $headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow + #using a slightly odd syntax otherwise header ends up as a 2D array + $ws.Cells[$headerRange].Value | ForEach-Object -Begin { $Script:header = @() } -Process { $Script:header += $_ } + $NoHeader = $true + #if we did not get AutoNameRange, but headers have ranges of the same name make autoNameRange True, otherwise make it false + if (-not $AutoNameRange) { + $AutoNameRange = $true ; foreach ($h in $header) { if ($ws.names.name -notcontains $h) { $AutoNameRange = $false } } + } + #if we did not get a Rangename but there is a Range which covers the active part of the sheet, set Rangename to that. + if (-not $RangeName -and $ws.names.where({ $_.name[0] -match '[a-z]' })) { + $theRange = $ws.names.where({ + ($_.Name[0] -match '[a-z]' ) -and + ($_.Start.Row -eq $StartRow) -and + ($_.Start.Column -eq $StartColumn) -and + ($_.End.Row -eq $ws.Dimension.End.Row) -and + ($_.End.Column -eq $ws.Dimension.End.column) } , 'First', 1) + if ($theRange) { $rangename = $theRange.name } + } + + #if we did not get a table name but there is a table which covers the active part of the sheet, set table name to that, and don't do anything with autofilter + $existingTable = $ws.Tables.Where({ $_.address.address -eq $ws.dimension.address }, 'First', 1) + if ($null -eq $TableName -and $existingTable) { + $TableName = $existingTable.Name + $TableStyle = $existingTable.StyleName -replace "^TableStyle", "" + $AutoFilter = $false + } + #if we did not get $autofilter but a filter range is set and it covers the right area, set autofilter to true + elseif (-not $AutoFilter -and $ws.Names['_xlnm._FilterDatabase']) { + if ( ($ws.Names['_xlnm._FilterDatabase'].Start.Row -eq $StartRow) -and + ($ws.Names['_xlnm._FilterDatabase'].Start.Column -eq $StartColumn) -and + ($ws.Names['_xlnm._FilterDatabase'].End.Row -eq $ws.Dimension.End.Row) -and + ($ws.Names['_xlnm._FilterDatabase'].End.Column -eq $ws.Dimension.End.Column) ) { $AutoFilter = $true } + } + + $row = $ws.Dimension.End.Row + Write-Debug -Message ("Appending: headers are " + ($script:Header -join ", ") + " Start row is $row") + if ($Title) { Write-Warning -Message "-Title Parameter is ignored when appending." } + } + elseif ($Title) { + #Can only add a title if not appending! + $row = $StartRow + $ws.Cells[$row, $StartColumn].Value = $Title + $ws.Cells[$row, $StartColumn].Style.Font.Size = $TitleSize + + if ($PSBoundParameters.ContainsKey("TitleBold")) { + #Set title to Bold face font if -TitleBold was specified. + #Otherwise the default will be unbolded. + $ws.Cells[$row, $StartColumn].Style.Font.Bold = [boolean]$TitleBold + } + if ($TitleBackgroundColor ) { + if ($TitleBackgroundColor -is [string]) { $TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor } + $ws.Cells[$row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern + $ws.Cells[$row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor) + } + $row ++ ; $startRow ++ + } + else { $row = $StartRow } + $ColumnIndex = $StartColumn + $Numberformat = Expand-NumberFormat -NumberFormat $Numberformat + if ((-not $ws.Dimension) -and ($Numberformat -ne $ws.Cells.Style.Numberformat.Format)) { + $ws.Cells.Style.Numberformat.Format = $Numberformat + $setNumformat = $false + } + else { $setNumformat = ($Numberformat -ne $ws.Cells.Style.Numberformat.Format) } + } + catch { throw "Failed preparing to export to worksheet '$WorksheetName' to '$Path': $_" } + #region Special case -inputobject passed a dataTable object + <# If inputObject was passed via the pipeline it won't be visible until the process block, we will only see it here if it was passed as a parameter + if it is a data table don't do foreach on it (slow) - put the whole table in and set dates on date columns, + set things up for the end block, and skip the process block #> + if ($InputObject -is [System.Data.DataTable]) { + if ($Append -and $ws.dimension) { + $row ++ + $null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, $false ) + if ($TableName -or $PSBoundParameters.ContainsKey('TableStyle')) { + Add-ExcelTable -Range $ws.Cells[$ws.Dimension] -TableName $TableName -TableStyle $TableStyle -TableTotalSettings $TableTotalSettings + } + } + else { + #Change TableName if $TableName is non-empty; don't leave caller with a renamed table! + $orginalTableName = $InputObject.TableName + if ($PSBoundParameters.ContainsKey("TableName")) { + $InputObject.TableName = $TableName + } + while ($InputObject.TableName -in $pkg.Workbook.Worksheets.Tables.name) { + Write-Warning "Table name $($InputObject.TableName) is not unique, adding '_' to it " + $InputObject.TableName += "_" + } + #Insert as a table, if Tablestyle didn't arrive as a default, or $TableName non-null - even if empty + if ($null -ne $TableName -or $PSBoundParameters.ContainsKey("TableStyle")) { + $null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, (-not $noHeader), $TableStyle ) + # Workaround for EPPlus not marking the empty row on an empty table as dummy row. + if ($InputObject.Rows.Count -eq 0) { + ($ws.Tables | Select-Object -Last 1).TableXml.table.SetAttribute('insertRow', 1) + } + } + else { + $null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, (-not $noHeader) ) + } + $InputObject.TableName = $orginalTableName + } + foreach ($c in $InputObject.Columns.where({ $_.datatype -eq [datetime] })) { + Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat 'Date-Time' + } + foreach ($c in $InputObject.Columns.where({ $_.datatype -eq [timespan] })) { + Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat '[h]:mm:ss' + } + $ColumnIndex += $InputObject.Columns.Count - 1 + if ($noHeader) { $row += $InputObject.Rows.Count - 1 } + else { $row += $InputObject.Rows.Count } + $null = $PSBoundParameters.Remove('InputObject') + $firstTimeThru = $false + } + #endregion + else { $firstTimeThru = $true } + } + + process { + if ($PSBoundParameters.ContainsKey("InputObject")) { + try { + if ($null -eq $InputObject) { $row += 1 } + foreach ($TargetData in $InputObject) { + if ($firstTimeThru) { + $firstTimeThru = $false + $isDataTypeValueType = ($null -eq $TargetData) -or ($TargetData.GetType().name -match 'string|timespan|datetime|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort|URI|ExcelHyperLink') + if ($isDataTypeValueType ) { + $script:Header = @(".") # dummy value to make sure we go through the "for each name in $header" + if (-not $Append) { $row -= 1 } # By default row will be 1, it is incremented before inserting values (so it ends pointing at final row.); si first data row is 2 - move back up 1 if there is no header . + } + if ($null -ne $TargetData) { Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" } + } + #region Add headers - if we are appending, or we have been through here once already we will have the headers + if (-not $script:Header) { + if ($DisplayPropertySet -and $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) { + $script:Header = $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( { $_ -notin $ExcludeProperty }) + } + else { + if ($NoAliasOrScriptPropeties) { $propType = "Property" } else { $propType = "*" } + $script:Header = $TargetData.PSObject.Properties.where( { $_.MemberType -like $propType }).Name + } + foreach ($exclusion in $ExcludeProperty) { $script:Header = $script:Header -notlike $exclusion } + if ($NoHeader) { + # Don't push the headers to the spreadsheet + $row -= 1 + } + else { + $ColumnIndex = $StartColumn + foreach ($Name in $script:Header) { + $ws.Cells[$row, $ColumnIndex].Value = $Name + Write-Verbose "Cell '$row`:$ColumnIndex' add header '$Name'" + $ColumnIndex += 1 + } + } + } + #endregion + #region Add non header values + $row += 1 + $ColumnIndex = $StartColumn + <# + For each item in the header OR for the Data item if this is a simple Type or data table : + If it is a date insert with one of Excel's built in formats - recognized as "Date and time to be localized" + if it is a timespan insert with a built in format for elapsed hours, minutes and seconds + if its any other numeric insert as is , setting format if need be. + Preserve URI, Insert a data table, convert non string objects to string. + For strings, check for fomula, URI or Number, before inserting as a string (ignore nulls) #> + foreach ($Name in $script:Header) { + if ($isDataTypeValueType) { $v = $TargetData } + else { $v = $TargetData.$Name } + try { + if ($v -is [DateTime]) { + $ws.Cells[$row, $ColumnIndex].Value = $v + $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = 'm/d/yy h:mm' # This is not a custom format, but a preset recognized as date and localized. + } + elseif ($v -is [TimeSpan]) { + $ws.Cells[$row, $ColumnIndex].Value = $v + $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = '[h]:mm:ss' + } + elseif ($v -is [System.ValueType]) { + $ws.Cells[$row, $ColumnIndex].Value = $v + if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat } + } + elseif ($v -is [uri] -and + $NoHyperLinkConversion -ne '*' -and + $NoHyperLinkConversion -notcontains $Name ) { + $ws.Cells[$row, $ColumnIndex].HyperLink = $v + $ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) + $ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true + } + elseif ($v -isnot [String] ) { + #Other objects or null. + if ($null -ne $v) { $ws.Cells[$row, $ColumnIndex].Value = $v.toString() } + } + elseif ($v[0] -eq '=') { + $ws.Cells[$row, $ColumnIndex].Formula = ($v -replace '^=', '') + if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat } + } + elseif ( $NoHyperLinkConversion -ne '*' -and # Put the check for 'NoHyperLinkConversion is null' first to skip checking for wellformedstring + $NoHyperLinkConversion -notcontains $Name -and + [System.Uri]::IsWellFormedUriString($v , [System.UriKind]::Absolute) + ) { + if ($v -match "^xl://internal/") { + $referenceAddress = $v -replace "^xl://internal/" , "" + $display = $referenceAddress -replace "!A1$" , "" + $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display + $ws.Cells[$row, $ColumnIndex].HyperLink = $h + } + else { $ws.Cells[$row, $ColumnIndex].HyperLink = $v } #$ws.Cells[$row, $ColumnIndex].Value = $v.AbsoluteUri + $ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) + $ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true + } + else { + $number = $null + if ( $NoNumberConversion -ne '*' -and # Check if NoNumberConversion isn't specified. Put this first as it's going to stop the if clause. Quicker than putting regex check first + $numberRegex.IsMatch($v) -and # and if it contains digit(s) - this syntax is quicker than -match for many items and cuts out slow checks for non numbers + $NoNumberConversion -notcontains $Name -and + [Double]::TryParse($v, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) + ) { + $ws.Cells[$row, $ColumnIndex].Value = $number + if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat } + } + else { + $ws.Cells[$row, $ColumnIndex].Value = $v + } + } + } + catch { Write-Warning -Message "Could not insert the '$Name' property at Row $row, Column $ColumnIndex" } + $ColumnIndex += 1 + } + $ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false + #endregion + } + } + catch { throw "Failed exporting data to worksheet '$WorksheetName' to '$Path': $_" } + } + } + + end { + if ($firstTimeThru -and $ws.Dimension) { + $LastRow = $ws.Dimension.End.Row + $LastCol = $ws.Dimension.End.Column + $endAddress = $ws.Dimension.End.Address + } + else { + $LastRow = $row + $LastCol = $ColumnIndex + $endAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($LastRow , $LastCol) + } + $startAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($StartRow, $StartColumn) + $dataRange = "{0}:{1}" -f $startAddress, $endAddress + + Write-Debug "Data Range '$dataRange'" + if ($AutoNameRange) { + try { + if (-not $script:header) { + # if there aren't any headers, use the the first row of data to name the ranges: this is the last point that headers will be used. + $headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow + #using a slightly odd syntax otherwise header ends up as a 2D array + $ws.Cells[$headerRange].Value | ForEach-Object -Begin { $Script:header = @() } -Process { $Script:header += $_ } + if ($PSBoundParameters.ContainsKey($TargetData)) { + #if Export was called with data that writes no header start the range at $startRow ($startRow is data) + $targetRow = $StartRow + } + else { $targetRow = $StartRow + 1 } #if Export was called without data to add names (assume $startRow is a header) or... + } # ... called with data that writes a header, then start the range at $startRow + 1 + else { $targetRow = $StartRow + 1 } + + #Dimension.start.row always seems to be one so we work out the target row + #, but start.column is the first populated one and .Columns is the count of populated ones. + # if we have 5 columns from 3 to 8, headers are numbered 0..4, so that is in the for loop and used for getting the name... + # but we have to add the start column on when referencing positions + foreach ($c in 0..($LastCol - $StartColumn)) { + $targetRangeName = @($script:Header)[$c] #Let Add-ExcelName fix (and warn about) bad names + Add-ExcelName -RangeName $targetRangeName -Range $ws.Cells[$targetRow, ($StartColumn + $c ), $LastRow, ($StartColumn + $c )] + try { + #this test can throw with some names, surpress any error + if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) { + Write-Warning -Message "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property." + } + } + catch { + Write-Warning -Message "AutoNameRange: Testing '$targetRangeName' caused an error. This should be harmless, but a change of property name may be needed.." + } + } + } + catch { Write-Warning -Message "Failed adding named ranges to worksheet '$WorksheetName': $_" } + } + #Empty string is not allowed as a name for ranges or tables. + if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName } + + #Allow table to be inserted by specifying Name, or Style or both; only process autoFilter if there is no table (they clash). + if ($null -ne $TableName -or $PSBoundParameters.ContainsKey('TableStyle')) { + #Already inserted Excel table if input was a DataTable + if ($InputObject -isnot [System.Data.DataTable]) { + Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName -TableStyle $TableStyle -TableTotalSettings $TableTotalSettings + } + } + elseif ($AutoFilter) { + try { + $ws.Cells[$dataRange].AutoFilter = $true + Write-Verbose -Message "Enabled autofilter. " + } + catch { Write-Warning -Message "Failed adding autofilter to worksheet '$WorksheetName': $_" } + } + + if ($PivotTableDefinition) { + foreach ($item in $PivotTableDefinition.GetEnumerator()) { + $params = $item.value + if ($Activate) { $params.Activate = $true } + if ($params.keys -notcontains 'SourceRange' -and + ($params.Keys -notcontains 'SourceWorksheet' -or $params.SourceWorksheet -eq $WorksheetName)) { $params.SourceRange = $dataRange } + if ($params.Keys -notcontains 'SourceWorksheet') { $params.SourceWorksheet = $ws } + if ($params.Keys -notcontains 'NoTotalsInPivot' -and $NoTotalsInPivot ) { $params.PivotTotals = 'None' } + if ($params.Keys -notcontains 'PivotTotals' -and $PivotTotals ) { $params.PivotTotals = $PivotTotals } + if ($params.Keys -notcontains 'PivotDataToColumn' -and $PivotDataToColumn) { $params.PivotDataToColumn = $true } + + Add-PivotTable -ExcelPackage $pkg -PivotTableName $item.key @Params + } + } + if ($IncludePivotTable -or $IncludePivotChart -or $PivotData) { + $params = @{ + 'SourceRange' = $dataRange + } + if ($PivotTableName -and ($pkg.workbook.worksheets.tables.name -contains $PivotTableName)) { + Write-Warning -Message "The selected PivotTable name '$PivotTableName' is already used as a table name. Adding a suffix of 'Pivot'." + $PivotTableName += 'Pivot' + } + + if ($PivotTableName) { $params.PivotTableName = $PivotTableName } + else { $params.PivotTableName = $WorksheetName + 'PivotTable' } + if ($Activate) { $params.Activate = $true } + if ($PivotFilter) { $params.PivotFilter = $PivotFilter } + if ($PivotRows) { $params.PivotRows = $PivotRows } + if ($PivotColumns) { $Params.PivotColumns = $PivotColumns } + if ($PivotData) { $Params.PivotData = $PivotData } + if ($NoTotalsInPivot) { $params.PivotTotals = "None" } + Elseif ($PivotTotals) { $params.PivotTotals = $PivotTotals } + if ($PivotDataToColumn) { $params.PivotDataToColumn = $true } + if ($IncludePivotChart -or + $PSBoundParameters.ContainsKey('PivotChartType')) { + $params.IncludePivotChart = $true + $Params.ChartType = $PivotChartType + if ($ShowCategory) { $params.ShowCategory = $true } + if ($ShowPercent) { $params.ShowPercent = $true } + if ($NoLegend) { $params.NoLegend = $true } + } + Add-PivotTable -ExcelPackage $pkg -SourceWorksheet $ws @params + } + + try { + #Allow single switch or two seperate ones. + if ($FreezeTopRowFirstColumn -or ($FreezeTopRow -and $FreezeFirstColumn)) { + if ($Title) { + $ws.View.FreezePanes(3, 2) + Write-Verbose -Message "Froze title and header rows and first column" + } + else { + $ws.View.FreezePanes(2, 2) + Write-Verbose -Message "Froze top row and first column" + } + } + elseif ($FreezeTopRow) { + if ($Title) { + $ws.View.FreezePanes(3, 1) + Write-Verbose -Message "Froze title and header rows" + } + else { + $ws.View.FreezePanes(2, 1) + Write-Verbose -Message "Froze top row" + } + } + elseif ($FreezeFirstColumn) { + $ws.View.FreezePanes(1, 2) + Write-Verbose -Message "Froze first column" + } + #Must be 1..maxrows or and array of 1..maxRows,1..MaxCols + if ($FreezePane) { + $freezeRow, $freezeColumn = $FreezePane + if (-not $freezeColumn -or $freezeColumn -eq 0) { + $freezeColumn = 1 + } + + if ($freezeRow -ge 1) { + $ws.View.FreezePanes($freezeRow, $freezeColumn) + Write-Verbose -Message "Froze panes at row $freezeRow and column $FreezeColumn" + } + } + } + catch { Write-Warning -Message "Failed adding Freezing the panes in worksheet '$WorksheetName': $_" } + + if ($PSBoundParameters.ContainsKey("BoldTopRow")) { + #it sets bold as far as there are populated cells: for whole row could do $ws.row($x).style.font.bold = $true + try { + if ($Title) { + $range = $ws.Dimension.Address -replace '\d+', ($StartRow + 1) + } + else { + $range = $ws.Dimension.Address -replace '\d+', $StartRow + } + $ws.Cells[$range].Style.Font.Bold = [boolean]$BoldTopRow + Write-Verbose -Message "Set $range font style to bold." + } + catch { Write-Warning -Message "Failed setting the top row to bold in worksheet '$WorksheetName': $_" } + } + if ($AutoSize -and -not $env:NoAutoSize) { + try { + #Don't fit the all the columns in the sheet; if we are adding cells beside things with hidden columns, that unhides them + if ($MaxAutoSizeRows -and $MaxAutoSizeRows -lt $LastRow ) { + $AutosizeRange = [OfficeOpenXml.ExcelAddress]::GetAddress($startRow, $StartColumn, $MaxAutoSizeRows , $LastCol) + $ws.Cells[$AutosizeRange].AutoFitColumns() + } + else { $ws.Cells[$dataRange].AutoFitColumns() } + Write-Verbose -Message "Auto-sized columns" + } + catch { Write-Warning -Message "Failed autosizing columns of worksheet '$WorksheetName': $_" } + } + elseif ($AutoSize) { Write-Warning -Message "Auto-fitting columns is not available with this OS configuration." } + + foreach ($Sheet in $HideSheet) { + try { + $pkg.Workbook.Worksheets.Where({ $_.Name -like $sheet }) | ForEach-Object { + $_.Hidden = 'Hidden' + Write-verbose -Message "Sheet '$($_.Name)' Hidden." + } + } + catch { Write-Warning -Message "Failed hiding worksheet '$sheet': $_" } + } + foreach ($Sheet in $UnHideSheet) { + try { + $pkg.Workbook.Worksheets.Where({ $_.Name -like $sheet }) | ForEach-Object { + $_.Hidden = 'Visible' + Write-verbose -Message "Sheet '$($_.Name)' shown" + } + } + catch { Write-Warning -Message "Failed showing worksheet '$sheet': $_" } + } + if (-not $pkg.Workbook.Worksheets.Where({ $_.Hidden -eq 'visible' })) { + Write-Verbose -Message "No Sheets were left visible, making $WorksheetName visible" + $ws.Hidden = 'Visible' + } + + foreach ($chartDef in $ExcelChartDefinition) { + if ($chartDef -is [System.Management.Automation.PSCustomObject]) { + $params = @{} + $chartDef.PSObject.Properties | ForEach-Object { if ( $null -ne $_.value) { $params[$_.name] = $_.value } } + Add-ExcelChart -Worksheet $ws @params + } + elseif ($chartDef -is [hashtable] -or $chartDef -is [System.Collections.Specialized.OrderedDictionary]) { + Add-ExcelChart -Worksheet $ws @chartDef + } + } + + if ($Calculate) { + try { [OfficeOpenXml.CalculationExtension]::Calculate($ws) } + catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook. $_" } + } + + if ($Barchart -or $PieChart -or $LineChart -or $ColumnChart) { + if ($NoHeader) { $FirstDataRow = $startRow } + else { $FirstDataRow = $startRow + 1 } + $range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $startColumn, $FirstDataRow, $lastCol ) + $xCol = $ws.cells[$range] | Where-Object { $_.value -is [string] } | ForEach-Object { $_.start.column } | Sort-Object | Select-Object -first 1 + if (-not $xcol) { + $xcol = $StartColumn + $range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, ($startColumn + 1), $FirstDataRow, $lastCol ) + } + $yCol = $ws.cells[$range] | Where-Object { $_.value -is [valueType] -or $_.Formula } | ForEach-Object { $_.start.column } | Sort-Object | Select-Object -first 1 + if (-not ($xCol -and $ycol)) { Write-Warning -Message "Can't identify a string column and a number column to use as chart labels and data. " } + else { + $params = @{ + XRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $xcol , $lastrow, $xcol) + YRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $ycol , $lastrow, $ycol) + Title = '' + Column = ($lastCol + 1) + Width = 800 + } + if ($ShowPercent) { $params["ShowPercent"] = $true } + if ($ShowCategory) { $params["ShowCategory"] = $true } + if ($NoLegend) { $params["NoLegend"] = $true } + if (-not $NoHeader) { $params["SeriesHeader"] = $ws.Cells[$startRow, $YCol].Value } + if ($ColumnChart) { $Params["chartType"] = "ColumnStacked" } + elseif ($Barchart) { $Params["chartType"] = "BarStacked" } + elseif ($PieChart) { $Params["chartType"] = "PieExploded3D" } + elseif ($LineChart) { $Params["chartType"] = "Line" } + + Add-ExcelChart -Worksheet $ws @params + } + } + + # It now doesn't matter if the conditional formating rules are passed in $conditionalText or $conditional format. + # Just one with an alias for compatiblity it will break things for people who are using both at once + foreach ($c in (@() + $ConditionalText + $ConditionalFormat) ) { + try { + #we can take an object with a .ConditionalType property made by New-ConditionalText or with a .Formatter Property made by New-ConditionalFormattingIconSet or a hash table + if ($c.ConditionalType) { + $cfParams = @{RuleType = $c.ConditionalType; ConditionValue = $c.Text ; + BackgroundColor = $c.BackgroundColor; BackgroundPattern = $c.PatternType ; + ForeGroundColor = $c.ConditionalTextColor + } + if ($c.Range) { $cfParams.Range = $c.Range } + else { $cfParams.Range = $ws.Dimension.Address } + Add-ConditionalFormatting -Worksheet $ws @cfParams + Write-Verbose -Message "Added conditional formatting to range $($c.range)" + } + elseif ($c.formatter) { + switch ($c.formatter) { + "ThreeIconSet" { Add-ConditionalFormatting -Worksheet $ws -ThreeIconsSet $c.IconType -range $c.range -reverse:$c.reverse -ShowIconOnly:$c.ShowIconOnly} + "FourIconSet" { Add-ConditionalFormatting -Worksheet $ws -FourIconsSet $c.IconType -range $c.range -reverse:$c.reverse -ShowIconOnly:$c.ShowIconOnly} + "FiveIconSet" { Add-ConditionalFormatting -Worksheet $ws -FiveIconsSet $c.IconType -range $c.range -reverse:$c.reverse -ShowIconOnly:$c.ShowIconOnly} + } + Write-Verbose -Message "Added conditional formatting to range $($c.range)" + } + elseif ($c -is [hashtable] -or $c -is [System.Collections.Specialized.OrderedDictionary]) { + if (-not $c.Range -or $c.Address) { $c.Address = $ws.Dimension.Address } + Add-ConditionalFormatting -Worksheet $ws @c + } + } + catch { throw "Error applying conditional formatting to worksheet $_" } + } + foreach ($s in $Style) { + if (-not $s.Range) { $s["Range"] = $ws.Dimension.Address } + Set-ExcelRange -Worksheet $ws @s + } + if ($CellStyleSB) { + try { + $TotalRows = $ws.Dimension.Rows + $LastColumn = $ws.Dimension.Address -replace "^.*:(\w*)\d+$" , '$1' + & $CellStyleSB $ws $TotalRows $LastColumn + } + catch { Write-Warning -Message "Failed processing CellStyleSB in worksheet '$WorksheetName': $_" } + } + + #Can only add password, may want to support -password $Null removing password. + if ($Password) { + try { + $ws.Protection.SetPassword($Password) + Write-Verbose -Message 'Set password on workbook' + } + catch { throw "Failed setting password for worksheet '$WorksheetName': $_" } + } + + if ($PassThru) { $pkg } + else { + if ($ReturnRange) { $dataRange } + + if ($Password) { $pkg.Save($Password) } + else { $pkg.Save() } + Write-Verbose -Message "Saved workbook $($pkg.File)" + if ($ReZip) { + Invoke-ExcelReZipFile -ExcelPackage $pkg + } + + $pkg.Dispose() + + if ($Show) { Invoke-Item $Path } + } + } +} diff --git a/Get-ExcelColumnName.ps1 b/Public/Get-ExcelColumnName.ps1 similarity index 50% rename from Get-ExcelColumnName.ps1 rename to Public/Get-ExcelColumnName.ps1 index 7562391d..239dcfb0 100644 --- a/Get-ExcelColumnName.ps1 +++ b/Public/Get-ExcelColumnName.ps1 @@ -1,22 +1,27 @@ function Get-ExcelColumnName { param( [Parameter(ValueFromPipeline=$true)] - $columnNumber=1 + $ColumnNumber=1 ) Process { - $dividend = $columnNumber - $columnName = @() + $dividend = $ColumnNumber + $columnName = New-Object System.Collections.ArrayList($null) + while($dividend -gt 0) { $modulo = ($dividend - 1) % 26 - $columnName += [char](65 + $modulo) + if ($columnName.length -eq 0) { + [char](65 + $modulo) + } else { + $columnName.insert(0,[char](65 + $modulo)) + } $dividend = [int](($dividend -$modulo)/26) } [PSCustomObject] @{ - ColumnNumber = $columnNumber + ColumnNumber = $ColumnNumber ColumnName = $columnName -join '' } } -} \ No newline at end of file +} diff --git a/Public/Get-ExcelFileSchema.ps1 b/Public/Get-ExcelFileSchema.ps1 new file mode 100644 index 00000000..ad3d1fdb --- /dev/null +++ b/Public/Get-ExcelFileSchema.ps1 @@ -0,0 +1,47 @@ +function Get-ExcelFileSchema { + <# + .SYNOPSIS + Gets the schema of an Excel file. + + .DESCRIPTION + The Get-ExcelFileSchema function gets the schema of an Excel file by returning the property names of the first row of each worksheet in the file. + + .PARAMETER Path + Specifies the path to the Excel file. + + .PARAMETER Compress + Indicates whether to compress the json output. + + .OUTPUTS + Json + + .EXAMPLE + Get-ExcelFileSchema -Path .\example.xlsx + #> + + [CmdletBinding()] + param( + [Parameter(ValueFromPipelineByPropertyName, Mandatory)] + [Alias('FullName')] + $Path, + [Switch]$Compress + ) + + Begin { + $result = @() + } + + Process { + $excelFiles = Get-ExcelFileSummary $Path + + foreach ($excelFile in $excelFiles) { + $data = Import-Excel $Path -WorksheetName $excelFile.WorksheetName | Select-Object -First 1 + $names = $data[0].PSObject.Properties.name + $result += $excelFile | Add-Member -MemberType NoteProperty -Name "PropertyNames" -Value $names -PassThru + } + } + + End { + $result | ConvertTo-Json -Compress:$Compress + } +} \ No newline at end of file diff --git a/Public/Get-ExcelFileSummary.ps1 b/Public/Get-ExcelFileSummary.ps1 new file mode 100644 index 00000000..3ffec1ed --- /dev/null +++ b/Public/Get-ExcelFileSummary.ps1 @@ -0,0 +1,29 @@ +function Get-ExcelFileSummary { + <# + .Synopsis + Gets summary information on an Excel file like number of rows, columns, and more + #> + param( + [Parameter(ValueFromPipelineByPropertyName, Mandatory)] + [Alias('FullName')] + $Path + ) + + Process { + $excel = Open-ExcelPackage -Path $Path + + foreach ($workSheet in $excel.Workbook.Worksheets) { + [PSCustomObject][Ordered]@{ + ExcelFile = Split-Path -Leaf $Path + WorksheetName = $workSheet.Name + Visible = $workSheet.Hidden -eq 'Visible' + Rows = $workSheet.Dimension.Rows + Columns = $workSheet.Dimension.Columns + Address = $workSheet.Dimension.Address + Path = Split-Path $Path + } + } + + Close-ExcelPackage -ExcelPackage $excel -NoSave + } +} \ No newline at end of file diff --git a/Public/Get-ExcelSheetDimensionAddress.ps1 b/Public/Get-ExcelSheetDimensionAddress.ps1 new file mode 100644 index 00000000..993b7f97 --- /dev/null +++ b/Public/Get-ExcelSheetDimensionAddress.ps1 @@ -0,0 +1,15 @@ +function Get-ExcelSheetDimensionAddress { + <# + .SYNOPSIS + Get the Excel address of the dimension of a sheet + + .EXAMPLE + Get-ExcelSheetDimensionAddress $excel.Sheet1 + #> + param( + [Parameter(Mandatory)] + [OfficeOpenXml.ExcelWorksheet]$Worksheet + ) + + $Worksheet.Dimension.Address +} diff --git a/Get-ExcelSheetInfo.ps1 b/Public/Get-ExcelSheetInfo.ps1 similarity index 59% rename from Get-ExcelSheetInfo.ps1 rename to Public/Get-ExcelSheetInfo.ps1 index 6ab93f59..f5c6cf32 100644 --- a/Get-ExcelSheetInfo.ps1 +++ b/Public/Get-ExcelSheetInfo.ps1 @@ -1,26 +1,4 @@ -Function Get-ExcelSheetInfo { - <# - .SYNOPSIS - Get worksheet names and their indices of an Excel workbook. - - .DESCRIPTION - The Get-ExcelSheetInfo cmdlet gets worksheet names and their indices of an Excel workbook. - - .PARAMETER Path - Specifies the path to the Excel file. This parameter is required. - - .EXAMPLE - Get-ExcelSheetInfo .\Test.xlsx - - .NOTES - CHANGELOG - 2016/01/07 Added Created by Johan Akerstrom (https://github.com/CosmosKey) - - .LINK - https://github.com/dfinke/ImportExcel - - #> - +function Get-ExcelSheetInfo { [CmdletBinding()] param( [Alias('FullName')] @@ -33,7 +11,7 @@ Function Get-ExcelSheetInfo { $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path,'Open','Read','ReadWrite' $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream $workbook = $xl.Workbook - + if ($workbook -and $workbook.Worksheets) { $workbook.Worksheets | Select-Object -Property name,index,hidden,@{ diff --git a/Public/Get-ExcelWorkbookInfo.ps1 b/Public/Get-ExcelWorkbookInfo.ps1 new file mode 100644 index 00000000..515cce45 --- /dev/null +++ b/Public/Get-ExcelWorkbookInfo.ps1 @@ -0,0 +1,27 @@ +function Get-ExcelWorkbookInfo { + [CmdletBinding()] + param ( + [Alias('FullName')] + [Parameter(ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, Mandatory=$true)] + [String]$Path + ) + + process { + try { + $Path = (Resolve-Path $Path).ProviderPath + + $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path,'Open','Read','ReadWrite' + $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream + $workbook = $xl.Workbook + $workbook.Properties + + $stream.Close() + $stream.Dispose() + $xl.Dispose() + $xl = $null + } + catch { + throw "Failed retrieving Excel workbook information for '$Path': $_" + } + } +} diff --git a/Public/Get-HtmlTable.ps1 b/Public/Get-HtmlTable.ps1 new file mode 100644 index 00000000..bc16842d --- /dev/null +++ b/Public/Get-HtmlTable.ps1 @@ -0,0 +1,85 @@ +# https://www.leeholmes.com/blog/2015/01/05/extracting-tables-from-powershells-invoke-webrequest/ +# tweaked from the above code +function Get-HtmlTable { + param( + [Parameter(Mandatory=$true)] + $Url, + $TableIndex=0, + $Header, + [int]$FirstDataRow=0, + [Switch]$UseDefaultCredentials + ) + if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command ConvertFrom-Html -ErrorAction SilentlyContinue)) { + # Invoke-WebRequest on .NET core doesn't have ParsedHtml so we need HtmlAgilityPack or similiar Justin Grote's PowerHTML wraps that nicely + throw "This version of PowerShell needs the PowerHTML module to process HTML Tables." + } + + $r = Invoke-WebRequest $Url -UseDefaultCredentials: $UseDefaultCredentials + $propertyNames = $Header + + if ($PSVersionTable.PSVersion.Major -le 5) { + $table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex] + $totalRows=@($table.rows).count + + for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) { + + $row = $table.rows[$idx] + $cells = @($row.cells) + + if(!$propertyNames) { + if($cells[0].tagName -eq 'th') { + $propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''}) + } else { + $propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" }) + } + continue + } + + $result = [ordered]@{} + + for($counter = 0; $counter -lt $cells.Count; $counter++) { + $propertyName = $propertyNames[$counter] + + if(!$propertyName) { $propertyName= '[missing]'} + $result.$propertyName= $cells[$counter].InnerText + } + + [PSCustomObject]$result + } + } + else { + $h = ConvertFrom-Html -Content $r.Content + if ($TableIndex -is [valuetype]) { $TableIndex += 1} + $rows = try { + $h.SelectSingleNode("//table[$TableIndex]").SelectNodes(".//tr") + } catch {} + if (-not $rows) {Write-Warning "Could not find rows for `"//table[$TableIndex]`" in $Url ."} + if ( -not $propertyNames) { + if ( $tableHeaders = $rows[$FirstDataRow].SelectNodes("th")) { + $propertyNames = $tableHeaders.foreach({[System.Web.HttpUtility]::HtmlDecode( $_.innerText ) -replace '\W+','_' -replace '(\w)_+$','$1' }) + $FirstDataRow += 1 + } + else { + $c = 0 + $propertyNames = $rows[$FirstDataRow].SelectNodes("td") | Foreach-Object { "P$c" ; $c ++ } + } + } + Write-Verbose ("Property names: " + ($propertyNames -join ",")) + foreach ($n in $FirstDataRow..($rows.Count-1)) { + $r = $rows[$n].SelectNodes("td|th") + if ($r -and $r.innerText -ne "" -and $r.count -gt $rows[$n].SelectNodes("th").count ) { + $c = 0 + $newObj = [ordered]@{} + foreach ($p in $propertyNames) { + $n = $null + #Join descentandts for cases where the text in the cell is split (e.g with a
    ). We also want to remove HTML codes, trim and convert unicode minus sign to "-" + $cellText = $r[$c].Descendants().where({$_.NodeType -eq "Text"}).foreach({[System.Web.HttpUtility]::HtmlDecode( $_.innerText ).Trim()}) -Join " " -replace "\u2212","-" + if ([double]::TryParse($cellText, [ref]$n)) {$newObj[$p] = $n } + else {$newObj[$p] = $cellText } + $c ++ + } + [pscustomObject]$newObj + } + } + } +} diff --git a/Public/Get-Range.ps1 b/Public/Get-Range.ps1 new file mode 100644 index 00000000..0ebfab62 --- /dev/null +++ b/Public/Get-Range.ps1 @@ -0,0 +1,5 @@ +function Get-Range { + [CmdletBinding()] + param($Start=0,$Stop,$Step=1) + for ($idx = $Start; $idx -lt $Stop; $idx+=$Step) {$idx} +} \ No newline at end of file diff --git a/Get-XYRange.ps1 b/Public/Get-XYRange.ps1 similarity index 57% rename from Get-XYRange.ps1 rename to Public/Get-XYRange.ps1 index 179679d5..32373336 100644 --- a/Get-XYRange.ps1 +++ b/Public/Get-XYRange.ps1 @@ -1,7 +1,8 @@ function Get-XYRange { - param($targetData) + [CmdletBinding()] + param($TargetData) - $record = $targetData| select -First 1 + $record = $TargetData | Select-Object -First 1 $p=$record.psobject.Properties.name $infer = for ($idx = 0; $idx -lt $p.Count; $idx++) { @@ -20,7 +21,7 @@ function Get-XYRange { } [PSCustomObject]@{ - XRange = $infer | ? {$_.datatype -match 'string'} | select -First 1 excelcolumn, name - YRange = $infer | ? {$_.datatype -match 'int|double'} |select -First 1 excelcolumn, name + XRange = $infer | Where-Object -FilterScript {$_.datatype -match 'string'} | Select-Object -First 1 -Property excelcolumn, name + YRange = $infer | Where-Object -FilterScript {$_.datatype -match 'int|double'} | Select-Object -First 1 -Property excelcolumn, name } } \ No newline at end of file diff --git a/Public/Import-Excel.ps1 b/Public/Import-Excel.ps1 new file mode 100644 index 00000000..3734f2bc --- /dev/null +++ b/Public/Import-Excel.ps1 @@ -0,0 +1,264 @@ +function Import-Excel { + [CmdLetBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectUsageOfAssignmentOperator', '', Justification = 'Intentional')] + param ( + [Alias('FullName')] + [Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [String[]]$Path, + [Parameter(ParameterSetName = "PackageA", Mandatory)] + [Parameter(ParameterSetName = "PackageB", Mandatory)] + [Parameter(ParameterSetName = "PackageC", Mandatory)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Alias('Sheet')] + [Parameter(Position = 1)] + [ValidateNotNullOrEmpty()] + [String[]]$WorksheetName, + [Parameter(ParameterSetName = 'PathB' , Mandatory)] + [Parameter(ParameterSetName = 'PackageB', Mandatory)] + [String[]]$HeaderName , + [Parameter(ParameterSetName = 'PathC' , Mandatory)] + [Parameter(ParameterSetName = 'PackageC', Mandatory)] + [Switch]$NoHeader , + [Alias('HeaderRow', 'TopRow')] + [ValidateRange(1, 1048576)] + [Int]$StartRow = 1, + [Alias('StopRow', 'BottomRow')] + [Int]$EndRow , + [Alias('LeftColumn')] + [Int]$StartColumn = 1, + [Alias('RightColumn')] + [Int]$EndColumn , + [Switch]$DataOnly, + [string[]]$AsText, + [string[]]$AsDate, + [ValidateNotNullOrEmpty()] + [String]$Password, + [Int[]]$ImportColumns, + [Switch]$Raw + ) + end { + $sw = [System.Diagnostics.Stopwatch]::StartNew() + if ($input) { + $Paths = $input + } + elseif ($Path) { + $Paths = $Path + } + else { + $Paths = '' + } + function Get-PropertyNames { + <# + .SYNOPSIS + Create objects containing the column number and the column name for each of the different header types. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")] + param( + [Parameter(Mandatory)] + [Int[]]$Columns, + [Parameter(Mandatory)] + [Int]$StartRow + ) + + try { + if ($ImportColumns) { + $end = $sheet.Dimension.End.Column + # Check $ImportColumns + if ($ImportColumns[0] -le 0) { throw "The first entry in ImportColumns must be equal or greater 1" ; return } + # Check $StartColumn and $EndColumn + if (($StartColumn -ne 1) -or ($EndColumn -ne $end)) { Write-Warning -Message "If ImportColumns is set, then individual StartColumn and EndColumn will be ignored." } + # Replace $Columns with $ImportColumns + $Columns = $ImportColumns + } + + if ($HeaderName) { + $i = 0 + foreach ($H in $HeaderName) { + $H | Select-Object @{N = 'Column'; E = { $Columns[$i] } }, @{N = 'Value'; E = { $H } } + $i++ + } + } + elseif ($NoHeader) { + $i = 0 + foreach ($C in $Columns) { + $i++ + $C | Select-Object @{N = 'Column'; E = { $_ } }, @{N = 'Value'; E = { 'P' + $i } } + } + } + + else { + if ($StartRow -lt 1) { + throw 'The top row can never be less than 1 when we need to retrieve headers from the worksheet.' ; return + } + + foreach ($C in $Columns) { + #allow "False" or "0" to be column headings + $sheet.Cells[$StartRow, $C] | Where-Object { -not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{N = 'Column'; E = { $C } }, Value + } + } + } + catch { + throw "Failed creating property names: $_" ; return + } + } + foreach ($Path in $Paths) { + if ($path) { + $extension = [System.IO.Path]::GetExtension($Path) + if ($extension -notmatch '.xlsx$|.xlsm$') { + throw "Import-Excel does not support reading this extension type $($extension)" + } + + $resolvedPath = (Resolve-Path $Path -ErrorAction SilentlyContinue) + if ($resolvedPath) { + $Path = $resolvedPath.ProviderPath + } + else { + throw "'$($Path)' file not found" + } + + $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, 'Open', 'Read', 'ReadWrite' + $ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage + if ($Password) { $ExcelPackage.Load($stream, $Password) } + else { $ExcelPackage.Load($stream) } + } + try { + #Select worksheet + if ($WorksheetName -eq '*') { $Worksheet = $ExcelPackage.Workbook.Worksheets } + elseif (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] } + elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorksheetName])) { + throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return + } + + $xlBook = [Ordered]@{} + foreach ($sheet in $Worksheet) { + if ($Worksheet.Count -gt 1 -or $Paths.Count -gt 1) { + <# + Needed under these conditions to handle sheets of different number of Row/Col + - When reading more than one xlsx file + - When reading more than one worksheet in the same file + #> + $EndRow = $null + $EndColumn = $null + } + + $targetSheetname = $sheet.Name + $xlBook["$targetSheetname"] = @() + #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 = $sheet.Dimension.End.Row } + if (-not $EndColumn) { $EndColumn = $sheet.Dimension.End.Column } + $endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0) + if ($DataOnly) { + #If we are using headers startrow will be the header-row so examine data from startRow + 1, + if ($NoHeader) { $range = "A" + ($StartRow ) + ":" + $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, + #using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times". + $colHash = @{ } + $rowHash = @{ } + foreach ($cell in $sheet.Cells[$range]) { + 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[$_] }) + } + 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." } } + elseif ($HeaderName) { $rows = $StartRow..$EndRow } + else { + $rows = (1 + $StartRow)..$EndRow + if ($StartRow -eq 1 -and $EndRow -eq 1) { + $rows = 0 + } + } + + # ; 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 + if ((-not $Columns) -or (-not ($PropertyNames = Get-PropertyNames -Columns $Columns -StartRow $StartRow))) { + throw "No column headers found on top row '$StartRow'. If column headers in the worksheet are not a requirement then please use the '-NoHeader' or '-HeaderName' parameter."; return + } + if ($Duplicates = $PropertyNames | Group-Object Value | Where-Object Count -GE 2) { + throw "Duplicate column headers found on row '$StartRow' in columns '$($Duplicates.Group.Column)'. Column headers must be unique, if this is not a requirement please use the '-NoHeader' or '-HeaderName' parameter."; return + } + #endregion + if (-not $rows) { + Write-Warning "Worksheet '$WorksheetName' in workbook '$Path' contains no data in the rows after top row '$StartRow'" + } + else { + #region Create one object per row + if ($AsText -or $AsDate) { + <#join items in AsText together with ~~~ . Escape any regex special characters... + # which turns "*" into "\*" make it ".*". Convert ~~~ to $|^ and top and tail with ^%; + So if we get "Week", "[Time]" and "*date*" ; make the expression ^week$|^\[Time\]$|^.*Date.*$ + $make a regex for this which is case insensitive (option 1) and compiled (option 8) + #> + $TextColExpression = '' + if ($AsText) { + $TextColExpression += '(?^' + [regex]::Escape($AsText -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)' + } + if ($AsText -and $AsDate) { + $TextColExpression += "|" + } + if ($AsDate) { + $TextColExpression += '(?^' + [regex]::Escape($AsDate -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)' + } + $TextColRegEx = New-Object -TypeName regex -ArgumentList $TextColExpression , 9 + } + else { $TextColRegEx = $null } + foreach ($R in $rows) { + #Disabled write-verbose for speed + # Write-Verbose "Import row '$R'" + $NewRow = [Ordered]@{ } + if ($TextColRegEx) { + foreach ($P in $PropertyNames) { + $MatchTest = $TextColRegEx.Match($P.value) + if ($MatchTest.groups.name -eq "astext") { + $NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Text + } + elseif ($MatchTest.groups.name -eq "asdate" -and $sheet.Cells[$R, $P.Column].Value -is [System.ValueType]) { + $NewRow[$P.Value] = [datetime]::FromOADate(($sheet.Cells[$R, $P.Column].Value)) + } + else { $NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Value } + } + } + else { + foreach ($P in $PropertyNames) { + $NewRow[$P.Value] = $sheet.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)'." + } + } + $xlBook["$targetSheetname"] += [PSCustomObject]$NewRow + } + #endregion + } + } + } + catch { throw "Failed importing the Excel workbook '$Path' with worksheet '$WorksheetName': $_"; return } + finally { + # $EndRow = 0 + # $EndColumn = 0 + if ($Path) { $stream.close(); $ExcelPackage.Dispose() } + + if ($Raw) { + foreach ($entry in $xlbook.GetEnumerator()) { + $entry.Value + } + } + elseif ($Worksheet.Count -eq 1) { + $xlBook["$targetSheetname"] + } + else { + $xlBook + } + } + } + } +} diff --git a/Import-Html.ps1 b/Public/Import-Html.ps1 similarity index 66% rename from Import-Html.ps1 rename to Public/Import-Html.ps1 index f467568b..6a22df44 100644 --- a/Import-Html.ps1 +++ b/Public/Import-Html.ps1 @@ -2,19 +2,19 @@ function Import-Html { [CmdletBinding()] param( - $url, - $index, + $Url, + [int]$Index = 0, $Header, - [int]$FirstDataRow=0, + [int]$FirstDataRow = 0, [Switch]$UseDefaultCredentials ) - - $xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp","xlsx" - rm $xlFile -ErrorAction Ignore + + $xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp", "xlsx" + Remove-Item $xlFile -ErrorAction Ignore Write-Verbose "Exporting to Excel file $($xlFile)" - $data = Get-HtmlTable -url $url -tableIndex $index -Header $Header -FirstDataRow $FirstDataRow -UseDefaultCredentials: $UseDefaultCredentials - + $data = Get-HtmlTable -Url $Url -TableIndex $Index -Header $Header -FirstDataRow $FirstDataRow -UseDefaultCredentials: $UseDefaultCredentials + $data | Export-Excel $xlFile -Show -AutoSize } \ No newline at end of file diff --git a/Public/Import-UPS.ps1 b/Public/Import-UPS.ps1 new file mode 100644 index 00000000..16d2636a --- /dev/null +++ b/Public/Import-UPS.ps1 @@ -0,0 +1,9 @@ +function Import-UPS { + [CmdletBinding()] + param( + $TrackingNumber, + [Switch]$UseDefaultCredentials + ) + + Import-Html "https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums=$($TrackingNumber)" 0 -UseDefaultCredentials: $UseDefaultCredentials +} \ No newline at end of file diff --git a/Public/Import-USPS.ps1 b/Public/Import-USPS.ps1 new file mode 100644 index 00000000..fcb8ad1a --- /dev/null +++ b/Public/Import-USPS.ps1 @@ -0,0 +1,10 @@ +function Import-USPS { + [CmdletBinding()] + param( + $TrackingNumber, + [Switch]$UseDefaultCredentials + + ) + + Import-Html "https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=$($TrackingNumber)" 0 -UseDefaultCredentials:$UseDefaultCredentials +} diff --git a/Public/Invoke-ExcelQuery.ps1 b/Public/Invoke-ExcelQuery.ps1 new file mode 100644 index 00000000..4cb01a94 --- /dev/null +++ b/Public/Invoke-ExcelQuery.ps1 @@ -0,0 +1,63 @@ +#Requires -Version 5 +function Invoke-ExcelQuery { + <# + .SYNOPSIS + Helper method for executing Read-OleDbData with some basic defaults. + + For additional help, see documentation for Read-OleDbData cmdlet. + + .DESCRIPTION + Uses Read-OleDbData to execute a sql statement against a xlsx file. For finer grained control over the interaction, you may use that cmdlet. This cmdlet assumes a file path will be passed in and the connection string will be built with no headers and treating all results as text. + + Running this command is equivalent to running the following: + + $FullName = (Get-ChildItem $Path).FullName + Read-OleDbData ` + -ConnectionString "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$FullName;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" ` + -SqlStatement $Query + + Note that this command uses the MICROSOFT.ACE.OLEDB provider and will not work without it. + + If needed, please download the appropriate package from https://www.microsoft.com/en-us/download/details.aspx?id=54920. + + .EXAMPLE + Invoke-ExcelQuery .\test.xlsx 'select ROUND(F1) as [A1] from [sheet3$A1:A1]' + + .EXAMPLE + $Path = (Get-ChildItem 'test.xlsx').FullName + $Query = "select ROUND(F1) as [A] from [sheet1$A1:A1]" + Read-XlsxUsingOleDb -Path $Path -Query $Query + + .EXAMPLE + $ReadDataArgs = @{ + Path = .\test.xlsx + Query = Get-Content query.sql -Raw + } + $Results = Invoke-ExcelQuery @ReadDataArgs + #> + param( + #The path to the file to open. + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String] $Path, # var name consistent with Import-Excel + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String] $Query # var name consistent with Invoke-Sqlcmd + ) + + try { + if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") { + Write-Error "Microsoft.ACE.OLEDB.12.0 provider is missing! Please install from https://www.microsoft.com/en-us/download/details.aspx?id=54920" + return + } + } + catch { + Write-Error "System.Data.OleDb is not working or you are on an unsupported platform." + return + } + + $FullName = (Get-ChildItem $Path).FullName + Read-OleDbData ` + -ConnectionString "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$FullName;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" ` + -SqlStatement $Query +} \ No newline at end of file diff --git a/Invoke-Sum.ps1 b/Public/Invoke-Sum.ps1 similarity index 70% rename from Invoke-Sum.ps1 rename to Public/Invoke-Sum.ps1 index 2b5bfa5c..6787adb0 100644 --- a/Invoke-Sum.ps1 +++ b/Public/Invoke-Sum.ps1 @@ -1,16 +1,17 @@ function Invoke-Sum { + [CmdletBinding()] param( - $data, - $dimension, - $measure + $Data, + $Dimension, + $Measure ) - if(!$measure) {$measure = $dimension} + if(!$Measure) {$Measure = $Dimension} $h=@{} - foreach ($item in $data){ - $key=$item.$dimension + foreach ($item in $Data){ + $key=$item.$Dimension if(!$key) {$key="[missing]"} @@ -18,7 +19,7 @@ function Invoke-Sum { $h.$key=[ordered]@{} } - foreach($m in $measure) { + foreach($m in $Measure) { $value = $item.$m if($value -is [string] -or $value -is [System.Enum]) { $value = 1 @@ -27,15 +28,15 @@ function Invoke-Sum { $h.$key.$m+=$value } } - + foreach ($entry in $h.GetEnumerator()){ - + $nh=[ordered]@{Name=$entry.key} - + foreach ($item in $entry.value.getenumerator()) { $nh.($item.key)=$item.value - } - + } + [pscustomobject]$nh } } \ No newline at end of file diff --git a/Public/Join-Worksheet.ps1 b/Public/Join-Worksheet.ps1 new file mode 100644 index 00000000..e5c58201 --- /dev/null +++ b/Public/Join-Worksheet.ps1 @@ -0,0 +1,135 @@ +function Join-Worksheet { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + [Parameter(ParameterSetName = "Default", Position = 0)] + [Parameter(ParameterSetName = "Table" , Position = 0)] + [String]$Path , + [Parameter(Mandatory = $true, ParameterSetName = "PackageDefault")] + [Parameter(Mandatory = $true, ParameterSetName = "PackageTable")] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + $WorksheetName = 'Combined', + [switch]$Clearsheet, + [switch]$NoHeader, + [string]$FromLabel = "From" , + [switch]$LabelBlocks, + [Switch]$AutoSize, + [Switch]$FreezeTopRow, + [Switch]$FreezeFirstColumn, + [Switch]$FreezeTopRowFirstColumn, + [Int[]]$FreezePane, + [Parameter(ParameterSetName = 'Default')] + [Parameter(ParameterSetName = 'PackageDefault')] + [Switch]$AutoFilter, + [Switch]$BoldTopRow, + [switch]$HideSource, + [String]$Title, + [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'Solid', + $TitleBackgroundColor, + [Switch]$TitleBold, + [Int]$TitleSize = 22, + [Hashtable]$PivotTableDefinition, + [Object[]]$ExcelChartDefinition, + [Object[]]$ConditionalFormat, + [Object[]]$ConditionalText, + [switch]$AutoNameRange, + [ValidateScript( { + if (-not $_) { throw 'RangeName is null or empty.' } + elseif ($_[0] -notmatch '[a-z]') { throw 'RangeName starts with an invalid character.' } + else { $true } + })] + [String]$RangeName, + [ValidateScript( { + if (-not $_) { throw 'Tablename is null or empty.' } + elseif ($_[0] -notmatch '[a-z]') { throw 'Tablename starts with an invalid character.' } + else { $true } + })] + [Parameter(ParameterSetName = 'Table' , Mandatory = $true)] + [Parameter(ParameterSetName = 'PackageTable' , Mandatory = $true)] + [String]$TableName, + [Parameter(ParameterSetName = 'Table')] + [Parameter(ParameterSetName = 'PackageTable')] + [OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6', + [switch]$ReturnRange, + [switch]$Show, + [switch]$PassThru + ) + #region get target worksheet, select it and move it to the end. + if ($Path -and -not $ExcelPackage) {$ExcelPackage = Open-ExcelPackage -path $Path } + $destinationSheet = Add-Worksheet -ExcelPackage $ExcelPackage -WorksheetName $WorksheetName -ClearSheet:$Clearsheet + foreach ($w in $ExcelPackage.Workbook.Worksheets) {$w.view.TabSelected = $false} + $destinationSheet.View.TabSelected = $true + $ExcelPackage.Workbook.Worksheets.MoveToEnd($WorksheetName) + #row to insert at will be 1 on a blank sheet and lastrow + 1 on populated one + $row = (1 + $destinationSheet.Dimension.End.Row ) + #endregion + + #region Setup title and header rows + #Title parameters work as they do in Export-Excel . + if ($row -eq 1 -and $Title) { + $destinationSheet.Cells[1, 1].Value = $Title + $destinationSheet.Cells[1, 1].Style.Font.Size = $TitleSize + if ($TitleBold) {$destinationSheet.Cells[1, 1].Style.Font.Bold = $True } + #Can only set TitleBackgroundColor if TitleFillPattern is something other than None. + if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) { + if ($TitleBackgroundColor -is [string]) {$TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor } + $destinationSheet.Cells[1, 1].Style.Fill.PatternType = $TitleFillPattern + $destinationSheet.Cells[1, 1].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor) + } + elseif ($TitleBackgroundColor) { Write-Warning "Title Background Color ignored. You must set the TitleFillPattern parameter to a value other than 'None'. Try 'Solid'." } + $row = 2 + } + + if (-not $noHeader) { + #Assume every row has titles in row 1, copy row 1 from first sheet to new sheet. + $destinationSheet.Select("A$row") + $ExcelPackage.Workbook.Worksheets[1].cells["1:1"].Copy($destinationSheet.SelectedRange) + #fromlabel can't be an empty string + if ($FromLabel ) { + #Add a column which says where the data comes from. + $fromColumn = ($destinationSheet.Dimension.Columns + 1) + $destinationSheet.Cells[$row, $fromColumn].Value = $FromLabel + } + $row += 1 + } + #endregion + + foreach ($i in 1..($ExcelPackage.Workbook.Worksheets.Count - 1) ) { + $sourceWorksheet = $ExcelPackage.Workbook.Worksheets[$i] + #Assume row one is titles, so data itself starts at A2. + if ($NoHeader) {$sourceRange = $sourceWorksheet.Dimension.Address} + else {$sourceRange = $sourceWorksheet.Dimension.Address -replace "A1:", "A2:"} + #Position insertion point/ + $destinationSheet.Select("A$row") + if ($LabelBlocks) { + $destinationSheet.Cells[$row, 1].value = $sourceWorksheet.Name + $destinationSheet.Cells[$row, 1].Style.Font.Bold = $true + $destinationSheet.Cells[$row, 1].Style.Font.Size += 2 + $row += 1 + } + $destinationSheet.Select("A$row") + + #And finally we're ready to copy the data. + $sourceWorksheet.Cells[$sourceRange].Copy($destinationSheet.SelectedRange) + #Fill in column saying where data came from. + if ($fromColumn) { $row..$destinationSheet.Dimension.Rows | ForEach-Object {$destinationSheet.Cells[$_, $fromColumn].Value = $sourceWorksheet.Name} } + #Update where next insertion will go. + $row = $destinationSheet.Dimension.Rows + 1 + if ($HideSource) {$sourceWorksheet.Hidden = [OfficeOpenXml.eWorkSheetHidden]::Hidden} + } + + #We accept a bunch of parameters work to pass on to Export-excel ( Autosize, Autofilter, boldtopRow Freeze ); if we have any of those call Export-excel otherwise close the package here. + $params = @{} + $PSBoundParameters + 'Path', 'Clearsheet', 'NoHeader', 'FromLabel', 'LabelBlocks', 'HideSource', + 'Title', 'TitleFillPattern', 'TitleBackgroundColor', 'TitleBold', 'TitleSize' | ForEach-Object {$null = $params.Remove($_)} + if ($params.Keys.Count) { + if ($Title) { $params.StartRow = 2} + $params.WorksheetName = $WorksheetName + $params.ExcelPackage = $ExcelPackage + Export-Excel @Params + } + else { + Close-ExcelPackage -ExcelPackage $ExcelPackage + $ExcelPackage.Dispose() + $ExcelPackage = $null + } +} \ No newline at end of file diff --git a/Public/Merge-MultipleSheets.ps1 b/Public/Merge-MultipleSheets.ps1 new file mode 100644 index 00000000..acbfe7ab --- /dev/null +++ b/Public/Merge-MultipleSheets.ps1 @@ -0,0 +1,147 @@ +function Merge-MultipleSheets { + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification="False positives when initializing variable in begin block")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification="MultipleSheet would be incorrect")] + #[Alias("Merge-MulipleSheets")] #There was a spelling error in the first release. This was there to ensure things didn't break but intelisense gave the alias first. + param ( + [Parameter(Mandatory=$true,ValueFromPipeline=$true)] + $Path , + [int]$Startrow = 1, + + [String[]]$Headername, + + [switch]$NoHeader, + + $WorksheetName = "Sheet1", + [Alias('OutFile')] + $OutputFile = ".\temp.xlsx", + [Alias('OutSheet')] + $OutputSheetName = "Sheet1", + $Property = "*" , + $ExcludeProperty , + $Key = "Name" , + $KeyFontColor = [System.Drawing.Color]::Red, + $ChangeBackgroundColor = [System.Drawing.Color]::Orange, + $DeleteBackgroundColor = [System.Drawing.Color]::LightPink, + $AddBackgroundColor = [System.Drawing.Color]::Orange, + [switch]$HideRowNumbers , + [switch]$Passthru , + [Switch]$Show + ) + begin { $filestoProcess = @() } + process { $filestoProcess += $Path} + end { + if ($filestoProcess.Count -eq 1 -and $WorksheetName -match '\*') { + Write-Progress -Activity "Merging sheets" -CurrentOperation "Expanding * to names of sheets in $($filestoProcess[0]). " + $excel = Open-ExcelPackage -Path $filestoProcess + $WorksheetName = $excel.Workbook.Worksheets.Name.where({$_ -like $WorksheetName}) + Close-ExcelPackage -NoSave -ExcelPackage $excel + } + + #Merge identically named sheets in different work books; + if ($filestoProcess.Count -ge 2 -and $WorksheetName -is "string" ) { + Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty','WorksheetName' -ErrorAction SilentlyContinue | + Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value} + + Write-Progress -Activity "Merging sheets" -CurrentOperation "comparing '$WorksheetName' in $($filestoProcess[-1]) against $($filestoProcess[0]). " + $merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[-1] + $nextFileNo = 2 + while ($nextFileNo -lt $filestoProcess.count -and $merged) { + Write-Progress -Activity "Merging sheets" -CurrentOperation "comparing '$WorksheetName' in $($filestoProcess[-$nextFileNo]) against $($filestoProcess[0]). " + $merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[-$nextFileNo] + $nextFileNo ++ + + } + } + #Merge different sheets from one workbook + elseif ($filestoProcess.Count -eq 1 -and $WorksheetName.Count -ge 2 ) { + Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty' -ErrorAction SilentlyContinue | + Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value} + + Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorksheetName[-1]) against $($WorksheetName[0]). " + $merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[0] -WorksheetName $WorksheetName[0,-1] + $nextSheetNo = 2 + while ($nextSheetNo -lt $WorksheetName.count -and $merged) { + Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorksheetName[-$nextSheetNo]) against $($WorksheetName[0]). " + $merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[0] -WorksheetName $WorksheetName[-$nextSheetNo] -DiffPrefix $WorksheetName[-$nextSheetNo] + $nextSheetNo ++ + } + } + #We either need one Worksheet name and many files or one file and many sheets. + else { Write-Warning -Message "Need at least two files to process" ; return } + #if the process didn't return data then abandon now. + if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return } + + $orderByProperties = $merged[0].psobject.properties.where({$_.name -match "row$"}).name + Write-Progress -Activity "Merging sheets" -CurrentOperation "creating output sheet '$OutputSheetName' in $OutputFile" + $excel = $merged | Sort-Object -Property $orderByProperties | + Export-Excel -Path $OutputFile -WorksheetName $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru + $sheet = $excel.Workbook.Worksheets[$OutputSheetName] + + #We will put in a conditional format for "if all the others are not flagged as 'same'" to mark rows where something is added, removed or changed + $sameChecks = @() + + #All the 'difference' columns in the sheet are labeled with the file they came from, 'reference' columns need their + #headers prefixed with the ref file name, $colnames is the basis of a regular expression to identify what should have $refPrefix appended + $colNames = @("^_Row$") + if ($Key -ne "*") + {$colnames += "^$Key$"} + if ($filesToProcess.Count -ge 2) { + $refPrefix = (Split-Path -Path $filestoProcess[0] -Leaf) -replace "\.xlsx$"," " + } + else {$refPrefix = $WorksheetName[0] + " "} + Write-Progress -Activity "Merging sheets" -CurrentOperation "applying formatting to sheet '$OutputSheetName' in $OutputFile" + #Find the column headings which are in the form "diffFile is"; which will hold 'Same', 'Added' or 'Changed' + foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "\sIS$"}) ) { + #Work leftwards across the headings applying conditional formatting which says + # 'Format this cell if the "IS" column has a value of ...' until you find a heading which doesn't have the prefix. + $prefix = $cell.value -replace "\sIS$","" + $columnNo = $cell.start.Column -1 + $cellAddr = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R1C$columnNo",1,$columnNo) + while ($sheet.cells[$cellAddr].value -match $prefix) { + $condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; Worksheet=$sheet; StopIfTrue=$true; Range=$([OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[1]C[$columnNo]:R[1048576]C[$columnNo]",0,0)) } + Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Added"' ) -BackgroundColor $AddBackgroundColor + Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Changed"') -BackgroundColor $ChangeBackgroundColor + Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Removed"') -BackgroundColor $DeleteBackgroundColor + $columnNo -- + $cellAddr = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R1C$columnNo",1,$columnNo) + } + #build up a list of prefixes in $colnames - we'll use that to set headers on rows from the reference file; and build up the "if the 'is' cell isn't same" list + $colNames += $prefix + $sameChecks += (($cell.Address -replace "1","2") +'<>"Same"') + } + + #For all the columns which don't match one of the Diff-file prefixes or "_Row" or the 'Key' columnn name; add the reference file prefix to their header. + $nameRegex = $colNames -Join '|' + foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -Notmatch $nameRegex}) ) { + $cell.Value = $refPrefix + $cell.Value + $condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; Worksheet=$sheet; StopIfTrue=$true; Range=[OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[2]C[$($cell.start.column)]:R[1048576]C[$($cell.start.column)]",0,0)} + Add-ConditionalFormatting @condFormattingParams -ConditionValue ("OR(" +(($sameChecks -join ",") -replace '<>"Same"','="Added"' ) +")" ) -BackgroundColor $DeleteBackgroundColor + Add-ConditionalFormatting @condFormattingParams -ConditionValue ("AND(" +(($sameChecks -join ",") -replace '<>"Same"','="Changed"') +")" ) -BackgroundColor $ChangeBackgroundColor + } + #We've made a bunch of things wider so now is the time to autofit columns. Any hiding has to come AFTER this, because it unhides things + if ($env:NoAutoSize) {Write-Warning "Autofit is not available with this OS configuration."} + else {$sheet.Cells.AutoFitColumns()} + + #if we have a key field (we didn't concatenate all fields) use what we built up in $sameChecks to apply conditional formatting to it (Row no will be in column A, Key in Column B) + if ($Key -ne '*') { + Add-ConditionalFormatting -Worksheet $sheet -Range "B2:B1048576" -ForeGroundColor $KeyFontColor -BackgroundPattern 'None' -RuleType Expression -ConditionValue ("OR(" +($sameChecks -join ",") +")" ) + $sheet.view.FreezePanes(2, 3) + } + else {$sheet.view.FreezePanes(2, 2) } + #Go back over the headings to find and hide the "is" columns; + foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "\sIS$"}) ) { + $sheet.Column($cell.start.Column).HIDDEN = $true + } + + #If specified, look over the headings for "row" and hide the columns which say "this was in row such-and-such" + if ($HideRowNumbers) { + foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "Row$"}) ) { + $sheet.Column($cell.start.Column).HIDDEN = $true + } + } + if ($Passthru) {$excel} + else {Close-ExcelPackage -ExcelPackage $excel -Show:$Show} + Write-Progress -Activity "Merging sheets" -Completed + } + } diff --git a/Public/Merge-Worksheet.ps1 b/Public/Merge-Worksheet.ps1 new file mode 100644 index 00000000..4347061c --- /dev/null +++ b/Public/Merge-Worksheet.ps1 @@ -0,0 +1,263 @@ +function Merge-Worksheet { + [CmdletBinding(SupportsShouldProcess=$true)] + param( + [parameter(ParameterSetName='A',Mandatory=$true,Position=0)] #A = Compare two files default headers + [parameter(ParameterSetName='B',Mandatory=$true,Position=0)] #B = Compare two files user supplied headers + [parameter(ParameterSetName='C',Mandatory=$true,Position=0)] #C = Compare two files headers P1, P2, P3 etc + $Referencefile , + + [parameter(ParameterSetName='A',Mandatory=$true,Position=1)] + [parameter(ParameterSetName='B',Mandatory=$true,Position=1)] + [parameter(ParameterSetName='C',Mandatory=$true,Position=1)] + [parameter(ParameterSetName='E',Mandatory=$true,Position=1)] #D Compare two objects; E = Compare one object one file that uses default headers + [parameter(ParameterSetName='F',Mandatory=$true,Position=1)] #F = Compare one object one file that uses user supplied headers + [parameter(ParameterSetName='G',Mandatory=$true,Position=1)] #G Compare one object one file that uses headers P1, P2, P3 etc + $Differencefile , + + [parameter(ParameterSetName='A',Position=2)] #Applies to all sets EXCEPT D which is two objects (no sheets) + [parameter(ParameterSetName='B',Position=2)] + [parameter(ParameterSetName='C',Position=2)] + [parameter(ParameterSetName='E',Position=2)] + [parameter(ParameterSetName='F',Position=2)] + [parameter(ParameterSetName='G',Position=2)] + $WorksheetName = "Sheet1", + + [parameter(ParameterSetName='A')] #Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + [parameter(ParameterSetName='B')] + [parameter(ParameterSetName='C')] + [parameter(ParameterSetName='E')] + [parameter(ParameterSetName='F')] + [parameter(ParameterSetName='G')] + [int]$Startrow = 1, + + [Parameter(ParameterSetName='B',Mandatory=$true)] #Compare object + sheet or 2 sheets with user supplied headers + [Parameter(ParameterSetName='F',Mandatory=$true)] + [String[]]$Headername, + + [Parameter(ParameterSetName='C',Mandatory=$true)] #Compare object + sheet or 2 sheets with headers of P1, P2, P3 ... + [Parameter(ParameterSetName='G',Mandatory=$true)] + [switch]$NoHeader, + + [parameter(ParameterSetName='D',Mandatory=$true)] + [parameter(ParameterSetName='E',Mandatory=$true)] + [parameter(ParameterSetName='F',Mandatory=$true)] + [parameter(ParameterSetName='G',Mandatory=$true)] + [Alias('RefObject')] + $ReferenceObject , + [parameter(ParameterSetName='D',Mandatory=$true,Position=1)] + [Alias('DiffObject')] + $DifferenceObject , + [parameter(ParameterSetName='D',Position=2)] + [parameter(ParameterSetName='E',Position=2)] + [parameter(ParameterSetName='F',Position=2)] + [parameter(ParameterSetName='G',Position=2)] + $DiffPrefix = "=>" , + [parameter(Position=3)] + [Alias('OutFile')] + $OutputFile , + [parameter(Position=4)] + [Alias('OutSheet')] + $OutputSheetName = "Sheet1", + $Property = "*" , + $ExcludeProperty , + $Key = "Name" , + $KeyFontColor = [System.Drawing.Color]::DarkRed , + $ChangeBackgroundColor = [System.Drawing.Color]::Orange, + $DeleteBackgroundColor = [System.Drawing.Color]::LightPink, + $AddBackgroundColor = [System.Drawing.Color]::PaleGreen, + [switch]$HideEqual , + [switch]$Passthru , + [Switch]$Show + ) + + #region Read Excel data + if ($Differencefile -is [System.IO.FileInfo]) {$Differencefile = $Differencefile.FullName} + if ($Referencefile -is [System.IO.FileInfo]) {$Referencefile = $Referencefile.FullName} + if ($Referencefile -and $Differencefile) { + #if the filenames don't resolve, give up now. + try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)} + catch { Write-Warning -Message "Could not Resolve the filenames." ; return } + + #If we have one file , we must have two different Worksheet names. If we have two files $WorksheetName can be a single string or two strings. + if ($onefile -and ( ($WorksheetName.count -ne 2) -or $WorksheetName[0] -eq $WorksheetName[1] ) ) { + Write-Warning -Message "If both the Reference and difference file are the same then Worksheet name must provide 2 different names" + return + } + if ($WorksheetName.count -eq 2) {$Worksheet2 = $DiffPrefix = $WorksheetName[1] ; $Worksheet1 = $WorksheetName[0] ; } + elseif ($WorksheetName -is [string]) {$Worksheet2 = $Worksheet1 = $WorksheetName ; + $DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" } + else {Write-Warning -Message "You must provide either a single Worksheet name or two names." ; return } + + $params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop } + foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}} + try { + $ReferenceObject = Import-Excel -Path $Referencefile -WorksheetName $Worksheet1 @params + $DifferenceObject = Import-Excel -Path $Differencefile -WorksheetName $Worksheet2 @Params + } + catch {Write-Warning -Message "Could not read the Worksheet from $Referencefile::$Worksheet1 and/or $Differencefile::$Worksheet2." ; return } + if ($NoHeader) {$firstDataRow = $Startrow } else {$firstDataRow = $Startrow + 1} + } + elseif ( $Differencefile) { + if ($WorksheetName -isnot [string]) {Write-Warning -Message "You must provide a single Worksheet name." ; return } + $params = @{WorksheetName=$WorksheetName; Path=$Differencefile; ErrorAction=[System.Management.Automation.ActionPreference]::Stop } + foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}} + try {$DifferenceObject = Import-Excel @Params } + catch {Write-Warning -Message "Could not read the Worksheet '$WorksheetName' from $Differencefile::$WorksheetName." ; return } + if ($DiffPrefix -eq "=>" ) { + $DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" + } + if ($NoHeader) {$firstDataRow = $Startrow } else {$firstDataRow = $Startrow + 1} + } + else { $firstDataRow = 1 } + #endregion + + #region Set lists of properties and row numbers + #Make a list of properties/headings using the Property (default "*") and ExcludeProperty parameters + $propList = @() + $DifferenceObject = $DifferenceObject | Update-FirstObjectProperties + $headings = $DifferenceObject[0].psobject.Properties.Name # This preserves the sequence - using Get-member would sort them alphabetically! There may be extra properties in + if ($NoHeader -and "Name" -eq $Key) {$Key = "p1"} + if ($headings -notcontains $Key -and + ('*' -ne $Key)) {Write-Warning -Message "You need to specify one of the headings in the sheet '$Worksheet2' as a key." ; return } + foreach ($p in $Property) { $propList += ($headings.where({$_ -like $p}) )} + foreach ($p in $ExcludeProperty) { $propList = $propList.where({$_ -notlike $p}) } + if (($propList -notcontains $Key) -and + ('*' -ne $Key)) { $propList += $Key} #If $Key isn't one of the headings we will have bailed by now + $propList = $propList | Select-Object -Unique #so, prolist must contain at least $Key if nothing else + + #If key is "*" we treat it differently , and we will create a script property which concatenates all the Properties in $Proplist + $ConCatblock = [scriptblock]::Create( ($proplist | ForEach-Object {'$this."' + $_ + '"'}) -join " + ") + + #Build the list of the properties to output, in order. + $diffpart = @() + $refpart = @() + foreach ($p in $proplist.Where({$Key -ne $_}) ) {$refPart += $p ; $diffPart += "$DiffPrefix $p" } + $lastRefColNo = $proplist.count + $FirstDiffColNo = $lastRefColNo + 1 + + if ($Key -ne '*') { + $outputProps = @($Key) + $refpart + $diffpart + #If we are using a single column as the key, don't duplicate it, so the last difference column will be A if there is one property, C if there are two, E if there are 3 + $lastDiffColNo = (2 * $proplist.count) - 1 + } + else { + $outputProps = @( ) + $refpart + $diffpart + #If we not using a single column as a key all columns are duplicated so, the Last difference column will be B if there is one property, D if there are two, F if there are 3 + $lastDiffColNo = (2 * $proplist.count ) + } + + #Add RowNumber to every row + #If one sheet has extra rows we can get a single "==" result from compare, with the row from the reference sheet, but + #the row in the other sheet might be different so we will look up the row number from the key field - build a hash table for that here + #If we have "*" as the key ad the script property to concatenate the [selected] properties. + + $rowHash = @{} + $rowNo = $firstDataRow + foreach ($row in $ReferenceObject) { + if ($null -eq $row._row) {Add-Member -InputObject $row -MemberType NoteProperty -Value ($rowNo ++) -Name "_Row" } + else {$rowNo++ } + if ($Key -eq '*' ) {Add-Member -InputObject $row -MemberType ScriptProperty -Value $ConCatblock -Name "_All" } + } + $rowNo = $firstDataRow + foreach ($row in $DifferenceObject) { + Add-Member -InputObject $row -MemberType NoteProperty -Value $rowNo -Name "$DiffPrefix Row" -Force + if ($Key -eq '*' ) { + Add-Member -InputObject $row -MemberType ScriptProperty -Value $ConCatblock -Name "_All" + $rowHash[$row._All] = $rowNo + } + else {$rowHash[$row.$Key] = $rowNo } + $rowNo ++ + } + if ($DifferenceObject.count -gt $rowHash.Keys.Count) { + Write-Warning -Message "Difference object has $($DifferenceObject.Count) rows; but only $($rowHash.keys.count) unique keys" + } + if ($Key -eq '*') {$Key = "_ALL"} + #endregion + #We need to know all the properties we've met on the objects we've diffed + $eDiffProps = [ordered]@{} + #When we do a compare object changes will result in two rows so we group them and join them together. + $expandedDiff = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $propList -PassThru -IncludeEqual | + Group-Object -Property $Key | ForEach-Object { + #The value of the key column is the name of the Group. + $keyVal = $_.name + #we're going to create a custom object from a hash table. + $hash = [ordered]@{} + foreach ($result in $_.Group) { + if ($result.SideIndicator -ne "=>") {$hash["_Row"] = $result._Row } + elseif (-not $hash["$DiffPrefix Row"]) {$hash["_Row"] = "" } + #if we have already set the side, this must be the second record, so set side to indicate "changed"; if we got two "Same" indicators we may have a classh of keys + if ($hash.Side) { + if ($hash.Side -eq $result.SideIndicator) {Write-Warning -Message "'$keyVal' may be a duplicate."} + $hash.Side = "<>" + } + else {$hash["Side"] = $result.SideIndicator} + switch ($hash.side) { + '==' { $hash["$DiffPrefix is"] = 'Same' } + '=>' { $hash["$DiffPrefix is"] = 'Added' } + '<>' { if (-not $hash["_Row"]) { + $hash["$DiffPrefix is"] = 'Added' + } + else { + $hash["$DiffPrefix is"] = 'Changed' + } + } + '<=' { $hash["$DiffPrefix is"] = 'Removed'} + } + #find the number of the row in the the "difference" object which has this key. If it is the object is only in the reference this will be blank. + $hash["$DiffPrefix Row"] = $rowHash[$keyVal] + $hash[$Key] = $keyVal + #Create FieldName and/or =>FieldName columns + foreach ($p in $result.psobject.Properties.name.where({$_ -ne $Key -and $_ -ne "SideIndicator" -and $_ -ne "$DiffPrefix Row" })) { + if ($result.SideIndicator -eq "==" -and $p -in $propList) + {$hash[("$p")] = $hash[("$DiffPrefix $p")] = $result.$P} + elseif ($result.SideIndicator -eq "==" -or $result.SideIndicator -eq "<=") + {$hash[("$p")] = $result.$P} + elseif ($result.SideIndicator -eq "=>") { $hash[("$DiffPrefix $p")] = $result.$P} + } + } + + foreach ($k in $hash.keys) {$eDiffProps[$k] = $true} + [Pscustomobject]$hash + } | Sort-Object -Property "_row" + + #Already sorted by reference row number, fill in any blanks in the difference-row column. + for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."$DiffPrefix Row") {$expandedDiff[$i]."$DiffPrefix Row" = $expandedDiff[$i-1]."$DiffPrefix Row" } } + + #Now re-Sort by difference row number, and fill in any blanks in the reference-row column. + $expandedDiff = $expandedDiff | Sort-Object -Property "$DiffPrefix Row" + for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."_Row") {$expandedDiff[$i]."_Row" = $expandedDiff[$i-1]."_Row" } } + + $AllProps = @("_Row") + $OutputProps + $eDiffProps.keys.where({$_ -notin ($outputProps + @("_row","side","SideIndicator","_ALL" ))}) + + if ($PassThru -or -not $OutputFile) {return ($expandedDiff | Select-Object -Property $allprops | Sort-Object -Property "_row", "$DiffPrefix Row" ) } + elseif ($PSCmdlet.ShouldProcess($OutputFile,"Write Output to Excel file")) { + $expandedDiff = $expandedDiff | Sort-Object -Property "_row", "$DiffPrefix Row" + $xl = $expandedDiff | Select-Object -Property $OutputProps | Update-FirstObjectProperties | + Export-Excel -Path $OutputFile -WorksheetName $OutputSheetName -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter -PassThru + $ws = $xl.Workbook.Worksheets[$OutputSheetName] + for ($i = 0; $i -lt $expandedDiff.Count; $i++ ) { + if ( $expandedDiff[$i].side -ne "==" ) { + Set-ExcelRange -Worksheet $ws -Range ("A" + ($i + 2 )) -FontColor $KeyFontColor + } + elseif ( $HideEqual ) {$ws.row($i+2).hidden = $true } + if ( $expandedDiff[$i].side -eq "<>" ) { + $range = $ws.Dimension -replace "\d+", ($i + 2 ) + Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $ChangeBackgroundColor + } + elseif ( $expandedDiff[$i].side -eq "<=" ) { + $rangeR1C1 = "R[{0}]C[1]:R[{0}]C[{1}]" -f ($i + 2 ) , $lastRefColNo + $range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0) + Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $DeleteBackgroundColor + } + elseif ( $expandedDiff[$i].side -eq "=>" ) { + if ($propList.count -gt 1) { + $rangeR1C1 = "R[{0}]C[{1}]:R[{0}]C[{2}]" -f ($i + 2 ) , $FirstDiffColNo , $lastDiffColNo + $range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0) + Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $AddBackgroundColor + } + Set-ExcelRange -Worksheet $ws -Range ("A" + ($i + 2 )) -BackgroundColor $AddBackgroundColor + } + } + Close-ExcelPackage -ExcelPackage $xl -Show:$Show + } +} diff --git a/New-ConditionalFormattingIconSet.ps1 b/Public/New-ConditionalFormattingIconSet.ps1 similarity index 74% rename from New-ConditionalFormattingIconSet.ps1 rename to Public/New-ConditionalFormattingIconSet.ps1 index c355150c..26fde957 100644 --- a/New-ConditionalFormattingIconSet.ps1 +++ b/Public/New-ConditionalFormattingIconSet.ps1 @@ -1,10 +1,12 @@ function New-ConditionalFormattingIconSet { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change system State')] param( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] $Range, - [ValidateSet("ThreeIconSet","FourIconSet","FiveIconSet")] + [ValidateSet("ThreeIconSet", "FourIconSet", "FiveIconSet")] $ConditionalFormat, - [Switch]$Reverse + [Switch]$Reverse, + [Switch]$ShowIconOnly ) DynamicParam { @@ -39,13 +41,14 @@ function New-ConditionalFormattingIconSet { End { - $bp = @{}+$PSBoundParameters + $bp = @{} + $PSBoundParameters $obj = [PSCustomObject]@{ - Range = $Range - Formatter = $ConditionalFormat - IconType = $bp.IconType - Reverse = $Reverse + Range = $Range + Formatter = $ConditionalFormat + IconType = $bp.IconType + Reverse = $Reverse + ShowIconOnly = $ShowIconOnly } $obj.pstypenames.Clear() diff --git a/Public/New-ConditionalText.ps1 b/Public/New-ConditionalText.ps1 new file mode 100644 index 00000000..402310c8 --- /dev/null +++ b/Public/New-ConditionalText.ps1 @@ -0,0 +1,42 @@ +function New-ConditionalText { + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',Justification='Does not change system State')] + param( + #[Parameter(Mandatory=$true)] + [Alias('ConditionValue')] + $Text, + [Alias('ForeGroundColor')] + $ConditionalTextColor=[System.Drawing.Color]::DarkRed, + $BackgroundColor=[System.Drawing.Color]::LightPink, + [String]$Range, + [OfficeOpenXml.Style.ExcelFillStyle]$PatternType=[OfficeOpenXml.Style.ExcelFillStyle]::Solid, + [ValidateSet( + 'LessThan', 'LessThanOrEqual', 'GreaterThan', 'GreaterThanOrEqual', + 'Equal', 'NotEqual', + 'Top', 'TopPercent', 'Bottom', 'BottomPercent', + 'ContainsText', 'NotContainsText', 'BeginsWith', 'EndsWith', + 'ContainsBlanks', 'NotContainsBlanks', 'ContainsErrors', 'NotContainsErrors', + 'DuplicateValues', 'UniqueValues', + 'Tomorrow', 'Today', 'Yesterday', 'Last7Days', + 'NextWeek', 'ThisWeek', 'LastWeek', + 'NextMonth', 'ThisMonth', 'LastMonth', + 'AboveAverage', 'AboveOrEqualAverage', 'BelowAverage', 'BelowOrEqualAverage', + 'Expression' + )] + [Alias('RuleType')] + $ConditionalType='ContainsText' + ) + + $obj = [PSCustomObject]@{ + Text = $Text + ConditionalTextColor = $ConditionalTextColor + ConditionalType = $ConditionalType + PatternType = $PatternType + Range = $Range + BackgroundColor = $BackgroundColor + } + + $obj.pstypenames.Clear() + $obj.pstypenames.Add("ConditionalText") + $obj +} \ No newline at end of file diff --git a/Public/New-ExcelChartDefinition.ps1 b/Public/New-ExcelChartDefinition.ps1 new file mode 100644 index 00000000..f024b9b1 --- /dev/null +++ b/Public/New-ExcelChartDefinition.ps1 @@ -0,0 +1,88 @@ +function New-ExcelChartDefinition { + [Alias("New-ExcelChart")] #This was the former name. The new name reflects that we are defining a chart, not making one in the workbook. + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change system State')] + param( + $Title = "Chart Title", + $Header, + [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = "ColumnStacked", + [OfficeOpenXml.Drawing.Chart.eTrendLine[]]$ChartTrendLine, + $XRange, + $YRange, + $Width = 500, + $Height = 350, + $Row = 0, + $RowOffSetPixels = 10, + $Column = 6, + $ColumnOffSetPixels = 5, + [OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPosition, + $LegendSize, + [Switch]$LegendBold, + [Switch]$NoLegend, + [Switch]$ShowCategory, + [Switch]$ShowPercent, + $SeriesHeader, + [Switch]$TitleBold, + [Int]$TitleSize , + [String]$XAxisTitleText, + [Switch]$XAxisTitleBold, + $XAxisTitleSize , + [string]$XAxisNumberformat, + $XMajorUnit, + $XMinorUnit, + $XMaxValue, + $XMinValue, + [OfficeOpenXml.Drawing.Chart.eAxisPosition]$XAxisPosition , + [String]$YAxisTitleText, + [Switch]$YAxisTitleBold, + $YAxisTitleSize, + [string]$YAxisNumberformat, + $YMajorUnit, + $YMinorUnit, + $YMaxValue, + $YMinValue, + [OfficeOpenXml.Drawing.Chart.eAxisPosition]$YAxisPosition + ) + if ( $Header ) { Write-Warning "The header parameter is ignored." } #Nothing was done with it when creating a chart. + #might be able to do [PSCustomObject]$PsboundParameters, the defaults here match those in Add-Excel Chart + [PSCustomObject]@{ + Title = $Title + ChartType = $ChartType + ChartTrendLine = $ChartTrendLine + XRange = $XRange + YRange = $YRange + Width = $Width + Height = $Height + Row = $Row + RowOffSetPixels = $RowOffSetPixels + Column = $Column + ColumnOffSetPixels = $ColumnOffSetPixels + LegendPosition = $LegendPosition + LegendSize = $LegendSize + Legendbold = $LegendBold + NoLegend = $NoLegend -as [Boolean] + ShowCategory = $ShowCategory -as [Boolean] + ShowPercent = $ShowPercent -as [Boolean] + SeriesHeader = $SeriesHeader + TitleBold = $TitleBold -as [Boolean] + TitleSize = $TitleSize + XAxisTitleText = $XAxisTitleText + XAxisTitleBold = $XAxisTitleBold -as [Boolean] + XAxisTitleSize = $XAxisTitleSize + XAxisNumberformat = $XAxisNumberformat + XMajorUnit = $XMajorUnit + XMinorUnit = $XMinorUnit + XMaxValue = $XMaxValue + XMinValue = $XMinValue + XAxisPosition = $XAxisPosition + YAxisTitleText = $YAxisTitleText + YAxisTitleBold = $YAxisTitleBold -as [Boolean] + YAxisTitleSize = $YAxisTitleSize + YAxisNumberformat = $YAxisNumberformat + YMajorUnit = $YMajorUnit + YMinorUnit = $YMinorUnit + YMaxValue = $YMaxValue + YMinValue = $YMinValue + YAxisPosition = $YAxisPosition + } +} diff --git a/Public/New-ExcelStyle.ps1 b/Public/New-ExcelStyle.ps1 new file mode 100644 index 00000000..c64df403 --- /dev/null +++ b/Public/New-ExcelStyle.ps1 @@ -0,0 +1,48 @@ +function New-ExcelStyle { + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change system State')] + param ( + [Alias("Address")] + $Range , + [Alias("NFormat")] + $NumberFormat, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, + $BorderColor=[System.Drawing.Color]::Black, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight, + [Alias('ForegroundColor')] + $FontColor, + $Value, + $Formula, + [Switch]$ArrayFormula, + [Switch]$ResetFont, + [Switch]$Bold, + [Switch]$Italic, + [Switch]$Underline, + [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, + [Switch]$StrikeThru, + [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, + [String]$FontName, + [float]$FontSize, + $BackgroundColor, + [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , + [Alias("PatternColour")] + $PatternColor, + [Switch]$WrapText, + [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, + [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, + [ValidateRange(-90, 90)] + [int]$TextRotation , + [Alias("AutoFit")] + [Switch]$AutoSize, + [float]$Width, + [float]$Height, + [Alias('Hide')] + [Switch]$Hidden, + [Switch]$Locked, + [Switch]$Merge + ) + $PSBoundParameters +} \ No newline at end of file diff --git a/New-PSItem.ps1 b/Public/New-PSItem.ps1 similarity index 66% rename from New-PSItem.ps1 rename to Public/New-PSItem.ps1 index b186dcc2..7dd2653e 100644 --- a/New-PSItem.ps1 +++ b/Public/New-PSItem.ps1 @@ -1,5 +1,7 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope='Function', Target='New*', Justification='Does not change system State')] +param() function New-PSItem { - + param() $totalArgs = $args.Count if($args[-1] -is [array]) { diff --git a/Public/New-PivotTableDefinition.ps1 b/Public/New-PivotTableDefinition.ps1 new file mode 100644 index 00000000..0568cf0d --- /dev/null +++ b/Public/New-PivotTableDefinition.ps1 @@ -0,0 +1,77 @@ + +function New-PivotTableDefinition { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',Justification='Does not change system State')] + param( + [Parameter(Mandatory)] + [Alias("PivtoTableName")]#Previous typo - use alias to avoid breaking scripts + $PivotTableName, + $SourceWorksheet, + $SourceRange, + $PivotRows, + [hashtable]$PivotData, + $PivotColumns, + $PivotFilter, + [Switch]$PivotDataToColumn, + [ValidateSet("Both", "Columns", "Rows", "None")] + [String]$PivotTotals = "Both", + [Switch]$NoTotalsInPivot, + [String]$GroupDateRow, + [String]$GroupDateColumn, + [OfficeOpenXml.Table.PivotTable.eDateGroupBy[]]$GroupDatePart, + [String]$GroupNumericRow, + [String]$GroupNumericColumn, + [double]$GroupNumericMin = 0 , + [double]$GroupNumericMax = [Double]::MaxValue , + [double]$GroupNumericInterval = 100 , + [string]$PivotNumberFormat, + [OfficeOpenXml.Table.TableStyles]$PivotTableStyle, + [Parameter(ParameterSetName = 'ChartbyDef', Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + $PivotChartDefinition, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$IncludePivotChart, + [Parameter(ParameterSetName = 'ChartbyParams')] + [String]$ChartTitle, + [Parameter(ParameterSetName = 'ChartbyParams')] + [int]$ChartHeight = 400 , + [Parameter(ParameterSetName = 'ChartbyParams')] + [int]$ChartWidth = 600, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartRow = 0 , + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartColumn = 4, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartRowOffSetPixels = 0 , + [Parameter(ParameterSetName = 'ChartbyParams')] + [Int]$ChartColumnOffSetPixels = 0, + [Parameter(ParameterSetName = 'ChartbyParams')] + [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie', + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$NoLegend, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$ShowCategory, + [Parameter(ParameterSetName = 'ChartbyParams')] + [Switch]$ShowPercent, + [switch]$Activate + ) + $validDataFuntions = [system.enum]::GetNames([OfficeOpenXml.Table.PivotTable.DataFieldFunctions]) + + if ($PivotData.values.Where( {$_ -notin $validDataFuntions}) ) { + Write-Warning -Message ("Pivot data functions might not be valid, they should be one of " + ($validDataFuntions -join ", ") + ".") + } + + $parameters = @{} + $PSBoundParameters + if ($NoTotalsInPivot) { + $parameters.Remove('NoTotalsInPivot') + $parameters["PivotTotals"] = "None" + } + if ($PSBoundParameters.ContainsKey('ChartType') -and -not $PSBoundParameters.ContainsKey('IncludePivotChart')) { + $parameters['IncludePivotChart'] = $true + } + $parameters.Remove('PivotTableName') + if ($PivotChartDefinition) { + $parameters.PivotChartDefinition.XRange = $null + $parameters.PivotChartDefinition.YRange = $null + $parameters.PivotChartDefinition.SeriesHeader = $null + } + @{$PivotTableName = $parameters} +} diff --git a/Public/Open-ExcelPackage.ps1 b/Public/Open-ExcelPackage.ps1 new file mode 100644 index 00000000..7c0d077e --- /dev/null +++ b/Public/Open-ExcelPackage.ps1 @@ -0,0 +1,49 @@ +function Open-ExcelPackage { + [CmdLetBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + [OutputType([OfficeOpenXml.ExcelPackage])] + param( + #The path to the file to open. + [Parameter(Mandatory = $true)]$Path, + #If specified, any running instances of Excel will be terminated before opening the file. + [switch]$KillExcel, + #The password for a protected worksheet, as a [normal] string (not a secure string). + [String]$Password, + #By default Open-ExcelPackage will only opens an existing file; -Create instructs it to create a new file if required. + [switch]$Create + ) + + if ($KillExcel) { + Get-Process -Name "excel" -ErrorAction Ignore | Stop-Process + while (Get-Process -Name "excel" -ErrorAction Ignore) {} + } + + $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) + #If -Create was not specified only open the file if it exists already (send a warning if it doesn't exist). + if ($Create -and -not (Test-Path -Path $path)) { + #Create the directory if required. + $targetPath = Split-Path -Parent -Path $Path + if (!(Test-Path -Path $targetPath)) { + Write-Debug "Base path $($targetPath) does not exist, creating" + $null = New-item -ItemType Directory -Path $targetPath -ErrorAction Ignore + } + New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path + } + elseif (Test-Path -Path $path) { + if ($Password) { $pkgobj = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path , $Password } + else { $pkgobj = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path } + if ($pkgobj) { + foreach ($w in $pkgobj.Workbook.Worksheets) { + $sb = [scriptblock]::Create(('$this.workbook.Worksheets["{0}"]' -f $w.name)) + try { + Add-Member -InputObject $pkgobj -MemberType ScriptProperty -Name $w.name -Value $sb -ErrorAction Stop + } + catch { + Write-Warning "Could not add sheet $($w.name) as 'short cut', you need to access it via `$wb.Worksheets['$($w.name)'] " + } + } + return $pkgobj + } + } + else { Write-Warning "Could not find $path" } +} diff --git a/Public/Read-Clipboard.ps1 b/Public/Read-Clipboard.ps1 new file mode 100644 index 00000000..18f81607 --- /dev/null +++ b/Public/Read-Clipboard.ps1 @@ -0,0 +1,85 @@ +#Requires -Version 5 +function Read-Clipboard { + <# + .SYNOPSIS + Read text from clipboard and pass to either ConvertFrom-Csv or ConvertFrom-Json. + Check out the how to video - https://youtu.be/dv2GOH5sbpA + + .DESCRIPTION + Read text from clipboard. It can read CSV or JSON. Plus, you can specify the delimiter and headers. + + .EXAMPLE + Read-Clipboard # Detects if the clipboard contains CSV, JSON, or Tab delimited data. + + .EXAMPLE + Read-Clipboard -Delimiter '|' # Converts data using a pipe delimiter + + .EXAMPLE + Read-Clipboard -Header 'P1', 'P2', 'P3' # Specify the header columns to be used + + #> + param( + $Delimiter, + $Header + ) + + if ($IsLinux -or $IsMacOS) { + Write-Error "Read-Clipboard only runs on Windows" + return + } + + $cvtParams = @{ + Data = Get-Clipboard -Raw + } + + if ($Delimiter) { + $cvtParams.Delimiter = $Delimiter + } + + if ($Header) { + $cvtParams.Header = $Header + } + + ReadClipboardImpl @cvtParams +} + +function ReadClipboardImpl { + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String] $data, + $Delimiter, + $Header + ) + + if (!$PSBoundParameters.ContainsKey('Delimiter') -and !$PSBoundParameters.ContainsKey('Header')) { + try { + ConvertFrom-Json $data + } + catch { + $dataLines = @($data -split "`r`n?" | Select-Object -First 1) + + if ($dataLines[0].indexOf(',') -gt -1) { + ConvertFrom-Csv $data + } + else { + ConvertFrom-Csv $data -Delimiter "`t" + } + } + } + else { + $cvtParams = @{ + InputObject = $data + } + + if ($Delimiter) { + $cvtParams.Delimiter = $Delimiter + } + + if ($Header) { + $cvtParams.Header = $Header + } + + ConvertFrom-Csv @cvtParams + } +} \ No newline at end of file diff --git a/Public/Read-OleDbData.ps1 b/Public/Read-OleDbData.ps1 new file mode 100644 index 00000000..491b54c6 --- /dev/null +++ b/Public/Read-OleDbData.ps1 @@ -0,0 +1,54 @@ +#Requires -Version 5 +function Read-OleDbData { + <# + .SYNOPSIS + Read data from an OleDb source using dotnet classes. This allows for OleDb queries against excel spreadsheets. Examples will only be for querying xlsx files. + + For additional documentation, see Microsoft's documentation on the System.Data OleDb namespace here: + https://docs.microsoft.com/en-us/dotnet/api/system.data.oledb + + .DESCRIPTION + Read data from an OleDb source using dotnet classes. This allows for OleDb queries against excel spreadsheets. Examples will only be for querying xlsx files using ACE. + + .EXAMPLE + Read-OleDbData ` + -ConnectionString "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=file.xlsx;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" ` + -SqlStatement "select ROUND(F1) as [A] from [sheet1$A1:A1]" + + .EXAMPLE + $ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=file.xlsx;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" + $SqlStatement = "select ROUND(F1) as [A] from [sheet1$A1:A1]" + Read-OleDbData -ConnectionString $ConnectionString -SqlStatement $SqlStatement + + .EXAMPLE + $ReadDataArgs = @{ + SqlStatement = Get-Content query.sql -Raw + ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=file.xlsx;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" + } + $Results = Read-OleDbData @ReadDataArgs + #> + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String] $ConnectionString, + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String] $SqlStatement + ) + + try { + if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") { + Write-Warning "Microsoft.ACE.OLEDB.12.0 provider is missing! You will not be able to query Excel files without it. Please install from https://www.microsoft.com/en-us/download/details.aspx?id=54920" + } + } + catch { + Write-Error "System.Data.OleDb is not working or you are on an unsupported platform." + return + } + + $DataTable = new-object System.Data.DataTable + $DataAdapter = new-object System.Data.OleDb.OleDbDataAdapter $SqlStatement, $ConnectionString + $null = $DataAdapter.Fill($DataTable) + $null = $DataAdapter.Dispose() + $DataTable.Rows | Select-Object $DataTable.Columns.ColumnName +} \ No newline at end of file diff --git a/Public/Remove-Worksheet.ps1 b/Public/Remove-Worksheet.ps1 new file mode 100644 index 00000000..e8d0d8f5 --- /dev/null +++ b/Public/Remove-Worksheet.ps1 @@ -0,0 +1,28 @@ +function Remove-Worksheet { + [CmdletBinding(SupportsShouldProcess=$true)] + param( + # [Parameter(ValueFromPipelineByPropertyName)] + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('Path')] + $FullName, + [String[]]$WorksheetName = "Sheet1", + [Switch]$Show + ) + + Process { + if (!$FullName) { + throw "Remove-Worksheet requires the and Excel file" + } + + $pkg = Open-ExcelPackage -Path $FullName + + if ($pkg) { + foreach ($wsn in $WorksheetName) { + if ($PSCmdlet.ShouldProcess($FullName,"Remove Sheet $wsn")) { + $pkg.Workbook.Worksheets.Delete($wsn) + } + } + Close-ExcelPackage -ExcelPackage $pkg -Show:$Show + } + } +} \ No newline at end of file diff --git a/Public/Select-Worksheet.ps1 b/Public/Select-Worksheet.ps1 new file mode 100644 index 00000000..0385876f --- /dev/null +++ b/Public/Select-Worksheet.ps1 @@ -0,0 +1,24 @@ +function Select-Worksheet { + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Package', Position = 0)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Parameter(Mandatory = $true, ParameterSetName = 'Workbook')] + [OfficeOpenXml.ExcelWorkbook]$ExcelWorkbook, + [Parameter(ParameterSetName='Package')] + [Parameter(ParameterSetName='Workbook')] + [string]$WorksheetName, + [Parameter(ParameterSetName='Sheet',Mandatory=$true)] + [OfficeOpenXml.ExcelWorksheet]$ExcelWorksheet + ) + #if we were given a package, use its workbook + if ($ExcelPackage -and -not $ExcelWorkbook) {$ExcelWorkbook = $ExcelPackage.Workbook} + #if we now have workbook, get the worksheet; if we were given a sheet get the workbook + if ($ExcelWorkbook -and $WorksheetName) {$ExcelWorksheet = $ExcelWorkbook.Worksheets[$WorksheetName]} + elseif ($ExcelWorksheet -and -not $ExcelWorkbook) {$ExcelWorkbook = $ExcelWorksheet.Workbook ; } + #if we didn't get to a worksheet give up. If we did set all works sheets to not selected and then the one we want to selected. + if (-not $ExcelWorksheet) {Write-Warning -Message "The worksheet $WorksheetName was not found." ; return } + else { + foreach ($w in $ExcelWorkbook.Worksheets) {$w.View.TabSelected = $false} + $ExcelWorksheet.View.TabSelected = $true + } +} diff --git a/Public/Send-SQLDataToExcel.ps1 b/Public/Send-SQLDataToExcel.ps1 new file mode 100644 index 00000000..28121c9d --- /dev/null +++ b/Public/Send-SQLDataToExcel.ps1 @@ -0,0 +1,112 @@ +function Send-SQLDataToExcel { + [CmdletBinding(DefaultParameterSetName="none")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Justification="Allowed to use DBSessions Global variable from GETSQL Module")] + + param ( + [Parameter(ParameterSetName="SQLConnection", Mandatory=$true)] + [Parameter(ParameterSetName="ODBCConnection", Mandatory=$true)] + $Connection, + [Parameter(ParameterSetName="ExistingSession", Mandatory=$true)] + $Session, + [Parameter(ParameterSetName="SQLConnection", Mandatory=$true)] + [switch]$MsSqlServer, + [Parameter(ParameterSetName="SQLConnection")] + [String]$DataBase, + [Parameter(ParameterSetName="SQLConnection", Mandatory=$true)] + [Parameter(ParameterSetName="ODBCConnection", Mandatory=$true)] + [Parameter(ParameterSetName="ExistingSession", Mandatory=$true)] + [string]$SQL, + [int]$QueryTimeout, + [Parameter(ParameterSetName="Pre-FetchedData", Mandatory=$true)] + [System.Data.DataTable]$DataTable, + [switch]$Force + ) +#Import the parameters from Export-Excel, we will pass InputObject, and we have the common parameters so exclude those, +#and re-write the [Parmameter] attribute on each one to avoid parameterSetName here competing with the settings in Export excel. +#The down side of this that impossible parameter combinations won't be filtered out and need to be caught later. + DynamicParam { + $ParameterAttribute = "System.Management.Automation.ParameterAttribute" + $RuntimeDefinedParam = "System.Management.Automation.RuntimeDefinedParameter" + $paramDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary + $attributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute] + $attributeCollection.Add((New-Object -TypeName $ParameterAttribute -Property @{ ParameterSetName = "__AllParameterSets" ;Mandatory = $false})) + foreach ($P in (Get-Command -Name Export-Excel).Parameters.values.where({$_.name -notmatch 'Verbose|Debug|Action$|Variable$|Buffer$|TargetData$|InputObject$'})) { + $paramDictionary.Add($p.Name, (New-Object -TypeName $RuntimeDefinedParam -ArgumentList $p.name, $p.ParameterType, $attributeCollection ) ) + } + return $paramDictionary + } + process { + #region Dynamic params mean we can get passed parameter combination Export-Excel will reject, so throw here, rather than get data and then have Export-Excel error. + if ($PSBoundParameters.Path -and $PSBoundParameters.ExcelPackage) { + throw 'Parameter error: you cannot specify both a path and an Excel Package.' + return + } + if ($PSBoundParameters.AutoFilter -and ($PSBoundParameters.TableName -or $PSBoundParameters.TableStyle)) { + Write-Warning "Tables are automatically auto-filtered, -AutoFilter will be ignored" + $null = $PSBoundParameters.Remove('AutoFilter') + } + #endregion + #region if we were either given a session object or a connection string (& optionally -MsSqlServer) make sure we can connect + try { + #If we got -MsSqlServer, create a SQL connection, if we didn't but we got -Connection create an ODBC connection + if ($MsSqlServer -and $Connection) { + if ($Connection -notmatch '=') {$Connection = "server=$Connection;trusted_connection=true;timeout=60"} + $Session = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $Connection + if ($Session.State -ne 'Open') {$Session.Open()} + if ($DataBase) {$Session.ChangeDatabase($DataBase) } + } + elseif ($Connection) { + $Session = New-Object -TypeName System.Data.Odbc.OdbcConnection -ArgumentList $Connection ; $Session.ConnectionTimeout = 30 + } + } + catch { + Write-Warning "An Error occured trying to connect to $Connection, the error was $([Environment]::NewLine + $_.Exception.InnerException))" + } + if ($Session -is [String] -and $Global:DbSessions[$Session]) {$Session = $Global:DbSessions[$Session]} + #endregion + #region we may have been given a table, but if there is a db session to connect to, send the query + if ($Session) { + try { + #If the session a SQL one make a SQL DataAdapter, otherwise make an ODBC one + if ($Session.GetType().name -match "SqlConnection") { + $dataAdapter = New-Object -TypeName System.Data.SqlClient.SqlDataAdapter -ArgumentList ( + New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $SQL, $Session) + } + else { + $dataAdapter = New-Object -TypeName System.Data.Odbc.OdbcDataAdapter -ArgumentList ( + New-Object -TypeName System.Data.Odbc.OdbcCommand -ArgumentList $SQL, $Session ) + } + if ($QueryTimeout) {$dataAdapter.SelectCommand.CommandTimeout = $QueryTimeout} + + #Both adapter types output the same kind of table, create one and fill it from the adapter + $DataTable = New-Object -TypeName System.Data.DataTable + $rowCount = $dataAdapter.fill($dataTable) + Write-Verbose -Message "Query returned $rowCount row(s)" + } + catch { + Write-Warning "An Error occured trying to run the query, the error was $([Environment]::NewLine + $_.Exception.InnerException))" + } + } + #endregion + #region send the table to Excel + #remove parameters which relate to querying SQL, leaving the ones used by Export-Excel + 'Connection' , 'Database' , 'Session' , 'MsSqlServer' , 'SQL' , 'DataTable' , 'QueryTimeout' , 'Force' | + ForEach-Object {$null = $PSBoundParameters.Remove($_) } + #if force was specified export even if there are no rows. If there are no columns, the query failed and export "null" if forced + if ($DataTable.Rows.Count) { + Export-Excel @PSBoundParameters -InputObject $DataTable + } + elseif ($Force -and $DataTable.Columns.Count) { + Write-Warning -Message "Zero rows returned, and -Force was specified, sending empty table to Excel." + Export-Excel @PSBoundParameters -InputObject $DataTable + } + elseif ($Force) { + Write-Warning -Message "-Force was specified but there is no data to send." + Export-Excel @PSBoundParameters -InputObject $null + } + else {Write-Warning -Message 'There is no Data to insert, and -Force was not specified.' } + #endregion + #If we were passed a connection and opened a session, close that session. + if ($Connection) {$Session.close() } + } +} \ No newline at end of file diff --git a/Public/Set-CellComment.ps1 b/Public/Set-CellComment.ps1 new file mode 100644 index 00000000..06ab5fba --- /dev/null +++ b/Public/Set-CellComment.ps1 @@ -0,0 +1,70 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope='Function', Target='Set*', Justification='Does not change system state')] +param() + +function Set-CellComment { + [CmdletBinding(DefaultParameterSetName = "Range")] + param( + [Parameter(Mandatory = $True, ParameterSetName = "ColumnLetter")] + [Parameter(Mandatory = $True, ParameterSetName = "ColumnNumber")] + [Parameter(Mandatory = $False, ParameterSetName = "Range")] + [OfficeOpenXml.ExcelWorkSheet]$Worksheet, + + [Parameter(Mandatory = $True, ParameterSetName = "Range", ValueFromPipeline = $true,Position=0)] + [Alias("Address")] + $Range, + + [Parameter(Mandatory = $True, ParameterSetName = "ColumnLetter")] + [Parameter(Mandatory = $True, ParameterSetName = "ColumnNumber")] + [Int]$Row, + + [Parameter(Mandatory = $True, ParameterSetName = "ColumnLetter")] + [String]$ColumnLetter, + + [Parameter(Mandatory = $True, ParameterSetName = "ColumnNumber")] + [Int]$ColumnNumber, + + [Parameter(Mandatory = $True)] + [String]$Text + ) + + If ($PSCmdlet.ParameterSetName -eq "Range") { + Write-Verbose "Using 'Range' Parameter Set" + if ($Range -is [Array]) { + $null = $PSBoundParameters.Remove("Range") + $Range | Set-CellComment @PSBoundParameters + } + else { + #We should accept, a worksheet and a name of a range or a cell address; a table; the address of a table; a named range; a row, a column or .Cells[ ] + if ($Range -is [OfficeOpenXml.Table.ExcelTable]) {$Range = $Range.Address} + elseif ($Worksheet -and $Range -is [string]) { + # Convert range as string to OfficeOpenXml.ExcelAddress + $Range = [OfficeOpenXml.ExcelAddress]::new($Range) + } + elseif ($Range -is [string]) {Write-Warning -Message "The range parameter you have specified also needs a worksheet parameter." ;return} + #else we assume $Range is a OfficeOpenXml.ExcelAddress + } + } + ElseIf ($PSCmdlet.ParameterSetName -eq "ColumnNumber") { + $Range = [OfficeOpenXml.ExcelAddress]::new($Row, $ColumnNumber, $Row, $ColumnNumber) + } + ElseIf ($PSCmdlet.ParameterSetName -eq "ColumnLetter") { + $Range = [OfficeOpenXml.ExcelAddress]::new(("{0}{1}" -f $ColumnLetter,$Row)) + } + + If ($Range -isnot [Array]) { + Foreach ($c in $Worksheet.Cells[$Range]) { + write-verbose $c.address + Try { + If ($Null -eq $c.comment) { + [Void]$c.AddComment($Text, "ImportExcel") + } + Else { + $c.Comment.Text = $Text + $c.Comment.Author = "ImportExcel" + } + $c.Comment.AutoFit = $True + } + Catch { "Could not add comment to cell {0}: {1}" -f $c.Address, $_.ToString() } + } + } +} \ No newline at end of file diff --git a/Public/Set-CellStyle.ps1 b/Public/Set-CellStyle.ps1 new file mode 100644 index 00000000..02a48b06 --- /dev/null +++ b/Public/Set-CellStyle.ps1 @@ -0,0 +1,17 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope='Function', Target='Set*', Justification='Does not change system state')] +param() + +function Set-CellStyle { + [CmdletBinding()] + param( + $Worksheet, + $Row, + $LastColumn, + [OfficeOpenXml.Style.ExcelFillStyle]$Pattern, + $Color + ) + if ($Color -is [string]) {$Color = [System.Drawing.Color]::$Color } + $t=$Worksheet.Cells["A$($Row):$($LastColumn)$($Row)"] + $t.Style.Fill.PatternType=$Pattern + $t.Style.Fill.BackgroundColor.SetColor($Color) +} \ No newline at end of file diff --git a/Public/Set-ExcelColumn.ps1 b/Public/Set-ExcelColumn.ps1 new file mode 100644 index 00000000..46133ed1 --- /dev/null +++ b/Public/Set-ExcelColumn.ps1 @@ -0,0 +1,128 @@ +function Set-ExcelColumn { + [CmdletBinding()] + [Alias("Set-Column")] + [OutputType([OfficeOpenXml.ExcelColumn],[String])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingfunctions', '',Justification='Does not change system state')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification="Variables created for script block which may be passed as a parameter, but not used in the script")] + param( + [Parameter(ParameterSetName="Package",Mandatory=$true)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Parameter(ParameterSetName="Package")] + [String]$WorksheetName = "Sheet1", + [Parameter(ParameterSetName="sheet",Mandatory=$true)] + [OfficeOpenXml.ExcelWorksheet]$Worksheet, + [Parameter(ValueFromPipeline=$true)] + [ValidateRange(0,16384)] + $Column = 0 , + [ValidateRange(1,1048576)] + [Int]$StartRow , + $Value , + $Heading , + [Alias("NFormat")] + $NumberFormat, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, + $FontColor, + [Switch]$Bold, + [Switch]$Italic, + [Switch]$Underline, + [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, + [Switch]$StrikeThru, + [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, + [String]$FontName, + [float]$FontSize, + $BackgroundColor, + [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , + [Alias("PatternColour")] + $PatternColor, + [Switch]$WrapText, + [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, + [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, + [ValidateRange(-90, 90)] + [int]$TextRotation , + [Alias("AutoFit")] + [Switch]$AutoSize, + [float]$Width, + [Switch]$AutoNameRange, + [Alias('Hidden')] + [Switch]$Hide, + [Switch]$Specified, + [Switch]$PassThru + ) + + begin { + #if we were passed a package object and a worksheet name , get the worksheet. + if ($ExcelPackage) { + if ($ExcelPackage.Workbook.Worksheets.Name -notcontains $WorksheetName) { + throw "The Workbook does not contain a sheet named '$WorksheetName'" + } + else {$Worksheet = $ExcelPackage.Workbook.Worksheets[$WorksheetName] } + } + + #In a script block to build a formula, we may want any of corners or the column name, + #if Column and Startrow aren't specified, assume first unused column, and first row + if (-not $StartRow) {$startRow = $Worksheet.Dimension.Start.Row } + $startColumn = $Worksheet.Dimension.Start.Column + $endColumn = $Worksheet.Dimension.End.Column + $endRow = $Worksheet.Dimension.End.Row + } + process { + if ($null -eq $Worksheet.Dimension) {Write-Warning "Can't format an empty worksheet."; return} + if ($Column -eq 0 ) {$Column = $endColumn + 1 } + $columnName = (New-Object 'OfficeOpenXml.ExcelCellAddress' @(1, $column)).Address -replace "1","" + Write-Verbose -Message "Updating Column $columnName" + #If there is a heading, insert it and use it as the name for a range (if we're creating one) + if ($PSBoundParameters.ContainsKey('Heading')) { + $Worksheet.Cells[$StartRow, $Column].Value = $Heading + $StartRow ++ + if ($AutoNameRange) { + Add-ExcelName -Range $Worksheet.Cells[$StartRow, $Column, $endRow, $Column] -RangeName $Heading + } + } + elseif ($AutoNameRange) { + Add-ExcelName -Range $Worksheet.Cells[($StartRow+1), $Column, $endRow, $Column] -RangeName $Worksheet.Cells[$StartRow, $Column].Value + } + + #Fill in the data -it can be zero null or and empty string. + if ($PSBoundParameters.ContainsKey('Value')) { foreach ($row in ($StartRow..$endRow)) { + if ($Value -is [scriptblock]) { #re-create the script block otherwise variables from this function are out of scope. + $cellData = & ([scriptblock]::create( $Value )) + if ($null -eq $cellData) {Write-Verbose -Message "Script block evaluates to null."} + else {Write-Verbose -Message "Script block evaluates to '$cellData'"} + } + else { $cellData = $Value} + if ($cellData -match "^=") { $Worksheet.Cells[$Row, $Column].Formula = ($cellData -replace '^=','') } #EPPlus likes formulas with no = sign; Excel doesn't care + elseif ( [System.Uri]::IsWellFormedUriString($cellData , [System.UriKind]::Absolute)) { + # Save a hyperlink : internal links can be in the form xl://sheet!E419 (use A1 as goto sheet), or xl://RangeName + if ($cellData -match "^xl://internal/") { + $referenceAddress = $cellData -replace "^xl://internal/" , "" + $display = $referenceAddress -replace "!A1$" , "" + $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display + $Worksheet.Cells[$Row, $Column].HyperLink = $h + } + else {$Worksheet.Cells[$Row, $Column].HyperLink = $cellData } + $Worksheet.Cells[$Row, $Column].Style.Font.UnderLine = $true + $Worksheet.Cells[$Row, $Column].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) + } + else { $Worksheet.Cells[$Row, $Column].Value = $cellData } + if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized. + if ($cellData -is [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' } + }} + + #region Apply formatting + $params = @{} + foreach ($p in @('Underline','UnderLineType','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation', + 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor' + 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { + if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} + } + if ($params.Count) { + $theRange = "$columnName$StartRow`:$columnName$endRow" + Set-ExcelRange -Worksheet $Worksheet -Range $theRange @params + } + #endregion + if ($PSBoundParameters.ContainsKey('Hide')) {$Worksheet.Column($Column).Hidden = [bool]$Hide} + #return the new data if -passthru was specified. + if ($PassThru) { $Worksheet.Column($Column)} + elseif ($ReturnRange) { $theRange} + } +} \ No newline at end of file diff --git a/Public/Set-ExcelRange.ps1 b/Public/Set-ExcelRange.ps1 new file mode 100644 index 00000000..79d9e808 --- /dev/null +++ b/Public/Set-ExcelRange.ps1 @@ -0,0 +1,200 @@ +function Set-ExcelRange { + [CmdletBinding()] + [Alias("Set-Format")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',Justification='Does not change system state')] + param( + [Parameter(ValueFromPipeline = $true,Position=0)] + [Alias("Address")] + $Range , + [OfficeOpenXml.ExcelWorksheet]$Worksheet , + [Alias("NFormat")] + $NumberFormat, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, + $BorderColor=[System.Drawing.Color]::Black, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight, + [Alias('ForegroundColor')] + $FontColor, + $Value, + $Formula, + [Switch]$ArrayFormula, + [Switch]$ResetFont, + [Switch]$Bold, + [Switch]$Italic, + [Switch]$Underline, + [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, + [Switch]$StrikeThru, + [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, + [String]$FontName, + [float]$FontSize, + $BackgroundColor, + [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , + [Alias("PatternColour")] + $PatternColor, + [Switch]$WrapText, + [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, + [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, + [ValidateRange(-90, 90)] + [int]$TextRotation , + [Alias("AutoFit")] + [Switch]$AutoSize, + [float]$Width, + [float]$Height, + [Alias('Hide')] + [Switch]$Hidden, + [Switch]$Locked, + [Switch]$Merge + ) + process { + if ($Range -is [Array]) { + $null = $PSBoundParameters.Remove("Range") + $Range | Set-ExcelRange @PSBoundParameters + } + else { + #We should accept, a worksheet and a name of a range or a cell address; a table; the address of a table; a named range; a row, a column or .Cells[ ] + if ($Range -is [OfficeOpenXml.Table.ExcelTable]) {$Range = $Range.Address} + elseif ($Worksheet -and ($Range -is [string] -or $Range -is [OfficeOpenXml.ExcelAddress])) { + $Range = $Worksheet.Cells[$Range] + } + elseif ($Range -is [string]) {Write-Warning -Message "The range parameter you have specified also needs a worksheet parameter." ;return} + #else we assume $Range is a range. + if ($ClearAll) { + $Range.Clear() + } + if ($ResetFont) { + $Range.Style.Font.Color.SetColor( ([System.Drawing.Color]::Black)) + $Range.Style.Font.Bold = $false + $Range.Style.Font.Italic = $false + $Range.Style.Font.UnderLine = $false + $Range.Style.Font.Strike = $false + $Range.Style.Font.VerticalAlign = [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]::None + } + if ($PSBoundParameters.ContainsKey('Underline')) { + $Range.Style.Font.UnderLine = [boolean]$Underline + $Range.Style.Font.UnderLineType = $UnderLineType + } + if ($PSBoundParameters.ContainsKey('Bold')) { + $Range.Style.Font.Bold = [boolean]$bold + } + if ($PSBoundParameters.ContainsKey('Italic')) { + $Range.Style.Font.Italic = [boolean]$italic + } + if ($PSBoundParameters.ContainsKey('StrikeThru')) { + $Range.Style.Font.Strike = [boolean]$StrikeThru + } + if ($PSBoundParameters.ContainsKey('FontSize')){ + $Range.Style.Font.Size = $FontSize + } + if ($PSBoundParameters.ContainsKey('FontName')){ + $Range.Style.Font.Name = $FontName + } + if ($PSBoundParameters.ContainsKey('FontShift')){ + $Range.Style.Font.VerticalAlign = $FontShift + } + if ($PSBoundParameters.ContainsKey('FontColor')){ + if ($FontColor -is [string]) {$FontColor = [System.Drawing.Color]::$FontColor } + $Range.Style.Font.Color.SetColor( $FontColor) + } + if ($PSBoundParameters.ContainsKey('TextRotation')) { + $Range.Style.TextRotation = $TextRotation + } + if ($PSBoundParameters.ContainsKey('WrapText')) { + $Range.Style.WrapText = [boolean]$WrapText + } + if ($PSBoundParameters.ContainsKey('HorizontalAlignment')) { + $Range.Style.HorizontalAlignment = $HorizontalAlignment + } + if ($PSBoundParameters.ContainsKey('VerticalAlignment')) { + $Range.Style.VerticalAlignment = $VerticalAlignment + } + if ($PSBoundParameters.ContainsKey('Merge')) { + $Range.Merge = [boolean]$Merge + } + if ($PSBoundParameters.ContainsKey('Value')) { + if ($Value -match '^=') {$PSBoundParameters["Formula"] = $Value -replace '^=','' } + else { + $Range.Value = $Value + if ($Value -is [datetime]) { $Range.Style.Numberformat.Format = 'm/d/yy h:mm' }# This is not a custom format, but a preset recognized as date and localized. It might be overwritten in a moment + if ($Value -is [timespan]) { $Range.Style.Numberformat.Format = '[h]:mm:ss' } + } + } + if ($PSBoundParameters.ContainsKey('Formula')) { + if ($ArrayFormula) {$Range.CreateArrayFormula(($Formula -replace '^=','')) } + else {$Range.Formula = ($Formula -replace '^=','') } + } + if ($PSBoundParameters.ContainsKey('NumberFormat')) { + $Range.Style.Numberformat.Format = (Expand-NumberFormat $NumberFormat) + } + if ($BorderColor -is [string]) {$BorderColor = [System.Drawing.Color]::$BorderColor } + if ($PSBoundParameters.ContainsKey('BorderAround')) { + $Range.Style.Border.BorderAround($BorderAround, $BorderColor) + } + if ($PSBoundParameters.ContainsKey('BorderBottom')) { + $Range.Style.Border.Bottom.Style=$BorderBottom + $Range.Style.Border.Bottom.Color.SetColor($BorderColor) + } + if ($PSBoundParameters.ContainsKey('BorderTop')) { + $Range.Style.Border.Top.Style=$BorderTop + $Range.Style.Border.Top.Color.SetColor($BorderColor) + } + if ($PSBoundParameters.ContainsKey('BorderLeft')) { + $Range.Style.Border.Left.Style=$BorderLeft + $Range.Style.Border.Left.Color.SetColor($BorderColor) + } + if ($PSBoundParameters.ContainsKey('BorderRight')) { + $Range.Style.Border.Right.Style=$BorderRight + $Range.Style.Border.Right.Color.SetColor($BorderColor) + } + if ($PSBoundParameters.ContainsKey('BackgroundColor')) { + $Range.Style.Fill.PatternType = $BackgroundPattern + if ($BackgroundColor -is [string]) {$BackgroundColor = [System.Drawing.Color]::$BackgroundColor } + $Range.Style.Fill.BackgroundColor.SetColor($BackgroundColor) + if ($PatternColor) { + if ($PatternColor -is [string]) {$PatternColor = [System.Drawing.Color]::$PatternColor } + $Range.Style.Fill.PatternColor.SetColor( $PatternColor) + } + } + if ($PSBoundParameters.ContainsKey('Height')) { + if ($Range -is [OfficeOpenXml.ExcelRow] ) {$Range.Height = $Height } + elseif ($Range -is [OfficeOpenXml.ExcelRange] ) { + ($Range.Start.Row)..($Range.Start.Row + $Range.Rows) | + ForEach-Object {$Range.Worksheet.Row($_).Height = $Height } + } + else {Write-Warning -Message ("Can set the height of a row or a range but not a {0} object" -f ($Range.GetType().name)) } + } + if ($Autosize -and -not $env:NoAutoSize) { + try { + if ($Range -is [OfficeOpenXml.ExcelColumn]) {$Range.AutoFit() } + elseif ($Range -is [OfficeOpenXml.ExcelRange] ) { + $Range.AutoFitColumns() + + } + else {Write-Warning -Message ("Can autofit a column or a range but not a {0} object" -f ($Range.GetType().name)) } + } + catch {Write-Warning -Message "Failed autosizing columns of worksheet '$WorksheetName': $_"} + } + elseif ($AutoSize) {Write-Warning -Message "Auto-fitting columns is not available with this OS configuration." } + elseif ($PSBoundParameters.ContainsKey('Width')) { + if ($Range -is [OfficeOpenXml.ExcelColumn]) {$Range.Width = $Width} + elseif ($Range -is [OfficeOpenXml.ExcelRange] ) { + ($Range.Start.Column)..($Range.Start.Column + $Range.Columns - 1) | + ForEach-Object { + #$ws.Column($_).Width = $Width + $Range.Worksheet.Column($_).Width = $Width + } + } + else {Write-Warning -Message ("Can set the width of a column or a range but not a {0} object" -f ($Range.GetType().name)) } + } + if ($PSBoundParameters.ContainsKey('Hidden')) { + if ($Range -is [OfficeOpenXml.ExcelRow] -or + $Range -is [OfficeOpenXml.ExcelColumn] ) {$Range.Hidden = [boolean]$Hidden} + else {Write-Warning -Message ("Can hide a row or a column but not a {0} object" -f ($Range.GetType().name)) } + } + if ($PSBoundParameters.ContainsKey('Locked')) { + $Range.Style.Locked=$Locked + } + } + } +} diff --git a/Public/Set-ExcelRow.ps1 b/Public/Set-ExcelRow.ps1 new file mode 100644 index 00000000..11b7de0b --- /dev/null +++ b/Public/Set-ExcelRow.ps1 @@ -0,0 +1,125 @@ +function Set-ExcelRow { + [CmdletBinding()] + [Alias("Set-Row")] + [OutputType([OfficeOpenXml.ExcelRow],[String])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingfunctions', '',Justification='Does not change system state')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification="Variables created for script block which may be passed as a parameter, but not used in the script")] + param( + [Parameter(ParameterSetName="Package",Mandatory=$true)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + [Parameter(ParameterSetName="Package")] + $WorksheetName = "Sheet1", + [Parameter(ParameterSetName="Sheet",Mandatory=$true)] + [OfficeOpenXml.Excelworksheet] $Worksheet, + [Parameter(ValueFromPipeline = $true)] + $Row = 0 , + [int]$StartColumn, + $Value, + $Heading , + [Switch]$HeadingBold, + [Int]$HeadingSize , + [Alias("NFormat")] + $NumberFormat, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, + $BorderColor=[System.Drawing.Color]::Black, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft, + [OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight, + $FontColor, + [Switch]$Bold, + [Switch]$Italic, + [Switch]$Underline, + [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, + [Switch]$StrikeThru, + [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, + [String]$FontName, + [float]$FontSize, + $BackgroundColor, + [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , + [Alias("PatternColour")] + $PatternColor, + [Switch]$WrapText, + [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, + [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, + [ValidateRange(-90, 90)] + [int]$TextRotation , + [float]$Height, + [Alias('Hidden')] + [Switch]$Hide, + [Switch]$ReturnRange, + [Switch]$PassThru + ) + begin { + #if we were passed a package object and a worksheet name , get the worksheet. + if ($ExcelPackage) { + if ($ExcelPackage.Workbook.Worksheets.Name -notcontains $WorksheetName) { + throw "The Workbook does not contain a sheet named '$WorksheetName'" + } + else {$Worksheet = $ExcelPackage.Workbook.Worksheets[$WorksheetName] } + } + #In a script block to build a formula, we may want any of corners or the columnname, + #if row and start column aren't specified assume first unused row, and first column + if (-not $StartColumn) {$StartColumn = $Worksheet.Dimension.Start.Column } + $startRow = $Worksheet.Dimension.Start.Row + 1 + $endColumn = $Worksheet.Dimension.End.Column + $endRow = $Worksheet.Dimension.End.Row + } + process { + if ($null -eq $Worksheet.Dimension) {Write-Warning "Can't format an empty worksheet."; return} + if ($Row -eq 0 ) {$Row = $endRow + 1 } + Write-Verbose -Message "Updating Row $Row" + #Add a row label + if ($Heading) { + $Worksheet.Cells[$Row, $StartColumn].Value = $Heading + if ($HeadingBold) {$Worksheet.Cells[$Row, $StartColumn].Style.Font.Bold = $true} + if ($HeadingSize) {$Worksheet.Cells[$Row, $StartColumn].Style.Font.Size = $HeadingSize} + $StartColumn ++ + } + #Fill in the data + if ($PSBoundParameters.ContainsKey('Value')) {foreach ($column in ($StartColumn..$endColumn)) { + #We might want the column name in a script block + $columnName = (New-Object -TypeName OfficeOpenXml.ExcelCellAddress @(1,$column)).Address -replace "1","" + if ($Value -is [scriptblock] ) { + #re-create the script block otherwise variables from this function are out of scope. + $cellData = & ([scriptblock]::create( $Value )) + if ($null -eq $cellData) {Write-Verbose -Message "Script block evaluates to null."} + else {Write-Verbose -Message "Script block evaluates to '$cellData'"} + } + else{$cellData = $Value} + if ($cellData -match "^=") { $Worksheet.Cells[$Row, $column].Formula = ($cellData -replace '^=','') } #EPPlus likes formulas with no = sign; Excel doesn't care + elseif ( [System.Uri]::IsWellFormedUriString($cellData , [System.UriKind]::Absolute)) { + # Save a hyperlink : internal links can be in the form xl://sheet!E419 (use A1 as goto sheet), or xl://RangeName + if ($cellData -match "^xl://internal/") { + $referenceAddress = $cellData -replace "^xl://internal/" , "" + $display = $referenceAddress -replace "!A1$" , "" + $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display + $Worksheet.Cells[$Row, $Column].HyperLink = $h + } + else {$Worksheet.Cells[$Row, $Column].HyperLink = $cellData } + $Worksheet.Cells[$Row, $Column].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) + $Worksheet.Cells[$Row, $Column].Style.Font.UnderLine = $true + } + else { $Worksheet.Cells[$Row, $column].Value = $cellData } + if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $column].Style.Numberformat.Format = 'm/d/yy h:mm' } #This is not a custom format, but a preset recognized as date and localized. + if ($cellData -is [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' } + }} + #region Apply formatting + $params = @{} + foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize', 'FontShift','NumberFormat','TextRotation', + 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor' + 'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor', + 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { + if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} + } + if ($params.Count) { + $theRange = New-Object -TypeName OfficeOpenXml.ExcelAddress @($Row, $StartColumn, $Row, $endColumn) + Set-ExcelRange -Worksheet $Worksheet -Range $theRange @params + } + #endregion + if ($PSBoundParameters.ContainsKey('Hide')) {$Worksheet.Row($Row).Hidden = [bool]$Hide} + #return the new data if -passthru was specified. + if ($passThru) {$Worksheet.Row($Row)} + elseif ($ReturnRange) {$theRange} + } +} \ No newline at end of file diff --git a/Public/Set-WorksheetProtection.ps1 b/Public/Set-WorksheetProtection.ps1 new file mode 100644 index 00000000..7cb7db5b --- /dev/null +++ b/Public/Set-WorksheetProtection.ps1 @@ -0,0 +1,55 @@ +function Set-WorksheetProtection { + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingfunctions', '',Justification='Does not change system state')] + param ( + [Parameter(Mandatory=$true)] + [OfficeOpenXml.ExcelWorksheet]$Worksheet , + [switch]$IsProtected, + [switch]$AllowAll, + [switch]$BlockSelectLockedCells, + [switch]$BlockSelectUnlockedCells, + [switch]$AllowFormatCells, + [switch]$AllowFormatColumns, + [switch]$AllowFormatRows, + [switch]$AllowInsertColumns, + [switch]$AllowInsertRows, + [switch]$AllowInsertHyperlinks, + [switch]$AllowDeleteColumns, + [switch]$AllowDeleteRows, + [switch]$AllowSort, + [switch]$AllowAutoFilter, + [switch]$AllowPivotTables, + [switch]$BlockEditObject, + [switch]$BlockEditScenarios, + [string]$LockAddress, + [string]$UnLockAddress + ) + + if ($PSBoundParameters.ContainsKey('isprotected') -and $IsProtected -eq $false) {$worksheet.Protection.IsProtected = $false} + elseif ($IsProtected) { + $worksheet.Protection.IsProtected = $true + foreach ($ParName in @('AllowFormatCells', + 'AllowFormatColumns', 'AllowFormatRows', + 'AllowInsertColumns', 'AllowInsertRows', 'AllowInsertHyperlinks', + 'AllowDeleteColumns', 'AllowDeleteRows', + 'AllowSort' , 'AllowAutoFilter', 'AllowPivotTables')) { + if ($AllowAll -and -not $PSBoundParameters.ContainsKey($Parname)) {$worksheet.Protection.$ParName = $true} + elseif ($PSBoundParameters[$ParName] -eq $true ) {$worksheet.Protection.$ParName = $true} + } + if ($BlockSelectLockedCells) {$worksheet.Protection.AllowSelectLockedCells = $false } + if ($BlockSelectUnlockedCells) {$worksheet.Protection.AllowSelectUnLockedCells = $false } + if ($BlockEditObject) {$worksheet.Protection.AllowEditObject = $false } + if ($BlockEditScenarios) {$worksheet.Protection.AllowEditScenarios = $false } + } + Else {Write-Warning -Message "You haven't said if you want to turn protection off, or on." } + + if ($LockAddress) { + Set-ExcelRange -Range $Worksheet.cells[$LockAddress] -Locked + } + elseif ($IsProtected) { + Set-ExcelRange -Range $Worksheet.Cells -Locked + } + if ($UnlockAddress) { + Set-ExcelRange -Range $Worksheet.cells[$UnlockAddress] -Locked:$false + } +} \ No newline at end of file diff --git a/Public/Update-FirstObjectProperties.ps1 b/Public/Update-FirstObjectProperties.ps1 new file mode 100644 index 00000000..d24758c7 --- /dev/null +++ b/Public/Update-FirstObjectProperties.ps1 @@ -0,0 +1,32 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope='Function', Target='Update*', Justification='Does not change system state')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Scope='Function', Target='Update*', Justification='Property would be incorrect')] + +param() + +function Update-FirstObjectProperties { + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$true)] + $InputObject + ) + begin { $union = New-Object -TypeName System.Collections.ArrayList } + process { + try { + If ($union.Count -eq 0) { + [void]$union.Add($InputObject) + $memberNames = (Get-Member -InputObject $InputObject -MemberType Properties).Name + } + else { + foreach ($propName in (Get-Member -InputObject $InputObject -MemberType Properties).Name) { + if ($propName -notin $memberNames) { + Add-Member -InputObject $Union[0] -MemberType NoteProperty -Name $propName -Value $Null + $memberNames += $propName + } + } + [void]$Union.Add($InputObject) + } + } + catch {throw "Failed updating the properties of the first object: $_"} + } + end { $Union } +} \ No newline at end of file diff --git a/PublishToGallery.ps1 b/PublishToGallery.ps1 index cc352c2f..0b55bd13 100644 --- a/PublishToGallery.ps1 +++ b/PublishToGallery.ps1 @@ -1,7 +1,6 @@ $p = @{ - Name = "ImportExcel" + Name = "ImportExcel" NuGetApiKey = $NuGetApiKey - ReleaseNote = "Add NumberFormat parameter" } Publish-Module @p \ No newline at end of file diff --git a/README.md b/README.md index 0320c2d2..01b50a21 100644 --- a/README.md +++ b/README.md @@ -1,795 +1,194 @@ -PowerShell Import-Excel -- +# PowerShell and Excel -## Build Status +![](images/logoWithInstall.png) -[![Build status](https://ci.appveyor.com/api/projects/status/21hko6eqtpccrkba?svg=true)](https://ci.appveyor.com/project/dfinke/importexcel) +
    -Install from the [PowerShell Gallery](https://www.powershellgallery.com/packages/ImportExcel/). +Has the ImportExcel module helped you? +- Made you look good to the boss? +- Saved you time? +- Made you more productive? -This PowerShell Module allows you to read and write Excel files without installing Microsoft Excel on your system. No need to bother with the cumbersome Excel COM-object. Creating Tables, Pivot Tables, Charts and much more has just become a lot easier. +Consider donating. Thank you! +
    +
    +Donate +
    +
    +![](https://media.giphy.com/media/hpXxJ78YtpT0s/giphy.gif) +
    +
    -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/testimonial.png) +[![Follow on Twitter](https://img.shields.io/twitter/follow/dfinke.svg?style=social&label=Follow%20%40dfinke)](https://twitter.com/dfinke) +[![Subscribe on YouTube](https://img.shields.io/youtube/channel/subscribers/UCP47ZkO5EDkoI2sr-3P4ShQ +)](https://youtube.com/@dougfinke/) +
    +
    +[![](https://img.shields.io/powershellgallery/v/ImportExcel.svg)](https://www.powershellgallery.com/packages/ImportExcel) +[![](https://img.shields.io/powershellgallery/dt/ImportExcel.svg)](https://www.powershellgallery.com/packages/ImportExcel) +Donate -# How to Vidoes -* [PowerShell Excel Module - ImportExcel](https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq) +# Overview -Installation -- -#### [PowerShell V5](https://www.microsoft.com/en-us/download/details.aspx?id=50395) and Later -You can install the `ImportExcel` module directly from the PowerShell Gallery +Automate Excel with PowerShell without having Excel installed. Works on Windows, Linux and Mac. Creating Tables, Pivot Tables, Charts and much more just got a lot easier. -* [Recommended] Install to your personal PowerShell Modules folder -```PowerShell -Install-Module ImportExcel -scope CurrentUser -``` -* [Requires Elevation] Install for Everyone (computer PowerShell Modules folder) -```PowerShell -Install-Module ImportExcel -``` - -#### PowerShell V4 and Earlier -To install to your personal modules folder (e.g. ~\Documents\WindowsPowerShell\Modules), run: - -```PowerShell -iex (new-object System.Net.WebClient).DownloadString('https://raw.github.com/dfinke/ImportExcel/master/Install.ps1') -``` - -# What's new - -- [James O'Neill](https://twitter.com/jamesoneill) added `Compare-Worksheet` - - Compares two worksheets with the same name in different files. +## Examples ✨ +Check out the [more than 100 examples](Examples/) on ways to create amazing reports as well as make you more productive with PowerShell and Excel. -#### 4/22/2018 -Thanks to the community yet again -- [ili101](https://github.com/ili101) for fixes and features - - Removed `[PSPlot]` as OutputType. Fixes it throwing an error -- [Nasir Zubair](https://github.com/nzubair) added `ConvertEmptyStringsToNull` to the function `ConvertFrom-ExcelToSQLInsert` - - If specified, cells without any data are replaced with NULL, instead of an empty string. This is to address behviors in certain DBMS where an empty string is insert as 0 for INT column, instead of a NULL value. - - -#### 4/10/2018 --New parameter `-ReZip`. It ReZips the xlsx so it can be imported to PowerBI - -Thanks to [Justin Grote](https://github.com/JustinGrote) for finding and fixing the error that Excel files created do not import to PowerBI online. Plus, thank you to [CrashM](https://github.com/CrashM) for confirming the fix. - -Super helpful! - -#### 3/31/2018 -- Updated `Set-Format` - * Added parameters to set borders for cells, including top, bottm, left and right - * Added parameters to set `value` and `formula` +# Basic Usage +## Installation ```powershell -$data = @" -From,To,RDollars,RPercent,MDollars,MPercent,Revenue,Margin -Atlanta,New York,3602000,.0809,955000,.09,245,65 -New York,Washington,4674000,.105,336000,.03,222,16 -Chicago,New York,4674000,.0804,1536000,.14,550,43 -New York,Philadelphia,12180000,.1427,-716000,-.07,321,-25 -New York,San Francisco,3221000,.0629,1088000,.04,436,21 -New York,Phoneix,2782000,.0723,467000,.10,674,33 -"@ +Install-Module -Name ImportExcel ``` -![](https://github.com/dfinke/ImportExcel/blob/master/images/CustomReport.png?raw=true) - - -- Added `-PivotFilter` parameter, allows you to set up a filter so you can drill down into a subset of the overall dataset. +## Create a spreadsheet +Here is a quick example that will create spreadsheet file from CSV data. Works with JSON, Databases, and more. ```powershell -$data =@" -Region,Area,Product,Units,Cost -North,A1,Apple,100,.5 -South,A2,Pear,120,1.5 -East,A3,Grape,140,2.5 -West,A4,Banana,160,3.5 -North,A1,Pear,120,1.5 -North,A1,Grape,140,2.5 +$data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 "@ -``` - -![](https://github.com/dfinke/ImportExcel/blob/master/images/PivotTableFilter.png?raw=true) - - -#### 3/14/2018 -- Thank you to [James O'Neill](https://twitter.com/jamesoneill), fixed bugs with ChangeDatabase parameter which would prevent it working - -#### -* Added -Force to New-Alias -* Add example to set the background color of a column -* Supports excluding Row Grand Totals for PivotTables -* Allow xlsm files to be read -* Fix `Set-Column.ps1`, `Set-Row.ps1`, `SetFormat.ps1`, `formatting.ps1` **$falsee** and **$BorderRound** -#### 1/1/2018 -* Added switch `[Switch]$NoTotalsInPivot`. Allows hiding of the row totals in the pivot table. -Thanks you to [jameseholt](https://github.com/jameseholt) for the request. -```powershell - get-process | where Company | select Company, Handles, WorkingSet | - export-excel C:\temp\testColumnGrand.xlsx ` - -Show -ClearSheet -KillExcel ` - -IncludePivotTable -PivotRows Company -PivotData @{"Handles"="average"} -NoTotalsInPivot +$data | Export-Excel .\salesData.xlsx ``` -* Fixed when using certain a `ChartType` for the Pivot Table Chart, would throw an error -* Fixed - when you specify a file, and the directory does not exit, it now creates it - -#### 11/23/2017 -More great additions and thanks to [James O'Neill](https://twitter.com/jamesoneill) - -* Added `Convert-XlRangeToImage` Gets the specified part of an Excel file and exports it as an image -* Fixed a typo in the message at line 373. -* Now catch an attempt to both clear the sheet and append to it. -* Fixed some issues when appending to sheets where the header isn't in row 1 or the data doesn't start in column 1. -* Added support for more settings when creating a pivot chart. -* Corrected a typo PivotTableName was PivtoTableName in definition of New-PivotTableDefinition -* Add-ConditionalFormat and Set-Format added to the parameters so each has the choice of working more like the other. -* Added Set-Row and Set-Column - fill a formula down or across. -* Added Send-SQLDataToExcel. Insert a rowset and then call Export-Excel for ranges, charts, pivots etc - -#### 10/30/2017 -Huge thanks to [James O'Neill](https://twitter.com/jamesoneill). PowerShell aficionado. He always brings a flare when working with PowerShell. This is no exception. - -(Check out the examples `help Export-Excel -Examples`) - -* New parameter `Package` allows an ExcelPackage object returned by `-passThru` to be passed in -* New parameter `ExcludeProperty` to remove unwanted properties without needing to go through `select-object` -* New parameter `Append` code to read the existing headers and move the insertion point below the current data -* New parameter `ClearSheet` which removes the worksheet and any past data +![](images/salesdata.png) -* Remove any existing Pivot table before trying to [re]create it -* Check for inserting a pivot table so if `-InsertPivotChart` is specified it implies `-InsertPivotTable` +## Read a spreadsheet -(Check out the examples `help Export-Excel -Examples`) - -* New function `Export-Charts` (requires Excel to be installed) - Export Excel charts out as JPG files -* New function `Add-ConditionalFormatting` Adds contitional formatting to worksheet -* New function `Set-Format` Applies Number, font, alignment and colour formatting to a range of Excel Cells -* `ColorCompletion` an argument completer for `Colors` for params across functions - -I also worked out the parameters so you can do this, which is the same as passing `-Now`. It creates an Excel file name for you, does an auto fit and sets up filters. - -`ps | select Company, Handles | Export-Excel` - -#### 10/13/2017 -Added `New-PivotTableDefinition`. You can create and wire up a PivotTable to a WorkSheet. You can also create as many PivotTable Worksheets to point a one Worksheet. Or, you create many Worksheets and many corresponding PivotTable Worksheets. - -Here you can create a WorkSheet with the data from `Get-Service`. Then create four PivotTables, pointing to the data each pivoting on a differnt dimension and showing a differnet chart +Quickly read a spreadsheet document into a PowerShell array. ```powershell -$base = @{ - SourceWorkSheet = 'gsv' - PivotData = @{'Status' = 'count'} - IncludePivotChart = $true -} - -$ptd = [ordered]@{} - -$ptd += New-PivotTableDefinition @base servicetype -PivotRows servicetype -ChartType Area3D -$ptd += New-PivotTableDefinition @base status -PivotRows status -ChartType PieExploded3D -$ptd += New-PivotTableDefinition @base starttype -PivotRows starttype -ChartType BarClustered3D -$ptd += New-PivotTableDefinition @base canstop -PivotRows canstop -ChartType ConeColStacked - -Get-Service | Export-Excel -path $file -WorkSheetname gsv -Show -PivotTableDefinition $ptd -``` - -#### 10/4/2017 -Thanks to https://github.com/ili101 : -- Fix Bug, Unable to find type [PSPlot] -- Fix Bug, AutoFilter with TableName create corrupted Excel file. - -#### 10/2/2017 -Thanks to [Jeremy Brun](https://github.com/jeremytbrun) -Fixed issues related to use of -Title parameter combined with column formatting parameters. -- [Issue #182](https://github.com/dfinke/ImportExcel/issues/182) -- [Issue #89](https://github.com/dfinke/ImportExcel/issues/89) - -#### 9/28/2017 (Version 4.0.1) -- Added a new parameter called `Password` to import password protected files -- Added even more `Pester` tests for a more robust and bug free module -- Renamed parameter 'TopRow' to 'StartRow' - This allows us to be more concise when new parameters ('StartColumn', ..) will be added in the future Your code will not break after the update, because we added an alias for backward compatibility - -Special thanks to [robinmalik](https://github.com/robinmalik) for providing us with [the code](https://github.com/dfinke/ImportExcel/issues/174) to implement this new feature. A high five to [DarkLite1](https://github.com/DarkLite1) for the implementation. - -#### 9/12/2017 (Version 4.0.0) - -Super thanks and hat tip to [DarkLite1](https://github.com/DarkLite1). There is now a new and improved `Import-Excel`, not only in functionality, but also improved readability, examples and more. Not only that, he's been running it in production in his company for a number of weeks! - -*Added* `Update-FirstObjectProperties` Updates the first object to contain all the properties of the object with the most properties in the array. Check out the help. - - -***Breaking Changes***: Due to a big portion of the code that is rewritten some slightly different behavior can be expected from the `Import-Excel` function. This is especially true for importing empty Excel files with or without using the `TopRow` parameter. To make sure that your code is still valid, please check the examples in the help or the accompanying `Pester` test file. - - -Moving forward, we are planning to include automatic testing with the help of `Pester`, `Appveyor` and `Travis`. From now on any changes in the module will have to be accompanied by the corresponding `Pester` tests to avoid breakages of code and functionality. This is in preparation for new features coming down the road. - -#### 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. The function converts the older Excel file format ending in `.xls` to the new format ending in `.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 fantastic to work with people like `DarkLite1` in the community, to help make the module 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 if it was possible to import an Excel worksheet and transform the data into SQL `INSERT` statements. We can now answer that question with a big 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` function and you can use a scriptblock to format the data however you want. - -```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" -} -``` -Generates - -``` -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 -* TableName with parameter validation, throws an error when the TableName: - - Starts with something else then a letter - - Is NULL or empty - - Contains spaces -- Numeric parsing now uses `CurrentInfo` to use the system settings - -#### 2/14/2017 -Big thanks to [DarkLite1](https://github.com/DarkLite1) for some great updates -* `-DataOnly` switch added to `Import-Excel`. When used it will only generate objects for rows that contain text values, not for empty rows or columns. - -* `Get-ExcelWorkBookInfo` - retrieves information of an Excel workbook. -``` - Get-ExcelWorkbookInfo .\Test.xlsx - - CorePropertiesXml : #document - Title : - Subject : - Author : Konica Minolta User - Comments : - Keywords : - LastModifiedBy : Bond, James (London) GBR - LastPrinted : 2017-01-21T12:36:11Z - Created : 17/01/2017 13:51:32 - Category : - Status : - ExtendedPropertiesXml : #document - Application : Microsoft Excel - HyperlinkBase : - AppVersion : 14.0300 - Company : Secret Service - Manager : - Modified : 10/02/2017 12:45:37 - CustomPropertiesXml : #document -``` - -#### 12/22/2016 -- Added `-Now` switch. This short cuts the process, automatically creating a temp file and enables the `-Show`, `-AutoFilter`, `-AutoSize` switches. - -```PowerShell -Get-Process | Select Company, Handles | Export-Excel -Now -``` - -- Added ScriptBlocks for coloring cells. Check out [Examples](https://github.com/dfinke/ImportExcel/tree/master/Examples/FormatCellStyles) - -```PowerShell -Get-Process | - Select-Object Company,Handles,PM, NPM| - Export-Excel $xlfile -Show -AutoSize -CellStyleSB { - param( - $workSheet, - $totalRows, - $lastColumn - ) - - Set-CellStyle $workSheet 1 $LastColumn Solid Cyan - - foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 0})) { - Set-CellStyle $workSheet $row $LastColumn Solid Gray - } - - foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 1})) { - Set-CellStyle $workSheet $row $LastColumn Solid LightGray - } - } -``` -![](https://github.com/dfinke/ImportExcel/blob/master/images/CellFormatting.png?raw=true) +$data = Import-Excel .\salesData.xlsx -#### 9/28/2016 -[Fixed](https://github.com/dfinke/ImportExcel/pull/126) PowerShell 3.0 compatibility. Thanks to [headsphere](https://github.com/headsphere). He used `$obj.PSObject.Methods[$target]` snytax to make it backward compatible. PS v4.0 and later allow `$obj.$target`. - -Thank you to [xelsirko](https://github.com/xelsirko) for fixing - *Import-module importexcel gives version warning if started inside background job* - -#### 8/12/2016 -[Fixed](https://github.com/dfinke/ImportExcel/issues/115) reading the headers from cells, moved from using `Text` property to `Value` property. - -#### 7/30/2016 -* Added `Copy-ExcelWorksheet`. Let's you copy a work sheet from one Excel workbook to another. - -#### 7/21/2016 -* Fixes `Import-Excel` #68 - -#### 7/7/2016 -[Attila Mihalicz](https://github.com/attilamihalicz) fixed two issues - -* Removing extra spaces after the backtick -* Uninitialized variable $idx leaks into the pipeline when `-TableName` parameter is used - -Thanks Attila. - - -#### 7/1/2016 -* Pushed 2.2.7 fixed resolve path in Get-ExcelSheetInfo -* Fixed [Casting Error in Export-Excel](https://github.com/dfinke/ImportExcel/issues/108) -* For `Import-Excel` change Resolve-Path to return ProviderPath for use with UNC - -#### 6/01/2016 -* Added -UseDefaultCredentials to both `Import-Html` and `Get-HtmlTable` -* New functions, `Import-UPS` and `Import-USPS`. Pass in a valid tracking # and it scrapes the page for the delivery details - -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/Tracking.gif) - -#### 4/30/2016 -Huge thank you to [Willie Möller](https://github.com/W1M0R) - -* He added a version check so the PowerShell Classes don't cause issues for downlevel version of PowerShell -* He also contributed the first Pester tests for the module. Super! Check them out, they'll be the way tests will be implemented going forward - -#### 4/18/2016 -Thanks to [Paul Williams](https://github.com/pauldalewilliams) for this feature. Now data can be transposed to columns for better charting. - -```PowerShell -$file = "C:\Temp\ps.xlsx" -rm $file -ErrorAction Ignore - -ps | - where company | - select Company,PagedMemorySize,PeakPagedMemorySize | - Export-Excel $file -Show -AutoSize ` - -IncludePivotTable ` - -IncludePivotChart ` - -ChartType ColumnClustered ` - -PivotRows Company ` - -PivotData @{PagedMemorySize='sum';PeakPagedMemorySize='sum'} +$data ``` -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PivotAsRows.png) - - -Add `-PivotDataToColumn` - -```PowerShell -$file = "C:\Temp\ps.xlsx" -rm $file -ErrorAction Ignore - -ps | - where company | - select Company,PagedMemorySize,PeakPagedMemorySize | - Export-Excel $file -Show -AutoSize ` - -IncludePivotTable ` - -IncludePivotChart ` - -ChartType ColumnClustered ` - -PivotRows Company ` - -PivotData @{PagedMemorySize='sum';PeakPagedMemorySize='sum'} ` - -PivotDataToColumn -``` -And here is the new chart view -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PivotAsColumns.png) -#### 4/7/2016 -Made more methods fluent -``` -$t=Get-Range 0 5 .2 - -$t2=$t|%{$_*$_} -$t3=$t|%{$_*$_*$_} - -(New-Plot). - Plot($t,$t, $t,$t2, $t,$t3). - SetChartPosition("i"). - SetChartSize(500,500). - Title("Hello World"). - Show() -``` -#### 3/31/2016 -* Thanks to [redoz](https://github.com/redoz) Multi Series Charts are now working - -Also check out how you can create a table and then with Excel notation, index into the data for charting `"Impressions[A]"` +```powershell +Region State Units Price +------ ----- ----- ----- +West Texas 927 923.71 +North Tennessee 466 770.67 +East Florida 520 458.68 +East Maine 828 661.24 +West Virginia 465 053.58 +North Missouri 436 235.67 +South Kansas 214 992.47 +North North Dakota 789 640.72 +South Delaware 712 508.55 ``` -$data = @" -A,B,C,Date -2,1,1,2016-03-29 -5,10,1,2016-03-29 -"@ | ConvertFrom-Csv - -$c = New-ExcelChart -Title Impressions ` - -ChartType Line -Header "Something" ` - -XRange "Impressions[Date]" ` - -YRange @("Impressions[B]","Impressions[A]") - -$data | - Export-Excel temp.xlsx -AutoSize -TableName Impressions -Show -ExcelChartDefinition $c -``` -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/MultiSeries.gif) - -#### 3/26/2016 -* Added `NumberFormat` parameter - -``` -$data | - Export-Excel -Path $file -Show -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' -``` -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/Formatting.png) - - -#### 3/18/2016 -* Added `Get-Range`, `New-Plot` and Plot Cos example -* Updated EPPlus DLL. Allows markers to be changed and colored -* Handles and warns if auto name range names are also valid Excel ranges - -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PSPlot.gif) - -#### 3/7/2016 -* Added `Header` and `FirstDataRow` for `Import-Html` - -#### 3/2/2016 -* Added `GreaterThan`, `GreaterThanOrEqual`, `LessThan`, `LessThanOrEqual` to `New-ConditionalText` - -```PowerShell -echo 489 668 299 777 860 151 119 497 234 788 | - Export-Excel c:\temp\test.xlsx -Show ` - -ConditionalText (New-ConditionalText -ConditionalType GreaterThan 525) -``` -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/GTConditional.png) -#### 2/22/2016 -* `Import-Html` using Lee Holmes [Extracting Tables from PowerShell’s Invoke-WebRequest](http://www.leeholmes.com/blog/2015/01/05/extracting-tables-from-PowerShells-invoke-webrequest/) +## Add a chart to spreadsheet -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/ImportHtml.gif) +Chart generation is as easy as 123. Building charts based on data in your worksheet doesn't get any easier. -#### 2/17/2016 -* Added Conditional Text types of `Equal` and `NotEqual` -* Phone #'s like '+33 011 234 34' will be now be handled correctly +Plus, it is automated and repeatable. -## Try *PassThru* - -```PowerShell -$file = "C:\Temp\passthru.xlsx" -rm $file -ErrorAction Ignore - -$xlPkg = $( - New-PSItem north 10 - New-PSItem east 20 - New-PSItem west 30 - New-PSItem south 40 -) | Export-Excel $file -PassThru - -$ws=$xlPkg.Workbook.Worksheets[1] - -$ws.Cells["A3"].Value = "Hello World" -$ws.Cells["B3"].Value = "Updating cells" -$ws.Cells["D1:D5"].Value = "Data" - -$ws.Cells.AutoFitColumns() +```powershell +$data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ -$xlPkg.Save() -$xlPkg.Dispose() +$chart = New-ExcelChartDefinition -XRange State -YRange Units -Title "Units by State" -NoLegend -Invoke-Item $file +$data | Export-Excel .\salesData.xlsx -AutoNameRange -ExcelChartDefinition $chart -Show ``` -## Result -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PassThru.png) - -#### 1/18/2016 - -* Added `Conditional Text Formatting`. [Boe Prox](https://twitter.com/proxb) posted about [HTML Reporting, Part 2: Take Your Reporting a Step Further](https://mcpmag.com/articles/2016/01/14/html-reporting-part-2.aspx) and colorized cells. Great idea, now part of the PowerShell Excel module. - -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/ConditionalText2.gif) - -#### 1/7/2016 -* Added `Get-ExcelSheetInfo` - Great contribution from *Johan Åkerström* check him out on [GitHub](https://github.com/CosmosKey) and [Twitter](https://twitter.com/neptune443) - -![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/GetExcelSheetInfo.png) - -#### 12/26/2015 +![](images/SalesDataChart.png) -* Added `NoLegend`, `Show-Category`, `ShowPercent` for all charts including Pivot Charts -* Updated PieChart, BarChart, ColumnChart and Line chart to work with the pipeline and added `NoLegend`, `Show-Category`, `ShowPercent` +## Add a pivot table to spreadsheet -#### 12/17/2015 +Categorize, sort, filter, and summarize any amount data with pivot tables. Then add charts. -These new features open the door for really sophisticated work sheet creation. - -Stay tuned for a [blog post](http://www.dougfinke.com/blog/) and examples. - -***Quick List*** -* StartRow, StartColumn for placing data anywhere in a sheet -* New-ExcelChart - Add charts to a sheet, multiple series for a chart, locate the chart anywhere on the sheet -* AutoNameRange, Use functions and/or calculations in a cell -* Quick charting using PieChart, BarChart, ColumnChart and more - -![](https://raw.githubusercontent.com/dfinke/GifCam/master/JustCharts.gif) - -#### 10/20/2015 - -Big bug fix for version 3.0 PowerShell folks! - -This technique fails in 3.0 and works in 4.0 and later. -```PowerShell -$m="substring" -"hello".$m(2,1) -``` - -Adding `.invoke` works in 3.0 and later. +```powershell +$data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ -```PowerShell -$m="substring" -"hello".$m.invoke(2,1) +$data | Export-Excel .\salesData.xlsx -AutoNameRange -Show -PivotRows Region -PivotData @{'Units'='sum'} -PivotChartType PieExploded3D ``` -A ***big thank you*** to [DarkLite1](https://github.com/DarkLite1) for adding the help to Export-Excel. - -Added `-HeaderRow` parameter. Sometimes the heading does not start in Row 1. - - -#### 10/16/2015 - -Fixes [Export-Excel generates corrupt Excel file](https://github.com/dfinke/ImportExcel/issues/46) - -#### 10/15/2015 - -`Import-Excel` has a new parameter `NoHeader`. If data in the sheet does not have headers and you don't want to supply your own, `Import-Excel` will generate the property name. - -`Import-Excel` now returns `.Value` rather than `.Text` - - -#### 10/1/2015 - -Merged ValidateSet for Encoding and Extension. Thank you [Irwin Strachan](https://github.com/irwins). - -#### 9/30/2015 - -Export-Excel can now handle data that is **not** an object - - echo a b c 1 $true 2.1 1/1/2015 | Export-Excel c:\temp\test.xlsx -Show -Or - - dir -Name | Export-Excel c:\temp\test.xlsx -Show - -#### 9/25/2015 - -**Hide worksheets** -Got a great request from [forensicsguy20012004](https://github.com/forensicsguy20012004) to hide worksheets. You create a few pivotables, generate charts and then pivotable worksheets don't need to be visible. +![](images/SalesDataChartPivotTable.png) -`Export-Excel` now has a `-HideSheet` parameter that takes and array of worksheet names and hides them. +# Convert Excel data to other formats -##### Example -Here, you create four worksheets named `PM`,`Handles`,`Services` and `Files`. +## Create a separate CSV file for each Excel sheet -The last line creates the `Files` sheet and then hides the `Handles`,`Services` sheets. +Do you have an Excel file with multiple sheets and you need to convert each sheet to CSV file? - $p = Get-Process +### Problem Solved - $p|select company, pm | Export-Excel $xlFile -WorkSheetname PM - $p|select company, handles| Export-Excel $xlFile -WorkSheetname Handles - Get-Service| Export-Excel $xlFile -WorkSheetname Services +The [yearlyRetailSales.xlsx](Examples/Import-Excel) has 12 sheets of retail data for the year. - dir -File | Export-Excel $xlFile -WorkSheetname Files -Show -HideSheet Handles, Services +This single line of PowerShell converts any number of sheets in an Excel workbook to separate CSV files. - -**Note** There is a bug in EPPlus that does not let you hide the first worksheet created. Hopefully it'll resolved soon. - -#### 9/11/2015 - -Added Conditional formatting. See [TryConditional.ps1](https://github.com/dfinke/ImportExcel/blob/master/TryConditional.ps1) as an example. - -Or, check out the short ***"How To"*** video. - -[![image](http://www.dougfinke.com/videos/excelpsmodule/ExcelPSModule_First_Frame.png)](http://www.dougfinke.com/videos/excelpsmodule/excelpsmodule.mp4) - - -#### 8/21/2015 -* Now import Excel sheets even if the file is open in Excel. Thank you [Francois Lachance-Guillemette](https://github.com/francoislg) - -#### 7/09/2015 -* For -PivotRows you can pass a `hashtable` with the name of the property and the type of calculation. `Sum`, `Average`, `Max`, `Min`, `Product`, `StdDev`, `StdDevp`, `Var`, `Varp` - -```PowerShell -Get-Service | - Export-Excel "c:\temp\test.xlsx" ` - -Show ` - -IncludePivotTable ` - -PivotRows status ` - -PivotData @{status='count'} +```powershell +(Import-Excel .\yearlyRetailSales.xlsx *).GetEnumerator() | +ForEach-Object { $_.Value | Export-Csv ($_.key + '.csv') } ``` -#### 6/16/2015 (Thanks [Justin](https://github.com/zippy1981)) -* Improvements to PivotTable overwriting -* Added two parameters to Export-Excel - * RangeName - Turns the data piped to Export-Excel into a named range. - * TableName - Turns the data piped to Export-Excel into an excel table. - -Examples - - Get-Process|Export-Excel foo.xlsx -Verbose -IncludePivotTable -TableName "Processes" -Show - Get-Process|Export-Excel foo.xlsx -Verbose -IncludePivotTable -RangeName "Processes" -Show - - -#### 5/25/2015 -* Fixed null header problem - -#### 5/17/2015 -* Added three parameters: - * FreezeTopRow - Freezes the first row of the data - * AutoFilter - Enables filtering for the data in the sheet - * BoldTopRow - Bolds the top row of data, the column headers - -Example - - Get-CimInstance win32_service | - select state, accept*, start*, caption | - Export-Excel test.xlsx -Show -BoldTopRow -AutoFilter -FreezeTopRow -AutoSize - -![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/FilterFreezeBold.gif) - - -#### 5/4/2015 -* Published to PowerShell Gallery. In PowerShell v5 use `Find-Module importexcel` then `Find-Module importexcel | Install-Module` - - -#### 4/27/2015 -* datetime properties were displaying as ints, now are formatted - -#### 4/25/2015 -* Now you can create multiple Pivot tables in one pass - * Thanks to [pscookiemonster](https://twitter.com/pscookiemonster), he submitted a repro case to the EPPlus CodePlex project and got it fixed - -#### Example - - $ps = ps - - $ps | - Export-Excel .\testExport.xlsx -WorkSheetname memory ` - -IncludePivotTable -PivotRows Company -PivotData PM ` - -IncludePivotChart -ChartType PieExploded3D - $ps | - Export-Excel .\testExport.xlsx -WorkSheetname handles ` - -IncludePivotTable -PivotRows Company -PivotData Handles ` - -IncludePivotChart -ChartType PieExploded3D -Show - -![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/MultiplePivotTables.png) - -#### 4/20/2015 -* Included and embellished [Claus Nielsen](https://github.com/Claustn) function to take all sheets in an Excel file workbook and create a text file for each `ConvertFrom-ExcelSheet` -* Renamed `Export-MultipleExcelSheets` to `ConvertFrom-ExcelSheet` - -#### 4/13/2015 -* You can add a title to the Excel "Report" `Title`, `TitleFillPattern`, `TitleBold`, `TitleSize`, `TitleBackgroundColor` - * Thanks to [Irwin Strachan](http://pshirwin.wordpress.com) for this and other great suggestions, testing and more - - -#### 4/10/2015 -* Renamed `AutoFitColumns` to `AutoSize` -* Implemented `Export-MultipleExcelSheets` -* Implemented `-Password` for a worksheet -* Replaced `-Force` switch with `-NoClobber` switch -* Added examples for `Get-Help` -* If Pivot table is requested, that sheet becomes the tab selected - -#### 4/8/2015 -* Implemented exporting data to **named sheets** via the -WorkSheetname parameter. - -Examples -- -`gsv | Export-Excel .\test.xlsx -WorkSheetname Services` - -`dir -file | Export-Excel .\test.xlsx -WorkSheetname Files` - -`ps | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM` - -#### Convert (All or Some) Excel Sheets to Text files - -Reads each sheet in TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt - - ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data - -Reads and outputs sheets like Sheet10 and Sheet20 form TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt - - ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data sheet?0 - -#### Example Adding a Title -You can set the pattern, size and of if the title is bold. - - $p=@{ - Title = "Process Report as of $(Get-Date)" - TitleFillPattern = "LightTrellis" - TitleSize = 18 - TitleBold = $true - - Path = "$pwd\testExport.xlsx" - Show = $true - AutoSize = $true - } - - Get-Process | - Where Company | Select Company, PM | - Export-Excel @p - -![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/Title.png) - -#### Example Export-MultipleExcelSheets -![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/ExportMultiple.gif) - - $p = Get-Process - - $DataToGather = @{ - PM = {$p|select company, pm} - Handles = {$p|select company, handles} - Services = {gsv} - Files = {dir -File} - Albums = {(Invoke-RestMethod http://www.dougfinke.com/PowerShellfordevelopers/albums.js)} - } - - Export-MultipleExcelSheets -Show -AutoSize .\testExport.xlsx $DataToGather - - +# Additional Resources -***NOTE*** If the sheet exists when using *-WorkSheetname* parameter, it will be deleted and then added with the new data. +## Videos -## Get-Process Exported to Excel +- [Export-Excel Hello World](https://youtu.be/fvKKdIzJCws?list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq) +- [Make Excel Data Pop](https://youtu.be/gQaYI5hxqM4?list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq) +- [Slice And Dice Data](https://youtu.be/kzllxvqr3TY?list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq) +- [Lightning talk - PowerShell Excel Module](https://youtu.be/znVu2q11Rp4?list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq) -### Total Physical Memory Grouped By Company -![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PivotTablesAndCharts.png) +## More Videos -## Importing data from an Excel spreadsheet +- [Look smarter: deliver your work in Excel](https://youtu.be/tu8Mfkwi8zI) - James O'Neill [@jamesoneill](https://twitter.com/jamesoneill) +- [Module Monday: ImportExcel](https://youtu.be/rBA_IeTmCb8?t=5) - Adam Driscoll [@adamdriscoll](https://twitter.com/adamdriscoll) +- [Tutorials Excel Module Part 1](https://youtu.be/2cwBuYbZ3To) +- [Tutorials Excel Module Part 2](https://youtu.be/8ojg-qjOnVI) +- [Tutorials Excel Module Part 3](https://youtu.be/3IgASPD0UrQ) +- [PowerShell Excel - Invoke-ExcelQuery](https://youtu.be/_7xuhsZm0Ao) +- [Powershell Excel - Data Validation](https://youtu.be/NGhahuY8j1M) +- [Creating Dashboards xPlatform](https://youtu.be/qMWkZt6ikgM) -![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/TryImportExcel.gif) +## Articles -You can also find EPPLus on [Nuget](https://www.nuget.org/packages/EPPlus/). +|Title|Author|Twitter| +|------|------|------| +|[More tricks with PowerShell and Excel](https://jamesone111.wordpress.com/2018/05/31/more-tricks-with-powershell-and-excel/)|James O'Neill|[@jamesoneill](https://twitter.com/jamesoneill)| +|[Using the Import-Excel module: Part 1 Importing](https://jamesone111.wordpress.com/2017/12/05/using-the-import-excel-part-1-importing/)|James O'Neill|[@jamesoneill](https://twitter.com/jamesoneill)| +|[Using the Import Excel module part 2: putting data into .XLSx files](https://jamesone111.wordpress.com/2017/12/11/using-the-import-excel-module-part-2-putting-data-into-xlsx-files/)|James O'Neill|[@jamesoneill](https://twitter.com/jamesoneill)| +|[Using the import Excel Module: Part 3, Pivots and charts, data and calculations](https://jamesone111.wordpress.com/2017/12/12/using-the-import-excel-module-part-3-pivots-and-charts-data-and-calculations/)|James O'Neill|[@jamesoneill](https://twitter.com/jamesoneill)| +|[Export AdventureWorksDW2017 to Excel for a Power BI Demo with Export-Excel](https://sqlvariant.com/2019/03/export-adventureworksdw2017-to-excel-for-a-powerbi-demo-with-export-excel-in-powershell/)|Aaron Nelson|[@sqlvariant](https://twitter.com/sqlvariant) +|[Creating beautiful Powershell Reports in Excel](https://dfinke.github.io/powershell/2019/07/31/Creating-beautiful-Powershell-Reports-in-Excel.html)|Doug Finke|[@dfinke](https://twitter.com/dfinke) +|[PowerShell Excel and Conditional Formatting](https://dfinke.github.io/powershell/2020/05/02/PowerShell-Excel-and-Conditional-Formatting.html)|Doug Finke|[@dfinke](https://twitter.com/dfinke) +|[Learn to Automate Excel like a Pro with PowerShell](https://dfinke.github.io/powershell/2019/08/29/Learn-to-Automate-Excel-like-a-Pro-with-PowerShell.html)|Doug Finke|[@dfinke](https://twitter.com/dfinke) -## Known Issues +## Contributing +Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change. -* Using `-IncludePivotTable`, if that pivot table name exists, you'll get an error. - * Investigating a solution - * *Workaround* delete the Excel file first, then do the export +Original [README.md](./README.original.md) \ No newline at end of file diff --git a/README.original.md b/README.original.md new file mode 100644 index 00000000..0c2648dd --- /dev/null +++ b/README.original.md @@ -0,0 +1,1253 @@ +# PowerShell + Excel = Better Together + + +Automate Excel via PowerShell without having Excel installed. Runs on Windows, Linux and MAC. Creating Tables, Pivot Tables, Charts and much more has just become a lot easier. + +
    + +[![](https://img.shields.io/powershellgallery/v/ImportExcel.svg)](https://www.powershellgallery.com/packages/ImportExcel) [![](https://img.shields.io/powershellgallery/dt/ImportExcel.svg)](https://www.powershellgallery.com/packages/ImportExcel) [![](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/dfinke/ImportExcel/tree/70ab9e46c776e96fb287682d5b9b4b51a0ec3bac/LICENSE.txt) + +
    + +| CI System | Environment | Status | +| :--- | :--- | :--- | +| Azure DevOps | Windows | [![Build Status](https://dougfinke.visualstudio.com/ImportExcel/_apis/build/status/dfinke.ImportExcel?branchName=master&jobName=Windows)](https://dougfinke.visualstudio.com/ImportExcel/_build/latest?definitionId=21&branchName=master) | +| Azure DevOps | Windows \(Core\) | [![Build Status](https://dougfinke.visualstudio.com/ImportExcel/_apis/build/status/dfinke.ImportExcel?branchName=master&jobName=WindowsPSCore)](https://dougfinke.visualstudio.com/ImportExcel/_build/latest?definitionId=21&branchName=master) | +| Azure DevOps | Ubuntu | [![Build Status](https://dougfinke.visualstudio.com/ImportExcel/_apis/build/status/dfinke.ImportExcel?branchName=master&jobName=Ubuntu)](https://dougfinke.visualstudio.com/ImportExcel/_build/latest?definitionId=21&branchName=master) | +| Azure DevOps | macOS | [![Build Status](https://dougfinke.visualstudio.com/ImportExcel/_apis/build/status/dfinke.ImportExcel?branchName=master&jobName=macOS)](https://dougfinke.visualstudio.com/ImportExcel/_build/latest?definitionId=21&branchName=master) | + +
    + +Install from the [PowerShell Gallery](https://www.powershellgallery.com/packages/ImportExcel/). + +```powershell +Install-Module -Name ImportExcel +``` +### Donation + +If this project helped you reduce the time to get your job done, let me know, send a coffee. + +
    + +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UCSB9YVPFSNCY) + +![](https://media.giphy.com/media/hpXxJ78YtpT0s/giphy.gif) + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/testimonial.png) + +## How to Videos + +* [PowerShell Excel Module - ImportExcel](https://www.youtube.com/watch?v=fvKKdIzJCws&list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq) + +Installation - + +**PowerShell V5 and Later** + +You can install the `ImportExcel` module directly from the PowerShell Gallery + +* \[Recommended\] Install to your personal PowerShell Modules folder + + ```text + Install-Module ImportExcel -scope CurrentUser + ``` + +* \[Requires Elevation\] Install for Everyone \(computer PowerShell Modules folder\) + + ```text + Install-Module ImportExcel + ``` + +## Continuous Integration Updates + +Big thanks to [Illy](https://github.com/ili101) for taking the Azure DevOps CI to the next level. Improved badges, improved matrix for cross platform OS testing and more. + +Plus, wiring the [PowerShell ScriptAnalyzer Excel report](https://github.com/dfinke/ImportExcel/pull/590#issuecomment-488659081) we built into each run as an artifact. + +![](.gitbook/assets/ScriptAnalyzerReport.png) + + +## What's new for 7.1.4 + +- Added GroupNumericColumn and GroupDateColumn to New-PivotTableDefinition and Add-PivotTable. + +## What's new 7.1.3 + +- Changed to `ProviderPath`. Thanks [Trevor Walker](https://github.com/sporkabob) + +## What's new 7.1.2 + +- `Get-ExcelFileSummary` - Gets summary information on an Excel file like number of rows, columns, and more + +``` +dir . -r *.xlsx | Get-ExcelFileSummary | ft + +ExcelFile WorksheetName Rows Columns Address Path +--------- ------------- ---- ------- ------- ---- +Grades.xlsx Sheet1 21 3 A1:C21 D:\temp\ExcelYouTube\Grades +GradesAverage.xlsx Sheet1 21 5 A1:E21 D:\temp\ExcelYouTube\Grades +AllShifts.xlsx Sheet1 21 2 A1:B21 D:\temp\ExcelYouTube\SeparateData +Shift_1.xlsx Sheet1 10 2 A1:B10 D:\temp\ExcelYouTube\SeparateData +Shift_2.xlsx Sheet1 8 2 A1:B8 D:\temp\ExcelYouTube\SeparateData +Shift_3.xlsx Sheet1 5 2 A1:B5 D:\temp\ExcelYouTube\SeparateData +Shifts.xlsx Shift_1 10 2 A1:B10 D:\temp\ExcelYouTube\SeparateData +Shifts.xlsx Shift_2 8 2 A1:B8 D:\temp\ExcelYouTube\SeparateData +``` + +## What's new 7.1.1 + +* Merged [Nate Ferrell](https://github.com/scrthq)'s Linux fix. Thanks! +* Moved `Export-MultipleExcelSheets` from psm1 to Examples/Experimental +* Deleted the CI build in Appveyor +* Thank you [Mikey Bronowski](https://github.com/MikeyBronowski) for + * Multiple sweeps + * Standardising casing of parameter names, and variables + * Plus updating > 50 of the examples and making them consistent. + +## What's new 7.1.0 + +Fixes, Updates and new Examples + +#### Fixed + +* Odd behavior on the return of Import-Excel function [https://github.com/dfinke/ImportExcel/issues/792](https://github.com/dfinke/ImportExcel/issues/792) +* Export-Excel -FreezeTopRow with -Title [https://github.com/dfinke/ImportExcel/issues/795](https://github.com/dfinke/ImportExcel/issues/795) +* Not importing when first row contains a 0 in a column [https://github.com/dfinke/ImportExcel/issues/802](https://github.com/dfinke/ImportExcel/issues/802) + +#### Updated + +* Add `-AsDate` support to `Import-Excel` and `ConvertFrom-ExcelSheet` + +#### New Examples + +| PS1 | Description | Link | +| :--- | :--- | :--- | +| Pester-To-XLSx | Runs Pester, collects the results, enriches it, and exports it to Excel | [Pester-To-XLSx.ps1](https://github.com/dfinke/ImportExcel/blob/fe68ddbb0dd86e9fd1f3bfe01c4d2b9ce5509510/Examples/Pester-To-XLSx.ps1) | +| DSUM | Sums up the numbers in a field \(column\) of records in a list or database that match conditions that you specify. | [DSUM.ps1](https://github.com/dfinke/ImportExcel/blob/12fa49e3142af2178ae1c6b18d8c757af0d629ac/Examples/ExcelBuiltIns/DSUM.ps1) | +| VLookup | Setups up a sheet, you enter the name of an item and the amount is looked up | [VLOOKUP.ps1](https://github.com/dfinke/ImportExcel/blob/e42f42fde92ca636af22252b753a8329f48e15f1/Examples/ExcelBuiltIns/VLOOKUP.ps1) | + +## What's new 7.0.1 + +More infrastructure improvements. + +* Refine pipeline script analysis +* Improve artifacts published +* Add manifest \(psd1\) checks + +## What's new 7.0.0 + +### Refactor + +* Remove all functions from the `psm1` +* Move functions into public subdirectory +* Align TDD and continuous integration workflow for this refactor +* Move help from functions to mdHelp and use [PlatyPS](https://www.powershellgallery.com/packages/platyPS) to generate external help file + +Thanks to [James O'Neill](https://twitter.com/jamesoneill) for the refactor and [Illy](https://twitter.com/ili_z) on the continuous integration. + +## What's new 6.5.3 + +Thanks again to the community for making this module even better. + +* [Fix import excel headers](https://github.com/dfinke/ImportExcel/pull/713) +* Numerous improvements for DataTables and exporting it to Excel [James O'Neill](https://twitter.com/jamesoneill) + * Names, styles, proper appending +* Handles marking the empty row on an empty table as dummy row +* Re-work code based on linting recommendations +* Update existing tests and add more +* Support PipelineVariable thanks to [Luc Dekens](https://twitter.com/LucD22) for reporting and [Ili](https://twitter.com/ili_z) for the PR +* Fix quoting in ConvertFromExcelToSQLInsert [beckerben](https://github.com/beckerben) + +## What's new 6.5.2 + +Thank you [uSlackr](https://github.com/uSlackr)ill + +* Fixes Column order issue \(plus tests\) for `Get-ExcelColumnName` + +Thank you [jhoneill](https://github.com/jhoneill) + +* Added -Force to Send-SQLDataToExcel so it sends something even if no rows are returned. \(see [\#703](https://github.com/dfinke/ImportExcel/issues/703)\) +* Added -asText to import-Excel see \(\#164\)\[[https://github.com/dfinke/ImportExcel/issues/164](https://github.com/dfinke/ImportExcel/issues/164)\] and multiple others +* Linux. Now set an environment variable if the support needed for Autosize is present, and use that Environment variable to decide to skip autosize operations. +* Fixed tests which needed autosize to work so they skip of the environment variable is set. +* Fixed another break where on azure the module never loaded. +* Add a comment to ci.ps1 re better .NET version detection and left some commented out code. + +Other + +* Added the example [ReadAllSheets.ps1](https://github.com/dfinke/ImportExcel/tree/master/Examples/ReadAllSheets) based on this thread [https://github.com/dfinke/ImportExcel/issues/678](https://github.com/dfinke/ImportExcel/issues/678) + +## What's new 6.5.0 + +This is now using the latest version of EPPlus. Unit tests are updated and passing, if you hit problems, please open an issue. You can rollback to an older version from the PowerShell Gallery if you are blocked. + +* Unit tests were updated and fixed +* "Set-WorksheetProtection" is now switched on +* Made a change to make Set-Excel range more friendly when Auto Sizing on non-windows platforms +* Fixed - Windows only tests don't attempt to run on non-windows systems +* Tests based on Get-Process don't attempt to run if <20 processes are returned +* If $env:TEMP is not set \(as will be the case on Linux\) +* Join-Path if used so paths are built with / or with as suits the OS where the test is running. +* Excel Sparklines now supported, check out the examples [SalesByQuarter](https://github.com/dfinke/ImportExcel/blob/master/Examples/Sparklines/SalesByQuarter.ps1) and [Sparklines](https://github.com/dfinke/ImportExcel/blob/master/Examples/Sparklines/Sparklines.ps1). + +![](.gitbook/assets/Sparklines.png) + +## What's new 6.2.4 + +Sensible parameter defaults, make your life easier and gets things done faster. + +* Thank you to [DomRRuggeri](https://github.com/DomRRuggeri) for the initial Out-Excel PR and kicking off the conversation on the improvements. +* Thank you to [ili101](https://github.com/ili101) for refactoring and improving the defaults, and adding the tests for parameters. +* Creates a table, with filtering +* Chooses a `TableStyle` +* Displays the Excel spreadsheet automatically + +```text +Get-Process | select Company, Name, Handles | Export-Excel +``` + +![image](.gitbook/assets/ImproveNowDefaults.png) + +## What's new 6.2.3 + +Thank you [jhoneill](https://github.com/jhoneill). + +* Refactored copy sheet and added pipe support +* Add `ClearAll` to `Set-ExcelRange` +* Fix broken test & regression for `passwords` + * **Note**: Passwords do not work on `pwsh`. The EPPlus library does not support these dotnet core APIs at this time. + +## What's new 6.2.2 + +* Added requested feature, chart trendlines. + * [Example PowerShell script](https://github.com/dfinke/ImportExcel/blob/master/Examples/Charts/NumberOfVisitors.ps1) + +![](.gitbook/assets/ChartTrendlines.png) + +* Fixed Import-Excel and relative path issue, added unit tests. + +## What's new 6.2.0 + +Thank you to [James O'Neill](https://github.com/jhoneill) + +* Fixed, Import-Excel can read xlsx files even if already open in Excel +* Added `New-ExcelStyle`, plus `-Style` to `Export-Excel` and `-Merge` to `Set-ExcelRange` +* Added [Style Examples](https://github.com/dfinke/ImportExcel/tree/master/Examples/Styles) + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/NewExcelStyle.png) + +## What's new 6.1.0 + +Thank you to [James O'Neill](https://github.com/jhoneill) + +* Instead of specifying a path provides an Excel Package object \(from `Open-ExcelPackage`\), using this avoids re-reading the whole file when importing multiple parts of it. To allow multiple read operations `Import-Excel` does NOT close the package, and you should use `Close-ExcelPackage -noSave` to close it. + +## What's new 6.0.0 + +Thank you to [James O'Neill](https://github.com/jhoneill) for the optimizations, and refactoring leading to a _**~10x**_ speed increase. Thanks to [ili101](https://github.com/ili101) for earlier PRs that provided the ground work for this. + +* Performance improvement to `Export-Excel` see [\#506](https://github.com/dfinke/ImportExcel/issues/506) and [\#555](https://github.com/dfinke/ImportExcel/issues/555). This has meant taking code in Add-CellValue back into process block of `Export-Excel`, as the overhead of calling the function was a lot greater than time executing the code inside it. [Blog post to follow](https://jamesone111.wordpress.com/). Some tests are showing a _**~10x**_ speed increase. [\#572](https://github.com/dfinke/ImportExcel/issues/572) was about a broken \#region tag in this part of the code and that has been cleaned up in the process. +* `Export-Excel` now has an -InputObject parameter \(this was previously -TargetData , which is now an alias for InputObject\). If the `inputobject` is an array, each item will be inserted, so you can run `export-excel -inputobject $x` rather than `$x | Export-Excel`, and if it is a `system.data.datatable` object it will be inserted directly rather than cell-by-cell. `Send-SQLDataToExcel` takes advantage of this new functionality. There are simple tests for these new items +* `Export-Excel` previously assumed `-Now` if there were no other parameters, it will now assume `-Now` if there is no `-Path` or `-ExcelPackage`. The .PSD1 file now itemizes the items exported by the module [\#557](https://github.com/dfinke/ImportExcel/issues/557) + +## What's new 5.4.5 + +Thank you to [James O'Neill](https://github.com/jhoneill) for the great additions. + +* Modified Send-SQLDataToExcel so it creates tables and ranges itself; previously it relied on export-excel to do this which cause problems when adding data to an existing sheet \(\#555\) +* Added new command Add-ExcelDataValidation which will apply different data-validation rules to ranges of cells +* Changed the export behavior so that \(1\) attempts to convert to a number only apply if the the value was a string; \(2\) Nulls are no longer converted to an empty string \(3\) there is a specific check for URIs and not just text which is a valid URI. Using UNC names in hyperlinks remains problematic. +* Changed the behavior of AutoSize in export excel so it only applies to the exported columns. Previously if something was exported next to pre-existing data, AutoSize would resize the whole sheet, potentially undoing things which had been set on the earlier data. If anyone relied on this behavior they will need to explicitly tell the sheet to auto size with $sheet.cells.autofitColumns. \(where $sheet points to the sheet, it might be $ExcelPackage.Workbook.Worksheets\['Name'\]\) +* In Compare-Worksheet,the Key for comparing the sheets can now be written as a hash table with an expression - it is used with a Group-Object command so if it is valid in Group-Object it should be accepted; this allows the creation of composite keys when data being compared doesn't have a column which uniquely identifies rows. +* In Set-ExcelRange , added a 'Locked' option equivalent to the checkbox on the Protection Tab of the format cells dialog box in Excel. +* Created a Set-WorksheetProtection function. This gives the same options the protection dialog in Excel but is 0.9 release at the moment. + +### New Example + +* Added [MutipleValidations.ps1](https://github.com/dfinke/ImportExcel/blob/master/Examples/ExcelDataValidation/MutipleValidations.ps1). Culled from the `tests`. + +## What's new 5.4.4 + +* Fix issue when only a single property is piped into Export-Excel +* Fix issue in `Copy-ExcelWorksheet`, close the `$Stream` + +## What's new 5.4.3 + +* Added Remove-Worksheet: Removes one or more worksheets from one or more workbooks + +## What's new 5.4.2 + +* Added parameters -GroupDateRow and -GroupDatePart & -GroupNumericRow, -GroupNumericMin, -GroupNumericMax and -GroupNumericInterval + + to Add-PivotTable and New-PivotTableDefinition. The date ones gather dates of the same year and/or quarter and/or month and/or day etc. + + the number ones group numbers into bands, starting at Min, and going up steps specified by Interval. Added tests and help for these. + +* Set-ExcelRow and Set-ExcelColumn now check that the worksheet name they passed exists in the workbook. + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/cf964e3e4f761ca4058c4a4b809e2206b16709da/images/GroupingNumeric.png) + +## What's new 5.4.0 + +* Thank you to Conrad Agramont, Twitter: [@AGramont](https://twitter.com/@AGramont) for the `AddMultiWorkSheet.ps1` example. Much appreciated! +* Fixed several more bugs where parameters were ignored if passed a zero value +* Fixed bug where chart series headers could not come form a cell reference \(=Sheet1!Z10 now works as a header reference\) +* Add-Chart will now allow a single X range, or as many X ranges as there are Y ranges. +* Merge-MultipleSheets is more robust. +* Set-ExcelRow and Set-ExcelColumn trap attempts to process a sheet with no rows/columns. +* Help has been proof-read \(thanks to Mrs. @Jhoneill !\). + +## What's new 5.3.4 + +* HotFix for parameter PivotTableStyle should be PivotTableStyle [https://github.com/dfinke/ImportExcel/issues/453](https://github.com/dfinke/ImportExcel/issues/453) + +## What's new 5.3.3 + +* Thank you to \(lazywinadmin\)\[[https://github.com/lazywinadmin](https://github.com/lazywinadmin)\] - Expand aliases in examples and elsewhere +* In Export-Excel fixed a bug where -AutoNameRange on pre-existing data included the header in the range. +* In Export-Excel fixed a bug which caused a zero, null, or empty string in a list of simple objects to be skipped. +* In Export-Excel improved the behaviour when a new worksheet is created without data, and Tables etc are added to it. +* In Join-Worksheet: added argument completer to -TitleBackgroundColor and set default for -TitleBackgroundStyle to 'Solid'. +* In Add-Excel chart, New-ExcelChart, tests and Examples fixed mis-spelling of "Position" +* In Send-SqlDataToExcel: improved robustness of check for no data returned. +* In Set-ExcelColumn: -column can come from the pipeline \(supporting an array introduces complications for supporting script blocks\); -AutoNameRange no longer requires heading to specified \(so you can do 1..10 \| Set-ExcelColumn -AutoNameRange \); In Set-ExcelRow: -Row can come from the pipeline +* Improved test coverage \(back over 80%\). +* Help and example improvements. In "Index - music.ps1" the module for querying the index can be downloaded from PowerShell gallery \#requires set to demand it. In SQL+FillColumns+Pivot\example2.ps1 the GetSQL module can be downloaded and \#Requires has been set. The F1 results spreadsheet is available from one drive and a link is provided. +* Added Azure DevOps continuous integration and badges + +## What's new in Release 5.3 + +* Help improvements and tidying up of examples and extra examples +* Open-Excel Package and Add-Worksheet now add worksheets as script properties so `$Excel = Open-ExcelPackage -path test.xlsx ; $excel.sheet1` will return the sheet named "sheet1" `$Excel.SheetName` is a script property which is defined as `$this.workbook.worksheets["Sheetname"]` +* Renamed Set-Column to `Set-ExcelColumn`, Set-Row to `Set-ExcelRow`, and Set-Format, to `Set-ExcelRange`. Added aliases so the old names still work. +* `Set-ExcelRange` \(or set-Format\) used "Address" and "Range" incorrectly. There is now a single parameter `-Range`, with an alias of "Address". If the worksheet parameter is present, the function accepts a string specifying cells \("A1:Z10"\) or a the name of range. Without the worksheet it accepts an object representing a named range or a Table; or a tables's address, or part of the worksheet.cells collection. +* `Add-ConditionalFormatting`: Used "address" correctly, and it will accept ranges in the address parameter \(range is now an alias for address\). It now wraps conditional value strings in quotes when needed \(for = <= >= operations string needs to be in double quotes see issue \#424\). Parameter intellisense has been improved. There are new parameters: `-StopIfTrue` and `-Priority` and support for using the `-Reverse` parameter with Color-scale rules \(issue \#430\). Booleans in the sheet are now supported as the value for a condition. Also brought the two different kinds of condition together inside Export-Excel, and fixed a bug where named-ranges didn't work in some places. In `New-ConditionalText`, more types of conditional format are supported, and the argument completer for -ConditionalTextColor was missing and has been added. +* Improved handling of hyperlinks in `Export-Excel` \(see issue \#426\)s +* `Export-Excel` has better checking of Table and PivotTable names \(for uniqueness\) and a new test in quick charts that there is suitable data for charting. It also accepts hash tables for chart, pivot table and conditional formatting parameters which are splatted into the functions which add these. +* Moved logic for adding a named-range out of Export-Excel and into a new function named `Add-ExcelName`, and logic for adding a table into a function named `Add-ExcelTable`; this is to make it easier to do these things independently of Export-Excel, but minimize duplication. The Add-ExcelTable command has extra parameters to toggle the options from table tools toolbar \(show totals etc.\) and set options in the totals row. +* Moved PivotTable Functions out of Export-Excel.PS1 into their own file and moved Add-ExcelChart out of Export-Excel.ps1 into New-ExcelChart.ps1 +* Fixed bug in Merge-MultipleSheets where background pattern was set to None, making background color invisible. +* Fixed issues where formatting could be reset when using Export-Excel to manipulate an existing sheet without appending data; this applied to number-formats and tables. +* `Add-PivotTable` has some new parameters `-PassThru` returns the pivot table \(e.g. to allow names /sort orders of data series to be tweaked \) `-Address` allows Pivot to be placed on an existing sheet; `-PivotTableStyle` allows a change from "Medium6", `-PivotNumberFormat` formats data cells. It is more flexible about how the source data is specified - copying the range options in Set-ExcelRange. `Add-ExcelChart` is now used for creating PivotCharts, and `-PivotChartDefinition` allows a definition created with `New-ExcelChartDefinition` to be used when setting up a PivotTable. This opens up all the things that Add-ExcelChart can do without duplicating the parameters on Add-Pivot table and Export-Excel. Definition, TableStyle, Numberformat and ChartDefiniton can be used in `New-PivotTableDefinition` . +* `Add-ExcelChart` now supports -PassThru to return the chart for tweaking after creation; there is now a -PivotTable parameter to allow Add-PivotTable to call the code in Add-ExcelChart. And in `New-ExcelChartDefinition` Legend parameters \(for size, bold & position \) are now supported +* ChartDefinition and conditional formatting parameters can now be hashtables - anything that splats Add-ExcelChart or Add-ConditionalFormatting, it should be acceptable as a definition. + +## What's new in Release 5.2 + +* Value does not need to be mandatory in Set-Row or Set-Column, also tidied their parameters a little. +* Added support for array formulas in Set-Format \(it really should be set range now that it sets values, formulas and hyperlinks - that can go on the to-do list \) +* Fixed a bug with -Append in Export-Excel which caused it to overwrite the last row if the new data was a simple type. +* NumberFormat in Export-Excel now sets the default for on a new / blank sheet; but \[still\] sets individual cells when adding to a sheet +* Added support for timespans in Export excel ; set as elapsed hours, mins, secs \[h\]:mm:sss +* In Export-Excel improved the catch-all handler for insuring values to cope better with nested objects \(\#419\) and reduce the number of parse operations +* Added -Calculate switch to Export-Excel and Close-Excel Package; EPPlus needs formulas to OMIT the leading = sign so where formula is set it now strips a leading = sign +* Added -PivotTotals parameter where there was already -NoTotalsInPivot new one allows None, Both, Rows, Columns. \(\#415\) +* When appending Export-Excel only extended tables and ranges if they were explicitly specified. It now does it automatically. +* Compare and Merge worksheet originally had a problem with > 26 columns, I fixed merge turns out I hadn't fixed compare ... I have now +* Fixed bug where Export-Excel would not recognize it had to set $TitleFillPattern - made the default 'Solid' +* ExcludeProperty in Export-Excel now supports wildcards. +* Added DateTime to the list of types which can be exported as single column. +* Added Password support to Open- and Close-ExcelPackage \(password was not doing anything in Export-Excel\) +* Gave Expand-NumberFormat a better grasp of currency layouts - it follows .NET which is not always the same as Excel would set:-\( + +## What's new in Release 5.1.1 + +* Set-Row and Set-Column will now create hyperlinks and insert dates correctly +* Import-Excel now has an argument completer for Worksheet name - this can be slow on large files +* The NumberFormat parameter \(in Export-Excel, Set-Row, Set-Column, Set-Format and Add-ConditionalFormat\) and X&YAxisNumberFormat parameters \(in New-ExcelChartDefinition and Add-ExcelChart\) now have an argument completer and the names Currency, Number, Percentage, Scientific, Fraction, Short Date ,Short time,Long time, Date-Time and Text will be converted to the correct Excel formatting strings. +* Added new function Select-Worksheet to make a named sheet active: Added -Activate switch to Add-Worksheet, to make current sheet active, Export-Excel and Add-PivotTable support -Activate and pass it to Add-Worksheet, and New-PivotTableDefinition allows it to be part of the Pivot TableDefinition. +* Fixed a bug in Set-Format which caused -Hidden not to work +* Made the same changes to Add-Conditional format as set format so -switch:$false is processed, and 0 enums and values are processed correctly +* In Export-Excel, wrapped calls to Add-CellValue in a try catch so a value which causes an issue doesn't crash the whole export but generates a warning instead \(\#410\) . +* Additional tests. + +## What's new to July 18 + +* Changed parameter evaluation in Set-Format to support -bold:$false \(and other switches so that if false is specified the attribute will be removed \), and to bug were enums with a value of zero, and other zero parameters were not set. +* Moved chart creation into its own function \(Add-Excel chart\) within Export-Excel.ps1. Renamed New-Excelchart to New-ExcelChartDefinition to make it clearer that it is not making anything in the workbook \(but for compatibility put an alias of New-ExcelChart in so existing code does not break\). Found that -Header does nothing, so it isn't Add-Excel chart and there is a message that does nothing in New-ExcelChartDefinition . +* Added -BarChart -ColumnChart -LineChart -PieChart parameters to Export-Excel for quick charts without giving a full chart definition. +* Added parameters for managing chart Axes and legend +* Added some chart tests to Export-Excel.tests.ps1. \(but tests & examples for quick charts , axes or legends still on the to do list \) +* Fixed some bad code which had been checked-in in-error and caused adding charts to break. \(This was not seen outside GitHub \#377\) +* Added "Reverse" parameter to Add-ConditionalFormatting ; and added -PassThru to make it easier to modify details of conditional formatting rules after creation \(\#396\) +* Refactored ConditionalFormatting code in Export excel to use Add-ConditionalFormatting. +* Rewrote Copy-ExcelWorksheet to use copy functionality rather than import \| export \(395\) +* Found sorts could be inconsistent in Merge-MultipleWorksheet, so now sort on more columns. +* Fixed a bug introduced into Compare-Worksheet by the change described in the June changes below, this meant the font color was only being set in one sheet, when a row was changed. Also found that the PowerShell ISE and shell return Compare-Object results in different sequences which broke some tests. Applied a sort to ensure things are in a predictable order. \(\#375\) +* Removed \(2\) calls to Get-ExcelColumnName \(Removed and then restored function itself\) +* Fixed an issue in Export-Excel where formulas were inserted as strings if "NoNumberConversion" is applied \(\#374\), and made sure formatting is applied to formula cells +* Fixed an issue with parameter sets in Export-Excel not being determined correctly in some cases \(I think this had been resolved before and might have regressed\) +* Reverted the \[double\]::tryParse in export excel to the previous \(longer\) way, as the shorter way was not behaving correctly with with the number formats in certain regions. \(also \#374\) +* Changed Table, Range and AutoRangeNames to apply to whole data area if no data has been inserted OR to inserted data only if it has.\(\#376\) This means that if there are multiple inserts only inserted data is touched, rather than going as far down and/or right as the furthest used cell. Added a test for this. +* Added more of the Parameters from Export-Excel to Join-worksheet, join just calls export-excel with these parameters so there is no code behind them \(\#383\) +* Added more of the Parameters from Export-Excel to Send-SQLDataToExcel, send just calls export-excel with these parameters... +* Added support for passing a System.Data.DataTable directly to Send-SQLDataToExcel +* Fixed a bug in Merge-MultipleSheets where if the key was "name", columns like "displayName" would not be processed correctly, nor would names like "something\_ROW". Added tests for Compare, Merge and Join Worksheet +* Add-Worksheet , fixed a regression with move-after \(\#392\), changed way default worksheet name is decided, so if none is specified, and an existing worksheet is copied \(see June additions\) and the name doesn't already exist, the original sheet name will be kept. \(\#393\) If no name is given an a blank sheet is created, then it will be named sheetX where X is the number of the sheet \(so if you have sheets FOO and BAR the new sheet will be Sheet3\). + +## New in June 18 + +* New commands - Diff , Merge and Join + * `Compare-Worksheet` \(introduced in 5.0\) uses the built in `Compare-object` command, to output a command-line DIFF and/or color the worksheet to show differences. For example, if my sheets are Windows services the _extra_ rows or rows where the startup status has changed get highlighted + * `Merge-Worksheet` \(also introduced in 5.0\) joins two lumps, side by highlighting the differences. So now I can have server A's services and Server Bs Services on the same page. I figured out a way to do multiple sheets. So I can have Server A,B,C,D on one page :-\) that is `Merge-MultpleSheets` + + For this release I've fixed heaven only knows how many typos and proof reading errors in the help for these two, the only code change is to fix a bug if two worksheets have different names, are in different files and the Comparison sends the delta in the second back before the one in first, then highlighting changed properties could throw an error. Correcting the spelling of Merge-MultipleSheets is potentially a breaking change \(and it is still plural!\) + + also fixed a bug in compare worksheet where color might not be applied correctly when the worksheets came from different files and had different name. + + * `Join-Worksheet` is **new** for this release. At it's simplest it copies all the data in Worksheet A to the end of Worksheet B +* Add-Worksheet + * I have moved this from ImportExcel.psm1 to ExportExcel.ps1 and it now can move a new worksheet to the right place, and can copy an existing worksheet \(from the same or a different workbook\) to a new one, and I set the Set return-type to aid intellisense +* New-PivotTableDefinition + * Now Supports `-PivotFilter` and `-PivotDataToColumn`, `-ChartHeight/width` `-ChartRow/Column`, `-ChartRow/ColumnPixelOffset` parameters +* Set-Format + * Fixed a bug where the `-address` parameter had to be named, although the examples in `export-excel` help showed it working by position \(which works now. \) +* Export-Excel + * I've done some re-factoring + 1. I "flattened out" small "called-once" functions , add-title, convert-toNumber and Stop-ExcelProcess. + 2. It now uses Add-Worksheet, Open-ExcelPackage and Add-ConditionalFormat instead of duplicating their functionality. + 3. I've moved the PivotTable functionality \(which was doubled up\) out to a new function "Add-PivotTable" which supports some extra parameters PivotFilter and PivotDataToColumn, ChartHeight/width ChartRow/Column, ChartRow/ColumnPixelOffsets. + 4. I've made the try{} catch{} blocks cover smaller blocks of code to give a better idea where a failure happened, some of these now Warn instead of throwing - I'd rather save the data with warnings than throw it away because we can't add a chart. Along with this I've added some extra write-verbose messages + * Bad column-names specified for Pivots now generate warnings instead of throwing. + * Fixed issues when pivot tables / charts already exist and an export tries to create them again. + * Fixed issue where AutoNamedRange, NamedRange, and TableName do not work when appending to a sheet which already contains the range\(s\) / table + * Fixed issue where AutoNamedRange may try to create ranges with an illegal name. + * Added check for illegal characters in RangeName or Table Name \(replace them with "\_"\), changed tablename validation to allow spaces and applied same validation to RangeName + * Fixed a bug where BoldTopRow is always bolds row 1 even if the export is told to start at a lower row. + * Fixed a bug where titles throw pivot table creation out of alignment. + * Fixed a bug where Append can overwrite the last rows of data if the initial export had blank rows at the top of the sheet. + * Removed the need to specify a fill type when specifying a title background color + * Added MoveToStart, MoveToEnd, MoveBefore and MoveAfter Parameters - these go straight through to Add worksheet + * Added "NoScriptOrAliasProperties" "DisplayPropertySet" switches \(names subject to change\) - combined with ExcludeProperty these are a quick way to reduce the data exported \(and speed things up\) + * Added PivotTableName Switch \(in line with 5.0.1 release\) + * Add-CellValue now understands URI item properties. If a property is of type URI it is created as a hyperlink to speed up Add-CellValue + * Commented out the write verbose statements even if verbose is silenced they cause a significant performance impact and if it's on they will cause a flood of messages. + * Re-ordered the choices in the switch and added an option to say "If it is numeric already post it as is" + * Added an option to only set the number format if doesn't match the default for the sheet. +* Export-Excel Pester Tests + * I have converted examples 1-9, 11 and 13 from Export-Excel help into tests and have added some additional tests, and extra parameters to the example command to get better test coverage. The test so far has 184 "should" conditions grouped as 58 "IT" statements; but is still a work in progress. +* Compare-Worksheet pester tests +* [James O'Neill](https://twitter.com/jamesoneill) added `Compare-Worksheet` + * Compares two worksheets with the same name in different files. + +**4/22/2018** + +Thanks to the community yet again + +* [ili101](https://github.com/ili101) for fixes and features + * Removed `[PSPlot]` as OutputType. Fixes it throwing an error +* [Nasir Zubair](https://github.com/nzubair) added `ConvertEmptyStringsToNull` to the function `ConvertFrom-ExcelToSQLInsert` + * If specified, cells without any data are replaced with NULL, instead of an empty string. This is to address behaviors in certain DBMS where an empty string is insert as 0 for INT column, instead of a NULL value. + +**4/10/2018** + +-New parameter `-ReZip`. It ReZips the xlsx so it can be imported to PowerBI + +Thanks to [Justin Grote](https://github.com/JustinGrote) for finding and fixing the error that Excel files created do not import to PowerBI online. Plus, thank you to [CrashM](https://github.com/CrashM) for confirming the fix. + +Super helpful! + +**3/31/2018** + +* Updated `Set-Format` + * Added parameters to set borders for cells, including top, bottom, left and right + * Added parameters to set `value` and `formula` + +```text +$data = @" +From,To,RDollars,RPercent,MDollars,MPercent,Revenue,Margin +Atlanta,New York,3602000,.0809,955000,.09,245,65 +New York,Washington,4674000,.105,336000,.03,222,16 +Chicago,New York,4674000,.0804,1536000,.14,550,43 +New York,Philadelphia,12180000,.1427,-716000,-.07,321,-25 +New York,San Francisco,3221000,.0629,1088000,.04,436,21 +New York,Phoneix,2782000,.0723,467000,.10,674,33 +"@ +``` + +![](https://github.com/dfinke/ImportExcel/blob/master/images/CustomReport.png?raw=true) + +* Added `-PivotFilter` parameter, allows you to set up a filter so you can drill down into a subset of the overall dataset. + +```text +$data =@" +Region,Area,Product,Units,Cost +North,A1,Apple,100,.5 +South,A2,Pear,120,1.5 +East,A3,Grape,140,2.5 +West,A4,Banana,160,3.5 +North,A1,Pear,120,1.5 +North,A1,Grape,140,2.5 +"@ +``` + +![](https://github.com/dfinke/ImportExcel/blob/master/images/PivotTableFilter.png?raw=true) + +**3/14/2018** + +* Thank you to [James O'Neill](https://twitter.com/jamesoneill), fixed bugs with ChangeDatabase parameter which would prevent it working +* Added -Force to New-Alias +* Add example to set the background color of a column +* Supports excluding Row Grand Totals for PivotTables +* Allow xlsm files to be read +* Fix `Set-Column.ps1`, `Set-Row.ps1`, `SetFormat.ps1`, `formatting.ps1` **$false** and **$BorderRound** + + **1/1/2018** + +* Added switch `[Switch]$NoTotalsInPivot`. Allows hiding of the row totals in the pivot table. + + Thanks you to [jameseholt](https://github.com/jameseholt) for the request. + +```text + get-process | where Company | select Company, Handles, WorkingSet | + export-excel C:\temp\testColumnGrand.xlsx ` + -Show -ClearSheet -KillExcel ` + -IncludePivotTable -PivotRows Company -PivotData @{"Handles"="average"} -NoTotalsInPivot +``` + +* Fixed when using certain a `ChartType` for the Pivot Table Chart, would throw an error +* Fixed - when you specify a file, and the directory does not exit, it now creates it + +**11/23/2017** + +More great additions and thanks to [James O'Neill](https://twitter.com/jamesoneill) + +* Added `Convert-XlRangeToImage` Gets the specified part of an Excel file and exports it as an image +* Fixed a typo in the message at line 373. +* Now catch an attempt to both clear the sheet and append to it. +* Fixed some issues when appending to sheets where the header isn't in row 1 or the data doesn't start in column 1. +* Added support for more settings when creating a pivot chart. +* Corrected a typo PivotTableName was PivtoTableName in definition of New-PivotTableDefinition +* Add-ConditionalFormat and Set-Format added to the parameters so each has the choice of working more like the other. +* Added Set-Row and Set-Column - fill a formula down or across. +* Added Send-SQLDataToExcel. Insert a rowset and then call Export-Excel for ranges, charts, pivots etc. + +**10/30/2017** + +Huge thanks to [James O'Neill](https://twitter.com/jamesoneill). PowerShell aficionado. He always brings a flare when working with PowerShell. This is no exception. + +\(Check out the examples `help Export-Excel -Examples`\) + +* New parameter `Package` allows an ExcelPackage object returned by `-passThru` to be passed in +* New parameter `ExcludeProperty` to remove unwanted properties without needing to go through `select-object` +* New parameter `Append` code to read the existing headers and move the insertion point below the current data +* New parameter `ClearSheet` which removes the worksheet and any past data +* Remove any existing Pivot table before trying to \[re\]create it +* Check for inserting a pivot table so if `-InsertPivotChart` is specified it implies `-InsertPivotTable` + +\(Check out the examples `help Export-Excel -Examples`\) + +* New function `Export-Charts` \(requires Excel to be installed\) - Export Excel charts out as JPG files +* New function `Add-ConditionalFormatting` Adds conditional formatting to worksheet +* New function `Set-Format` Applies Number, font, alignment and color formatting to a range of Excel Cells +* `ColorCompletion` an argument completer for `Colors` for params across functions + +I also worked out the parameters so you can do this, which is the same as passing `-Now`. It creates an Excel file name for you, does an auto fit and sets up filters. + +`ps | select Company, Handles | Export-Excel` + +**10/13/2017** + +Added `New-PivotTableDefinition`. You can create and wire up a PivotTable to a WorkSheet. You can also create as many PivotTable Worksheets to point a one Worksheet. Or, you create many Worksheets and many corresponding PivotTable Worksheets. + +Here you can create a WorkSheet with the data from `Get-Service`. Then create four PivotTables, pointing to the data each pivoting on a different dimension and showing a different chart + +```text +$base = @{ + SourceWorkSheet = 'gsv' + PivotData = @{'Status' = 'count'} + IncludePivotChart = $true +} + +$ptd = [ordered]@{} + +$ptd += New-PivotTableDefinition @base servicetype -PivotRows servicetype -ChartType Area3D +$ptd += New-PivotTableDefinition @base status -PivotRows status -ChartType PieExploded3D +$ptd += New-PivotTableDefinition @base starttype -PivotRows starttype -ChartType BarClustered3D +$ptd += New-PivotTableDefinition @base canstop -PivotRows canstop -ChartType ConeColStacked + +Get-Service | Export-Excel -path $file -WorkSheetname gsv -Show -PivotTableDefinition $ptd +``` + +**10/4/2017** + +Thanks to [https://github.com/ili101](https://github.com/ili101) : + +* Fix Bug, Unable to find type \[PSPlot\] +* Fix Bug, AutoFilter with TableName create corrupted Excel file. + +**10/2/2017** + +Thanks to [Jeremy Brun](https://github.com/jeremytbrun) Fixed issues related to use of -Title parameter combined with column formatting parameters. + +* [Issue \#182](https://github.com/dfinke/ImportExcel/issues/182) +* [Issue \#89](https://github.com/dfinke/ImportExcel/issues/89) + +**9/28/2017 \(Version 4.0.1\)** + +* Added a new parameter called `Password` to import password protected files +* Added even more `Pester` tests for a more robust and bug free module +* Renamed parameter 'TopRow' to 'StartRow' + + This allows us to be more concise when new parameters \('StartColumn', ..\) will be added in the future Your code will not break after the update, because we added an alias for backward compatibility + +Special thanks to [robinmalik](https://github.com/robinmalik) for providing us with [the code](https://github.com/dfinke/ImportExcel/issues/174) to implement this new feature. A high five to [DarkLite1](https://github.com/DarkLite1) for the implementation. + +**9/12/2017 \(Version 4.0.0\)** + +Super thanks and hat tip to [DarkLite1](https://github.com/DarkLite1). There is now a new and improved `Import-Excel`, not only in functionality, but also improved readability, examples and more. Not only that, he's been running it in production in his company for a number of weeks! + +_Added_ `Update-FirstObjectProperties` Updates the first object to contain all the properties of the object with the most properties in the array. Check out the help. + +_**Breaking Changes**_: Due to a big portion of the code that is rewritten some slightly different behavior can be expected from the `Import-Excel` function. This is especially true for importing empty Excel files with or without using the `TopRow` parameter. To make sure that your code is still valid, please check the examples in the help or the accompanying `Pester` test file. + +Moving forward, we are planning to include automatic testing with the help of `Pester`, `Appveyor` and `Travis`. From now on any changes in the module will have to be accompanied by the corresponding `Pester` tests to avoid breakages of code and functionality. This is in preparation for new features coming down the road. + +**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. The function converts the older Excel file format ending in `.xls` to the new format ending in `.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 fantastic to work with people like `DarkLite1` in the community, to help make the module 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 if it was possible to import an Excel worksheet and transform the data into SQL `INSERT` statements. We can now answer that question with a big YES! + +```text +ConvertFrom-ExcelToSQLInsert People .\testSQLGen.xlsx +``` + +```text +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` function and you can use a scriptblock to format the data however you want. + +```text +ConvertFrom-ExcelData .\testSQLGen.xlsx { + param($propertyNames, $record) + + $reportRecord = @() + foreach ($pn in $propertyNames) { + $reportRecord += "{0}: {1}" -f $pn, $record.$pn + } + $reportRecord +="" + $reportRecord -join "`r`n" +} +``` + +Generates + +```text +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 + +* TableName with parameter validation, throws an error when the TableName: + * Starts with something else then a letter + * Is NULL or empty + * Contains spaces +* Numeric parsing now uses `CurrentInfo` to use the system settings + +**2/14/2017** + +Big thanks to [DarkLite1](https://github.com/DarkLite1) for some great updates + +* `-DataOnly` switch added to `Import-Excel`. When used it will only generate objects for rows that contain text values, not for empty rows or columns. +* `Get-ExcelWorkBookInfo` - retrieves information of an Excel workbook. + + ```text + Get-ExcelWorkbookInfo .\Test.xlsx + + CorePropertiesXml : #document + Title : + Subject : + Author : Konica Minolta User + Comments : + Keywords : + LastModifiedBy : Bond, James (London) GBR + LastPrinted : 2017-01-21T12:36:11Z + Created : 17/01/2017 13:51:32 + Category : + Status : + ExtendedPropertiesXml : #document + Application : Microsoft Excel + HyperlinkBase : + AppVersion : 14.0300 + Company : Secret Service + Manager : + Modified : 10/02/2017 12:45:37 + CustomPropertiesXml : #document + ``` + +**12/22/2016** + +* Added `-Now` switch. This short cuts the process, automatically creating a temp file and enables the `-Show`, `-AutoFilter`, `-AutoSize` switches. + +```text +Get-Process | Select Company, Handles | Export-Excel -Now +``` + +* Added ScriptBlocks for coloring cells. Check out [Examples](https://github.com/dfinke/ImportExcel/tree/master/Examples/FormatCellStyles) + +```text +Get-Process | + Select-Object Company,Handles,PM, NPM| + Export-Excel $xlfile -Show -AutoSize -CellStyleSB { + param( + $workSheet, + $totalRows, + $lastColumn + ) + + Set-CellStyle $workSheet 1 $LastColumn Solid Cyan + + foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 0})) { + Set-CellStyle $workSheet $row $LastColumn Solid Gray + } + + foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 1})) { + Set-CellStyle $workSheet $row $LastColumn Solid LightGray + } + } +``` + +![](https://github.com/dfinke/ImportExcel/blob/master/images/CellFormatting.png?raw=true) + +**9/28/2016** + +[Fixed](https://github.com/dfinke/ImportExcel/pull/126) PowerShell 3.0 compatibility. Thanks to [headsphere](https://github.com/headsphere). He used `$obj.PSObject.Methods[$target]` syntax to make it backward compatible. PS v4.0 and later allow `$obj.$target`. + +Thank you to [xelsirko](https://github.com/xelsirko) for fixing - _Import-module importexcel gives version warning if started inside background job_ + +**8/12/2016** + +[Fixed](https://github.com/dfinke/ImportExcel/issues/115) reading the headers from cells, moved from using `Text` property to `Value` property. + +**7/30/2016** + +* Added `Copy-ExcelWorksheet`. Let's you copy a work sheet from one Excel workbook to another. + +**7/21/2016** + +* Fixes `Import-Excel` \#68 + +**7/7/2016** + +[Attila Mihalicz](https://github.com/attilamihalicz) fixed two issues + +* Removing extra spaces after the backtick +* Uninitialized variable $idx leaks into the pipeline when `-TableName` parameter is used + +Thanks Attila. + +**7/1/2016** + +* Pushed 2.2.7 fixed resolve path in Get-ExcelSheetInfo +* Fixed [Casting Error in Export-Excel](https://github.com/dfinke/ImportExcel/issues/108) +* For `Import-Excel` change Resolve-Path to return ProviderPath for use with UNC + +**6/01/2016** + +* Added -UseDefaultCredentials to both `Import-Html` and `Get-HtmlTable` +* New functions, `Import-UPS` and `Import-USPS`. Pass in a valid tracking \# and it scrapes the page for the delivery details + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/Tracking.gif) + +**4/30/2016** + +Huge thank you to [Willie Möller](https://github.com/W1M0R) + +* He added a version check so the PowerShell Classes don't cause issues for down-level version of PowerShell +* He also contributed the first Pester tests for the module. Super! Check them out, they'll be the way tests will be implemented going forward + +**4/18/2016** + +Thanks to [Paul Williams](https://github.com/pauldalewilliams) for this feature. Now data can be transposed to columns for better charting. + +```text +$file = "C:\Temp\ps.xlsx" +rm $file -ErrorAction Ignore + +ps | + where company | + select Company,PagedMemorySize,PeakPagedMemorySize | + Export-Excel $file -Show -AutoSize ` + -IncludePivotTable ` + -IncludePivotChart ` + -ChartType ColumnClustered ` + -PivotRows Company ` + -PivotData @{PagedMemorySize='sum';PeakPagedMemorySize='sum'} +``` + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PivotAsRows.png) + +Add `-PivotDataToColumn` + +```text +$file = "C:\Temp\ps.xlsx" +rm $file -ErrorAction Ignore + +ps | + where company | + select Company,PagedMemorySize,PeakPagedMemorySize | + Export-Excel $file -Show -AutoSize ` + -IncludePivotTable ` + -IncludePivotChart ` + -ChartType ColumnClustered ` + -PivotRows Company ` + -PivotData @{PagedMemorySize='sum';PeakPagedMemorySize='sum'} ` + -PivotDataToColumn +``` + +And here is the new chart view ![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PivotAsColumns.png) + +**4/7/2016** + +Made more methods fluent + +```text +$t=Get-Range 0 5 .2 + +$t2=$t|%{$_*$_} +$t3=$t|%{$_*$_*$_} + +(New-Plot). + Plot($t,$t, $t,$t2, $t,$t3). + SetChartPosition("i"). + SetChartSize(500,500). + Title("Hello World"). + Show() +``` + +**3/31/2016** + +* Thanks to [redoz](https://github.com/redoz) Multi Series Charts are now working + +Also check out how you can create a table and then with Excel notation, index into the data for charting `"Impressions[A]"` + +```text +$data = @" +A,B,C,Date +2,1,1,2016-03-29 +5,10,1,2016-03-29 +"@ | ConvertFrom-Csv + +$c = New-ExcelChart -Title Impressions ` + -ChartType Line -Header "Something" ` + -XRange "Impressions[Date]" ` + -YRange @("Impressions[B]","Impressions[A]") + +$data | + Export-Excel temp.xlsx -AutoSize -TableName Impressions -Show -ExcelChartDefinition $c +``` + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/MultiSeries.gif) + +**3/26/2016** + +* Added `NumberFormat` parameter + +```text +$data | + Export-Excel -Path $file -Show -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' +``` + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/Formatting.png) + +**3/18/2016** + +* Added `Get-Range`, `New-Plot` and Plot Cos example +* Updated EPPlus DLL. Allows markers to be changed and colored +* Handles and warns if auto name range names are also valid Excel ranges + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PSPlot.gif) + +**3/7/2016** + +* Added `Header` and `FirstDataRow` for `Import-Html` + +**3/2/2016** + +* Added `GreaterThan`, `GreaterThanOrEqual`, `LessThan`, `LessThanOrEqual` to `New-ConditionalText` + +```text +echo 489 668 299 777 860 151 119 497 234 788 | + Export-Excel c:\temp\test.xlsx -Show ` + -ConditionalText (New-ConditionalText -ConditionalType GreaterThan 525) +``` + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/GTConditional.png) + +**2/22/2016** + +* `Import-Html` using Lee Holmes [Extracting Tables from PowerShell’s Invoke-WebRequest](http://www.leeholmes.com/blog/2015/01/05/extracting-tables-from-PowerShells-invoke-webrequest/) + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/ImportHtml.gif) + +**2/17/2016** + +* Added Conditional Text types of `Equal` and `NotEqual` +* Phone \#'s like '+33 011 234 34' will be now be handled correctly + +### Try _PassThru_ + +```text +$file = "C:\Temp\passthru.xlsx" +rm $file -ErrorAction Ignore + +$xlPkg = $( + New-PSItem north 10 + New-PSItem east 20 + New-PSItem west 30 + New-PSItem south 40 +) | Export-Excel $file -PassThru + +$ws=$xlPkg.Workbook.Worksheets[1] + +$ws.Cells["A3"].Value = "Hello World" +$ws.Cells["B3"].Value = "Updating cells" +$ws.Cells["D1:D5"].Value = "Data" + +$ws.Cells.AutoFitColumns() + +$xlPkg.Save() +$xlPkg.Dispose() + +Invoke-Item $file +``` + +### Result + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PassThru.png) + +**1/18/2016** + +* Added `Conditional Text Formatting`. [Boe Prox](https://twitter.com/proxb) posted about [HTML Reporting, Part 2: Take Your Reporting a Step Further](https://mcpmag.com/articles/2016/01/14/html-reporting-part-2.aspx) and colorized cells. Great idea, now part of the PowerShell Excel module. + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/ConditionalText2.gif) + +**1/7/2016** + +* Added `Get-ExcelSheetInfo` - Great contribution from _Johan Åkerström_ check him out on [GitHub](https://github.com/CosmosKey) and [Twitter](https://twitter.com/neptune443) + +![](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/GetExcelSheetInfo.png) + +**12/26/2015** + +* Added `NoLegend`, `Show-Category`, `ShowPercent` for all charts including Pivot Charts +* Updated PieChart, BarChart, ColumnChart and Line chart to work with the pipeline and added `NoLegend`, `Show-Category`, `ShowPercent` + +**12/17/2015** + +These new features open the door for really sophisticated work sheet creation. + +Stay tuned for a [blog post](http://www.dougfinke.com/blog/) and examples. + +_**Quick List**_ + +* StartRow, StartColumn for placing data anywhere in a sheet +* New-ExcelChart - Add charts to a sheet, multiple series for a chart, locate the chart anywhere on the sheet +* AutoNameRange, Use functions and/or calculations in a cell +* Quick charting using PieChart, BarChart, ColumnChart and more + +![](https://raw.githubusercontent.com/dfinke/GifCam/master/JustCharts.gif) + +**10/20/2015** + +Big bug fix for version 3.0 PowerShell folks! + +This technique fails in 3.0 and works in 4.0 and later. + +```text +$m="substring" +"hello".$m(2,1) +``` + +Adding `.invoke` works in 3.0 and later. + +```text +$m="substring" +"hello".$m.invoke(2,1) +``` + +A _**big thank you**_ to [DarkLite1](https://github.com/DarkLite1) for adding the help to Export-Excel. + +Added `-HeaderRow` parameter. Sometimes the heading does not start in Row 1. + +**10/16/2015** + +Fixes [Export-Excel generates corrupt Excel file](https://github.com/dfinke/ImportExcel/issues/46) + +**10/15/2015** + +`Import-Excel` has a new parameter `NoHeader`. If data in the sheet does not have headers and you don't want to supply your own, `Import-Excel` will generate the property name. + +`Import-Excel` now returns `.Value` rather than `.Text` + +**10/1/2015** + +Merged ValidateSet for Encoding and Extension. Thank you [Irwin Strachan](https://github.com/irwins). + +**9/30/2015** + +Export-Excel can now handle data that is **not** an object + +```text +echo a b c 1 $true 2.1 1/1/2015 | Export-Excel c:\temp\test.xlsx -Show +``` + +Or + +```text +dir -Name | Export-Excel c:\temp\test.xlsx -Show +``` + +**9/25/2015** + +**Hide worksheets** Got a great request from [forensicsguy20012004](https://github.com/forensicsguy20012004) to hide worksheets. You create a few pivotables, generate charts and then pivot table worksheets don't need to be visible. + +`Export-Excel` now has a `-HideSheet` parameter that takes and array of worksheet names and hides them. + +**Example** + +Here, you create four worksheets named `PM`,`Handles`,`Services` and `Files`. + +The last line creates the `Files` sheet and then hides the `Handles`,`Services` sheets. + +```text +$p = Get-Process + +$p|select company, pm | Export-Excel $xlFile -WorkSheetname PM +$p|select company, handles| Export-Excel $xlFile -WorkSheetname Handles +Get-Service| Export-Excel $xlFile -WorkSheetname Services + +dir -File | Export-Excel $xlFile -WorkSheetname Files -Show -HideSheet Handles, Services +``` + +**Note** There is a bug in EPPlus that does not let you hide the first worksheet created. Hopefully it'll resolved soon. + +**9/11/2015** + +Added Conditional formatting. See [TryConditional.ps1](https://github.com/dfinke/ImportExcel/blob/master/TryConditional.ps1) as an example. + +Or, check out the short _**"How To"**_ video. + +[![image](http://www.dougfinke.com/videos/excelpsmodule/ExcelPSModule_First_Frame.png)](http://www.dougfinke.com/videos/excelpsmodule/excelpsmodule.mp4) + +**8/21/2015** + +* Now import Excel sheets even if the file is open in Excel. Thank you [Francois Lachance-Guillemette](https://github.com/francoislg) + +**7/09/2015** + +* For -PivotRows you can pass a `hashtable` with the name of the property and the type of calculation. `Sum`, `Average`, `Max`, `Min`, `Product`, `StdDev`, `StdDevp`, `Var`, `Varp` + +```text +Get-Service | + Export-Excel "c:\temp\test.xlsx" ` + -Show ` + -IncludePivotTable ` + -PivotRows status ` + -PivotData @{status='count'} +``` + +**6/16/2015 \(Thanks Justin\)** + +* Improvements to PivotTable overwriting +* Added two parameters to Export-Excel + * RangeName - Turns the data piped to Export-Excel into a named range. + * TableName - Turns the data piped to Export-Excel into an excel table. + +Examples + +```text +Get-Process|Export-Excel foo.xlsx -Verbose -IncludePivotTable -TableName "Processes" -Show +Get-Process|Export-Excel foo.xlsx -Verbose -IncludePivotTable -RangeName "Processes" -Show +``` + +**5/25/2015** + +* Fixed null header problem + +**5/17/2015** + +* Added three parameters: + * FreezeTopRow - Freezes the first row of the data + * AutoFilter - Enables filtering for the data in the sheet + * BoldTopRow - Bolds the top row of data, the column headers + +Example + +```text +Get-CimInstance win32_service | + select state, accept*, start*, caption | + Export-Excel test.xlsx -Show -BoldTopRow -AutoFilter -FreezeTopRow -AutoSize +``` + +![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/FilterFreezeBold.gif) + +**5/4/2015** + +* Published to PowerShell Gallery. In PowerShell v5 use `Find-Module importexcel` then `Find-Module importexcel | Install-Module` + +**4/27/2015** + +* datetime properties were displaying as ints, now are formatted + +**4/25/2015** + +* Now you can create multiple Pivot tables in one pass + * Thanks to [pscookiemonster](https://twitter.com/pscookiemonster), he submitted a repro case to the EPPlus CodePlex project and got it fixed + +**Example** + +```text +$ps = ps + +$ps | + Export-Excel .\testExport.xlsx -WorkSheetname memory ` + -IncludePivotTable -PivotRows Company -PivotData PM ` + -IncludePivotChart -ChartType PieExploded3D +$ps | + Export-Excel .\testExport.xlsx -WorkSheetname handles ` + -IncludePivotTable -PivotRows Company -PivotData Handles ` + -IncludePivotChart -ChartType PieExploded3D -Show +``` + +![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/MultiplePivotTables.png) + +**4/20/2015** + +* Included and embellished [Claus Nielsen](https://github.com/Claustn) function to take all sheets in an Excel file workbook and create a text file for each `ConvertFrom-ExcelSheet` +* Renamed `Export-MultipleExcelSheets` to `ConvertFrom-ExcelSheet` + +**4/13/2015** + +* You can add a title to the Excel "Report" `Title`, `TitleFillPattern`, `TitleBold`, `TitleSize`, `TitleBackgroundColor` + * Thanks to [Irwin Strachan](http://pshirwin.wordpress.com) for this and other great suggestions, testing and more + +**4/10/2015** + +* Renamed `AutoFitColumns` to `AutoSize` +* Implemented `Export-MultipleExcelSheets` +* Implemented `-Password` for a worksheet +* Replaced `-Force` switch with `-NoClobber` switch +* Added examples for `Get-Help` +* If Pivot table is requested, that sheet becomes the tab selected + +**4/8/2015** + +* Implemented exporting data to **named sheets** via the -WorkSheetname parameter. + +Examples - `gsv | Export-Excel .\test.xlsx -WorkSheetname Services` + +`dir -file | Export-Excel .\test.xlsx -WorkSheetname Files` + +`ps | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM` + +**Convert \(All or Some\) Excel Sheets to Text files** + +Reads each sheet in TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt + +```text +ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data +``` + +Reads and outputs sheets like Sheet10 and Sheet20 form TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt + +```text +ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data sheet?0 +``` + +**Example Adding a Title** + +You can set the pattern, size and of if the title is bold. + +```text +$p=@{ + Title = "Process Report as of $(Get-Date)" + TitleFillPattern = "LightTrellis" + TitleSize = 18 + TitleBold = $true + + Path = "$pwd\testExport.xlsx" + Show = $true + AutoSize = $true +} + +Get-Process | + Where Company | Select Company, PM | + Export-Excel @p +``` + +![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/Title.png) + +**Example Export-MultipleExcelSheets** + +![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/ExportMultiple.gif) + +```text +$p = Get-Process + +$DataToGather = @{ + PM = {$p|select company, pm} + Handles = {$p|select company, handles} + Services = {gsv} + Files = {dir -File} + Albums = {(Invoke-RestMethod http://www.dougfinke.com/PowerShellfordevelopers/albums.js)} +} + +Export-MultipleExcelSheets -Show -AutoSize .\testExport.xlsx $DataToGather +``` + +_**NOTE**_ If the sheet exists when using _-WorkSheetname_ parameter, it will be deleted and then added with the new data. + +### Get-Process Exported to Excel + +#### Total Physical Memory Grouped By Company + +![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/PivotTablesAndCharts.png) + +### Importing data from an Excel spreadsheet + +![image](https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/TryImportExcel.gif) + +You can also find EPPLus on [Nuget](https://www.nuget.org/packages/EPPlus/). + +### Known Issues + +* Using `-IncludePivotTable`, if that pivot table name exists, you'll get an error. + * Investigating a solution + * _Workaround_ delete the Excel file first, then do the export + diff --git a/RemoveWorksheet.ps1 b/RemoveWorksheet.ps1 deleted file mode 100644 index 0b2c06b2..00000000 --- a/RemoveWorksheet.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -Function Remove-WorkSheet { - Param ( - $Path, - $WorksheetName - ) - - $Path = (Resolve-Path $Path).ProviderPath - - $Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage $Path - - $workSheet = $Excel.Workbook.Worksheets[$WorkSheetName] - - if($workSheet) { - if($Excel.Workbook.Worksheets.Count -gt 1) { - $Excel.Workbook.Worksheets.Delete($workSheet) - } else { - throw "Cannot delete $WorksheetName. A workbook must contain at least one visible worksheet" - } - - } else { - throw "$WorksheetName not found" - } - - $Excel.Save() - $Excel.Dispose() -} - -cls - -ipmo .\ImportExcel.psd1 -Force - -$names = Get-ExcelSheetInfo C:\Temp\testDelete.xlsx -$names | % { Remove-WorkSheet C:\Temp\testDelete.xlsx $_.Name} - -##Remove-WorkSheet C:\Temp\testDelete.xlsx sheet6 \ No newline at end of file diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 00000000..a7f9fbb1 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,74 @@ +# Table of contents + +* [README](README.md) +* [InferData](inferdata/README.md) + * [Test-Boolean](inferdata/test-boolean.md) + * [Invoke-AllTests](inferdata/invoke-alltests.md) + * [Test-Integer](inferdata/test-integer.md) + * [Test-String](inferdata/test-string.md) + * [Test-Date](inferdata/test-date.md) + * [Test-Number](inferdata/test-number.md) +* [mdHelp](mdhelp/README.md) + * [en](mdhelp/en/README.md) + * [Expand-NumberFormat](mdhelp/en/expand-numberformat.md) + * [Open-ExcelPackage](mdhelp/en/open-excelpackage.md) + * [Add-ExcelChart](mdhelp/en/add-excelchart.md) + * [Copy-ExcelWorkSheet](mdhelp/en/copy-excelworksheet.md) + * [Set-ExcelRange](mdhelp/en/set-excelrange.md) + * [Import-Excel](mdhelp/en/import-excel.md) + * [Set-ExcelRow](mdhelp/en/set-excelrow.md) + * [Get-ExcelSheetInfo](mdhelp/en/get-excelsheetinfo.md) + * [New-PivotTableDefinition](mdhelp/en/new-pivottabledefinition.md) + * [Add-ExcelDataValidationRule](mdhelp/en/add-exceldatavalidationrule.md) + * [Join-Worksheet](mdhelp/en/join-worksheet.md) + * [New-ConditionalFormattingIconSet](mdhelp/en/new-conditionalformattingiconset.md) + * [Send-SQLDataToExcel](mdhelp/en/send-sqldatatoexcel.md) + * [Get-ExcelWorkbookInfo](mdhelp/en/get-excelworkbookinfo.md) + * [New-ConditionalText](mdhelp/en/new-conditionaltext.md) + * [Compare-WorkSheet](mdhelp/en/compare-worksheet.md) + * [New-ExcelChartDefinition](mdhelp/en/new-excelchartdefinition.md) + * [Remove-WorkSheet](mdhelp/en/remove-worksheet.md) + * [ConvertFrom-ExcelToSQLInsert](mdhelp/en/convertfrom-exceltosqlinsert.md) + * [Close-ExcelPackage](mdhelp/en/close-excelpackage.md) + * [Set-ExcelColumn](mdhelp/en/set-excelcolumn.md) + * [Add-WorkSheet](mdhelp/en/add-worksheet.md) + * [Add-ExcelTable](mdhelp/en/add-exceltable.md) + * [Convert-ExcelRangeToImage](mdhelp/en/convert-excelrangetoimage.md) + * [Add-ConditionalFormatting](mdhelp/en/add-conditionalformatting.md) + * [Update-FirstObjectProperties](mdhelp/en/update-firstobjectproperties.md) + * [Export-Excel](mdhelp/en/export-excel.md) + * [Select-Worksheet](mdhelp/en/select-worksheet.md) + * [Merge-Worksheet](mdhelp/en/merge-worksheet.md) + * [Merge-MultipleSheets](mdhelp/en/merge-multiplesheets.md) + * [Add-ExcelName](mdhelp/en/add-excelname.md) + * [ConvertFrom-ExcelSheet](mdhelp/en/convertfrom-excelsheet.md) + * [Add-PivotTable](mdhelp/en/add-pivottable.md) +* [Public](public/README.md) + * [Import-USPS](public/import-usps.md) + * [Get-Range](public/get-range.md) + * [Get-XYRange](public/get-xyrange.md) + * [Set-CellStyle](public/set-cellstyle.md) + * [Invoke-Sum](public/invoke-sum.md) + * [Get-ExcelColumnName](public/get-excelcolumnname.md) + * [Import-UPS](public/import-ups.md) + * [Set-WorksheetProtection](public/set-worksheetprotection.md) + * [New-Plot](public/new-plot.md) + * [Import-Html](public/import-html.md) + * [New-ExcelStyle](public/new-excelstyle.md) + * [ConvertFrom-ExcelData](public/convertfrom-exceldata.md) + * [ConvertTo-ExcelXlsx](public/convertto-excelxlsx.md) + * [New-PSItem](public/new-psitem.md) + * [Get-HtmlTable](public/get-htmltable.md) +* [Charting](charting/README.md) + * [LineChart](charting/linechart.md) + * [PieChart](charting/piechart.md) + * [ColumnChart](charting/columnchart.md) + * [BarChart](charting/barchart.md) + * [DoChart](charting/dochart.md) +* [Examples](examples/README.md) + * [Untitled](examples/untitled.md) + * [Charts](examples/charts/README.md) + * [Multiplecharts](examples/charts/multiplecharts.md) +* [Pivot](pivot/README.md) + * [Pivot](pivot/pivot.md) + diff --git a/Send-SqlDataToExcel.ps1 b/Send-SqlDataToExcel.ps1 deleted file mode 100644 index 15a1b1ce..00000000 --- a/Send-SqlDataToExcel.ps1 +++ /dev/null @@ -1,133 +0,0 @@ -Function Send-SQLDataToExcel { -<# - .Synopsis - Runs a SQL query and inserts the results into an ExcelSheet, more efficiently than sending it via Export-Excel - .Description - This command takes either an object representing a session with a SQL server or ODBC database, or a connection String to make one. - It the runs a SQL command, and inserts the rows of data returned into a worksheet. - It takes most of the parameters of Export-Excel, but it is more efficient than getting dataRows and piping them into Export-Excel, - data-rows have additional properties which need to be stripped off. - .Example - C:\> Send-SQLDataToExcel -MsSQLserver -Connection localhost -SQL "select name,type,type_desc from [master].[sys].[all_objects]" -Path .\temp.xlsx -WorkSheetname master -AutoSize -FreezeTopRow -AutoFilter -BoldTopRow - Connects to the local SQL server and selects 3 columns from [Sys].[all_objects] and exports then to a sheet named master with some basic header manager - .Example - C:\> $SQL="SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" - C:\> $Connection = 'Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DriverId=790;ReadOnly=0;Dbq=C:\users\James\Documents\f1Results.xlsx;' - C:\> Send-SQLDataToExcel -Connection $connection -SQL $sql -path .\demo4.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange - - This declares a SQL statement and creates an ODBC connection string to read from an Excel file, it then runs the statement and outputs the resulting data to a new spreadsheet. - .Example - C:\> Send-SQLDataToExcel -path .\demo4.xlsx -WorkSheetname "LR" -Connection "DSN=LR" -sql "SELECT name AS CollectionName FROM AgLibraryCollection Collection ORDER BY CollectionName" - - This example uses an Existing ODBC datasource name "LR" which maps to an adobe lightroom database and gets a list of collection names into a worksheet - - - -#> - param ( - #Database connection string; either DSN=ODBC_Data_Source_Name, a full odbc or SQL Connection string, or the name of a SQL server - [Parameter(ParameterSetName="SQLConnection", Mandatory=$true)] - [Parameter(ParameterSetName="ODBCConnection",Mandatory=$true)] - $Connection, - #A pre-existing database session object - [Parameter(ParameterSetName="ExistingSession",Mandatory=$true)] - [System.Data.Common.DbConnection]$Session, - #Specifies the connection string is for SQL server not ODBC - [Parameter(ParameterSetName="SQLConnection",Mandatory=$true)] - [switch]$MsSQLserver, - #Switches to a specific database on a SQL server - [Parameter(ParameterSetName="SQLConnection")] - [String]$DataBase, - #The SQL query to run - [Parameter(Mandatory=$true)] - [string]$SQL, - $Path, - [String]$WorkSheetname = 'Sheet1', - [Switch]$KillExcel, - #If Specified, open the file created. - [Switch]$Show, - [String]$Title, - [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None', - [Switch]$TitleBold, - [Int]$TitleSize = 22, - [System.Drawing.Color]$TitleBackgroundColor, - [String]$Password, - [String[]]$PivotRows, - [String[]]$PivotColumns, - $PivotData, - [Switch]$PivotDataToColumn, - [Hashtable]$PivotTableDefinition, - [Switch]$IncludePivotChart, - [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie', - [Switch]$NoLegend, - [Switch]$ShowCategory, - [Switch]$ShowPercent, - [Switch]$AutoSize, - [Switch]$FreezeTopRow, - [Switch]$FreezeFirstColumn, - [Switch]$FreezeTopRowFirstColumn, - [Int[]]$FreezePane, - [Switch]$AutoFilter, - [Switch]$BoldTopRow, - [Switch]$NoHeader, - [String]$RangeName, - [String]$TableName, - [OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6', - [Object[]]$ExcelChartDefinition, - [Switch]$AutoNameRange, - [Object[]]$ConditionalFormat, - [Object[]]$ConditionalText, - [ScriptBlock]$CellStyleSB, - [Int]$StartRow = 1, - [Int]$StartColumn = 1, - #If Specified, return an ExcelPackage object to allow further work to be done on the file. - [Switch]$Passthru - ) - - if ($KillExcel) { - Get-Process excel -ErrorAction Ignore | Stop-Process - while (Get-Process excel -ErrorAction Ignore) {} - } - - #We were either given a session object or a connection string (with, optionally a MSSQLServer parameter) - # If we got -MSSQLServer, create a SQL connection, if we didn't but we got -Connection create an ODBC connection - if ($MsSQLserver) { - if ($connection -notmatch "=") {$Connection = "server=$Connection;trusted_connection=true;timeout=60"} - $Session = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $Connection - if ($Session.State -ne 'Open') {$session.Open()} - if ($DataBase) {$Session.ChangeDatabase($DataBase) } - } - elseif ($Connection) { - $Session = New-Object -TypeName System.Data.Odbc.OdbcConnection -ArgumentList $Connection ; $Session.ConnectionTimeout = 30 - } - - #A session was either passed in or just created. If it's a SQL one make a SQL DataAdapter, otherwise make an ODBC one - if ($Session.gettype().name -match "SqlConnection") { - $dataAdapter = New-Object -TypeName System.Data.SqlClient.SqlDataAdapter -ArgumentList ( - New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $sql, $Session) - } - else { - $dataAdapter = New-Object -TypeName System.Data.Odbc.OdbcDataAdapter -ArgumentList ( - New-Object -TypeName System.Data.Odbc.OdbcCommand -ArgumentList $sql, $Session ) - } - - #Both adapter types output the same kind of table, create one and fill it from the adapter - $dataTable = New-Object -TypeName System.Data.DataTable - $rowCount = $dataAdapter.fill($dataTable) - Write-Verbose "Query returned $rowcount row(s)" - - #ExportExcel user a -NoHeader parameter so that's what we use here, but needs to be the other way around. - $PrintHeaders = -not $NoHeader - if ($Title) {$r = $StartRow +1 } - else {$r = $StartRow} - #Get our Excel sheet and fill it with the data - $excelPackage = Export-Excel -Path $Path -WorkSheetname $WorkSheetname -PassThru - $excelPackage.Workbook.Worksheets[$WorkSheetname].Cells[$r,$StartColumn].LoadFromDataTable($dataTable, $PrintHeaders ) | Out-Null - - #Call export-excel with any parameters which don't relate to the SQL query - "Connection", "Database" , "Session", "MsSQLserver", "Destination" , "sql" ,"Path" | foreach-object {$null = $PSBoundParameters.Remove($_) } - Export-Excel -ExcelPackage $excelPackage @PSBoundParameters - - #If we were not passed a session close the session we created. - if ($Connection) {$Session.close() } -} diff --git a/Set-CellStyle.ps1 b/Set-CellStyle.ps1 deleted file mode 100644 index 43cef70c..00000000 --- a/Set-CellStyle.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -function Set-CellStyle { - param( - $WorkSheet, - $Row, - $LastColumn, - [OfficeOpenXml.Style.ExcelFillStyle]$Pattern, - [System.Drawing.Color]$Color - ) - - $t=$WorkSheet.Cells["A$($Row):$($LastColumn)$($Row)"] - $t.Style.Fill.PatternType=$Pattern - $t.Style.Fill.BackgroundColor.SetColor($Color) -} \ No newline at end of file diff --git a/Set-Column.ps1 b/Set-Column.ps1 deleted file mode 100644 index 5246a6ae..00000000 --- a/Set-Column.ps1 +++ /dev/null @@ -1,139 +0,0 @@ -Function Set-Column { -<# - .SYNOPSIS - Adds a column to the existing data area in an Excel sheet, fills values and sets formatting - .DESCRIPTION - Set-Column takes a value which is either string containing a value or formula or a scriptblock - which evaluates to a string, and optionally a column number and fills that value down the column. - A column name can be specified and the new column can be made a named range. - The column can be formatted. - .Example - C:> Set-Column -Worksheet $ws -Heading "WinsToFastLaps" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange - Here $WS already contains a worksheet which contains counts of races won and fastest laps recorded by racing drivers (in columns C and E) - Set-Column specifies that Column 7 should have a heading of "WinsToFastLaps" and the data cells should contain =E2/C2 , =E3/C3 - the data celss should become a named range, which will also be "WinsToFastLaps" the column width will be set automatically - -#> -[cmdletbinding()] - Param ( - [Parameter(ParameterSetName="Package",Mandatory=$true)] - [OfficeOpenXml.ExcelPackage]$ExcelPackage, - #Sheet to update - [Parameter(ParameterSetName="Package")] - $Worksheetname = "Sheet1", - [Parameter(ParameterSetName="sheet",Mandatory=$true)] - [OfficeOpenXml.ExcelWorksheet] - $Worksheet, - #Column to fill down - first column is 1. 0 will be interpreted as first unused column - $Column = 0 , - [Int]$StartRow , - #value, formula or script block for to fill in. Script block can use $row, $column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn - [parameter(Mandatory=$true)] - $Value , - #Optional column heading - $Heading , - #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc - [Alias("NFormat")] - $NumberFormat, - #Style of border to draw around the row - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, - #Colour for the text - if none specified it will be left as it it is - [System.Drawing.Color]$FontColor, - #Make text bold - [switch]$Bold, - #Make text italic - [switch]$Italic, - #Underline the text using the underline style in -underline type - [switch]$Underline, - #Should Underline use single or double, normal or accounting mode : default is single normal - [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, - #StrikeThrough text - [switch]$StrikeThru, - #Subscript or superscript - [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, - #Font to use - Excel defaults to Calibri - [String]$FontName, - #Point size for the text - [float]$FontSize, - #Change background colour - [System.Drawing.Color]$BackgroundColor, - #Background pattern - solid by default - [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , - #Secondary colour for background pattern - [Alias("PatternColour")] - [System.Drawing.Color]$PatternColor, - #Turn on text wrapping - [switch]$WrapText, - #Position cell contents to left, right or centre ... - [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, - #Position cell contents to top bottom or centre - [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, - #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. - [ValidateRange(-90, 90)] - [int]$TextRotation , - #Autofit cells to width - [Alias("AutoFit")] - [Switch]$AutoSize, - #Set cells to a fixed width, ignored if Autosize is specified - [float]$Width, - #Set the inserted data to be a named range (ignored if header is not specified) d - [Switch]$AutoNameRange, - [switch]$PassThru - ) - #if we were passed a package object and a worksheet name , get the worksheet. - if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] } - - #In a script block to build a formula, we may want any of corners or the columnname, - #if column and startrow aren't specified, assume first unused column, and first row - if (-not $StartRow) {$startRow = $Worksheet.Dimension.Start.Row } - $StartColumn = $Worksheet.Dimension.Start.Column - $endColumn = $Worksheet.Dimension.End.Column - $endRow = $Worksheet.Dimension.End.Row - if ($Column -lt 2 ) {$Column = $endColumn + 1 } - $ColumnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" - - Write-Verbose -Message "Updating Column $ColumnName" - #If there is a heading, insert it and use it as the name for a range (if we're creating one) - if ($Heading) { - $Worksheet.Cells[$StartRow, $Column].Value = $heading - $startRow ++ - if ($AutoNameRange) { $Worksheet.Names.Add( $heading, ($Worksheet.Cells[$startrow, $Column, $endRow, $Column]) ) | Out-Null } - } - #Fill in the data - if ($value) { foreach ($row in ($StartRow.. $endRow)) { - if ($Value -is [scriptblock]) { #re-create the script block otherwise variables from this function are out of scope. - $cellData = & ([scriptblock]::create( $Value )) - Write-Verbose -Message $cellData - } - else { $cellData = $Value} - if ($cellData -match "^=") { $Worksheet.Cells[$Row, $Column].Formula = $cellData } - else { $Worksheet.Cells[$Row, $Column].Value = $cellData } - if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized. - }} - #region Apply formatting - if ($Underline) { - $Worksheet.Column( $Column).Style.Font.UnderLine = $true - $Worksheet.Column( $Column).Style.Font.UnderLineType = $UnderLineType - } - if ($Bold) { $Worksheet.Column( $Column).Style.Font.Bold = $true } - if ($Italic) { $Worksheet.Column( $Column).Style.Font.Italic = $true } - if ($StrikeThru) { $Worksheet.Column( $Column).Style.Font.Strike = $true } - if ($FontShift) { $Worksheet.Column( $Column).Style.Font.VerticalAlign = $FontShift } - if ($NumberFormat) { $Worksheet.Column( $Column).Style.Numberformat.Format = $NumberFormat } - if ($TextRotation) { $Worksheet.Column( $Column).Style.TextRotation = $TextRotation } - if ($WrapText) { $Worksheet.Column( $Column).Style.WrapText = $true } - if ($HorizontalAlignment) { $Worksheet.Column( $Column).Style.HorizontalAlignment = $HorizontalAlignment} - if ($VerticalAlignment) { $Worksheet.Column( $Column).Style.VerticalAlignment = $VerticalAlignment } - if ($FontColor) { $Worksheet.Column( $Column).Style.Font.Color.SetColor( $FontColor ) } - if ($BorderAround) { $Worksheet.Column( $Column).Style.Border.BorderAround( $BorderAround ) } - if ($BackgroundColor) { - $Worksheet.Column( $Column).Style.Fill.PatternType = $BackgroundPattern - $Worksheet.Column( $Column).Style.Fill.BackgroundColor.SetColor($BackgroundColor ) - if ($PatternColor) { $Worksheet.Column( $Column).Style.Fill.PatternColor.SetColor( $PatternColor ) } - } - if ($Autosize) { $Worksheet.Column( $Column).AutoFit() } - elseif ($Width) { $Worksheet.Column( $Column).Width = $Width } - #endregion - #return the new data if -passthru was specified. - if ($passThru) { $Worksheet.Column( $Column)} -} \ No newline at end of file diff --git a/Set-Row.ps1 b/Set-Row.ps1 deleted file mode 100644 index 9250c1a4..00000000 --- a/Set-Row.ps1 +++ /dev/null @@ -1,142 +0,0 @@ -Function Set-Row { -<# -.Synopsis - Fills values into a row in a Excel spreadsheet -.Description - Set-Row accepts either a Worksheet object or an Excel package object returned by Export-Excel and the name of a sheet, - and inserts the chosen contents into a row of the sheet. - The contents can be a constant "42" , a formula or a script block which is converted into a constant or formula. - The first cell of the row can optional be given a heading. -.Example - Set-row -Worksheet $ws -Heading Total -Value {"=sum($columnName`2:$columnName$endrow)" } - - $Ws contains a worksheet object, and no Row number is specified so Set-Row will select the next row after the end of the data in the sheet - The first cell will contain "Total", and each other cell will contain - =Sum(xx2:xx99) - where xx is the column name, and 99 is the last row of data. - Note the use of `2 to Prevent 2 becoming part of the variable "ColumnName" - The script block can use $row, $column, $ColumnName, $startRow/Column $endRow/Column - - -#> -[cmdletbinding()] - Param ( - #An Excel package object - e.g. from Export-Excel -passthru - requires a sheet name - [Parameter(ParameterSetName="Package",Mandatory=$true)] - [OfficeOpenXml.ExcelPackage]$ExcelPackage, - #the name to update in the package - [Parameter(ParameterSetName="Package")] - $Worksheetname = "Sheet1", - #A worksheet object - [Parameter(ParameterSetName="sheet",Mandatory=$true)] - [OfficeOpenXml.Excelworksheet] - $Worksheet, - #Row to fill right - first row is 1. 0 will be interpreted as first unused row - $Row = 0 , - #Position in the row to start from - [Int]$StartColumn, - #value, formula or script block for to fill in. Script block can use $row, $column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn - [parameter(Mandatory=$true)] - $Value, - #Optional Row heading - $Heading , - #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc - [Alias("NFormat")] - $NumberFormat, - #Style of border to draw around the row - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, - #Colour for the text - if none specified it will be left as it it is - [System.Drawing.Color]$FontColor, - #Make text bold - [switch]$Bold, - #Make text italic - [switch]$Italic, - #Underline the text using the underline style in -underline type - [switch]$Underline, - #Should Underline use single or double, normal or accounting mode : default is single normal - [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, - #StrikeThrough text - [switch]$StrikeThru, - #Subscript or superscript - [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, - #Font to use - Excel defaults to Calibri - [String]$FontName, - #Point size for the text - [float]$FontSize, - #Change background colour - [System.Drawing.Color]$BackgroundColor, - #Background pattern - solid by default - [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , - #Secondary colour for background pattern - [Alias("PatternColour")] - [System.Drawing.Color]$PatternColor, - #Turn on text wrapping - [switch]$WrapText, - #Position cell contents to left, right or centre ... - [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, - #Position cell contents to top bottom or centre - [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, - #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. - [ValidateRange(-90, 90)] - [int]$TextRotation , - #Set cells to a fixed hieght - [float]$Height, - [switch]$PassThru - ) - - #if we were passed a package object and a worksheet name , get the worksheet. - if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.worksheets[$Worksheetname] } - - #In a script block to build a formula, we may want any of corners or the columnname, - #if row and start column aren't specified assume first unused row, and first column - if (-not $StartColumn) {$StartColumn = $Worksheet.Dimension.Start.Column } - $startRow = $Worksheet.Dimension.Start.Row + 1 - $endColumn = $Worksheet.Dimension.End.Column - $endRow = $Worksheet.Dimension.End.Row - if ($Row -lt 2 ) {$Row = $endRow + 1 } - - Write-Verbose -Message "Updating Row $Row" - #Add a row label - if ($Heading) { - $Worksheet.Cells[$Row, $StartColumn].Value = $Heading - $StartColumn ++ - } - #Fill in the data - if ($value) {foreach ($column in ($StartColumn..$EndColumn)) { - #We might want the column name in a script block - $ColumnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" - if ($Value -is [scriptblock] ) { - #re-create the script block otherwise variables from this function are out of scope. - $cellData = & ([scriptblock]::create( $Value )) - Write-Verbose -Message $cellData - } - else{$cellData = $Value} - if ($cellData -match "^=") { $Worksheet.Cells[$Row, $column].Formula = $cellData } - else { $Worksheet.Cells[$Row, $Column].Value = $cellData } - if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized. - }} - #region Apply formatting - if ($Underline) { - $worksheet.row( $Row ).Style.Font.UnderLine = $true - $worksheet.row( $Row ).Style.Font.UnderLineType = $UnderLineType - } - if ($Bold) { $worksheet.row( $Row ).Style.Font.Bold = $true } - if ($Italic) { $worksheet.row( $Row ).Style.Font.Italic = $true } - if ($StrikeThru) { $worksheet.row( $Row ).Style.Font.Strike = $true } - if ($FontShift) { $worksheet.row( $Row ).Style.Font.VerticalAlign = $FontShift } - if ($NumberFormat) { $worksheet.row( $Row ).Style.Numberformat.Format = $NumberFormat } - if ($TextRotation) { $worksheet.row( $Row ).Style.TextRotation = $TextRotation } - if ($WrapText) { $worksheet.row( $Row ).Style.WrapText = $true } - if ($HorizontalAlignment) { $worksheet.row( $Row ).Style.HorizontalAlignment = $HorizontalAlignment} - if ($VerticalAlignment) { $worksheet.row( $Row ).Style.VerticalAlignment = $VerticalAlignment } - if ($Height) { $worksheet.row( $Row ).Height = $Height } - if ($FontColor) { $worksheet.row( $Row ).Style.Font.Color.SetColor( $FontColor ) } - if ($BorderAround) { $worksheet.row( $Row ).Style.Border.BorderAround( $BorderAround ) } - if ($BackgroundColor) { - $worksheet.row( $Row ).Style.Fill.PatternType = $BackgroundPattern - $worksheet.row( $Row ).Style.Fill.BackgroundColor.SetColor($BackgroundColor ) - if ($PatternColor) { $worksheet.row( $Row ).Style.Fill.PatternColor.SetColor( $PatternColor ) } - } - #endregion - #return the new data if -passthru was specified. - if ($passThru) {$Worksheet.Row($Row)} -} \ No newline at end of file diff --git a/SetFormat.ps1 b/SetFormat.ps1 deleted file mode 100644 index 3c24aa4f..00000000 --- a/SetFormat.ps1 +++ /dev/null @@ -1,191 +0,0 @@ -Function Set-Format { -<# -.SYNOPSIS - Applies Number, font, alignment and colour formatting to a range of Excel Cells -.EXAMPLE - $sheet.Column(3) | Set-Format -HorizontalAlignment Right -NumberFormat "#,###" - Selects column 3 from a sheet object (within a workbook object, which is a child of the ExcelPackage object) and passes it to Set-Format which formats as an integer with comma seperated groups -.EXAMPLE - Set-Format -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NumberFormat "#,###" - Instead of piping the address in this version specifies a block of cells and applies similar formatting - -#> - Param ( - #One or more row(s), Column(s) and/or block(s) of cells to format - [Parameter(ValueFromPipeline = $true,ParameterSetName="Address",Mandatory=$True)] - $Address , - #The worksheet where the format is to be applied - [Parameter(ParameterSetName="SheetAndRange",Mandatory=$True)] - [OfficeOpenXml.ExcelWorksheet]$WorkSheet , - #The area of the worksheet where the format is to be applied - [Parameter(ParameterSetName="SheetAndRange",Mandatory=$True)] - [OfficeOpenXml.ExcelAddress]$Range, - #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc - [Alias("NFormat")] - $NumberFormat, - #Style of border to draw around the range - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, - [System.Drawing.Color]$BorderColor=[System.Drawing.Color]::Black, - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom, - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop, - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft, - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight, - #Colour for the text - if none specified it will be left as it it is - [System.Drawing.Color]$FontColor, - #Value for the cell - $Value, - #Formula for the cell - $Formula, - #Clear Bold, Italic, StrikeThrough and Underline and set colour to black - [switch]$ResetFont, - #Make text bold - [switch]$Bold, - #Make text italic - [switch]$Italic, - #Underline the text using the underline style in -underline type - [switch]$Underline, - #Should Underline use single or double, normal or accounting mode : default is single normal - [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, - #StrikeThrough text - [switch]$StrikeThru, - #Subscript or superscript - [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, - #Font to use - Excel defaults to Calibri - [String]$FontName, - #Point size for the text - [float]$FontSize, - #Change background colour - [System.Drawing.Color]$BackgroundColor, - #Background pattern - solid by default - [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , - #Secondary colour for background pattern - [Alias("PatternColour")] - [System.Drawing.Color]$PatternColor, - #Turn on text wrapping - [switch]$WrapText, - #Position cell contents to left, right or centre ... - [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, - #Position cell contents to top bottom or centre - [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, - #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. - [ValidateRange(-90, 90)] - [int]$TextRotation , - #Autofit cells to width (columns or ranges only) - [Alias("AutoFit")] - [Switch]$AutoSize, - #Set cells to a fixed width (columns or ranges only), ignored if Autosize is specified - [float]$Width, - #Set cells to a fixed hieght (rows or ranges only) - [float]$Height, - #Hide a row or column (not a range) - [switch]$Hidden - ) - begin { - #Allow Set-Format to take Worksheet and range parameters (like Add Contitional formatting) - convert them to an address - if ($WorkSheet -and $Range) {$Address = $WorkSheet.Cells[$Range] } - } - - process { - if ($Address -is [Array]) { - [void]$PSBoundParameters.Remove("Address") - $Address | Set-Format @PSBoundParameters - } - else { - if ($ResetFont) { - $Address.Style.Font.Color.SetColor("Black") - $Address.Style.Font.Bold = $false - $Address.Style.Font.Italic = $false - $Address.Style.Font.UnderLine = $false - $Address.Style.Font.Strike = $false - } - if ($Underline) { - $Address.Style.Font.UnderLine = $true - $Address.Style.Font.UnderLineType = $UnderLineType - } - if ($Bold) {$Address.Style.Font.Bold = $true } - if ($Italic) {$Address.Style.Font.Italic = $true } - if ($StrikeThru) {$Address.Style.Font.Strike = $true } - if ($FontShift) {$Address.Style.Font.VerticalAlign = $FontShift } - if ($FontColor) {$Address.Style.Font.Color.SetColor( $FontColor ) } - - if ($BorderAround) { - $Address.Style.Border.BorderAround($BorderAround, $BorderColor) - } - - if ($BorderBottom) { - $Address.Style.Border.Bottom.Style=$BorderBottom - $Address.Style.Border.Bottom.Color.SetColor($BorderColor) - } - - if ($BorderTop) { - $Address.Style.Border.Top.Style=$BorderTop - $Address.Style.Border.Top.Color.SetColor($BorderColor) - } - - if ($BorderLeft) { - $Address.Style.Border.Left.Style=$BorderLeft - $Address.Style.Border.Left.Color.SetColor($BorderColor) - } - - if ($BorderRight) { - $Address.Style.Border.Right.Style=$BorderRight - $Address.Style.Border.Right.Color.SetColor($BorderColor) - } - - if ($NumberFormat) {$Address.Style.Numberformat.Format = $NumberFormat } - if ($TextRotation) {$Address.Style.TextRotation = $TextRotation } - if ($WrapText) {$Address.Style.WrapText = $true } - if ($HorizontalAlignment) {$Address.Style.HorizontalAlignment = $HorizontalAlignment } - if ($VerticalAlignment) {$Address.Style.VerticalAlignment = $VerticalAlignment } - - if ($BackgroundColor) { - $Address.Style.Fill.PatternType = $BackgroundPattern - $Address.Style.Fill.BackgroundColor.SetColor($BackgroundColor) - if ($PatternColor) { - $Address.Style.Fill.PatternColor.SetColor( $PatternColor) - } - } - - if ($Height) { - if ($Address -is [OfficeOpenXml.ExcelRow] ) {$Address.Height = $Height } - elseif ($Address -is [OfficeOpenXml.ExcelRange] ) { - ($Address.Start.Row)..($Address.Start.Row + $Address.Rows) | - ForEach-Object {$Address.WorkSheet.Row($_).Height = $Height } - } - else {Write-Warning -Message ("Can set the height of a row or a range but not a {0} object" -f ($Address.GetType().name)) } - } - if ($Autosize) { - if ($Address -is [OfficeOpenXml.ExcelColumn]) {$Address.AutoFit() } - elseif ($Address -is [OfficeOpenXml.ExcelRange] ) { - $Address.AutoFitColumns() - } - else {Write-Warning -Message ("Can autofit a column or a range but not a {0} object" -f ($Address.GetType().name)) } - - } - elseif ($Width) { - if ($Address -is [OfficeOpenXml.ExcelColumn]) {$Address.Width = $Width} - elseif ($Address -is [OfficeOpenXml.ExcelRange] ) { - ($Address.Start.Column)..($Address.Start.Column + $Address.Columns - 1) | - ForEach-Object { - #$ws.Column($_).Width = $Width - $Address.Worksheet.Column($_).Width = $Width - } - } - else {Write-Warning -Message ("Can set the width of a column or a range but not a {0} object" -f ($Address.GetType().name)) } - } - if ($Hidden) { - if ($Address -is [OfficeOpenXml.ExcelRow] -or - $Address -is [OfficeOpenXml.ExcelColumn] ) {$Address.Hidden = $True} - else {Write-Warning -Message ("Can hide a row or a column but not a {0} object" -f ($Address.GetType().name)) } - } - - if ($Value) { - $Address.Value = $Value - } - - if ($Formula) { - $Address.Formula = $Formula - } - } - } -} \ No newline at end of file diff --git a/ToDo.md b/ToDo.md deleted file mode 100644 index 82fad235..00000000 --- a/ToDo.md +++ /dev/null @@ -1 +0,0 @@ -- [ ] Create an autocomplete for WorkSheetName param on ImportExcel diff --git a/TrackingUtils.ps1 b/TrackingUtils.ps1 deleted file mode 100644 index d71601fb..00000000 --- a/TrackingUtils.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -function Import-USPS { - param( - $TrackingNumber, - [Switch]$UseDefaultCredentials - - ) - - Import-Html "https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=$($TrackingNumber)" 0 -UseDefaultCredentials: $UseDefaultCredentials -} - -function Import-UPS { - param( - $TrackingNumber, - [Switch]$UseDefaultCredentials - ) - - Import-Html "https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums=$($TrackingNumber)" 0 -UseDefaultCredentials: $UseDefaultCredentials -} \ No newline at end of file diff --git a/TryEPPlus.ps1 b/TryEPPlus.ps1 deleted file mode 100644 index 3c903eeb..00000000 --- a/TryEPPlus.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -$xlFile = ".\testExport.xlsx" - -Remove-Item -ErrorAction Ignore $xlFile - -$ExportOptions = @{ - Path = $xlFile - Show = $true - IncludePivotTable = $true - IncludePivotChart = $true - PivotRows = echo Company Name - PivotData = "PM" - ChartType = "BarClustered3D" - #Password = "Test" -} - -Get-Process | - Where Company | - Select Company, Name, Handles, PM | - Export-Excel @ExportOptions \ No newline at end of file diff --git a/UnitTests/ImportExcelTests/Simple.tests.ps1 b/UnitTests/ImportExcelTests/Simple.tests.ps1 deleted file mode 100644 index 0b120de9..00000000 --- a/UnitTests/ImportExcelTests/Simple.tests.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 - -Describe "Tests" { - BeforeAll { - $data = $null - $timer = Measure-Command { - $data = Import-Excel $PSScriptRoot\Simple.xlsx - } - } - - It "Should have two items" { - $data.count | Should be 2 - } - - It "Should have items a and b" { - $data[0].p1 | Should be "a" - $data[1].p1 | Should be "b" - } - - It "Should read fast < 1000 milliseconds" { - $timer.TotalMilliseconds | should BeLessThan 1000 - } - - It "Should read larger xlsx, 4k rows 1 col < 1500 milliseconds" { - $timer = Measure-Command { - $null = Import-Excel $PSScriptRoot\LargerFile.xlsx - } - - $timer.TotalMilliseconds | should BeLessThan 1500 - } - -} \ No newline at end of file diff --git a/Update-FirstObjectProperties.ps1 b/Update-FirstObjectProperties.ps1 deleted file mode 100644 index 6716a592..00000000 --- a/Update-FirstObjectProperties.ps1 +++ /dev/null @@ -1,92 +0,0 @@ -Function Update-FirstObjectProperties { - <# - .SYNOPSIS - Updates the first object to contain all the properties of the object with the most properties in the array. - - .DESCRIPTION - Updates the first object to contain all the properties of the object with the most properties in the array. This is usefull when not all objects have the same quantity of properties and CmdLets like Out-GridView or Export-Excel are not able to show all the properties because the first object doesn't have them all. - - .EXAMPLE - $Array = @() - - $Obj1 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - } - - $Obj2 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - Member3 = 'Third' - } - - $Obj3 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - Member3 = 'Third' - Member4 = 'Fourth' - } - - $Array = $Obj1, $Obj2, $Obj3 - $Array | Out-GridView -Title 'Not showing Member3 and Member4' - $Array | Update-FirstObjectProperties | Out-GridView -Title 'All properties are visible' - - Updates the fist object of the array by adding Member3 and Member4. - - .EXAMPLE - $ExcelParams = @{ - Path = $env:TEMP + '\Excel.xlsx' - Show = $true - Verbose = $true - } - Remove-Item -Path $ExcelParams.Path -Force -EA Ignore - - $Array = @() - - $Obj1 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - } - - $Obj2 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - Member3 = 'Third' - } - - $Obj3 = [PSCustomObject]@{ - Member1 = 'First' - Member2 = 'Second' - Member3 = 'Third' - Member4 = 'Fourth' - } - - $Array = $Obj1, $Obj2, $Obj3 - $Array | Out-GridView -Title 'Not showing Member3 and Member4' - $Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorkSheetname Numbers - - Updates the first object of the array by adding property 'Member3' and 'Member4'. Afterwards. all objects are exported to an Excel file and all column headers are visible. - - .LINK - https://github.com/dfinke/ImportExcel - - .NOTES - CHANGELOG - 2017/06/08 Function born #> - - Try { - $Union = @() - $Input | ForEach-Object { - If ($Union.Count) { - $_ | Get-Member | Where {-not ($Union[0] | Get-Member $_.Name)} | ForEach-Object { - $Union[0] | Add-Member -MemberType NoteProperty -Name $_.Name -Value $Null - } - } - $Union += $_ - } - $Union - } - Catch { - throw "Failed updating the properties of the first object: $_" - } -} \ No newline at end of file diff --git a/__tests__/AddTrendlinesToAChart.tests.ps1 b/__tests__/AddTrendlinesToAChart.tests.ps1 new file mode 100644 index 00000000..212b3e68 --- /dev/null +++ b/__tests__/AddTrendlinesToAChart.tests.ps1 @@ -0,0 +1,52 @@ +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} +Describe "Test adding trendlines to charts" { + BeforeAll { + $script:data = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screws,60 +South,lemon,48 +South,apple,71 +East,screwdriver,70 +East,kiwi,32 +West,screwdriver,1 +South,melon,21 +East,apple,79 +South,apple,68 +South,avocado,73 +"@ + + } + + BeforeEach { + $xlfile = "TestDrive:\trendLine.xlsx" + Remove-Item $xlfile -ErrorAction SilentlyContinue + } + + It "Should add a linear trendline".PadRight(90) { + + $cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine Linear + $data | Export-Excel $xlfile -ExcelChartDefinition $cd -AutoNameRange + + $excel = Open-ExcelPackage -Path $xlfile + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $ws.Drawings[0].Series.TrendLines.Type | Should -Be 'Linear' + + Close-ExcelPackage $excel + } + + It "Should add a MovingAvgerage trendline".PadRight(90) { + + $cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine MovingAvgerage + $data | Export-Excel $xlfile -ExcelChartDefinition $cd -AutoNameRange + + $excel = Open-ExcelPackage -Path $xlfile + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $ws.Drawings[0].Series.TrendLines.Type | Should -Be 'MovingAvgerage' + + Close-ExcelPackage $excel + } +} \ No newline at end of file diff --git a/__tests__/Compare-WorkSheet.tests.ps1 b/__tests__/Compare-WorkSheet.tests.ps1 new file mode 100644 index 00000000..1c647cd4 --- /dev/null +++ b/__tests__/Compare-WorkSheet.tests.ps1 @@ -0,0 +1,370 @@ +#Requires -Modules Pester +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')] +param() +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} +Describe "Compare Worksheet" { + BeforeAll { + <# if ($PSVersionTable.PSVersion.Major -gt 5) { + It "GridView Support" { + Set-ItResult -Pending -Because "Can't test grid view on V6 and later" + } + } + else { Add-Type -AssemblyName System.Windows.Forms } #> + if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) { + Function Get-Service {Import-Clixml $PSScriptRoot\Mockservices.xml} + } + . "$PSScriptRoot\Samples\Samples.ps1" + Remove-Item -Path "TestDrive:\server*.xlsx" + [System.Collections.ArrayList]$s = Get-Service | Select-Object -first 25 -Property Name, RequiredServices, CanPauseAndContinue, CanShutdown, CanStop, DisplayName, DependentServices, MachineName + $s | Export-Excel -Path TestDrive:\server1.xlsx + #$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s + $row4Displayname = $s[2].DisplayName + $s[2].DisplayName = "Changed from the orginal" + $d = $s[-1] | Select-Object -Property * + $d.DisplayName = "Dummy Service" + $d.Name = "Dummy" + $s.Insert(3,$d) + $row6Name = $s[5].name + $s.RemoveAt(5) + $s | Export-Excel -Path TestDrive:\server2.xlsx + #Assume default worksheet name, (sheet1) and column header for key ("name") + $comp = Compare-Worksheet "TestDrive:\server1.xlsx" "TestDrive:\server2.xlsx" | Sort-Object -Property _row, _file + } + Context "Simple comparison output" { + it "Found the right number of differences " { + $comp | Should -Not -BeNullOrEmpty + $comp.Count | Should -Be 4 + } + it "Found the data row with a changed property " { + $comp | Should -Not -BeNullOrEmpty + $comp[0]._Side | Should -Not -Be $comp[1]._Side + $comp[0]._Row | Should -Be 4 + $comp[1]._Row | Should -Be 4 + $comp[1].Name | Should -Be $comp[0].Name + $comp[0].DisplayName | Should -Be $row4Displayname + $comp[1].DisplayName | Should -Be "Changed from the orginal" + } + it "Found the inserted data row " { + $comp | Should -Not -BeNullOrEmpty + $comp[2]._Side | Should -Be '=>' + $comp[2]._Row | Should -Be 5 + $comp[2].Name | Should -Be "Dummy" + } + it "Found the deleted data row " { + $comp | Should -Not -BeNullOrEmpty + $comp[3]._Side | Should -Be '<=' + $comp[3]._Row | Should -Be 6 + $comp[3].Name | Should -Be $row6Name + } + } + + Context "Setting the background to highlight different rows" { + BeforeAll { + if ($PSVersionTable.PSVersion.Major -ne 5) { + $null = Compare-Worksheet "TestDrive:\server1.xlsx" "TestDrive:\server2.xlsx" -BackgroundColor ([System.Drawing.Color]::LightGreen) + } + else { + $cmdline = 'Import-Module {0}; $null = Compare-WorkSheet "{1}" "{2}" -BackgroundColor ([System.Drawing.Color]::LightGreen) -GridView; Start-Sleep -sec 5; exit' + $cmdline = $cmdline -f (Resolve-Path "$PSScriptRoot\..\importExcel.psd1" ) , + (Join-Path (Get-PSDrive TestDrive).root "server1.xlsx"), + (Join-Path (Get-PSDrive TestDrive).root "server2.xlsx") + powershell.exe -Command $cmdline + } + $xl1 = Open-ExcelPackage -Path "TestDrive:\server1.xlsx" + $xl2 = Open-ExcelPackage -Path "TestDrive:\server2.xlsx" + $s1Sheet = $xl1.Workbook.Worksheets[1] + $s2Sheet = $xl2.Workbook.Worksheets[1] + } + it "Set the background on the right rows " { + $s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + $s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + $s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + $s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + } + it "Didn't set other cells " { + $s1Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | Should -Not -Be "FF90EE90" + $s1Sheet.Cells["F4"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s2Sheet.Cells["F4"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s2Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | Should -Not -Be "FF90EE90" + } + AfterAll { + Close-ExcelPackage -ExcelPackage $xl1 -NoSave + Close-ExcelPackage -ExcelPackage $xl2 -NoSave + } + } + + Context "Setting the forgound to highlight changed properties" { + BeforeAll { + $null = Compare-Worksheet "TestDrive:\server1.xlsx" "TestDrive:\server2.xlsx" -AllDataBackgroundColor([System.Drawing.Color]::white) -BackgroundColor ([System.Drawing.Color]::LightGreen) -FontColor ([System.Drawing.Color]::DarkRed) + $xl1 = Open-ExcelPackage -Path "TestDrive:\server1.xlsx" + $xl2 = Open-ExcelPackage -Path "TestDrive:\server2.xlsx" + $s1Sheet = $xl1.Workbook.Worksheets[1] + $s2Sheet = $xl2.Workbook.Worksheets[1] + } + it "Added foreground colour to the right cells " { + $s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + $s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + $s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + $s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | Should -Be "FF90EE90" + # $s1Sheet.Cells["F4"].Style.Font.Color.Rgb | Should -Be "FF8B0000" + $s2Sheet.Cells["F4"].Style.Font.Color.Rgb | Should -Be "FF8B0000" + } + it "Didn't set the foreground on other cells " { + $s1Sheet.Cells["F5"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s2Sheet.Cells["F5"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s1Sheet.Cells["G4"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s2Sheet.Cells["G4"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + + } + AfterAll { + Close-ExcelPackage -ExcelPackage $xl1 -NoSave + Close-ExcelPackage -ExcelPackage $xl2 -NoSave + } + } + + Context "More complex comparison: output check and different worksheet names " { + BeforeAll { + [System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property RequiredServices, CanPauseAndContinue, CanShutdown, CanStop, + DisplayName, DependentServices, MachineName, ServiceName, ServicesDependedOn, ServiceHandle, Status, ServiceType, StartType -ExcludeProperty Name + $s | Export-Excel -Path TestDrive:\server1.xlsx -WorkSheetname server1 + #$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s + $row4Displayname = $s[2].DisplayName + $s[2].DisplayName = "Changed from the orginal" + $d = $s[-1] | Select-Object -Property * + $d.DisplayName = "Dummy Service" + $d.ServiceName = "Dummy" + $s.Insert(3,$d) + $row6Name = $s[5].ServiceName + $s.RemoveAt(5) + $s[10].ServiceType = "Changed should not matter" + + $s | Select-Object -Property ServiceName, DisplayName, StartType, ServiceType | Export-Excel -Path TestDrive:\server2.xlsx -WorkSheetname server2 + #Assume default worksheet name, (sheet1) and column header for key ("name") + $comp = Compare-Worksheet "TestDrive:\server1.xlsx" "TestDrive:\server2.xlsx" -WorkSheetName server1,server2 -Key ServiceName -Property DisplayName,StartType -AllDataBackgroundColor ([System.Drawing.Color]::AliceBlue) -BackgroundColor ([System.Drawing.Color]::White) -FontColor ([System.Drawing.Color]::Red) | Sort-Object _row,_file + $xl1 = Open-ExcelPackage -Path "TestDrive:\server1.xlsx" + $xl2 = Open-ExcelPackage -Path "TestDrive:\server2.xlsx" + $s1Sheet = $xl1.Workbook.Worksheets["server1"] + $s2Sheet = $xl2.Workbook.Worksheets["server2"] + } + it "Found the right number of differences " { + $comp | Should -Not -BeNullOrEmpty + $comp.Count | Should -Be 4 + } + it "Found the data row with a changed property " { + $comp | Should -Not -BeNullOrEmpty + $comp[0]._Side | Should -Not -Be $comp[1]._Side + $comp[0]._Row | Should -Be 4 + $comp[1]._Row | Should -Be 4 + $comp[1].ServiceName | Should -Be $comp[0].ServiceName + $comp[0].DisplayName | Should -Be $row4Displayname + $comp[1].DisplayName | Should -Be "Changed from the orginal" + } + it "Found the inserted data row " { + $comp | Should -Not -BeNullOrEmpty + $comp[2]._Side | Should -Be '=>' + $comp[2]._Row | Should -Be 5 + $comp[2].ServiceName | Should -Be "Dummy" + } + it "Found the deleted data row " { + $comp | Should -Not -BeNullOrEmpty + $comp[3]._Side | Should -Be '<=' + $comp[3]._Row | Should -Be 6 + $comp[3].ServiceName | Should -Be $row6Name + } + it "Set the background on the right rows " { + $s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | Should -Be "FFFFFFFF" + $s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | Should -Be "FFFFFFFF" + $s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | Should -Be "FFFFFFFF" + $s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | Should -Be "FFFFFFFF" + + $s1Sheet.Cells["E4"].Style.Font.Color.Rgb | Should -Be "FFFF0000" + $s2Sheet.Cells["E4"].Style.Font.Color.Rgb | Should -Be "FFFF0000" + } + it "Didn't set other cells " { + $s1Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | Should -Not -Be "FFFFFFFF" + $s2Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | Should -Not -Be "FFFFFFFF" + $s1Sheet.Cells["E5"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s2Sheet.Cells["E5"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s1Sheet.Cells["F4"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + $s2Sheet.Cells["F4"].Style.Font.Color.Rgb | Should -BeNullOrEmpty + } + AfterAll { + Close-ExcelPackage -ExcelPackage $xl1 -NoSave # -Show + Close-ExcelPackage -ExcelPackage $xl2 -NoSave # -Show + } + } +} + +Describe "Merge Worksheet" { + BeforeAll { + if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) { + Function Get-Service {Import-Clixml $PSScriptRoot\Mockservices.xml} + } + Remove-Item -Path "TestDrive:\server*.xlsx" , "TestDrive:\combined*.xlsx" -ErrorAction SilentlyContinue + [System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property * + + $s | Export-Excel -Path TestDrive:\server1.xlsx + + #$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s + $s[2].DisplayName = "Changed from the orginal" + + $d = $s[-1] | Select-Object -Property * + $d.DisplayName = "Dummy Service" + $d.Name = "Dummy" + $s.Insert(3,$d) + + $s.RemoveAt(5) + + $s | Export-Excel -Path TestDrive:\server2.xlsx + #Assume default worksheet name, (sheet1) and column header for key ("name") + Merge-Worksheet -Referencefile "TestDrive:\server1.xlsx" -Differencefile "TestDrive:\server2.xlsx" -OutputFile "TestDrive:\combined1.xlsx" -Property name,displayname,startType -Key name + $excel = Open-ExcelPackage -Path "TestDrive:\combined1.xlsx" + $ws = $excel.Workbook.Worksheets["sheet1"] + } + Context "Merge with 3 properties" { + it "Created a worksheet with the correct headings " { + $ws | Should -Not -BeNullOrEmpty + $ws.Cells[ 1,1].Value | Should -Be "name" + $ws.Cells[ 1,2].Value | Should -Be "DisplayName" + $ws.Cells[ 1,3].Value | Should -Be "StartType" + $ws.Cells[ 1,4].Value | Should -Be "server2 DisplayName" + $ws.Cells[ 1,5].Value | Should -Be "server2 StartType" + } + it "Joined the two sheets correctly " { + $ws.Cells[ 2,2].Value | Should -Be $ws.Cells[ 2,4].Value + $ws.Cells[ 2,3].Value | Should -Be $ws.Cells[ 2,5].Value + $ws.cells[ 4,4].value | Should -Be "Changed from the orginal" + $ws.cells[ 5,1].value | Should -Be "Dummy" + $ws.cells[ 5,2].value | Should -BeNullOrEmpty + $ws.cells[ 5,3].value | Should -BeNullOrEmpty + $ws.cells[ 5,4].value | Should -Be "Dummy Service" + $ws.cells[ 7,4].value | Should -BeNullOrEmpty + $ws.cells[ 7,5].value | Should -BeNullOrEmpty + $ws.Cells[12,2].Value | Should -Be $ws.Cells[12,4].Value + $ws.Cells[12,3].Value | Should -Be $ws.Cells[12,5].Value + } + it "Highlighted the keys in the added / deleted / changed rows " { + $ws.cells[4,1].Style.font.color.rgb | Should -Be "FF8b0000" + $ws.cells[5,1].Style.font.color.rgb | Should -Be "FF8b0000" + $ws.cells[7,1].Style.font.color.rgb | Should -Be "FF8b0000" + } + it "Set the background for the added / deleted / changed rows " { + $ws.cells["A3:E3"].style.Fill.BackgroundColor.Rgb | Should -BeNullOrEmpty + $ws.cells["A4:E4"].style.Fill.BackgroundColor.Rgb | Should -Be "FFFFA500" + $ws.cells["A5" ].style.Fill.BackgroundColor.Rgb | Should -Be "FF98FB98" + $ws.cells["B5:C5"].style.Fill.BackgroundColor.rgb | Should -BeNullOrEmpty + $ws.cells["D5:E5"].style.Fill.BackgroundColor.Rgb | Should -Be "FF98FB98" + $ws.cells["A7:C7"].style.Fill.BackgroundColor.Rgb | Should -Be "FFFFB6C1" + $ws.cells["D7:E7"].style.Fill.BackgroundColor.rgb | Should -BeNullOrEmpty + } + } + Context "Wider data set" { + it "Coped with columns beyond Z in the Output sheet " { + { Merge-Worksheet -Referencefile "TestDrive:\server1.xlsx" -Differencefile "TestDrive:\server2.xlsx" -OutputFile "TestDrive:\combined2.xlsx" } | Should -Not -Throw + } + } +} +Describe "Merge Multiple sheets" { + BeforeAll { + if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) { + Function Get-Service {Import-Clixml $PSScriptRoot\Mockservices.xml} + } + } + Context "Merge 3 sheets with 3 properties" { + BeforeAll { + Remove-Item -Path "TestDrive:\server*.xlsx" , "TestDrive:\combined*.xlsx" -ErrorAction SilentlyContinue + [System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property Name,DisplayName,StartType + $s | Export-Excel -Path TestDrive:\server1.xlsx + + #$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s + $row4Displayname = $s[2].DisplayName + $s[2].DisplayName = "Changed from the orginal" + + $d = $s[-1] | Select-Object -Property * + $d.DisplayName = "Dummy Service" + $d.Name = "Dummy" + $s.Insert(3,$d) + + $s.RemoveAt(5) + + $s | Export-Excel -Path TestDrive:\server2.xlsx + + $s[2].displayname = $row4Displayname + + $d = $s[-1] | Select-Object -Property * + $d.DisplayName = "Second Service" + $d.Name = "Service2" + $s.Insert(6,$d) + $s.RemoveAt(8) + + $s | Export-Excel -Path TestDrive:\server3.xlsx + + Merge-MultipleSheets -Path "TestDrive:\server1.xlsx", "TestDrive:\server2.xlsx","TestDrive:\server3.xlsx" -OutputFile "TestDrive:\combined3.xlsx" -Property name,displayname,startType -Key name + $excel = Open-ExcelPackage -Path "TestDrive:\combined3.xlsx" + $ws = $excel.Workbook.Worksheets["sheet1"] + + } + it "Created a worksheet with the correct headings " { + $ws | Should -Not -BeNullOrEmpty + $ws.Cells[ 1,2 ].Value | Should -Be "name" + $ws.Cells[ 1,3 ].Value | Should -Be "server1 DisplayName" + $ws.Cells[ 1,4 ].Value | Should -Be "server1 StartType" + $ws.Cells[ 1,5 ].Value | Should -Be "server2 DisplayName" + $ws.Cells[ 1,6 ].Value | Should -Be "server2 StartType" + $ws.Column(7).hidden | Should -Be $true + $ws.Cells[ 1,8].Value | Should -Be "server2 Row" + $ws.Cells[ 1,9 ].Value | Should -Be "server3 DisplayName" + $ws.Cells[ 1,10].Value | Should -Be "server3 StartType" + $ws.Column(11).hidden | Should -Be $true + $ws.Cells[ 1,12].Value | Should -Be "server3 Row" + } + it "Joined the three sheets correctly " { + $ws.Cells[ 2,3 ].Value | Should -Be $ws.Cells[ 2,5 ].Value + $ws.Cells[ 2,4 ].Value | Should -Be $ws.Cells[ 2,6 ].Value + $ws.Cells[ 2,5 ].Value | Should -Be $ws.Cells[ 2,9 ].Value + $ws.Cells[ 2,6 ].Value | Should -Be $ws.Cells[ 2,10].Value + $ws.cells[ 4,5 ].value | Should -Be "Changed from the orginal" + $ws.cells[ 4,9 ].value | Should -Be $ws.Cells[ 4,3 ].Value + $ws.cells[ 5,2 ].value | Should -Be "Dummy" + $ws.cells[ 5,3 ].value | Should -BeNullOrEmpty + $ws.cells[ 5,4 ].value | Should -BeNullOrEmpty + $ws.cells[ 5,5 ].value | Should -Be "Dummy Service" + $ws.cells[ 5,8 ].value | Should -Be ($ws.cells[ 4,1].value +1) + $ws.cells[ 5,9 ].value | Should -Be $ws.cells[ 5,5 ].value + $ws.cells[ 7,5 ].value | Should -BeNullOrEmpty + $ws.cells[ 7,6 ].value | Should -BeNullOrEmpty + $ws.cells[ 7,9 ].value | Should -BeNullOrEmpty + $ws.cells[ 7,10].value | Should -BeNullOrEmpty + $ws.cells[ 8,3 ].value | Should -BeNullOrEmpty + $ws.cells[ 8,4 ].value | Should -BeNullOrEmpty + $ws.cells[ 8,5 ].value | Should -BeNullOrEmpty + $ws.cells[ 8,6 ].value | Should -BeNullOrEmpty + $ws.cells[11,9 ].value | Should -BeNullOrEmpty + $ws.cells[11,10].value | Should -BeNullOrEmpty + $ws.Cells[12,3 ].Value | Should -Be $ws.Cells[12,5].Value + $ws.Cells[12,4 ].Value | Should -Be $ws.Cells[12,6].Value + $ws.Cells[12,9 ].Value | Should -Be $ws.Cells[12,5].Value + $ws.Cells[12,10].Value | Should -Be $ws.Cells[12,6].Value + } + it "Created Conditional formatting rules " { + $cf=$ws.ConditionalFormatting + $cf.Count | Should -Be 17 + $cf[16].Address.Address | Should -Be 'B2:B1048576' + $cf[16].Type | Should -Be 'Expression' + $cf[16].Formula | Should -Be 'OR(G2<>"Same",K2<>"Same")' + $cf[16].Style.Font.Color.Color.Name | Should -Be "FFFF0000" + $cf[14].Address.Address | Should -Be 'D2:D1048576' + $cf[14].Type | Should -Be 'Expression' + $cf[14].Formula | Should -Be 'OR(G2="Added",K2="Added")' + $cf[14].Style.Fill.BackgroundColor.Color.Name | Should -Be 'ffffb6c1' + $cf[14].Style.Fill.PatternType.ToString() | Should -Be 'Solid' + $cf[ 0].Address.Address | Should -Be 'F1:F1048576' + $cf[ 0].Type | Should -Be 'Expression' + $cf[ 0].Formula | Should -Be 'G1="Added"' + $cf[ 0].Style.Fill.BackgroundColor.Color.Name | Should -Be 'ffffa500' + $cf[ 0].Style.Fill.PatternType.ToString() | Should -Be 'Solid' + } + } +} \ No newline at end of file diff --git a/__tests__/ConvertFrom-ExcelSheet.Tests.ps1 b/__tests__/ConvertFrom-ExcelSheet.Tests.ps1 new file mode 100644 index 00000000..8e6130c7 --- /dev/null +++ b/__tests__/ConvertFrom-ExcelSheet.Tests.ps1 @@ -0,0 +1,40 @@ +Describe 'ConvertFrom-ExcelSheet / Export-ExcelSheet' { + BeforeAll { + $scriptPath = $PSScriptRoot + $dataPath = Join-Path -Path $scriptPath -ChildPath "First10Races.xlsx" + + $Outpath = "TestDrive:\" + ConvertFrom-ExcelSheet -Path $dataPath -OutputPath $Outpath + $script:firstText = Get-Content (Join-path -Path $Outpath -ChildPath "First10Races.csv") + ConvertFrom-ExcelSheet -Path $dataPath -OutputPath $Outpath -AsText GridPosition, date + $script:SecondText = Get-Content (Join-path -Path $Outpath -ChildPath "First10Races.csv") + ConvertFrom-ExcelSheet -Path $dataPath -OutputPath $Outpath -AsText "GridPosition" -Property driver, + @{n = "date"; e = { [datetime]::FromOADate($_.Date).tostring("#MM/dd/yyyy#") } } , FinishPosition, GridPosition + $script:ThirdText = Get-Content (Join-path -Path $Outpath -ChildPath "First10Races.csv") + ConvertFrom-ExcelSheet -Path $dataPath -OutputPath $Outpath -AsDate "date" + $script:FourthText = Get-Content (Join-path -Path $Outpath -ChildPath "First10Races.csv") + } + Context "Exporting to CSV" { + it "Exported the expected columns to a CSV file " { + $firstText[0] | Should -Be '"Race","Date","FinishPosition","Driver","GridPosition","Team","Points"' + $SecondText[0] | Should -Be '"Race","Date","FinishPosition","Driver","GridPosition","Team","Points"' + $ThirdText[0] | Should -Be '"Driver","date","FinishPosition","GridPosition"' + $FourthText[0] | Should -Be '"Race","Date","FinishPosition","Driver","GridPosition","Team","Points"' + } + it "Applied AsText, AsDate and Properties correctly " { + $firstText[1] | Should -Match '^"\w+","\d{5}","\d{1,2}","\w+ \w+","[1-9]\d?","\w+","\d{1,2}"$' + $date = $firstText[1] -replace '^.*(\d{5}).*$', '$1' + $date = [datetime]::FromOADate($date).toString("D") + $secondText[1] | Should -Belike "*$date*" + $secondText[1] | Should -Match '"0\d","\w+","\d{1,2}"$' + $ThirdText[1] | Should -Match '^"\w+ \w+","#\d\d/\d\d/\d{4}#","\d","0\d"$' + $FourthText[1] | Should -Match '^"\w+","([012]\d/|[1-9]/)' + } + } + Context "Export aliased to ConvertFrom" { + it "Definded the alias name with " { + (Get-Alias Export-ExcelSheet).source | Should -Be "ImportExcel" + (Get-Alias Export-ExcelSheet).Definition | Should -Be "ConvertFrom-ExcelSheet" + } + } +} \ No newline at end of file diff --git a/__tests__/ConvertFromExcelToSQLInsert.tests.ps1 b/__tests__/ConvertFromExcelToSQLInsert.tests.ps1 new file mode 100644 index 00000000..db3d1705 --- /dev/null +++ b/__tests__/ConvertFromExcelToSQLInsert.tests.ps1 @@ -0,0 +1,37 @@ +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +Describe "ConvertFrom-ExcelToSQLInsert" { + BeforeAll { + $script:xlFile = "TestDrive:\testSQL.xlsx" + } + + BeforeEach { + + $([PSCustomObject]@{ + Name = "John" + Age = $null + }) | Export-Excel $xlFile + } + + AfterAll { + Remove-Item $xlFile -Recurse -Force -ErrorAction Ignore + } + + It "Should be empty double single quotes".PadRight(90) { + $expected = "INSERT INTO Sheet1 ('Name', 'Age') Values('John', '');" + + $actual = ConvertFrom-ExcelToSQLInsert -Path $xlFile Sheet1 + + $actual | Should -Be $expected + } + + It "Should have NULL".PadRight(90) { + $expected = "INSERT INTO Sheet1 ('Name', 'Age') Values('John', NULL);" + + $actual = ConvertFrom-ExcelToSQLInsert -Path $xlFile Sheet1 -ConvertEmptyStringsToNull + + $actual | Should -Be $expected + } +} \ No newline at end of file diff --git a/__tests__/Copy-ExcelWorksheet.Tests.ps1 b/__tests__/Copy-ExcelWorksheet.Tests.ps1 new file mode 100644 index 00000000..2ae3ac7d --- /dev/null +++ b/__tests__/Copy-ExcelWorksheet.Tests.ps1 @@ -0,0 +1,149 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +param() + +Describe "Copy-Worksheet" { + BeforeAll { + $path1 = "TestDrive:\Test1.xlsx" + $path2 = "TestDrive:\Test2.xlsx" + Remove-Item -Path $path1, $path2 -ErrorAction SilentlyContinue + + $ProcRange = Get-Process | Export-Excel $path1 -DisplayPropertySet -WorkSheetname Processes -ReturnRange + + if ((Get-Culture).NumberFormat.CurrencySymbol -eq "£") { $OtherCurrencySymbol = "$" } + else { $OtherCurrencySymbol = "£" } + [PSCustOmobject][Ordered]@{ + Date = Get-Date + Formula1 = '=SUM(F2:G2)' + String1 = 'My String' + Float = [math]::pi + IPAddress = '10.10.25.5' + StrLeadZero = '07670' + StrComma = '0,26' + StrEngThousand = '1,234.56' + StrEuroThousand = '1.555,83' + StrDot = '1.2' + StrNegInt = '-31' + StrTrailingNeg = '31-' + StrParens = '(123)' + strLocalCurrency = ('{0}123.45' -f (Get-Culture).NumberFormat.CurrencySymbol ) + strOtherCurrency = ('{0}123.45' -f $OtherCurrencySymbol ) + StrE164Phone = '+32 (444) 444 4444' + StrAltPhone1 = '+32 4 4444 444' + StrAltPhone2 = '+3244444444' + StrLeadSpace = ' 123' + StrTrailSpace = '123 ' + Link1 = [uri]"https://github.com/dfinke/ImportExcel" + Link2 = "https://github.com/dfinke/ImportExcel" # Links are not copied correctly, hopefully this will be fixed at some future date + } | Export-Excel -NoNumberConversion IPAddress, StrLeadZero, StrAltPhone2 -WorkSheetname MixedTypes -Path $path2 + } + Context "Simplest copy" { + BeforeAll { + $path1 = "TestDrive:\Test1.xlsx" + $path2 = "TestDrive:\Test2.xlsx" + + Copy-ExcelWorksheet -SourceWorkbook $path1 -DestinationWorkbook $path2 + $excel = Open-ExcelPackage -Path $path2 + $ws = $excel.Workbook.Worksheets["Processes"] + } + it "Inserted a worksheet " { + $Excel.Workbook.Worksheets.count | Should -Be 2 + $ws | Should -Not -BenullorEmpty + $ws.Dimension.Address | Should -Be $ProcRange + } + } + Context "Mixed types using a package object" { + BeforeAll { + $excel = Open-ExcelPackage -Path $path2 + Copy-ExcelWorksheet -SourceWorkbook $excel -DestinationWorkbook $excel -DestinationWorkSheet "CopyOfMixedTypes" + Close-ExcelPackage -ExcelPackage $excel + $excel = Open-ExcelPackage -Path $path2 + $ws = $Excel.Workbook.Worksheets[3] + } + it "Copied a worksheet, giving the expected name, number of rows and number of columns " { + $Excel.Workbook.Worksheets.count | Should -Be 3 + $ws | Should -Not -BenullorEmpty + $ws.Name | Should -Be "CopyOfMixedTypes" + $ws.Dimension.Columns | Should -Be 22 + $ws.Dimension.Rows | Should -Be 2 + } + it "Copied the expected data into the worksheet " { + $ws.Cells[2, 1].Value.Gettype().name | Should -Be 'DateTime' + $ws.Cells[2, 2].Formula | Should -Be 'SUM(F2:G2)' + $ws.Cells[2, 5].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 6].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 18].Value.GetType().name | Should -Be 'String' + ($ws.Cells[2, 11].Value -is [valuetype] ) | Should -Be $true + ($ws.Cells[2, 12].Value -is [valuetype] ) | Should -Be $true + ($ws.Cells[2, 13].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 11].Value | Should -BeLessThan 0 + $ws.Cells[2, 12].Value | Should -BeLessThan 0 + $ws.Cells[2, 13].Value | Should -BeLessThan 0 + if ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ",") { + ($ws.Cells[2, 8].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 9].Value.GetType().name | Should -Be 'String' + } + elseif ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ".") { + ($ws.Cells[2, 9].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 8].Value.GetType().name | Should -Be 'String' + } + ($ws.Cells[2, 14].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 15].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 16].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 17].Value.GetType().name | Should -Be 'String' + ($ws.Cells[2, 19].Value -is [valuetype] ) | Should -Be $true + ($ws.Cells[2, 20].Value -is [valuetype] ) | Should -Be $true + } + } + + Context "Copy worksheet should close all files" { + BeforeAll { + $xlfile = "TestDrive:\reports.xlsx" + $xlfileArchive = "TestDrive:\reportsArchive.xlsx" + + Remove-Item $xlfile -ErrorAction SilentlyContinue + Remove-Item $xlfileArchive -ErrorAction SilentlyContinue + + $sheets = "1.1.2019", "1.2.2019", "1.3.2019", "1.4.2019", "1.5.2019" + + $sheets | ForEach-Object { + "Hello World" | Export-Excel $xlfile -WorksheetName $_ + } + } + + it "Should copy and remove sheets " { + $targetSheets = "1.1.2019", "1.4.2019" + + $targetSheets | ForEach-Object { + Copy-ExcelWorksheet -SourceWorkbook $xlfile -DestinationWorkbook $xlfileArchive -SourceWorkSheet $_ -DestinationWorkSheet $_ + } + + $targetSheets | ForEach-Object { Remove-Worksheet -FullName $xlfile -WorksheetName $_ } + + (Get-ExcelSheetInfo -Path $xlfile ).Count | Should -Be 3 + } + } + + Context "Copy worksheet should support piped input" { + BeforeAll { + $xlfile = "TestDrive:\reports.xlsx" + $xlfileArchive = "TestDrive:\reportsArchive.xlsx" + + Remove-Item $xlfile -ErrorAction SilentlyContinue + Remove-Item $xlfileArchive -ErrorAction SilentlyContinue + + $sheets = "1.1.2019", "1.2.2019", "1.3.2019", "1.4.2019", "1.5.2019" + + $sheets | ForEach-Object { + "Hello World" | Export-Excel $xlfile -WorksheetName $_ + } + $e = Open-ExcelPackage $xlfile + $e.Workbook.Worksheets | Copy-ExcelWorksheet -DestinationWorkbook $xlfileArchive + Close-ExcelPackage -NoSave $e + } + it "Should copy sheets piped into the command " { + $excel = Open-ExcelPackage $xlfileArchive + $excel.Workbook.Worksheets.Count | should -be 5 + $excel.Workbook.Worksheets['1.3.2019'].Cells['A1'].Value | should -be 'Hello World' + } + } +} \ No newline at end of file diff --git a/__tests__/Export-Excel.Tests.ps1 b/__tests__/Export-Excel.Tests.ps1 new file mode 100644 index 00000000..def74455 --- /dev/null +++ b/__tests__/Export-Excel.Tests.ps1 @@ -0,0 +1,1356 @@ +#Requires -Modules @{ ModuleName="Pester"; ModuleVersion="4.0.0" } +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Only executes on versions without the automatic variable')] +param() +Describe ExportExcel -Tag "ExportExcel" { + BeforeAll { + if ($null -eq $IsWindows) { $IsWindows = [environment]::OSVersion.Platform -like "win*" } + $WarningAction = "SilentlyContinue" + . "$PSScriptRoot\Samples\Samples.ps1" + if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) { + Function Get-Service { Import-Clixml $PSScriptRoot\Mockservices.xml } + } + if (Get-process -Name Excel, xlim -ErrorAction SilentlyContinue) { + It "Excel is open" { + $Warning = "You need to close Excel before running the tests." + Write-Warning -Message $Warning + Set-ItResult -Inconclusive -Because $Warning + } + return + } + } + Context "#Example 1 # Creates and opens a file with the right number of rows and columns" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + #Test with a maximum of 100 processes for speed; export all properties, then export smaller subsets. + $processes = Get-Process | Where-Object { $_.StartTime } | Select-Object -First 100 -Property * -ExcludeProperty Parent + $propertyNames = $Processes[0].psobject.properties.name + $rowcount = $Processes.Count + $Processes | Export-Excel $path #-show + } + + BeforeEach { + #Open-ExcelPackage with -Create is tested in Export-Excel + #This is a test of using it with -KillExcel + #TODO Need to test opening pre-existing file with no -create switch (and graceful failure when file does not exist) somewhere else + $Excel = Open-ExcelPackage -Path $path -KillExcel + $ws = $Excel.Workbook.Worksheets[1] + $headingNames = $ws.cells["1:1"].Value + } + + it "Created a new file " { + Test-Path -Path $path -ErrorAction SilentlyContinue | Should -Be $true + } + + it "Killed Excel when Open-Excelpackage was told to " { + Get-process -Name Excel, xlim -ErrorAction SilentlyContinue | Should -BeNullOrEmpty + } + + it "Created 1 worksheet, named 'Sheet1' " { + $Excel.Workbook.Worksheets.count | Should -Be 1 + $Excel.Workbook.Worksheets["Sheet1"] | Should -Not -BeNullOrEmpty + } + + it "Added a 'Sheet1' property to the Package object " { + $Excel.Sheet1 | Should -Not -BeNullOrEmpty + } + + it "Created the worksheet with the expected name, number of rows and number of columns " { + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be $propertyNames.Count + $ws.Dimension.Rows | Should -Be ($rowcount + 1) + } + + it "Created the worksheet with the correct header names " { + foreach ($p in $propertyNames) { + $headingnames -contains $p | Should -Be $true + } + } + + it "Formatted the process StartTime field as 'localized Date-Time' " { + $STHeader = $ws.cells["1:1"].where( { $_.Value -eq "StartTime" })[0] + $STCell = $STHeader.Address -replace '1$', '2' + $ws.cells[$stcell].Style.Numberformat.NumFmtID | Should -Be 22 + } + + it "Formatted the process ID field as 'General' " { + $IDHeader = $ws.cells["1:1"].where( { $_.Value -eq "ID" })[0] + $IDCell = $IDHeader.Address -replace '1$', '2' + $ws.cells[$IDcell].Style.Numberformat.NumFmtID | Should -Be 0 + } + } + + Context " # NoAliasOrScriptPropeties -ExcludeProperty and -DisplayPropertySet work" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + $processes = Get-Process | Select-Object -First 100 + $propertyNames = $Processes[0].psobject.properties.where( { $_.MemberType -eq 'Property' }).name + $rowcount = $Processes.Count + #Test -NoAliasOrScriptPropeties option and creating a range with a name which needs illegal chars removing - check this sends back a warning + $warnVar = $null + $Processes | Export-Excel $path -NoAliasOrScriptPropeties -RangeName "No Spaces" -WarningVariable warnvar -WarningAction SilentlyContinue + + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + it "Created a new file with Alias & Script Properties removed. " { + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be $propertyNames.Count + $ws.Dimension.Rows | Should -Be ($rowcount + 1 ) # +1 for the header. + } + it "Created a Range - even though the name given was invalid. " { + $ws.Names["No_spaces"] | Should -Not -BeNullOrEmpty + $ws.Names["No_spaces"].End.Column | Should -Be $propertyNames.Count + $ws.names["No_spaces"].End.Row | Should -Be ($rowcount + 1 ) # +1 for the header. + $warnVar.Count | Should -Be 1 + } + #This time use clearsheet instead of deleting the file test -Exclude properties, including wildcards. + $Processes | Export-Excel $path -ClearSheet -NoAliasOrScriptPropeties -ExcludeProperty SafeHandle, threads, modules, MainModule, StartInfo, MachineName, MainWindow*, M*workingSet + + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + } + + it "Created a new file with further properties excluded and cleared the old sheet " { + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be ($propertyNames.Count - 10) + $ws.Dimension.Rows | Should -Be ($rowcount + 1) # +1 for the header + } + + it "Created a new file with just the members of the Display Property Set " { + $propertyNames = $Processes[0].psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames + Remove-item -Path $path -ErrorAction SilentlyContinue + #Test -DisplayPropertySet + $Processes | Export-Excel $path -DisplayPropertySet + + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be $propertyNames.Count + $ws.Dimension.Rows | Should -Be ($rowcount + 1) + } + } + + Context "#Example 2 # Exports a list of numbers and applies number format " { + + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + #testing -ReturnRange switch and applying number format to Formulas as well as values. + $returnedRange = @($null, -1, 0, 34, 777, "", -0.5, 119, -0.1, 234, 788, "=A9+A10") | Export-Excel -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' -Path $path -ReturnRange + it "Created a new file and returned the expected range " { + Test-Path -Path $path -ErrorAction SilentlyContinue | Should -Be $true + $returnedRange | Should -Be "A1:A12" + } + + $Excel = Open-ExcelPackage -Path $path + } + + BeforeEach { + $ws = $Excel.Workbook.Worksheets[1] + } + + it "Created 1 worksheet " { + $Excel.Workbook.Worksheets.count | Should -Be 1 + } + + it "Created the worksheet with the expected name, number of rows and number of columns " { + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be 1 + $ws.Dimension.End.Row | Should -Be 12 + } + + it "Set the default style for the sheet as expected " { + $ws.cells.Style.Numberformat.Format | Should -Be '[Blue]$#,##0.00;[Red]-$#,##0.00' + } + + it "Set the default style and set values for Cells as expected, handling null,0 and '' " { + $ws.cells[1, 1].Style.Numberformat.Format | Should -Be '[Blue]$#,##0.00;[Red]-$#,##0.00' + $ws.cells[1, 1].Value | Should -BeNullorEmpty + $ws.cells[2, 1].Value | Should -Be -1 + $ws.cells[3, 1].Value | Should -Be 0 + $ws.cells[5, 1].Value | Should -Be 777 + $ws.cells[6, 1].Value | Should -Be "" + $ws.cells[4, 1].Style.Numberformat.Format | Should -Be '[Blue]$#,##0.00;[Red]-$#,##0.00' + + } + } + + Context " # Number format parameter" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + 1..10 | Export-Excel -Path $path -Numberformat 'Number' + 1..10 | Export-Excel -Path $path -Numberformat 'Percentage' -Append + 21..30 | Export-Excel -Path $path -Numberformat 'Currency' -StartColumn 3 + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Workbook.Worksheets[1] + } + it "Set the worksheet default number format correctly " { + $ws.Cells.Style.Numberformat.Format | Should -Be "0.00" + } + it "Set number formats on specific blocks of cells " { + $ws.Cells["A2" ].Style.Numberformat.Format | Should -Be "0.00" + $ws.Cells["c19"].Style.Numberformat.Format | Should -Be "0.00" + $ws.Cells["A20"].Style.Numberformat.Format | Should -Be "0.00%" + $ws.Cells["C6" ].Style.Numberformat.Format | Should -Be (Expand-NumberFormat "currency") + } + } + + Context "#Examples 3 & 4 # Setting cells for different data types Also added test for URI type" { + + BeforeAll { + if ((Get-Culture).NumberFormat.CurrencySymbol -eq "£") { $OtherCurrencySymbol = "$" } + else { $OtherCurrencySymbol = "£" } + $path = "TestDrive:\test.xlsx" + $warnVar = $null + #Test correct export of different data types and number formats; test hyperlinks, test -NoNumberConversion and -NoHyperLinkConversion test object is converted to a string with no warnings, test calcuation of formula + Remove-item -Path $path -ErrorAction SilentlyContinue + [PSCustOmobject][Ordered]@{ + Date = Get-Date + Formula1 = '=SUM(S2:T2)' + String1 = 'My String' + Float = [math]::pi + IPAddress = '10.10.25.5' + StrLeadZero = '07670' + StrComma = '0,26' + StrEngThousand = '1,234.56' + StrEuroThousand = '1.555,83' + StrDot = '1.2' + StrNegInt = '-31' + StrTrailingNeg = '31-' + StrParens = '(123)' + strLocalCurrency = ('{0}123{1}45' -f (Get-Culture).NumberFormat.CurrencySymbol, (Get-Culture).NumberFormat.CurrencyDecimalSeparator) + strOtherCurrency = ('{0}123{1}45' -f $OtherCurrencySymbol , (Get-Culture).NumberFormat.CurrencyDecimalSeparator) + StrE164Phone = '+32 (444) 444 4444' + StrAltPhone1 = '+32 4 4444 444' + StrAltPhone2 = '+3244444444' + StrLeadSpace = ' 123' + StrTrailSpace = '123 ' + Link1 = [uri]"https://github.com/dfinke/ImportExcel" + Link2 = "https://github.com/dfinke/ImportExcel" + Link3 = "xl://internal/sheet1!A1" + Link4 = "xl://internal/sheet1!C5" + Link5 = (New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!E2" , "Display Text") + Link6 = "xl://internal/sheet1!C5" + Process = (Get-Process -Id $PID) + TimeSpan = [datetime]::Now.Subtract([datetime]::Today) + } | Export-Excel -NoNumberConversion IPAddress, StrLeadZero, StrAltPhone2 -NoHyperLinkConversion Link6 -Path $path -Calculate -WarningVariable $warnVar + } + + BeforeEach { + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + } + + it "Created a new file " { + Test-Path -Path $path -ErrorAction SilentlyContinue | Should -Be $true + } + + it "Created 1 worksheet with no warnings " { + $Excel.Workbook.Worksheets.count | Should -Be 1 + $warnVar | Should -BeNullorEmpty + } + it "Created the worksheet with the expected name, number of rows and number of columns " { + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be 28 + $ws.Dimension.Rows | Should -Be 2 + } + it "Set a date in Cell A2 " { + $ws.Cells[2, 1].Value.Gettype().name | Should -Be 'DateTime' + } + it "Set a formula in Cell B2 " { + $ws.Cells[2, 2].Formula | Should -Be 'SUM(S2:T2)' + } + it "Forced a successful calculation of the Value in Cell B2 " { + $ws.Cells[2, 2].Value | Should -Be 246 + } + it "Set strings in Cells E2, F2 and R2 (no number conversion) " { + $ws.Cells[2, 5].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 6].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 18].Value.GetType().name | Should -Be 'String' + } + it "Set numbers in Cells K2,L2,M2 (diferent Negative integer formats) " { + ($ws.Cells[2, 11].Value -is [valuetype] ) | Should -Be $true + ($ws.Cells[2, 12].Value -is [valuetype] ) | Should -Be $true + ($ws.Cells[2, 13].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 11].Value | Should -BeLessThan 0 + $ws.Cells[2, 12].Value | Should -BeLessThan 0 + $ws.Cells[2, 13].Value | Should -BeLessThan 0 + } + it "Set external hyperlinks in Cells U2 and V2 " { + $ws.Cells[2, 21].Hyperlink | Should -Be "https://github.com/dfinke/ImportExcel" + $ws.Cells[2, 22].Hyperlink | Should -Be "https://github.com/dfinke/ImportExcel" + } + it "Set internal hyperlinks in Cells W2 and X2 " { + $ws.Cells[2, 23].Hyperlink.Scheme | Should -Be "xl" + $ws.Cells[2, 23].Hyperlink.ReferenceAddress | Should -Be "sheet1!A1" + $ws.Cells[2, 23].Hyperlink.Display | Should -Be "sheet1" + $ws.Cells[2, 24].Hyperlink.Scheme | Should -Be "xl" + $ws.Cells[2, 24].Hyperlink.ReferenceAddress | Should -Be "sheet1!c5" + $ws.Cells[2, 24].Hyperlink.Display | Should -Be "sheet1!c5" + $ws.Cells[2, 25].Hyperlink.ReferenceAddress | Should -Be "sheet1!E2" + $ws.Cells[2, 25].Hyperlink.Display | Should -Be "Display Text" + } + it "Create no link in cell Z2 (no hyperlink conversion) " { + $ws.Cells[2, 26].Hyperlink | Should -BeNullOrEmpty + } + it "Processed thousands according to local settings (Cells H2 and I2) " { + if ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ",") { + ($ws.Cells[2, 8].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 9].Value.GetType().name | Should -Be 'String' + } + elseif ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ".") { + ($ws.Cells[2, 9].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 8].Value.GetType().name | Should -Be 'String' + } + } + it "Processed local currency as a number and other currency as a string (N2 & O2) " { + ($ws.Cells[2, 14].Value -is [valuetype] ) | Should -Be $true + $ws.Cells[2, 15].Value.GetType().name | Should -Be 'String' + } + it "Processed numbers with spaces between digits as strings (P2 & Q2) " { + $ws.Cells[2, 16].Value.GetType().name | Should -Be 'String' + $ws.Cells[2, 17].Value.GetType().name | Should -Be 'String' + } + it "Processed numbers leading or trailing speaces as Numbers (S2 & T2) " { + ($ws.Cells[2, 19].Value -is [valuetype] ) | Should -Be $true + ($ws.Cells[2, 20].Value -is [valuetype] ) | Should -Be $true + } + it "Converted a nested object to a string (AA2) " { + $ws.Cells[2, 27].Value | Should -Match '^System\.Diagnostics\.Process\s+\(.*\)$' + } + it "Processed a timespan object (AB2) " { + $ws.cells[2, 28].Value.ToOADate() | Should -BeGreaterThan 0 + $ws.cells[2, 28].Value.ToOADate() | Should -BeLessThan 1 + $ws.cells[2, 28].Style.Numberformat.Format | Should -Be '[h]:mm:ss' + } + } + + Context "# # Setting cells for different data types with -noHeader" { + + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + #Test -NoHeader & -NoNumberConversion + [PSCustOmobject][Ordered]@{ + Date = Get-Date + Formula1 = '=SUM(F1:G1)' + 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' + Link1 = [uri]"https://github.com/dfinke/ImportExcel" + Link2 = [uri]"https://github.com/dfinke/ImportExcel" + } | Export-Excel -NoHyperLinkConversion Link2 -NoNumberConversion IPAddress, Number1 -Path $path -NoHeader + } + + BeforeEach { + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + } + + it "Created a new file " { + Test-Path -Path $path -ErrorAction SilentlyContinue | Should -Be $true + } + + it "Created 1 worksheet " { + $Excel.Workbook.Worksheets.count | Should -Be 1 + } + + it "Created the worksheet with the expected name, number of rows and number of columns " { + $ws.Name | Should -Be "sheet1" + $ws.Dimension.Columns | Should -Be 15 + $ws.Dimension.Rows | Should -Be 1 + } + + it "Set a date in Cell A1 " { + $ws.Cells[1, 1].Value.Gettype().name | Should -Be 'DateTime' + } + + it "Set a formula in Cell B1 " { + $ws.Cells[1, 2].Formula | Should -Be 'SUM(F1:G1)' + } + + it "Set strings in Cells E1 and F1 " { + $ws.Cells[1, 5].Value.GetType().name | Should -Be 'String' + $ws.Cells[1, 6].Value.GetType().name | Should -Be 'String' + } + + it "Set a number in Cell I1 " { + ($ws.Cells[1, 9].Value -is [valuetype] ) | Should -Be $true + } + + it "Set a hyperlink in Cell N1 " { + $ws.Cells[1, 14].Hyperlink | Should -Be "https://github.com/dfinke/ImportExcel" + } + + it "Does not set a hyperlink in Cell O1 " { + $ws.Cells[1, 15].Hyperlink | Should -BeNullOrEmpty + } + } + + Context "#Example 5 # Adding a single conditional format " { + BeforeEach { + #Test New-ConditionalText builds correctly + $ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor ([System.Drawing.Color]::DarkRed) -BackgroundColor ([System.Drawing.Color]::LightPink) + + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + #Test -ConditionalText with a single conditional spec. + 489, 668, 299, 777, 860, 151, 119, 497, 234, 788 | Export-Excel -Path $path -ConditionalText $ct + + + #ToDo need to test applying conitional formatting to a pre-existing worksheet and removing = from formula + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + $cf = $ws.ConditionalFormatting[0] + } + + it "Added one block of conditional formating for the data range " { + $ws.ConditionalFormatting.Count | Should -Be 1 + $ws.ConditionalFormatting[0].Address | Should -Be ($ws.Dimension.Address) + } + + it "Set the conditional formatting properties correctly " { + $cf.Formula | Should -Be $ct.Text + $cf.Type.ToString() | Should -Be $ct.ConditionalType + #$cf.Style.Fill.BackgroundColor | Should -Be $ct.BackgroundColor + # $cf.Style.Font.Color | Should -Be $ct.ConditionalTextColor - have to compare r.g.b + } + } + + Context "#Example 6 # Adding multiple conditional formats using short form syntax. " { + BeforeAll { + #Test adding mutliple conditional blocks and using the minimal syntax for New-ConditionalText + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + + #Testing -Passthrough + $Excel = Get-Service | Select-Object Name, Status, DisplayName, ServiceName | + Export-Excel $path -PassThru -ConditionalText $( + New-ConditionalText Stop ([System.Drawing.Color]::DarkRed) ([System.Drawing.Color]::LightPink) + New-ConditionalText Running ([System.Drawing.Color]::Blue) ([System.Drawing.Color]::Cyan) + ) + $ws = $Excel.Workbook.Worksheets[1] + } + + AfterAll { + Close-ExcelPackage -ExcelPackage $Excel + } + + it "Added two blocks of conditional formating for the data range " { + $ws.ConditionalFormatting.Count | Should -Be 2 + $ws.ConditionalFormatting[0].Address | Should -Be ($ws.Dimension.Address) + $ws.ConditionalFormatting[1].Address | Should -Be ($ws.Dimension.Address) + } + it "Set the conditional formatting properties correctly " { + $ws.ConditionalFormatting[0].Text | Should -Be "Stop" + $ws.ConditionalFormatting[1].Text | Should -Be "Running" + $ws.ConditionalFormatting[0].Type | Should -Be "ContainsText" + $ws.ConditionalFormatting[1].Type | Should -Be "ContainsText" + #Add RGB Comparison + } + } -skip + + Context "#Example 7 # Update-FirstObjectProperties works " { + BeforeAll { + $Array = @() + + $Obj1 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + } + + $Obj2 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' + } + + $Obj3 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' + Member4 = 'Fourth' + } + + $Array = $Obj1, $Obj2, $Obj3 + #test Update-FirstObjectProperties + $newarray = $Array | Update-FirstObjectProperties + } + + it "Outputs as many objects as it input " { + $newarray.Count | Should -Be $Array.Count + } + it "Added properties to item 0 " { + $newarray[0].psobject.Properties.name.Count | Should -Be 4 + $newarray[0].Member1 | Should -Be 'First' + $newarray[0].Member2 | Should -Be 'Second' + $newarray[0].Member3 | Should -BeNullOrEmpty + $newarray[0].Member4 | Should -BeNullOrEmpty + } + } + + Context "#Examples 8 & 9 # Adding Pivot tables and charts from parameters" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + #Test -passthru and -worksheetName creating a new, named, sheet in an existing file. + $Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company | Export-Excel $path -WorkSheetname Processes -PassThru + #Testing -Excel Pacakage and adding a Pivot-table as a second step. Want to save and re-open it ... + Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate + + $Excel = Open-ExcelPackage $path + $PTws = $Excel.Workbook.Worksheets["ProcessesPivotTable"] + $wCount = $Excel.Workbook.Worksheets.Count + $pt = $PTws.PivotTables[0] + + #test adding pivot chart using the already open sheet + $warnvar = $null + Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -ShowCategory -ShowPercent -NoLegend -WarningAction SilentlyContinue -WarningVariable warnvar + + $Excel = Open-ExcelPackage $path + } + + it "Added the named sheet and pivot table to the workbook " { + $excel.ProcessesPivotTable | Should -Not -BeNullOrEmpty + $excel.ProcessesPivotTable.PivotTables.Count | Should -Be 1 + $Excel.Workbook.Worksheets["Processes"] | Should -Not -BeNullOrEmpty + $Excel.Workbook.Worksheets.Count | Should -BeGreaterOrEqual 2 + $excel.Workbook.Worksheets["Processes"].Dimension.rows | Should -Be 21 #20 data + 1 header + } + it "Selected the Pivottable page " { + Set-ItResult -Pending -Because "Bug in EPPLus 4.5" + $PTws.View.TabSelected | Should -Be $true + } + it "Built the expected Pivot table " { + $pt.RowFields.Count | Should -Be 1 + $pt.RowFields[0].Name | Should -Be "Company" + $pt.DataFields.Count | Should -Be 1 + $pt.DataFields[0].Function | Should -Be "Count" + $pt.DataFields[0].Field.Name | Should -Be "PM" + $PTws.Drawings.Count | Should -Be 0 + } + it "Added a chart to the pivot table without rebuilding " { + $ws = $Excel.Workbook.Worksheets["ProcessesPivotTable"] + $Excel.Workbook.Worksheets.Count | Should -Be $wCount + $ws.Drawings.count | Should -Be 1 + $ws.Drawings[0].ChartType.ToString() | Should -Be "PieExploded3D" + } + it "Generated a message on re-processing the Pivot table " { + $warnVar | Should -Not -BeNullOrEmpty + } + it "Appended to the Worksheet and Extended the Pivot table (with a warning) " { + + #Test appending data extends pivot chart (with a warning) . + $warnVar = $null + Get-Process | Select-Object -Last 20 -Property Name, cpu, pm, handles, company | + Export-Excel $path -WorkSheetname Processes -Append -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar + $Excel = Open-ExcelPackage $path + $pt = $Excel.Workbook.Worksheets["ProcessesPivotTable"].PivotTables[0] + + $Excel.Workbook.Worksheets.Count | Should -Be $wCount + $excel.Workbook.Worksheets["Processes"].Dimension.rows | Should -Be 41 #appended 20 rows to the previous total + $pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref | + Should -Be "A1:E41" + + $warnVar | Should -Not -BeNullOrEmpty + } + } + + Context " # Add-Worksheet inserted sheets, moved them correctly, and copied a sheet" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + #Test the -CopySource and -Movexxxx parameters for Add-Worksheet + $Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company | + Export-Excel $path -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate + + $Excel = Open-ExcelPackage $path + #At this point Sheets Should be in the order Sheet1, Processes, ProcessesPivotTable + $null = Add-Worksheet -ExcelPackage $Excel -WorkSheetname "Processes" -MoveToEnd # order now ProcessesPivotTable, Processes + $null = Add-Worksheet -ExcelPackage $Excel -WorkSheetname "NewSheet" -MoveAfter "*" -CopySource ($excel.Workbook.Worksheets["Processes"]) # Now its NewSheet, ProcessesPivotTable, Processes + $null = Add-Worksheet -ExcelPackage $Excel -WorkSheetname "Sheet1" -MoveAfter "Processes" # Now its NewSheet, ProcessesPivotTable, Processes, Sheet1 + $null = Add-Worksheet -ExcelPackage $Excel -WorkSheetname "Another" -MoveToStart # Now its Another, NewSheet, ProcessesPivotTable, Processes, Sheet1 + $null = Add-Worksheet -ExcelPackage $Excel -WorkSheetname "NearDone" -MoveBefore 5 # Now its Another, NewSheet, ProcessesPivotTable, Processes, NearDone ,Sheet1 + $null = Add-Worksheet -ExcelPackage $Excel -WorkSheetname "OneLast" -MoveBefore "ProcessesPivotTable" # Now its Another, NewSheet, Onelast, ProcessesPivotTable, Processes,NearDone ,Sheet1 + Close-ExcelPackage $Excel + + $Excel = Open-ExcelPackage $path + } + + it "Got the Sheets in the right order " { + $excel.Workbook.Worksheets[1].Name | Should -Be "Another" + $excel.Workbook.Worksheets[2].Name | Should -Be "NewSheet" + $excel.Workbook.Worksheets[3].Name | Should -Be "Onelast" + $excel.Workbook.Worksheets[4].Name | Should -Be "ProcessesPivotTable" + $excel.Workbook.Worksheets[5].Name | Should -Be "Processes" + $excel.Workbook.Worksheets[6].Name | Should -Be "NearDone" + $excel.Workbook.Worksheets[7].Name | Should -Be "Sheet1" + } + + it "Cloned 'Processes' to 'NewSheet' " { + $newWs = $excel.Workbook.Worksheets["NewSheet"] + $newWs.Dimension.Address | Should -Be ($excel.Workbook.Worksheets["Processes"].Dimension.Address) + } + + } + + Context " # Create and append with Start row and Start Column, inc ranges and Pivot table. " { + BeforeAll { + $path = "TestDrive:\test.xlsx" + remove-item -Path $path -ErrorAction SilentlyContinue + #Catch warning + $warnVar = $null + #Test -Append with no existing sheet. Test adding a named pivot table from command line parameters and extending ranges when they're not specified explictly + Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -StartRow 3 -StartColumn 3 -BoldTopRow -IncludePivotTable -PivotRows Company -PivotData PM -PivotTableName 'PTOffset' -Path $path -WorkSheetname withOffset -Append -PivotFilter Name -NoTotalsInPivot -RangeName procs -AutoFilter -AutoNameRange + Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -StartRow 3 -StartColumn 3 -BoldTopRow -IncludePivotTable -PivotRows Company -PivotData PM -PivotTableName 'PTOffset' -Path $path -WorkSheetname withOffset -Append -WarningAction SilentlyContinue -WarningVariable warnvar + $Excel = Open-ExcelPackage $path + $dataWs = $Excel.Workbook.Worksheets["withOffset"] + $pt = $Excel.Workbook.Worksheets["PTOffset"].PivotTables[0] + } + + it "Created and appended to a sheet offset from the top left corner " { + $dataWs.Cells[1, 1].Value | Should -BeNullOrEmpty + $dataWs.Cells[2, 2].Value | Should -BeNullOrEmpty + $dataWs.Cells[3, 3].Value | Should -Not -BeNullOrEmpty + $dataWs.Cells[3, 3].Style.Font.Bold | Should -Be $true + $dataWs.Dimension.End.Row | Should -Be 23 + $dataWs.names[0].Start.row | Should -Be 4 # StartRow + 1 + $dataWs.names[0].End.row | Should -Be $dataWs.Dimension.End.Row + $dataWs.names[0].Name | Should -Be 'Name' + $dataWs.names.Count | Should -Be 7 # Name, cpu, pm, handles & company + Named Range "Procs" + xl one for autofilter + $dataWs.cells[$dataws.Dimension].AutoFilter | Should -Be true + } + it "Applied and auto-extended an autofilter " { + $dataWs.Names["_xlnm._FilterDatabase"].Start.Row | Should -Be 3 #offset + $dataWs.Names["_xlnm._FilterDatabase"].Start.Column | Should -Be 3 + $dataWs.Names["_xlnm._FilterDatabase"].Rows | Should -Be 21 #2 x 10 data + 1 header + $dataWs.Names["_xlnm._FilterDatabase"].Columns | Should -Be 5 #Name, cpu, pm, handles & company + $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | Should -Be $true + } + it "Created and auto-extended the named ranges " { + $dataWs.names["procs"].rows | Should -Be 21 + $dataWs.names["procs"].Columns | Should -Be 5 + $dataWs.Names["CPU"].Rows | Should -Be 20 + $dataWs.Names["CPU"].Columns | Should -Be 1 + } + it "Created and extended the pivot table " { + $pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref | Should -be "C3:G23" + $pt.ColumGrandTotals | Should -Be $false + $pt.RowGrandTotals | Should -Be $false + $pt.Fields["Company"].IsRowField | Should -Be $true + $pt.Fields["PM"].IsDataField | Should -Be $true + $pt.Fields["Name"].IsPageField | Should -Be $true + } + it "Generated a message on extending the Pivot table " { + $warnVar | Should -Not -BeNullOrEmpty + } + } + + Context " # Create and append explicit and auto table and range extension" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + #Test -Append automatically extends a table, even when it is not specified in the append command; + Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -TableName ProcTab -AutoNameRange -WorkSheetname NoOffset -ClearSheet + #Test number format applying to new data + Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -AutoNameRange -WorkSheetname NoOffset -Append -Numberformat 'Number' + $Excel = Open-ExcelPackage $path + $dataWs = $Excel.Workbook.Worksheets["NoOffset"] + } + + #table should be 20 rows + header after extending the data. CPU range should be 1x20 + it "Created a new sheet and auto-extended a table and explicitly extended named ranges " { + $dataWs.Tables["ProcTab"].Address.Address | Should -Be "A1:E21" + $dataWs.Names["CPU"].Rows | Should -Be 20 + $dataWs.Names["CPU"].Columns | Should -Be 1 + } + it "Set the expected number formats " { + $dataWs.cells["C2"].Style.Numberformat.Format | Should -Be "General" + $dataWs.cells["C12"].Style.Numberformat.Format | Should -Be "0.00" + } + + + it "Created a new sheet and explicitly extended named range and autofilter " { + #Test extending autofilter and range when explicitly specified in the append + $excel = Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -ClearSheet -PassThru + Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -Append + $Excel = Open-ExcelPackage $path + $dataWs = $Excel.Workbook.Worksheets["NoOffset"] + $dataWs.names["procs"].rows | Should -Be 21 + $dataWs.names["procs"].Columns | Should -Be 5 + $dataWs.Names["_xlnm._FilterDatabase"].Rows | Should -Be 21 #2 x 10 data + 1 header + $dataWs.Names["_xlnm._FilterDatabase"].Columns | Should -Be 5 #Name, cpu, pm, handles & company + $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | Should -Be $true + } + } + + Context "#Example 10 # Creates a file with a table with a 'totals' row".PadRight(87) { + BeforeEach { + $path = "TestDrive:\test.xlsx" + Remove-item -Path $path -ErrorAction SilentlyContinue + + #Test with a maximum of 50 processes for speed; export limited set of properties. + $processes = Get-Process | Where-Object { $_.StartTime } | Select-Object -First 50 + + # Export as table with a totals row with a set of possibilities + $TableTotalSettings = @{ + Id = "COUNT" + WS = "SUM" + Handles = "AVERAGE" + CPU = '=COUNTIF([CPU];"<1")' + NPM = @{ + Function = '=SUMIF([Name];"=Chrome";[NPM])' + Comment = "Sum of Non-Paged Memory (NPM) for all chrome processes" + } + } + $Processes | Export-Excel $path -TableName "processes" -TableTotalSettings $TableTotalSettings + $TotalRows = $Processes.count + 2 # Column header + Data (50 processes) + Totals row + $Excel = Open-ExcelPackage -Path $path + $ws = $Excel.Workbook.Worksheets[1] + } + + it "Totals row was created".PadRight(87) { + $ws.Tables[0].Address.Rows | Should -Be $TotalRows + $ws.tables[0].ShowTotal | Should -Be $True + } + + it "Added four calculations in the totals row".PadRight(87) { + $IDcolumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "id" } + $WScolumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "WS" } + $HandlesColumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "Handles" } + $CPUColumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "CPU" } + $NPMColumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "NPM" } + + # Testing column properties + $IDcolumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Count" + $WScolumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Sum" + $HandlesColumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Average" + $CPUColumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Custom" + $CPUColumn | Select-Object -ExpandProperty TotalsRowFormula | Should -Be 'COUNTIF([CPU],"<1")' + $NPMColumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Custom" + $NPMColumn | Select-Object -ExpandProperty TotalsRowFormula | Should -Be 'SUMIF([Name],"=Chrome",[NPM])' + + # Testing actual cell properties + $CountAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $IDcolumn.Id).ColumnName, $TotalRows + $SumAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $WScolumn.Id).ColumnName, $TotalRows + $AverageAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $HandlesColumn.Id).ColumnName, $TotalRows + $CustomAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $CPUColumn.Id).ColumnName, $TotalRows + $CustomCommentAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $NPMColumn.Id).ColumnName, $TotalRows + + $ws.Cells[$CountAddress].Formula | Should -Be "SUBTOTAL(103,processes[Id])" + $ws.Cells[$SumAddress].Formula | Should -Be "SUBTOTAL(109,processes[Ws])" + $ws.Cells[$AverageAddress].Formula | Should -Be "SUBTOTAL(101,processes[Handles])" + $ws.Cells[$CustomAddress].Formula | Should -Be 'COUNTIF([CPU],"<1")' + $ws.Cells[$CustomCommentAddress].Formula | Should -Be 'SUMIF([Name],"=Chrome",[NPM])' + $ws.Cells[$CustomCommentAddress].Comment.Text | Should -Not -BeNullOrEmpty + } + + AfterEach { + Close-ExcelPackage -ExcelPackage $Excel + } + } + + # Context "#Example 11 # Create and append with title, inc ranges and Pivot table" { + # $path = "TestDrive:\test.xlsx" + # #Test New-PivotTableDefinition builds definition using -Pivotfilter and -PivotTotals options. + # $ptDef = [ordered]@{} + # $ptDef += New-PivotTableDefinition -PivotTableName "PT1" -SourceWorkSheet 'Sheet1' -PivotRows "Status" -PivotData @{'Status' = 'Count' } -PivotTotals Columns -PivotFilter "StartType" -IncludePivotChart -ChartType BarClustered3D -ChartTitle "Services by status" -ChartHeight 512 -ChartWidth 768 -ChartRow 10 -ChartColumn 0 -NoLegend -PivotColumns CanPauseAndContinue + # $ptDef += New-PivotTableDefinition -PivotTableName "PT2" -SourceWorkSheet 'Sheet2' -PivotRows "Company" -PivotData @{'Company' = 'Count' } -PivotTotalS Rows -IncludePivotChart -ChartType PieExploded3D -ShowPercent -WarningAction SilentlyContinue + + Context "#Example 13 # Formatting and another way to do a pivot. " { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-Item $path -ErrorAction SilentlyContinue + #Test freezing top row/first column, adding formats and a pivot table - from Add-Pivot table not a specification variable - after the export + $Ex13Data = Get-Process | Select-Object -Property Name, Company, Handles, CPU, PM, NPM, WS + $excel = $Ex13Data | Export-Excel -Path $path -ClearSheet -WorkSheetname "Processes" -FreezeTopRowFirstColumn -PassThru + # Add extra worksheets for testing 'Freeze Top Row' and 'Freeze First Column' with or without title + $excel = Export-Excel -InputObject $Ex13Data -ExcelPackage $excel -WorksheetName "FreezeTopRow" -FreezeTopRow -Passthru + $excel = Export-Excel -InputObject $Ex13Data -ExcelPackage $excel -WorksheetName "FreezeFirstColumn" -FreezeFirstColumn -Passthru + $excel = Export-Excel -InputObject $Ex13Data -Title "Freeze Top Row" -ExcelPackage $excel -WorksheetName "FreezeTopRowTitle" -FreezeTopRow -Passthru + $excel = Export-Excel -InputObject $Ex13Data -Title "Freeze Top Row First Column" -ExcelPackage $excel -WorksheetName "FreezeTRFCTitle" -FreezeTopRowFirstColumn -Passthru + $sheet = $excel.Workbook.Worksheets["Processes"] + if ($isWindows) { $sheet.Column(1) | Set-ExcelRange -Bold -AutoFit } + else { $sheet.Column(1) | Set-ExcelRange -Bold } + $sheet.Column(2) | Set-ExcelRange -Width 29 -WrapText + $sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NFormat "#,###" + Set-ExcelRange -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" + Set-ExcelRange -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold + Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center + Add-ConditionalFormatting -Worksheet $sheet -Range "D2:D1048576" -DataBarColor ([System.Drawing.Color]::Red) + #test Add-ConditionalFormatting -passthru and using a range (and no worksheet) + $rule = Add-ConditionalFormatting -passthru -Address $sheet.cells["C:C"] -RuleType TopPercent -ConditionValue 20 -Bold -StrikeThru + Add-ConditionalFormatting -Worksheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor ([System.Drawing.Color]::Red) -Bold -Italic -Underline -BackgroundColor ([System.Drawing.Color]::Beige) -BackgroundPattern LightUp -PatternColor ([System.Drawing.Color]::Gray) + #Test Set-ExcelRange with a column + if ($isWindows) { foreach ($c in 5..9) { Set-ExcelRange $sheet.Column($c) -AutoFit } } + Add-PivotTable -PivotTableName "PT_Procs" -ExcelPackage $excel -SourceWorkSheet 1 -PivotRows Company -PivotData @{'Name' = 'Count' } -IncludePivotChart -ChartType ColumnClustered -NoLegend + Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -AutoNameRange #Test adding named ranges seperately from adding data. + + $excel = Open-ExcelPackage $path + $sheet = $excel.Workbook.Worksheets["Processes"] + $sheetftr = $excel.Workbook.Worksheets["FreezeTopRow"] + $sheetffc = $excel.Workbook.Worksheets["FreezeFirstColumn"] + $sheetftrt = $excel.Workbook.Worksheets["FreezeTopRowTitle"] + $sheetftrfct = $excel.Workbook.Worksheets["FreezeTRFCTitle"] + } + it "Returned the rule when calling Add-ConditionalFormatting -passthru " { + $rule | Should -Not -BeNullOrEmpty + $rule.getType().fullname | Should -Be "OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormattingTopPercent" + $rule.Style.Font.Strike | Should -Be true + } + it "Applied the formating " { + $sheet | Should -Not -BeNullOrEmpty + if ($isWindows) { + $sheet.Column(1).width | Should -Not -Be $sheet.DefaultColWidth + $sheet.Column(7).width | Should -Not -Be $sheet.DefaultColWidth + } + $sheet.Column(1).style.font.bold | Should -Be $true + $sheet.Column(2).style.wraptext | Should -Be $true + $sheet.Column(2).width | Should -Be 29 + $sheet.Column(3).style.horizontalalignment | Should -Be 'right' + $sheet.Column(4).style.horizontalalignment | Should -Be 'right' + $sheet.Cells["A1"].Style.HorizontalAlignment | Should -Be 'Center' + $sheet.Cells['E2'].Style.HorizontalAlignment | Should -Be 'right' + $sheet.Cells['A1'].Style.Font.Bold | Should -Be $true + $sheet.Cells['D2'].Style.Font.Bold | Should -Be $true + $sheet.Cells['E2'].style.numberformat.format | Should -Be '#,###' + $sheet.Column(3).style.numberformat.format | Should -Be '#,###' + $sheet.Column(4).style.numberformat.format | Should -Be '#,##0.0' + $sheet.ConditionalFormatting.Count | Should -Be 3 + $sheet.ConditionalFormatting[0].type | Should -Be 'Databar' + $sheet.ConditionalFormatting[0].Color.name | Should -Be 'ffff0000' + $sheet.ConditionalFormatting[0].Address.Address | Should -Be 'D2:D1048576' + $sheet.ConditionalFormatting[1].Style.Font.Strike | Should -Be $true + $sheet.ConditionalFormatting[1].type | Should -Be "TopPercent" + $sheet.ConditionalFormatting[2].type | Should -Be 'GreaterThan' + $sheet.ConditionalFormatting[2].Formula | Should -Be '104857600' + $sheet.ConditionalFormatting[2].Style.Font.Color.Color.Name | Should -Be 'ffff0000' + } + it "Created the named ranges " { + $sheet.Names.Count | Should -Be 7 + $sheet.Names[0].Start.Column | Should -Be 1 + $sheet.Names[0].Start.Row | Should -Be 2 + $sheet.Names[0].End.Row | Should -Be $sheet.Dimension.End.Row + $sheet.Names[0].Name | Should -Be $sheet.Cells['A1'].Value + $sheet.Names[6].Start.Column | Should -Be 7 + $sheet.Names[6].Start.Row | Should -Be 2 + $sheet.Names[6].End.Row | Should -Be $sheet.Dimension.End.Row + $sheet.Names[6].Name | Should -Be $sheet.Cells['G1'].Value + } + it "Froze the panes " { + $sheetPaneInfo = $sheet.worksheetxml.worksheet.sheetViews.sheetView.pane + $sheetftrPaneInfo = $sheetftr.worksheetxml.worksheet.sheetViews.sheetView.pane + $sheetffcPaneInfo = $sheetffc.worksheetxml.worksheet.sheetViews.sheetView.pane + $sheetftrtPaneInfo = $sheetftrt.worksheetxml.worksheet.sheetViews.sheetView.pane + $sheetftrfctPaneInfo = $sheetftrfct.worksheetxml.worksheet.sheetViews.sheetView.pane + $sheet.view.Panes.Count | Should -Be 3 # Don't know if this actually checks anything + $sheetPaneInfo.xSplit | Should -Be 1 + $sheetPaneInfo.ySplit | Should -Be 1 + $sheetPaneInfo.topLeftCell | Should -Be "B2" + $sheetftrPaneInfo.xSplit | Should -BeNullOrEmpty + $sheetftrPaneInfo.ySplit | Should -Be 1 + $sheetftrPaneInfo.topLeftCell | Should -Be "A2" + $sheetffcPaneInfo.xSplit | Should -Be 1 + $sheetffcPaneInfo.ySplit | Should -BeNullOrEmpty + $sheetffcPaneInfo.topLeftCell | Should -Be "B1" + $sheetftrtPaneInfo.xSplit | Should -BeNullOrEmpty + $sheetftrtPaneInfo.ySplit | Should -Be 2 + $sheetftrtPaneInfo.topLeftCell | Should -Be "A3" + $sheetftrfctPaneInfo.xSplit | Should -Be 1 + $sheetftrfctPaneInfo.ySplit | Should -Be 2 + $sheetftrfctPaneInfo.topLeftCell | Should -Be "B3" + } + + it "Created the pivot table " { + $ptsheet1 = $Excel.Workbook.Worksheets["Pt_procs"] + $ptsheet1 | Should -Not -BeNullOrEmpty + $ptsheet1.PivotTables[0].DataFields[0].Field.Name | Should -Be "Name" + $ptsheet1.PivotTables[0].DataFields[0].Function | Should -Be "Count" + $ptsheet1.PivotTables[0].RowFields[0].Name | Should -Be "Company" + $ptsheet1.PivotTables[0].CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref | + Should -be $sheet.Dimension.address + } + } + + Context " # Chart from MultiSeries.ps1 in the Examples\charts Directory" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + } + + it "Found the same parameters for Add-ExcelChart and New-ExcelChartDefinintion " { + #Test we haven't missed any parameters on New-ChartDefinition which are on add chart or vice versa. + $ParamChk1 = (Get-command Add-ExcelChart ).Parameters.Keys.where( { -not (Get-command New-ExcelChartDefinition).Parameters.ContainsKey($_) }) | Sort-Object + $ParamChk2 = (Get-command New-ExcelChartDefinition).Parameters.Keys.where( { -not (Get-command Add-ExcelChart ).Parameters.ContainsKey($_) }) + $ParamChk1.count | Should -Be 3 + $ParamChk1[0] | Should -Be "PassThru" + $ParamChk1[1] | Should -Be "PivotTable" + $ParamChk1[2] | Should -Be "Worksheet" + $ParamChk2.count | Should -Be 1 + $ParamChk2[0] | Should -Be "Header" + } + it "Used Invoke-Sum to create a data set " { + #Test Invoke-Sum + $data = Invoke-Sum (Get-Process) Company Handles, PM, VirtualMemorySize + $data | Should -Not -BeNullOrEmpty + $data.count | Should -BeGreaterThan 1 + $data[1].Name | Should -Not -BeNullOrEmpty + $data[1].Handles | Should -Not -BeNullOrEmpty + $data[1].PM | Should -Not -BeNullOrEmpty + $data[1].VirtualMemorySize | Should -Not -BeNullOrEmpty + } + + it "Created an Excel chart definition and used it " { + $c = New-ExcelChartDefinition -Title Stats -ChartType LineMarkersStacked -XRange "Processes[Name]" -YRange "Processes[PM]", "Processes[VirtualMemorySize]" -SeriesHeader 'PM', 'VMSize' + $c | Should -Not -BeNullOrEmpty + $c.ChartType.gettype().name | Should -Be "eChartType" + $c.ChartType.tostring() | Should -Be "LineMarkersStacked" + $c.yrange -is [array] | Should -Be $true + $c.yrange.count | Should -Be 2 + $c.yrange[0] | Should -Be "Processes[PM]" + $c.yrange[1] | Should -Be "Processes[VirtualMemorySize]" + $c.xrange | Should -Be "Processes[Name]" + $c.Title | Should -Be "Stats" + $c.Nolegend | Should -Not -Be $true + $c.ShowCategory | Should -Not -Be $true + $c.ShowPercent | Should -Not -Be $true + + $data | Export-Excel $path -AutoSize -TableName Processes -ExcelChartDefinition $c + $excel = Open-ExcelPackage -Path $path + $drawings = $excel.Workbook.Worksheets[1].drawings + + $drawings.count | Should -Be 1 + $drawings[0].ChartType | Should -Be "LineMarkersStacked" + $drawings[0].Series.count | Should -Be 2 + $drawings[0].Series[0].Series | Should -Be "'Sheet1'!Processes[PM]" + $drawings[0].Series[0].XSeries | Should -Be "'Sheet1'!Processes[Name]" + $drawings[0].Series[1].Series | Should -Be "'Sheet1'!Processes[VirtualMemorySize]" + $drawings[0].Series[1].XSeries | Should -Be "'Sheet1'!Processes[Name]" + $drawings[0].Title.text | Should -Be "Stats" + + Close-ExcelPackage $excel + } + } + + Context " # variation of plot.ps1 from Examples Directory using Add chart outside ExportExcel" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + #Test inserting a fomual + $excel = 0..360 | ForEach-Object { [pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) " } } | Export-Excel -AutoNameRange -Path $path -WorkSheetname SinX -ClearSheet -FreezeFirstColumn -PassThru + #Test-Add Excel Chart to existing data. Test add Conditional formatting with a formula + Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -SeriesHeader "Sin(x)" -Title "Graph of Sine X" -TitleBold -TitleSize 14 ` + -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" ` + -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 ` + -LegendSize 8 -legendBold -LegendPosition Bottom + Add-ConditionalFormatting -Worksheet $excel.Workbook.Worksheets["Sinx"] -Range "B2:B362" -RuleType LessThan -ConditionValue "=B1" -ForeGroundColor ([System.Drawing.Color]::Red) + $ws = $Excel.Workbook.Worksheets["Sinx"] + $d = $ws.Drawings[0] + } + + It "Controled the axes and title and legend of the chart " { + $d.XAxis.MaxValue | Should -Be 361 + $d.XAxis.MajorUnit | Should -Be 30 + $d.XAxis.MinorUnit | Should -Be 10 + $d.XAxis.Title.Text | Should -Be "degrees" + $d.XAxis.Title.Font.bold | Should -Be $true + $d.XAxis.Title.Font.Size | Should -Be 12 + $d.XAxis.MajorUnit | Should -Be 30 + $d.XAxis.MinorUnit | Should -Be 10 + $d.XAxis.MinValue | Should -Be 0 + $d.XAxis.MaxValue | Should -Be 361 + $d.YAxis.Format | Should -Be "0.00" + $d.Title.Text | Should -Be "Graph of Sine X" + $d.Title.Font.Bold | Should -Be $true + $d.Title.Font.Size | Should -Be 14 + $d.yAxis.MajorUnit | Should -Be 0.25 + $d.yAxis.MaxValue | Should -Be 1.25 + $d.yaxis.MinValue | Should -Be -1.25 + $d.Legend.Position.ToString() | Should -Be "Bottom" + $d.Legend.Font.Bold | Should -Be $true + $d.Legend.Font.Size | Should -Be 8 + $d.ChartType.tostring() | Should -Be "line" + $d.From.Column | Should -Be 2 + } + It "Appplied conditional formatting to the data " { + $ws.ConditionalFormatting[0].Formula | Should -Be "B1" + } + + AfterAll { + Close-ExcelPackage -ExcelPackage $excel -nosave + } + } + + Context " # Quick line chart" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + #test drawing a chart when data doesn't have a string + 0..360 | ForEach-Object { [pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) " } } | Export-Excel -AutoNameRange -Path $path -LineChart + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Sheet1 + $d = $ws.Drawings[0] + } + it "Created the chart " { + $d.Title.text | Should -BeNullOrEmpty + $d.ChartType | Should -Be "line" + $d.Series[0].Header | Should -Be "Sinx" + $d.Series[0].xSeries | Should -Be "'Sheet1'!A2:A362" + $d.Series[0].Series | Should -Be "'Sheet1'!B2:B362" + } + + } + + Context " # Quick Pie chart and three icon conditional formating" { + BeforeAll { + $path = "TestDrive:\Pie.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + $range = Get-Process | Group-Object -Property company | Where-Object -Property name | + Select-Object -Property Name, @{n = "TotalPm"; e = { ($_.group | Measure-Object -sum -Property pm).sum } } | + Export-Excel -NoHeader -AutoNameRange -path $path -ReturnRange -PieChart -ShowPercent + $Cf = New-ConditionalFormattingIconSet -Range ($range -replace "^.*:", "B2:") -ConditionalFormat ThreeIconSet -Reverse -IconType Flags + $ct = New-ConditionalText -Text "Microsoft" -ConditionalTextColor ([System.Drawing.Color]::Red) -BackgroundColor([System.Drawing.Color]::AliceBlue) -ConditionalType ContainsText + } + + it "Created the Conditional formatting rules " { + $cf.Formatter | Should -Be "ThreeIconSet" + $cf.IconType | Should -Be "Flags" + $cf.Range | Should -Be ($range -replace "^.*:", "B2:") + $cf.Reverse | Should -Be $true + $ct.BackgroundColor.Name | Should -Be "AliceBlue" + $ct.ConditionalTextColor.Name | Should -Be "Red" + $ct.ConditionalType | Should -Be "ContainsText" + $ct.Text | Should -Be "Microsoft" + } + + BeforeEach { + #Test -ConditionalFormat & -ConditionalText + Export-Excel -Path $path -ConditionalFormat $cf -ConditionalText $ct + $excel = Open-ExcelPackage -Path $path + $rows = $range -replace "^.*?(\d+)$", '$1' + $chart = $excel.Workbook.Worksheets["sheet1"].Drawings[0] + $cFmt = $excel.Workbook.Worksheets["sheet1"].ConditionalFormatting + } + + it "Created the chart with the right series " { + $chart.ChartType | Should -Be "PieExploded3D" + $chart.series.series | Should -Be "'Sheet1'!B1:B$rows" #would be B2 and A2 if we had a header. + $chart.series.Xseries | Should -Be "'Sheet1'!A1:A$rows" + $chart.DataLabel.ShowPercent | Should -Be $true + } + it "Created two Conditional formatting rules " { + $cFmt.Count | Should -Be $true + $cFmt.Where( { $_.type -eq "ContainsText" }) | Should -Not -BeNullOrEmpty + $cFmt.Where( { $_.type -eq "ThreeIconSet" }) | Should -Not -BeNullOrEmpty + } + } + + Context " # Awkward multiple tables" { + BeforeEach { + $path = "TestDrive:\test.xlsx" + #Test creating 3 on overlapping tables on the same page. Create rightmost the left most then middle. + remove-item -Path $path -ErrorAction SilentlyContinue + if ($IsLinux -or $IsMacOS) { + $SystemFolder = '/etc' + } + else { + $SystemFolder = 'C:\WINDOWS\system32' + } + $r = Get-ChildItem -path $SystemFolder -File + + "Biggest files" | Export-Excel -Path $path -StartRow 1 -StartColumn 7 + $r | Sort-Object length -Descending | Select-Object -First 14 Name, @{n = "Size"; e = { $_.Length } } | + Export-Excel -Path $path -TableName FileSize -StartRow 2 -StartColumn 7 -TableStyle Medium2 + + $r.extension | Group-Object | Sort-Object -Property count -Descending | Select-Object -First 12 Name, Count | + Export-Excel -Path $path -TableName ExtSize -Title "Frequent Extensions" -TitleSize 11 -BoldTopRow + + $r | Group-Object -Property extension | Select-Object Name, @{n = "Size"; e = { ($_.group | Measure-Object -property length -sum).sum } } | + Sort-Object -Property size -Descending | Select-Object -First 10 | + Export-Excel -Path $path -TableName ExtCount -Title "Biggest extensions" -TitleSize 11 -StartColumn 4 -AutoSize + + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Workbook.Worksheets[1] + } + + it "Created 3 tables " { + $ws.tables.count | Should -Be 3 + } + it "Created the FileSize table in the right place with the right size and style " { + $ws.Tables["FileSize"].Address.Address | Should -Be "G2:H16" #Insert at row 2, Column 7, 14 rows x 2 columns of data + $ws.Tables["FileSize"].StyleName | Should -Be "TableStyleMedium2" + } + it "Created the ExtSize table in the right place with the right size and style " { + $ws.Tables["ExtSize"].Address.Address | should -be "A2:B14" #tile, then 12 rows x 2 columns of data + $ws.Tables["ExtSize"].StyleName | should -be "TableStyleMedium6" + } + it "Created the ExtCount table in the right place with the right size " { + $ws.Tables["ExtCount"].Address.Address | Should -Be "D2:E12" #title, then 10 rows x 2 columns of data + } + } + + Context " # Parameters and ParameterSets" { + BeforeAll { + $Path = Join-Path (Resolve-Path 'TestDrive:').ProviderPath "test.xlsx" + Remove-Item -Path $Path -ErrorAction SilentlyContinue + $Processes = Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company + } + + it "Allows the default parameter set with Path".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Path $Path -PassThru + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should -Be $Path + $Worksheet.Cells['A1'].Value | Should -Be 'Name' + $Worksheet.Tables | Should -BeNullOrEmpty + $Worksheet.AutoFilterAddress | Should -BeNullOrEmpty + } + it "throws when the ExcelPackage is specified with either -path or -Now".PadRight(87) { + $ExcelPackage = Export-Excel -Path $Path -PassThru + { Export-Excel -ExcelPackage $ExcelPackage -Path $Path } | Should -Throw + { Export-Excel -ExcelPackage $ExcelPackage -Now } | Should -Throw + + $Processes | Export-Excel -ExcelPackage $ExcelPackage + Remove-Item -Path $Path + } + it "If TableName and AutoFilter provided AutoFilter will be ignored".PadRight(87) { + $ExcelPackage = Export-Excel -Path $Path -PassThru -TableName 'Data' -AutoFilter + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $Worksheet.Tables[0].Name | Should -Be 'Data' + $Worksheet.AutoFilterAddress | Should -BeNullOrEmpty + } + it "Default Set with Path and TableName with generated name".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Path $Path -PassThru -TableName '' + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should -Be $Path + $Worksheet.Tables[0].Name | Should -Be 'Table1' + } + it "Now will use temp Path, set TableName with generated name and AutoSize".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File.FullName | Should -BeLike ([IO.Path]::GetTempPath() + '*') + $Worksheet.Tables[0].Name | Should -Be 'Table1' + $Worksheet.AutoFilterAddress | Should -BeNullOrEmpty + if ($isWindows) { + $Worksheet.Column(5).Width | Should -BeGreaterThan 9.5 + } + } + it "Now allows override of Path and TableName".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru -Path $Path -TableName:$false + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should -Be $Path + $Worksheet.Tables | Should -BeNullOrEmpty + $Worksheet.AutoFilterAddress | Should -BeNullOrEmpty + if ($isWindows) { + $Worksheet.Column(5).Width | Should -BeGreaterThan 9.5 + } + } + <# Mock looks unreliable need to check + Mock -CommandName 'Invoke-Item' + it "Now will Show".PadRight(87) { + $Processes | Export-Excel + Assert-MockCalled -CommandName 'Invoke-Item' -Times 1 -Exactly -Scope 'It' + } + it "Now allows override of Show".PadRight(87) { + $Processes | Export-Excel -Show:$false + Assert-MockCalled -CommandName 'Invoke-Item' -Times 0 -Exactly -Scope 'It' + } + #> + it "Now allows override of AutoSize and TableName to AutoFilter".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru -AutoSize:$false -AutoFilter + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $Worksheet.Tables | Should -BeNullOrEmpty + $Worksheet.AutoFilterAddress | Should -Not -BeNullOrEmpty + [math]::Round($Worksheet.Column(5).Width, 2) | Should -Be 9.14 + } + it "Now allows to set TableName".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru -TableName 'Data' + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $Worksheet.Tables[0].Name | Should -Be 'Data' + $Worksheet.AutoFilterAddress | Should -BeNullOrEmpty + if ($isWindows) { + $Worksheet.Column(5).Width | Should -BeGreaterThan 9.5 + } + } + } + + Context " # Check UnderLineType" -Tag CheckUnderLineType { + BeforeAll { + $Path = Join-Path (Resolve-Path 'TestDrive:').ProviderPath "testUnderLineType.xlsx" + Remove-Item -Path $Path -ErrorAction SilentlyContinue + + $data = " + Set-ExcelRange,Set-ExcelColumn + Should be double underlined,Should be double underlined + Should be double underlined,Should be double underlined + " | ConvertFrom-Csv + + $data | Export-Excel $Path -AutoSize + + $excel = Open-ExcelPackage $Path + $ws = $excel.Workbook.Worksheets["sheet1"] + + Set-ExcelRange -Range $ws.Cells["A2:A3"] -Underline -UnderLineType "Double" + Set-ExcelColumn -Worksheet $ws -Column 2 -StartRow 2 -Underline -UnderLineType "Double" + + Close-ExcelPackage $excel + } + + AfterAll { + Remove-Item -Path $Path -ErrorAction SilentlyContinue + } + + it "Check Cell Style Font via Set-ExcelColumn".PadRight(87) { + $excel = Open-ExcelPackage $Path + $cell = $excel.Sheet1.Cells["B2"] + + $actual = $cell.Style.Font + + $actual.Underline | Should -BeTrue + $actual.UnderlineType | Should -Be "Double" + + Close-ExcelPackage $excel -NoSave + } + + it "Check Cell Style Font via Set-ExcelRange".PadRight(87) { + $excel = Open-ExcelPackage $Path + $cell = $excel.Sheet1.Cells["A2"] + + $actual = $cell.Style.Font + + $actual.Underline | Should -BeTrue + $actual.UnderlineType | Should -Be "Double" + + Close-ExcelPackage $excel -NoSave + } + } + + It "Should have hyperlink created" -Tag hyperlink { + $path = "TestDrive:\testHyperLink.xlsx" + + $license = "cognc:MCOMEETADV_GOV,cognc:M365_G3_GOV,cognc:ENTERPRISEPACK_GOV,cognc:RIGHTSMANAGEMENT_ADHOC" + $ms365 = [PSCustomObject]@{ + DisplayName = "Test Subject" + UserPrincipalName = "test@contoso.com" + licenses = $license + } + + $ms365 | Export-Excel $path + + $excel = Open-ExcelPackage $Path + + $ws = $excel.Sheet1 + + $ws.Dimension.Rows | Should -Be 2 + $ws.Dimension.Columns | Should -Be 3 + + $ws.Cells["C2"].Hyperlink | Should -BeExactly $license + + Close-ExcelPackage $excel + + Remove-Item $path + } + + It "Should have no hyperlink created" -Tag hyperlink { + $path = "TestDrive:\testHyperLink.xlsx" + + $license = "cognc:MCOMEETADV_GOV,cognc:M365_G3_GOV,cognc:ENTERPRISEPACK_GOV,cognc:RIGHTSMANAGEMENT_ADHOC" + $ms365 = [PSCustomObject]@{ + DisplayName = "Test Subject" + UserPrincipalName = "test@contoso.com" + licenses = $license + } + + $ms365 | Export-Excel $path -NoHyperLinkConversion licenses + + $excel = Open-ExcelPackage $Path + + $ws = $excel.Sheet1 + + $ws.Dimension.Rows | Should -Be 2 + $ws.Dimension.Columns | Should -Be 3 + + $ws.Cells["C2"].Hyperlink | Should -BeNullOrEmpty + + Close-ExcelPackage $excel + Remove-Item $path + } + + It "Should have no hyperlink created using wild card" -Tag hyperlink { + $path = "TestDrive:\testHyperLink.xlsx" + + $license = "cognc:MCOMEETADV_GOV,cognc:M365_G3_GOV,cognc:ENTERPRISEPACK_GOV,cognc:RIGHTSMANAGEMENT_ADHOC" + $ms365 = [PSCustomObject]@{ + DisplayName = "Test Subject" + UserPrincipalName = "test@contoso.com" + licenses = $license + } + + $ms365 | Export-Excel $path -NoHyperLinkConversion * + + $excel = Open-ExcelPackage $Path + + $ws = $excel.Sheet1 + + $ws.Dimension.Rows | Should -Be 2 + $ws.Dimension.Columns | Should -Be 3 + + $ws.Cells["A2"].Value | Should -BeExactly "Test Subject" + $ws.Cells["B2"].Value | Should -BeExactly "test@contoso.com" + $ws.Cells["C2"].Hyperlink | Should -BeNullOrEmpty + + Close-ExcelPackage $excel + Remove-Item $path + } + + It "Should freeze the correct rows" -tag Freeze { + <# + Export-Excel -InputObject $Data -Path $OutputFile -TableName $SheetName.Replace(' ', '_') -WorksheetName $SheetName -AutoSize -FreezeTopRow -TableStyle $TableStyle -Title $SheetName -TitleBold -TitleSize 18 + #> + + $path = "TestDrive:\testFreeze.xlsx" + + $data = ConvertFrom-Csv @" + Region,State,Units,Price + West,Texas,927,923.71 + North,Tennessee,466,770.67 + East,Florida,520,458.68 + East,Maine,828,661.24 + West,Virginia,465,053.58 + North,Missouri,436,235.67 + South,Kansas,214,992.47 + North,North Dakota,789,640.72 + South,Delaware,712,508.55 +"@ + + Export-Excel -InputObject $data -Path $path -TableName 'TestTable' -WorksheetName 'TestSheet' -AutoSize -TableStyle Medium2 -Title 'Test Title' -TitleBold -TitleSize 18 -FreezeTopRow + + $excel = Open-ExcelPackage -Path $path + $ws = $excel.TestSheet + + $r = $ws.worksheetxml.worksheet.sheetViews.sheetView.pane + + $r | Should -Not -BeNullOrEmpty + $r.ySplit | Should -Be 2 + $r.topLeftCell | Should -BeExactly 'A3' + $r.state | Should -BeExactly 'frozen' + $r.activePane | Should -BeExactly 'bottomLeft' + + Close-ExcelPackage $excel + + Remove-Item $path + } +} \ No newline at end of file diff --git a/__tests__/ExtraLongCmd.tests.ps1 b/__tests__/ExtraLongCmd.tests.ps1 new file mode 100644 index 00000000..70d045b5 --- /dev/null +++ b/__tests__/ExtraLongCmd.tests.ps1 @@ -0,0 +1,72 @@ + + +Describe "Creating workbook with a single line" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + remove-item -path $path -ErrorAction SilentlyContinue + ConvertFrom-Csv @" +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 + +"@ | Export-Excel -Path $path -TableStyle Medium13 -tablename "RawData" -ConditionalFormat @{Range = "C2:C7"; DataBarColor = "Green" } -ExcelChartDefinition @{ChartType = "Doughnut"; XRange = "A2:B7"; YRange = "C2:C7"; width = 800; } -PivotTableDefinition @{Sales = @{ + PivotRows = "City"; PivotColumns = "Product"; PivotData = @{Gross = "Sum"; Net = "Sum" }; PivotNumberFormat = "$#,##0.00"; PivotTotals = "Both"; PivotTableStyle = "Medium12"; Activate = $true + + PivotChartDefinition = @{Title = "Gross and net by city and product"; ChartType = "ColumnClustered"; Column = 6; Width = 600; Height = 360; YMajorUnit = 500; YMinorUnit = 100; YAxisNumberformat = "$#,##0"; LegendPosition = "Bottom" } + } + } + + $excel = Open-ExcelPackage $path + $ws1 = $excel.Workbook.Worksheets[1] + $ws2 = $excel.Workbook.Worksheets[2] + } + Context "Data Page" { + It "Inserted the data and created the table " { + $ws1.Tables[0] | Should -Not -BeNullOrEmpty + $ws1.Tables[0].Address.Address | Should -Be "A1:D7" + $ws1.Tables[0].StyleName | Should -Be "TableStyleMedium13" + } + It "Applied conditional formatting " { + $ws1.ConditionalFormatting[0] | Should -Not -BeNullOrEmpty + $ws1.ConditionalFormatting[0].type.ToString() | Should -Be "DataBar" + $ws1.ConditionalFormatting[0].Color.G | Should -BeGreaterThan 100 + $ws1.ConditionalFormatting[0].Color.R | Should -BeLessThan 100 + $ws1.ConditionalFormatting[0].Address.Address | Should -Be "C2:C7" + } + It "Added the chart " { + $ws1.Drawings[0] | Should -Not -BeNullOrEmpty + $ws1.Drawings[0].ChartType.ToString() | Should -Be "DoughNut" + $ws1.Drawings[0].Series[0].Series | Should -Be "'Sheet1'!C2:C7" + } + } + Context "PivotTable" { + it "Created the PivotTable on a new page " { + $ws2 | Should -Not -BeNullOrEmpty + $ws2.PivotTables[0] | Should -Not -BeNullOrEmpty + $ws2.PivotTables[0].Fields.Count | Should -Be 4 + $ws2.PivotTables[0].DataFields[0].Format | Should -Be "$#,##0.00" + $ws2.PivotTables[0].RowFields[0].Name | Should -Be "City" + $ws2.PivotTables[0].ColumnFields[0].Name | Should -Be "Product" + $ws2.PivotTables[0].RowGrandTotals | Should -Be $true + $ws2.PivotTables[0].ColumGrandTotals | Should -Be $true #Epplus's mis-spelling of column not mine + } + it "Made the PivotTable page active " { + Set-ItResult -Pending -Because "Bug in EPPLus 4.5" + $ws2.View.TabSelected | Should -Be $true + } + it "Created the Pivot Chart " { + $ws2.Drawings[0] | Should -Not -BeNullOrEmpty + $ws2.Drawings[0].ChartType.ToString() | Should -Be ColumnClustered + $ws2.Drawings[0].YAxis.MajorUnit | Should -Be 500 + $ws2.Drawings[0].YAxis.MinorUnit | Should -Be 100 + $ws2.Drawings[0].YAxis.Format | Should -Be "$#,##0" + $ws2.Drawings[0].Legend.Position.ToString() | Should -Be "Bottom" + } + + } + +} diff --git a/__tests__/First10Races.csv b/__tests__/First10Races.csv new file mode 100644 index 00000000..46b31804 --- /dev/null +++ b/__tests__/First10Races.csv @@ -0,0 +1,101 @@ +Race,Date,FinishPosition,Driver,GridPosition,Team,Points +Australian,25/03/2018,1,Sebastian Vettel,3,Ferrari,25 +Australian,25/03/2018,2,Lewis Hamilton,1,Mercedes,18 +Australian,25/03/2018,3,Kimi Räikkönen,2,Ferrari,15 +Australian,25/03/2018,4,Daniel Ricciardo,8,Red Bull Racing-TAG Heuer,12 +Australian,25/03/2018,5,Fernando Alonso,10,McLaren-Renault,10 +Australian,25/03/2018,6,Max Verstappen,4,Red Bull Racing-TAG Heuer,8 +Australian,25/03/2018,7,Nico Hülkenberg,7,Renault,6 +Australian,25/03/2018,8,Valtteri Bottas,15,Mercedes,4 +Australian,25/03/2018,9,Stoffel Vandoorne,11,McLaren-Renault,2 +Australian,25/03/2018,10,Carlos Sainz,9,Renault,1 +Bahrain,08/04/2018,1,Sebastian Vettel,1,Ferrari,25 +Bahrain,08/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Bahrain,08/04/2018,3,Lewis Hamilton,9,Mercedes,15 +Bahrain,08/04/2018,4,Pierre Gasly,5,STR-Honda,12 +Bahrain,08/04/2018,5,Kevin Magnussen,6,Haas-Ferrari,10 +Bahrain,08/04/2018,6,Nico Hülkenberg,7,Renault,8 +Bahrain,08/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Bahrain,08/04/2018,8,Stoffel Vandoorne,14,McLaren-Renault,4 +Bahrain,08/04/2018,9,Marcus Ericsson,17,Sauber-Ferrari,2 +Bahrain,08/04/2018,10,Esteban Ocon,8,Force India-Mercedes,1 +Chinese,15/04/2018,1,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,25 +Chinese,15/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Chinese,15/04/2018,3,Kimi Räikkönen,2,Ferrari,15 +Chinese,15/04/2018,4,Lewis Hamilton,4,Mercedes,12 +Chinese,15/04/2018,5,Max Verstappen,5,Red Bull Racing-TAG Heuer,10 +Chinese,15/04/2018,6,Nico Hülkenberg,7,Renault,8 +Chinese,15/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Chinese,15/04/2018,8,Sebastian Vettel,1,Ferrari,4 +Chinese,15/04/2018,9,Carlos Sainz,9,Renault,2 +Chinese,15/04/2018,10,Kevin Magnussen,11,Haas-Ferrari,1 +Azerbaijan,29/04/2018,1,Lewis Hamilton,2,Mercedes,25 +Azerbaijan,29/04/2018,2,Kimi Räikkönen,6,Ferrari,18 +Azerbaijan,29/04/2018,3,Sergio Pérez,8,Force India-Mercedes,15 +Azerbaijan,29/04/2018,4,Sebastian Vettel,1,Ferrari,12 +Azerbaijan,29/04/2018,5,Carlos Sainz,9,Renault,10 +Azerbaijan,29/04/2018,6,Charles Leclerc,13,Sauber-Ferrari,8 +Azerbaijan,29/04/2018,7,Fernando Alonso,12,McLaren-Renault,6 +Azerbaijan,29/04/2018,8,Lance Stroll,10,Williams-Mercedes,4 +Azerbaijan,29/04/2018,9,Stoffel Vandoorne,16,McLaren-Renault,2 +Azerbaijan,29/04/2018,10,Brendon Hartley,19,STR-Honda,1 +Spanish,13/05/2018,1,Lewis Hamilton,1,Mercedes,25 +Spanish,13/05/2018,2,Valtteri Bottas,2,Mercedes,18 +Spanish,13/05/2018,3,Max Verstappen,5,Red Bull Racing-TAG Heuer,15 +Spanish,13/05/2018,4,Sebastian Vettel,3,Ferrari,12 +Spanish,13/05/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +Spanish,13/05/2018,6,Kevin Magnussen,7,Haas-Ferrari,8 +Spanish,13/05/2018,7,Carlos Sainz,9,Renault,6 +Spanish,13/05/2018,8,Fernando Alonso,8,McLaren-Renault,4 +Spanish,13/05/2018,9,Sergio Pérez,15,Force India-Mercedes,2 +Spanish,13/05/2018,10,Charles Leclerc,14,Sauber-Ferrari,1 +Monaco,27/05/2018,1,Daniel Ricciardo,1,Red Bull Racing-TAG Heuer,25 +Monaco,27/05/2018,2,Sebastian Vettel,2,Ferrari,18 +Monaco,27/05/2018,3,Lewis Hamilton,3,Mercedes,15 +Monaco,27/05/2018,4,Kimi Räikkönen,4,Ferrari,12 +Monaco,27/05/2018,5,Valtteri Bottas,5,Mercedes,10 +Monaco,27/05/2018,6,Esteban Ocon,6,Force India-Mercedes,8 +Monaco,27/05/2018,7,Pierre Gasly,10,STR-Honda,6 +Monaco,27/05/2018,8,Nico Hülkenberg,11,Renault,4 +Monaco,27/05/2018,9,Max Verstappen,20,Red Bull Racing-TAG Heuer,2 +Monaco,27/05/2018,10,Carlos Sainz,8,Renault,1 +Canadian,10/06/2018,1,Sebastian Vettel,1,Ferrari,25 +Canadian,10/06/2018,2,Valtteri Bottas,2,Mercedes,18 +Canadian,10/06/2018,3,Max Verstappen,3,Red Bull Racing-TAG Heuer,15 +Canadian,10/06/2018,4,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,12 +Canadian,10/06/2018,5,Lewis Hamilton,4,Mercedes,10 +Canadian,10/06/2018,6,Kimi Räikkönen,5,Ferrari,8 +Canadian,10/06/2018,7,Nico Hülkenberg,7,Renault,6 +Canadian,10/06/2018,8,Carlos Sainz,9,Renault,4 +Canadian,10/06/2018,9,Esteban Ocon,8,Force India-Mercedes,2 +Canadian,10/06/2018,10,Charles Leclerc,13,Sauber-Ferrari,1 +French,24/06/2018,1,Lewis Hamilton,1,Mercedes,25 +French,24/06/2018,2,Max Verstappen,4,Red Bull Racing-TAG Heuer,18 +French,24/06/2018,3,Kimi Räikkönen,6,Ferrari,15 +French,24/06/2018,4,Daniel Ricciardo,5,Red Bull Racing-TAG Heuer,12 +French,24/06/2018,5,Sebastian Vettel,3,Ferrari,10 +French,24/06/2018,6,Kevin Magnussen,9,Haas-Ferrari,8 +French,24/06/2018,7,Valtteri Bottas,2,Mercedes,6 +French,24/06/2018,8,Carlos Sainz,7,Renault,4 +French,24/06/2018,9,Nico Hülkenberg,12,Renault,2 +French,24/06/2018,10,Charles Leclerc,8,Sauber-Ferrari,1 +Austrian,01/07/2018,1,Max Verstappen,4,Red Bull Racing-TAG Heuer,25 +Austrian,01/07/2018,2,Kimi Räikkönen,3,Ferrari,18 +Austrian,01/07/2018,3,Sebastian Vettel,6,Ferrari,15 +Austrian,01/07/2018,4,Romain Grosjean,5,Haas-Ferrari,12 +Austrian,01/07/2018,5,Kevin Magnussen,8,Haas-Ferrari,10 +Austrian,01/07/2018,6,Esteban Ocon,11,Force India-Mercedes,8 +Austrian,01/07/2018,7,Sergio Pérez,15,Force India-Mercedes,6 +Austrian,01/07/2018,8,Fernando Alonso,20,McLaren-Renault,4 +Austrian,01/07/2018,9,Charles Leclerc,17,Sauber-Ferrari,2 +Austrian,01/07/2018,10,Marcus Ericsson,18,Sauber-Ferrari,1 +British,08/07/2018,1,Sebastian Vettel,2,Ferrari,25 +British,08/07/2018,2,Lewis Hamilton,1,Mercedes,18 +British,08/07/2018,3,Kimi Räikkönen,3,Ferrari,15 +British,08/07/2018,4,Valtteri Bottas,4,Mercedes,12 +British,08/07/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +British,08/07/2018,6,Nico Hülkenberg,11,Renault,8 +British,08/07/2018,7,Esteban Ocon,10,Force India-Mercedes,6 +British,08/07/2018,8,Fernando Alonso,13,McLaren-Renault,4 +British,08/07/2018,9,Kevin Magnussen,7,Haas-Ferrari,2 +British,08/07/2018,10,Sergio Pérez,12,Force India-Mercedes,1 \ No newline at end of file diff --git a/__tests__/First10Races.tests.ps1 b/__tests__/First10Races.tests.ps1 new file mode 100644 index 00000000..d1b17333 --- /dev/null +++ b/__tests__/First10Races.tests.ps1 @@ -0,0 +1,211 @@ + +Describe "Creating small named ranges with hyperlinks" { + BeforeAll { + $scriptPath = $PSScriptRoot + $dataPath = Join-Path -Path $scriptPath -ChildPath "First10Races.csv" + $WarningAction = "SilentlyContinue" + $path = "TestDrive:\Results.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + #Read race results, and group by race name : export 1 row to get headers, leaving enough rows aboce to put in a link for each race + $results = Import-Csv -Path $dataPath | + Select-Object Race, @{n = "Date"; e = { [datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture)) } }, FinishPosition, Driver, GridPosition, Team, Points | + Group-Object -Property RACE + $topRow = $lastDataRow = 1 + $results.Count + $excel = $results[0].Group[0] | Export-Excel -Path $path -StartRow $TopRow -BoldTopRow -PassThru + + #export each group (race) below the last one, without headers, and create a range for each using the group name (Race) + foreach ($r in $results) { + $excel = $R.Group | Export-Excel -ExcelPackage $excel -NoHeader -StartRow ($lastDataRow + 1) -RangeName $R.Name -PassThru -AutoSize + $lastDataRow += $R.Group.Count + } + $worksheet = $excel.Workbook.Worksheets[1] + $columns = $worksheet.Dimension.Columns + + 1..$columns | ForEach-Object { Add-ExcelName -Range $worksheet.cells[$topRow, $_, $lastDataRow, $_] } #Test Add-Excel Name on its own (outside Export-Excel) + + $scwarnVar = $null + Set-ExcelColumn -Worksheet $worksheet -StartRow $topRow -Heading "PlacesGained/Lost" ` + -Value "=GridPosition-FinishPosition" -AutoNameRange -WarningVariable scWarnVar -WarningAction SilentlyContinue #Test as many set column options as possible. + $columns ++ + + #create a table which covers all the data. And define a pivot table which uses the same address range. + $table = Add-ExcelTable -PassThru -Range $worksheet.cells[$topRow, 1, $lastDataRow, $columns] -TableName "AllResults" -TableStyle Light4 ` + -ShowHeader -ShowFilter -ShowColumnStripes -ShowRowStripes:$false -ShowFirstColumn:$false -ShowLastColumn:$false -ShowTotal:$false #Test Add-ExcelTable outside Export-Excel with as many options as possible. + $pt = New-PivotTableDefinition -PivotTableName Analysis -SourceWorkSheet $worksheet -SourceRange $table.address.address -PivotRows Driver -PivotData @{Points = "SUM" } -PivotTotals None + + $cf = Add-ConditionalFormatting -Address $worksheet.cells[$topRow, $columns, $lastDataRow, $columns] -ThreeIconsSet Arrows -Passthru #Test using cells[r1,c1,r2,c2] + $cf.Icon2.Type = $cf.Icon3.Type = "Num" + $cf.Icon2.Value = 0 + $cf.Icon3.Value = 1 + Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor ([System.Drawing.Color]::Purple) -Bold -Priority 1 -StopIfTrue #Test Priority and stopIfTrue and using range name + Add-ConditionalFormatting -Address $worksheet.Cells["GridPosition"] -RuleType ThreeColorScale -Reverse #Test Reverse + $ct = New-ConditionalText -Text "Ferrari" + $ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalText ([System.Drawing.Color]::Red) -Background ([System.Drawing.Color]::White) #Test New-ConditionalText in shortest and longest forms. + #Create links for each group name (race) and Export them so they start at Cell A1; create a pivot table with definition just created, save the file and open in Excel + $excel = $results | ForEach-Object { (New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP") } | #Test Exporting Hyperlinks with display property. + Export-Excel -ExcelPackage $excel -AutoSize -PivotTableDefinition $pt -Calculate -ConditionalFormat $ct, $ct2 -PassThru #Test conditional text rules in conditional format (orignally icon sets only ) + + $null = Add-Worksheet -ExcelPackage $excel -WorksheetName "Points1" + Add-PivotTable -PivotTableName "Points1" -Address $excel.Points1.Cells["A1"] -ExcelPackage $excel -SourceWorkSheet sheet1 -SourceRange $excel.Sheet1.Tables[0].Address.Address -PivotRows Driver, Date -PivotData @{Points = "SUM" } -GroupDateRow Date -GroupDatePart Years, Months + + $null = Add-Worksheet -ExcelPackage $excel -WorksheetName "Places1" + $newpt = Add-PivotTable -PivotTableName "Places1" -Address $excel.Places1.Cells["A1"] -ExcelPackage $excel -SourceWorkSheet sheet1 -SourceRange $excel.Sheet1.Tables[0].Address.Address -PivotRows Driver, FinishPosition -PivotData @{Date = "Count" } -GroupNumericRow FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3 -PassThru + $newpt.RowFields[0].SubTotalFunctions = [OfficeOpenXml.Table.PivotTable.eSubTotalFunctions]::None + Close-ExcelPackage -ExcelPackage $excel + + $excel = Open-ExcelPackage $path + $sheet = $excel.Workbook.Worksheets[1] + $m = $results | Measure-Object -sum -Property count + $expectedRows = 1 + $m.count + $m.sum + } + Context "Creating hyperlinks" { + it "Put the data into the sheet and created the expected named ranges " { + $sheet.Dimension.Rows | Should -Be $expectedRows + $sheet.Dimension.Columns | Should -Be $columns + $sheet.Names.Count | Should -Be ($columns + $results.Count) + $sheet.Names[$results[0].Name] | Should -Not -BenullorEmpty + $sheet.Names[$results[-1].Name] | Should -Not -BenullorEmpty + } + it "Added hyperlinks to the named ranges " { + $sheet.cells["a1"].Hyperlink.Display | Should -Match $results[0].Name + $sheet.cells["a1"].Hyperlink.ReferenceAddress | Should -Match $results[0].Name + } + } + Context "Adding calculated column" { + It "Populated the cells with the right heading and formulas " { + $sheet.Cells[( $results.Count), $columns] | Should -BenullorEmpty + $sheet.Cells[(1 + $results.Count), $columns].Value | Should -Be "PlacesGained/Lost" + $sheet.Cells[(2 + $results.Count), $columns].Formula | Should -Be "GridPosition-FinishPosition" + $sheet.Names["PlacesGained_Lost"] | Should -Not -BenullorEmpty + } + It "Performed the calculation " { + $placesMade = $Sheet.Cells[(2 + $results.Count), 5].value - $Sheet.Cells[(2 + $results.Count), 3].value + $sheet.Cells[(2 + $results.Count), $columns].value | Should -Be $placesmade + } + It "Applied ConditionalFormatting, including StopIfTrue, Priority " { + $sheet.ConditionalFormatting[0].Address.Start.Column | Should -Be $columns + $sheet.ConditionalFormatting[0].Address.End.Column | Should -Be $columns + $sheet.ConditionalFormatting[0].Address.End.Row | Should -Be $expectedRows + $sheet.ConditionalFormatting[0].Address.Start.Row | Should -Be ($results.Count + 1) + $sheet.ConditionalFormatting[0].Icon3.Type.ToString() | Should -Be "Num" + $sheet.ConditionalFormatting[0].Icon3.Value | Should -Be 1 + $sheet.ConditionalFormatting[1].Priority | Should -Be 1 + $sheet.ConditionalFormatting[1].StopIfTrue | Should -Be $true + } + It "Applied ConditionalFormatting, including Reverse " { + Set-ItResult -Pending -Because "Bug in EPPLus 4.5" + $sheet.ConditionalFormatting[3].LowValue.Color.R | Should -BegreaterThan 180 + $sheet.ConditionalFormatting[3].LowValue.Color.G | Should -BeLessThan 128 + $sheet.ConditionalFormatting[3].HighValue.Color.R | Should -BeLessThan 128 + $sheet.ConditionalFormatting[3].HighValue.Color.G | Should -BegreaterThan 180 + } + } + Context "Adding a table" { + it "Created a table " { + $sheet.tables[0] | Should -Not -BeNullOrEmpty + $sheet.tables[0].Address.Start.Column | Should -Be 1 + $sheet.tables[0].Address.End.Column | Should -Be $columns + $sheet.tables[0].Address.Start.row | Should -Be ($results.Count + 1) + $sheet.Tables[0].Address.End.Row | Should -Be $expectedRows + $sheet.Tables[0].StyleName | Should -Be "TableStyleLight4" + $sheet.Tables[0].ShowColumnStripes | Should -Be $true + $sheet.Tables[0].ShowRowStripes | Should -Not -Be $true + } + } + Context "Adding Pivot tables" { + it "Added a worksheet with a pivot table grouped by date " { + $excel.Points1 | Should -Not -BeNullOrEmpty + $excel.Points1.PivotTables.Count | Should -Be 1 + $pt = $excel.Points1.PivotTables[0] + $pt.RowFields.Count | Should -Be 3 + $pt.RowFields[0].name | Should -Be "Driver" + $pt.RowFields[0].Grouping | Should -BenullorEmpty + $pt.RowFields[1].name | Should -Be "years" + $pt.RowFields[1].Grouping | Should -Not -BenullorEmpty + $pt.RowFields[2].name | Should -Be "date" + $pt.RowFields[2].Grouping | Should -Not -BenullorEmpty + } + it "Added a worksheet with a pivot table grouped by Number " { + $excel.Places1 | Should -Not -BeNullOrEmpty + $excel.Places1.PivotTables.Count | Should -Be 1 + $pt = $excel.Places1.PivotTables[0] + $pt.RowFields.Count | Should -Be 2 + $pt.RowFields[0].name | Should -Be "Driver" + $pt.RowFields[0].Grouping | Should -BenullorEmpty + $pt.RowFields[0].SubTotalFunctions.ToString() | Should -Be "None" + $pt.RowFields[1].name | Should -Be "FinishPosition" + $pt.RowFields[1].Grouping | Should -Not -BenullorEmpty + $pt.RowFields[1].Grouping.Start | Should -Be 1 + $pt.RowFields[1].Grouping.End | Should -Be 25 + $pt.RowFields[1].Grouping.Interval | Should -Be 3 + } + } + Context "Adding group date column" -Tag GroupColumnTests { + it "Tests adding a group date column" { + $xlFile = "TestDrive:\Results.xlsx" + Remove-Item $xlFile -ErrorAction Ignore + + $PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points ` + -PivotRows Driver -PivotColumns Date -PivotData @{Points = "SUM" } -GroupDateColumn Date -GroupDatePart Years, Months + + $excel = Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = { [datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture)) } }, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlFile -AutoSize -PivotTableDefinition $PivotTableDefinition -PassThru + + $excel.Workbook.Worksheets.Count | Should -Be 2 + $excel.Workbook.Worksheets[1].Name | Should -BeExactly 'Sheet1' + $excel.Workbook.Worksheets[2].Name | Should -BeExactly 'Points' + $excel.Points.PivotTables.Count | Should -Be 1 + $pt = $excel.Points.PivotTables[0] + $pt.RowFields.Count | Should -Be 1 + $pt.RowFields[0].name | Should -Be "Driver" + + $pt.ColumnFields.Count | Should -Be 2 + + $pt.ColumnFields[0].name | Should -Be "Years" + $pt.ColumnFields[0].Grouping | Should -Not -BeNullOrEmpty + $pt.ColumnFields[0].Grouping.GroupBy | Should -Be "Years" + + $pt.ColumnFields[1].name | Should -Be "Date" + $pt.ColumnFields[1].Grouping | Should -Not -BeNullOrEmpty + $pt.ColumnFields[1].Grouping.GroupBy | Should -Be "Months" + + Close-ExcelPackage $excel + + Remove-Item $xlFile -ErrorAction Ignore + } + } + Context "Adding group numeric column" -Tag GroupColumnTests { + it "Tests adding numeric group column" { + $xlFile = "TestDrive:\Results.xlsx" + Remove-Item $xlFile -ErrorAction Ignore + + $PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places ` + -PivotRows Driver -PivotColumns FinishPosition -PivotData @{Date = "Count" } -GroupNumericColumn FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3 + + $excel = Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = { [datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture)) } }, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlFile -AutoSize -PivotTableDefinition $PivotTableDefinition -PassThru + + $excel.Workbook.Worksheets.Count | Should -Be 2 + $excel.Workbook.Worksheets[1].Name | Should -BeExactly 'Sheet1' + $excel.Workbook.Worksheets[2].Name | Should -BeExactly 'Places' + $excel.Places.PivotTables.Count | Should -Be 1 + $pt = $excel.Places.PivotTables[0] + $pt.RowFields.Count | Should -Be 1 + $pt.RowFields[0].name | Should -Be "Driver" + + $pt.ColumnFields.Count | Should -Be 1 + + $pt.ColumnFields[0].name | Should -Be "FinishPosition" + $pt.ColumnFields[0].Grouping | Should -Not -BeNullOrEmpty + $pt.ColumnFields[0].Grouping.Start | Should -Be 1 + $pt.ColumnFields[0].Grouping.End | Should -Be 25 + $pt.ColumnFields[0].Grouping.Interval | Should -Be 3 + + Close-ExcelPackage $excel + + Remove-Item $xlFile -ErrorAction Ignore + } + } +} \ No newline at end of file diff --git a/__tests__/First10Races.xlsx b/__tests__/First10Races.xlsx new file mode 100644 index 00000000..5fe17090 Binary files /dev/null and b/__tests__/First10Races.xlsx differ diff --git a/__tests__/FunctionAlias.tests.ps1 b/__tests__/FunctionAlias.tests.ps1 new file mode 100644 index 00000000..0fc954c1 --- /dev/null +++ b/__tests__/FunctionAlias.tests.ps1 @@ -0,0 +1,28 @@ +#Requires -Modules Pester +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +Describe "Check if Function aliases exist" { + + It "Set-Column should exist".PadRight(90) { + ${Alias:Set-Column} | Should -Not -BeNullOrEmpty + } + + It "Set-Row should exist".PadRight(90) { + ${Alias:Set-Row} | Should -Not -BeNullOrEmpty + } + + It "Set-Format should exist".PadRight(90) { + ${Alias:Set-Format} | Should -Not -BeNullOrEmpty + } + + <#It "Merge-MulipleSheets should exist" { + Get-Command Merge-MulipleSheets | Should -Not -Be $null + } +#> + It "New-ExcelChart should exist".PadRight(90) { + ${Alias:New-ExcelChart} | Should -Not -BeNullOrEmpty + } + +} \ No newline at end of file diff --git a/__tests__/Get-ExcelColumnName.Test.ps1 b/__tests__/Get-ExcelColumnName.Test.ps1 new file mode 100644 index 00000000..ed3bc9e8 --- /dev/null +++ b/__tests__/Get-ExcelColumnName.Test.ps1 @@ -0,0 +1,29 @@ +$map = @{ + 1024 = 'AMJ' + 2048 = 'BZT' + 3072 = 'DND' + 4096 = 'FAN' + 5120 = 'GNX' + 6144 = 'IBH' + 7168 = 'JOR' + 8192 = 'LCB' + 9216 = 'MPL' + 10240 = 'OCV' + 11264 = 'PQF' + 12288 = 'RDP' + 13312 = 'SQZ' + 14336 = 'UEJ' + 15360 = 'VRT' + 16384 = 'XFD' +} + +(Get-ExcelColumnName 26).columnName | Should -Be 'Z' +(Get-ExcelColumnName 27).columnName | Should -Be 'AA' +(Get-ExcelColumnName 28).columnName | Should -Be 'AB' +(Get-ExcelColumnName 30).columnName | Should -Be 'AD' +(Get-ExcelColumnName 48).columnName | Should -Be 'AV' + +1..16 | ForEach-Object { + $number = $_ * 1024 + (Get-ExcelColumnName $number).columnName | Should -Be $map.$number +} diff --git a/__tests__/Get-ExcelFileSchema.tests.ps1 b/__tests__/Get-ExcelFileSchema.tests.ps1 new file mode 100644 index 00000000..c5ca5d81 --- /dev/null +++ b/__tests__/Get-ExcelFileSchema.tests.ps1 @@ -0,0 +1,54 @@ +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +Describe "Test getting the schema of an Excel file" -Tag GetExcelFileSchema { + + BeforeAll { + $script:excelFile = "TestDrive:\test.xlsx" + $data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + $data | Export-Excel $excelFile + } + + It "Test Get-ExcelFileSchema function exists" { + $function = Get-Command Get-ExcelFileSchema -ErrorAction SilentlyContinue + $function | Should -Not -Be $null + } + + It "Test Get-ExcelFileSchema returns json" { + $actual = Get-ExcelFileSchema -Path $excelFile + $actual | Should -Not -Be $null + $actual | Should -BeOfType [string] + } + + It "Test Get-ExcelFileSchema correct json" { + $actual = Get-ExcelFileSchema -Path $excelFile + $actual = $actual | ConvertFrom-Json + + $actual.ExcelFile | Should -BeExactly "test.xlsx" + $actual.WorksheetName | Should -BeExactly "Sheet1" + $actual.Visible | Should -Be $true + $actual.Rows | Should -Be 10 + $actual.Columns | Should -Be 4 + $actual.Address | Should -BeExactly "A1:D10" + + $actual.Path | Should -BeExactly ("TestDrive:" + [System.IO.Path]::DirectorySeparatorChar) + + $actual.PropertyNames.Count | Should -Be 4 + $actual.PropertyNames[0] | Should -BeExactly "Region" + $actual.PropertyNames[1] | Should -BeExactly "State" + $actual.PropertyNames[2] | Should -BeExactly "Units" + $actual.PropertyNames[3] | Should -BeExactly "Price" + } +} \ No newline at end of file diff --git a/__tests__/Get-ExcelFileSummary.Tests.ps1 b/__tests__/Get-ExcelFileSummary.Tests.ps1 new file mode 100644 index 00000000..b6e2edb7 --- /dev/null +++ b/__tests__/Get-ExcelFileSummary.Tests.ps1 @@ -0,0 +1,52 @@ +#Requires -Modules Pester +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Only executes on versions without the automatic variable')] +param() + +Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force + +Describe 'All tests for Get-ExcelFileSummary' -Tag "Get-ExcelFileSummary" { + Context "Test Get-ExcelFileSummary" { + It "Tests summary on TestData2.xlsx" { + $actual = Get-ExcelFileSummary "$PSScriptRoot\ImportExcelTests\TestData1.xlsx" + + $actual.ExcelFile | Should -BeExactly 'TestData1.xlsx' + $actual.WorksheetName | Should -BeExactly 'Sheet1' + $actual.Visible | Should -BeTrue + $actual.Rows | Should -Be 3 + $actual.Columns | Should -Be 2 + $actual.Address | Should -BeExactly 'A1:B3' + $actual.Path | Should -Not -BeNullOrEmpty + } + + It "Tests summary on xlsx with multiple sheets" { + + $actual = Get-ExcelFileSummary "$PSScriptRoot\ImportExcelTests\MultipleSheets.xlsx" + + $actual[0].ExcelFile | Should -BeExactly 'MultipleSheets.xlsx' + $actual[0].WorksheetName | Should -BeExactly 'Sheet1' + $actual[0].Visible | Should -BeTrue + $actual[0].Rows | Should -Be 1 + $actual[0].Columns | Should -Be 4 + $actual[0].Address | Should -BeExactly 'A1:D1' + $actual[0].Path | Should -Not -BeNullOrEmpty + + $actual[1].ExcelFile | Should -BeExactly 'MultipleSheets.xlsx' + $actual[1].WorksheetName | Should -BeExactly 'Sheet2' + $actual[1].Visible | Should -BeTrue + $actual[1].Rows | Should -Be 2 + $actual[1].Columns | Should -Be 2 + $actual[1].Address | Should -BeExactly 'A1:B2' + $actual[1].Path | Should -Not -BeNullOrEmpty + } + + It "Tests if sheet is hidden or not" { + $actual = Get-ExcelFileSummary "$PSScriptRoot\ImportExcelTests\SheetVisibleTesting.xlsx" + + $actual[0].Visible | Should -BeTrue + $actual[1].Visible | Should -BeFalse + $actual[2].Visible | Should -BeTrue + $actual[3].Visible | Should -BeFalse + } + } +} diff --git a/__tests__/ImportExcelHeaderName.tests.ps1 b/__tests__/ImportExcelHeaderName.tests.ps1 new file mode 100644 index 00000000..48d85721 --- /dev/null +++ b/__tests__/ImportExcelHeaderName.tests.ps1 @@ -0,0 +1,400 @@ +#Requires -Modules Pester + +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +Describe "Import-Excel on a sheet with no headings" { + BeforeAll { + + $xlfile = "$PSScriptRoot\testImportExcel.xlsx" + $xlfileHeaderOnly = "$PSScriptRoot\testImportExcelHeaderOnly.xlsx" + $xlfileImportColumns = "$PSScriptRoot\testImportExcelImportColumns.xlsx" + + # Create $xlfile if it does not exist + if (!(Test-Path -Path $xlfile)) { + $xl = "" | Export-excel $xlfile -PassThru + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C' + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A2 -Value 'D' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B2 -Value 'E' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C2 -Value 'F' + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A3 -Value 'G' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B3 -Value 'H' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C3 -Value 'I' + + Close-ExcelPackage $xl + } + + # Create $xlfileHeaderOnly if it does not exist + if (!(Test-Path -Path $xlfileHeaderOnly)) { + $xl = "" | Export-excel $xlfileHeaderOnly -PassThru + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C' + + Close-ExcelPackage $xl + } + + # Create $xlfileImportColumns if it does not exist + if (!(Test-Path -Path $xlfileImportColumns)) { + $xl = "" | Export-Excel $xlfileImportColumns -PassThru + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range D1 -Value 'D' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range E1 -Value 'E' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range F1 -Value 'F' + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A2 -Value '1' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B2 -Value '2' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C2 -Value '3' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range D2 -Value '4' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range E2 -Value '5' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range F2 -Value '6' + + Close-ExcelPackage $xl + } + } + + AfterAll { + Remove-Item $PSScriptRoot\testImportExcelSparse.xlsx -ErrorAction SilentlyContinue + } + + It "Import-Excel should have this shape" { + $actual = @(Import-Excel $xlfile) + + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'A' + $actualNames[1] | Should -BeExactly 'B' + $actualNames[2] | Should -BeExactly 'C' + + $actual.Count | Should -Be 2 + $actual[0].A | Should -BeExactly 'D' + $actual[0].B | Should -BeExactly 'E' + $actual[0].C | Should -BeExactly 'F' + } + + It "Import-Excel -NoHeader should have this shape" { + $actual = @(Import-Excel $xlfile -NoHeader) + + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'P1' + $actualNames[1] | Should -BeExactly 'P2' + $actualNames[2] | Should -BeExactly 'P3' + + $actual.Count | Should -Be 3 + } + + It "Import-Excel -HeaderName should have this shape" { + $actual = @(Import-Excel $xlfile -HeaderName 'Q', 'R', 'S') + + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'Q' + $actualNames[1] | Should -BeExactly 'R' + $actualNames[2] | Should -BeExactly 'S' + + $actual.Count | Should -Be 3 + + $actual[0].Q | Should -BeExactly 'A' + $actual[0].R | Should -BeExactly 'B' + $actual[0].S | Should -BeExactly 'C' + + $actual[1].Q | Should -BeExactly 'D' + $actual[1].R | Should -BeExactly 'E' + $actual[1].S | Should -BeExactly 'F' + } + + It "Should work with StartRow" { + $actual = @(Import-Excel $xlfile -HeaderName 'Q', 'R', 'S' -startrow 2) + + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'Q' + $actualNames[1] | Should -BeExactly 'R' + $actualNames[2] | Should -BeExactly 'S' + + $actual.Count | Should -Be 2 + + $actual[0].Q | Should -BeExactly 'D' + $actual[0].R | Should -BeExactly 'E' + $actual[0].S | Should -BeExactly 'F' + + $actual[1].Q | Should -BeExactly 'G' + $actual[1].R | Should -BeExactly 'H' + $actual[1].S | Should -BeExactly 'I' + + } + + It "Should work with -NoHeader" { + $actual = @(Import-Excel $xlfile -NoHeader) + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'P1' + $actualNames[1] | Should -BeExactly 'P2' + $actualNames[2] | Should -BeExactly 'P3' + + $actual.Count | Should -Be 3 + + $actual[0].P1 | Should -BeExactly 'A' + $actual[0].P2 | Should -BeExactly 'B' + $actual[0].P3 | Should -BeExactly 'C' + + $actual[1].P1 | Should -BeExactly 'D' + $actual[1].P2 | Should -BeExactly 'E' + $actual[1].P3 | Should -BeExactly 'F' + + $actual[2].P1 | Should -BeExactly 'G' + $actual[2].P2 | Should -BeExactly 'H' + $actual[2].P3 | Should -BeExactly 'I' + } + + It "Should work with -NoHeader -DataOnly" { + $actual = @(Import-Excel $xlfile -NoHeader -DataOnly) + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'P1' + $actualNames[1] | Should -BeExactly 'P2' + $actualNames[2] | Should -BeExactly 'P3' + + $actual.Count | Should -Be 3 + + $actual[0].P1 | Should -BeExactly 'A' + $actual[0].P2 | Should -BeExactly 'B' + $actual[0].P3 | Should -BeExactly 'C' + + $actual[1].P1 | Should -BeExactly 'D' + $actual[1].P2 | Should -BeExactly 'E' + $actual[1].P3 | Should -BeExactly 'F' + + $actual[2].P1 | Should -BeExactly 'G' + $actual[2].P2 | Should -BeExactly 'H' + $actual[2].P3 | Should -BeExactly 'I' + } + + It "Should work with -HeaderName -DataOnly -StartRow" { + $actual = @(Import-Excel $xlfile -HeaderName 'Q', 'R', 'S' -DataOnly -StartRow 2) + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'Q' + $actualNames[1] | Should -BeExactly 'R' + $actualNames[2] | Should -BeExactly 'S' + + $actual.Count | Should -Be 1 + + $actual[0].Q | Should -BeExactly 'G' + $actual[0].R | Should -BeExactly 'H' + $actual[0].S | Should -BeExactly 'I' + } + + It "Should" { + $xlfile = "$PSScriptRoot\testImportExcelSparse.xlsx" + $xl = "" | Export-excel $xlfile -PassThru + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'Chuck' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value '' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'Norris' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range D1 -Value 'California' + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A2 -Value '' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B2 -Value '' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C2 -Value '' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range D2 -Value '' + + Set-ExcelRange -Worksheet $xl.Sheet1 -Range A3 -Value 'Jean-Claude' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range B3 -Value '' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range C3 -Value 'Vandamme' + Set-ExcelRange -Worksheet $xl.Sheet1 -Range D3 -Value 'Brussels' + + Close-ExcelPackage $xl + + $actual = @(Import-Excel -Path $xlfile -DataOnly -HeaderName 'FirstName', 'SecondName', 'City' -StartRow 2) + $actualNames = $actual[0].psobject.properties.name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -BeExactly 'FirstName' + $actualNames[1] | Should -BeExactly 'SecondName' + $actualNames[2] | Should -BeExactly 'City' + + $actual.Count | Should -Be 1 + + Remove-Item $xlfile + # Looks like -DataOnly does not handle empty columns + # $actual[0].FirstName | Should -BeExactly 'Jean-Claude' + # $actual[0].SecondName | Should -BeExactly 'Vandamme' + # $actual[0].City | Should -BeExactly 'Brussels' + } + + It "Should handle data correctly if there is only a single row" { + $actual = Import-Excel $xlfileHeaderOnly -WarningAction SilentlyContinue + $names = $actual.psobject.properties.Name + $names | Should -Be $null + $actual.Count | Should -Be 0 + } + + It "Should handle data correctly if there is only a single row and using -NoHeader " { + $actual = @(Import-Excel $xlfileHeaderOnly -WorksheetName Sheet1 -NoHeader) + + $names = $actual[0].psobject.properties.Name + $names.count | Should -Be 3 + $names[0] | Should -Be 'P1' + $names[1] | Should -Be 'P2' + $names[2] | Should -Be 'P3' + + $actual.Count | Should -Be 1 + $actual[0].P1 | Should -Be 'A' + $actual[0].P2 | Should -Be 'B' + $actual[0].P3 | Should -Be 'C' + } + + It "Should import correct data if -ImportColumns is used with the first column" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(1,2,4,5)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 4 + $actualNames[0] | Should -Be 'A' + $actualNames[2] | Should -Be 'D' + + $actual.Count | Should -Be 1 + $actual[0].A | Should -Be 1 + $actual[0].B | Should -Be 2 + $actual[0].D | Should -Be 4 + $actual[0].E | Should -Be 5 + } + + It "Should import correct data if -ImportColumns is used with the first column" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(1,3,4,5)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 4 + $actualNames[0] | Should -Be 'A' + $actualNames[2] | Should -Be 'D' + + $actual.Count | Should -Be 1 + $actual[0].A | Should -Be 1 + $actual[0].C | Should -Be 3 + $actual[0].D | Should -Be 4 + $actual[0].E | Should -Be 5 + } + + It "Should import correct data if -ImportColumns is used without the first column" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(2,3,6)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -Be 'B' + $actualNames[2] | Should -Be 'F' + + $actual.Count | Should -Be 1 + $actual[0].B | Should -Be 2 + $actual[0].C | Should -Be 3 + $actual[0].F | Should -Be 6 + } + + It "Should import correct data if -ImportColumns is used without the first column" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(2,5,6)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -Be 'B' + $actualNames[2] | Should -Be 'F' + + $actual.Count | Should -Be 1 + $actual[0].B | Should -Be 2 + $actual[0].E | Should -Be 5 + $actual[0].F | Should -Be 6 + } + + It "Should import correct data if -ImportColumns is used with only 1 column" { + $actual = @(Import-Excel $xlfile -ImportColumns @(2)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 1 + $actualNames[0] | Should -Be 'B' + + $actual.Count | Should -Be 2 + $actual[0].B | Should -Be 'E' + } + + It "Should import correct data if -ImportColumns is used with only 1 column which is also the last" { + $actual = @(Import-Excel $xlfile -ImportColumns @(3)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 1 + $actualNames[0] | Should -Be 'C' + + $actual.Count | Should -Be 2 + $actual[1].C | Should -Be 'I' + } + + It "Should import correct data if -ImportColumns contains all columns" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(1,2,3,4,5,6)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 6 + $actualNames[0] | Should -Be 'A' + $actualNames[2] | Should -Be 'C' + + $actual.Count | Should -Be 1 + $actual[0].A | Should -Be 1 + $actual[0].B | Should -Be 2 + $actual[0].C | Should -Be 3 + $actual[0].D | Should -Be 4 + $actual[0].E | Should -Be 5 + $actual[0].F | Should -Be 6 + } + + It "Should ignore -StartColumn and -EndColumn if -ImportColumns is set aswell" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(5) -StartColumn 2 -EndColumn 7) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 1 + $actualNames[0] | Should -Be 'E' + + $actual[0].E | Should -Be '5' + } + + It "Should arrange the columns if -ImportColumns is not in order" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(5,1,4)) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -Be 'E' + $actualNames[1] | Should -Be 'A' + $actualNames[2] | Should -Be 'D' + + $actual[0].E | Should -Be '5' + $actual[0].A | Should -Be '1' + $actual[0].D | Should -Be '4' + } + + It "Should arrange the columns if -ImportColumns is not in order and -NoHeader is used" { + $actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(5,1,4) -NoHeader -StartRow 2) + $actualNames = $actual[0].psobject.properties.Name + + $actualNames.Count | Should -Be 3 + $actualNames[0] | Should -Be 'P1' + $actualNames[1] | Should -Be 'P2' + $actualNames[2] | Should -Be 'P3' + + $actual[0].P1 | Should -Be '5' + $actual[0].P2 | Should -Be '1' + $actual[0].P3 | Should -Be '4' + } +} \ No newline at end of file diff --git a/__tests__/ImportExcelTests/DataInDiffRowCol.xlsx b/__tests__/ImportExcelTests/DataInDiffRowCol.xlsx new file mode 100644 index 00000000..f09b5b7d Binary files /dev/null and b/__tests__/ImportExcelTests/DataInDiffRowCol.xlsx differ diff --git a/__tests__/ImportExcelTests/DataInDiffRowColMultipleSheets.xlsx b/__tests__/ImportExcelTests/DataInDiffRowColMultipleSheets.xlsx new file mode 100644 index 00000000..cc3eaff5 Binary files /dev/null and b/__tests__/ImportExcelTests/DataInDiffRowColMultipleSheets.xlsx differ diff --git a/__tests__/ImportExcelTests/ImportExcelEndRowEndColumn.tests.ps1 b/__tests__/ImportExcelTests/ImportExcelEndRowEndColumn.tests.ps1 new file mode 100644 index 00000000..779571d4 --- /dev/null +++ b/__tests__/ImportExcelTests/ImportExcelEndRowEndColumn.tests.ps1 @@ -0,0 +1,57 @@ +Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +Describe 'Test' -Tag ImportExcelEndRowAndCols { + BeforeAll { + $script:xlFilename = "$PSScriptRoot\DataInDiffRowCol.xlsx" + } + + Context 'Test reading a partial sheet' { + It 'Should read 2 rows and first 3 columns' { + $actual = Import-Excel $xlFilename -StartRow 5 -EndRow 7 -StartColumn 3 -EndColumn 5 + + # $actual | out-host + $actual.Count | Should -Be 2 + + $colNames = $actual[0].psobject.properties.Name + $colNames.Count | Should -Be 3 + + $colNames[0] | Should -Be 'Region' + $colNames[1] | Should -Be 'State' + $colNames[2] | Should -Be 'Units' + } + + It 'Should read second 2 rows and last 2 columns' { + $actual = Import-Excel $xlFilename -StartRow 8 -EndRow 9 -StartColumn 5 -EndColumn 6 -HeaderName 'Units', 'Price' + + # $actual | out-host + $actual.Count | Should -Be 2 + + $colNames = $actual[0].psobject.properties.Name + $colNames.Count | Should -Be 2 + + $colNames[0] | Should -Be 'Units' + $colNames[1] | Should -Be 'Price' + } + + It 'Should read any row up to maximum allowed row' { + $xlMaxRows = "$PSScriptRoot\MaxRows.xlsx" + $actual = Import-Excel $xlMaxRows -StartRow 1048576 -EndRow 1048576 -NoHeader + $actual.P1 | Should -Be 1048576 + } + } + + Context 'Test reading multiple sheets with data in differnt rows and columns' { + It 'Should read 2 sheets same StartRow different dimensions' { + $xlFilename = "$PSScriptRoot\DataInDiffRowColMultipleSheets.xlsx" + + $actual = Import-Excel $xlFilename -StartRow 5 -WorksheetName * + + $actual.Keys.Count | Should -Be 2 + $actual.Contains('Sheet1') | Should -BeTrue + $actual.Contains('Sheet2') | Should -BeTrue + + $actual['Sheet1'].Count | Should -Be 9 + $actual['Sheet2'].Count | Should -Be 12 + } + } +} \ No newline at end of file diff --git a/__tests__/ImportExcelTests/ImportExcelReadSheets.tests.ps1 b/__tests__/ImportExcelTests/ImportExcelReadSheets.tests.ps1 new file mode 100644 index 00000000..1b8dfad9 --- /dev/null +++ b/__tests__/ImportExcelTests/ImportExcelReadSheets.tests.ps1 @@ -0,0 +1,82 @@ +#Requires -Modules Pester +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +param() + +Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +Describe 'Different ways to import sheets' -Tag ImportExcelReadSheets { + BeforeAll { + $xlFilename = "$PSScriptRoot\yearlySales.xlsx" + } + + Context 'Test reading sheets' { + It 'Should read one sheet' { + $actual = Import-Excel $xlFilename + + $actual.Count | Should -Be 100 + $actual[0].Month | Should -BeExactly "April" + $actual[99].Month | Should -BeExactly "April" + } + + It 'Should read two sheets' { + $actual = Import-Excel $xlFilename march, june + + $actual.keys.Count | Should -Be 2 + $actual["March"].Count | Should -Be 100 + $actual["June"].Count | Should -Be 100 + } + + It 'Should read all the sheets' { + $actual = Import-Excel $xlFilename * + + $actual.keys.Count | Should -Be 12 + + $actual["January"].Count | Should -Be 100 + $actual["February"].Count | Should -Be 100 + $actual["March"].Count | Should -Be 100 + $actual["April"].Count | Should -Be 100 + $actual["May"].Count | Should -Be 100 + $actual["June"].Count | Should -Be 100 + $actual["July"].Count | Should -Be 100 + $actual["August"].Count | Should -Be 100 + $actual["September"].Count | Should -Be 100 + $actual["October"].Count | Should -Be 100 + $actual["November"].Count | Should -Be 100 + $actual["December"].Count | Should -Be 100 + } + + It 'Should throw if it cannot find the sheet' { + { Import-Excel $xlFilename april, june, notthere } | Should -Throw + } + + It 'Should return an array not a dictionary' { + $actual = Import-Excel $xlFilename april, june -Raw + + $actual.Count | Should -Be 200 + $group = $actual | Group-Object month -NoElement + + $group.Count | Should -Be 2 + $group[0].Name | Should -BeExactly 'April' + $group[1].Name | Should -BeExactly 'June' + } + + It "Should read multiple sheets with diff number of rows correctly" { + $xlFilename = "$PSScriptRoot\construction.xlsx" + + $actual = Import-Excel $xlFilename 2015, 2016 + $actual.keys.Count | Should -Be 2 + + $actual["2015"].Count | Should -Be 12 + $actual["2016"].Count | Should -Be 1 + } + + It "Should read multiple sheets with diff number of rows correctly and flatten it" { + $xlFilename = "$PSScriptRoot\construction.xlsx" + + $actual = Import-Excel $xlFilename 2015, 2016 -Raw + + $actual.Count | Should -Be 13 + } + + } +} \ No newline at end of file diff --git a/UnitTests/ImportExcelTests/LargerFile.xlsx b/__tests__/ImportExcelTests/LargerFile.xlsx similarity index 100% rename from UnitTests/ImportExcelTests/LargerFile.xlsx rename to __tests__/ImportExcelTests/LargerFile.xlsx diff --git a/__tests__/ImportExcelTests/MaxRows.xlsx b/__tests__/ImportExcelTests/MaxRows.xlsx new file mode 100644 index 00000000..e671240e Binary files /dev/null and b/__tests__/ImportExcelTests/MaxRows.xlsx differ diff --git a/__tests__/ImportExcelTests/MultipleSheets.xlsx b/__tests__/ImportExcelTests/MultipleSheets.xlsx new file mode 100644 index 00000000..7b8d43b8 Binary files /dev/null and b/__tests__/ImportExcelTests/MultipleSheets.xlsx differ diff --git a/__tests__/ImportExcelTests/ReadMultipleXLSXFiles.tests.ps1 b/__tests__/ImportExcelTests/ReadMultipleXLSXFiles.tests.ps1 new file mode 100644 index 00000000..27ff8416 --- /dev/null +++ b/__tests__/ImportExcelTests/ReadMultipleXLSXFiles.tests.ps1 @@ -0,0 +1,57 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +Param() + +Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +Describe "Test reading multiple XLSX files of different row count" -Tag ReadMultipleXLSX { + It "Should find these xlsx files" { + Test-Path -Path $PSScriptRoot\rows05.xlsx | Should -BeTrue + Test-Path -Path $PSScriptRoot\rows10.xlsx | Should -BeTrue + } + + It "Should find two xlsx files" { + (Get-ChildItem $PSScriptRoot\row*xlsx).Count | Should -Be 2 + } + + It "Should get 5 rows" { + (Import-Excel $PSScriptRoot\rows05.xlsx).Count | Should -Be 5 + } + + It "Should get 10 rows" { + (Import-Excel $PSScriptRoot\rows10.xlsx).Count | Should -Be 10 + } + + It "Should get 15 rows" { + $actual = Get-ChildItem $PSScriptRoot\row*xlsx | Import-Excel + + $actual.Count | Should -Be 15 + } + + It "Should get 4 property names" { + $actual = Get-ChildItem $PSScriptRoot\row*xlsx | Import-Excel + + $names = $actual[0].psobject.properties.name + $names.Count | Should -Be 4 + + $names[0] | Should -BeExactly "Region" + $names[1] | Should -BeExactly "State" + $names[2] | Should -BeExactly "Units" + $names[3] | Should -BeExactly "Price" + } + + It "Should have the correct data" { + $actual = Get-ChildItem $PSScriptRoot\row*xlsx | Import-Excel + + # rows05.xlsx + $actual[0].Region | Should -BeExactly "South" + $actual[0].Price | Should -Be 181.52 + $actual[4].Region | Should -BeExactly "West" + $actual[4].Price | Should -Be 216.56 + + # rows10.xlsx + $actual[5].Region | Should -BeExactly "South" + $actual[5].Price | Should -Be 199.85 + $actual[14].Region | Should -BeExactly "East" + $actual[14].Price | Should -Be 965.25 + } +} \ No newline at end of file diff --git a/__tests__/ImportExcelTests/SheetVisibleTesting.xlsx b/__tests__/ImportExcelTests/SheetVisibleTesting.xlsx new file mode 100644 index 00000000..72509079 Binary files /dev/null and b/__tests__/ImportExcelTests/SheetVisibleTesting.xlsx differ diff --git a/__tests__/ImportExcelTests/Simple.tests.ps1 b/__tests__/ImportExcelTests/Simple.tests.ps1 new file mode 100644 index 00000000..949889be --- /dev/null +++ b/__tests__/ImportExcelTests/Simple.tests.ps1 @@ -0,0 +1,69 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')] +Param() + +Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +Describe "Tests" { + BeforeAll { + $data = $null + $timer = Measure-Command { + $data = Import-Excel $PSScriptRoot\Simple.xlsx + } + } + It "Should have a valid manifest".PadRight(90){ + {try {Test-ModuleManifest -Path $PSScriptRoot\..\..\ImportExcel.psd1 -ErrorAction stop} + catch {throw} } | Should -Not -Throw + } + It "Should have two items in the imported simple data".PadRight(90) { + $data.count | Should -Be 2 + } + + It "Should have items a and b in the imported simple data".PadRight(90) { + $data[0].p1 | Should -Be "a" + $data[1].p1 | Should -Be "b" + } + + It "Should read the simple xlsx in < 2100 milliseconds".PadRight(90) { + $timer.TotalMilliseconds | Should -BeLessThan 2100 + } + + It "Should read larger xlsx, 4k rows 1 col < 3000 milliseconds".PadRight(90) { + $timer = Measure-Command { + $null = Import-Excel $PSScriptRoot\LargerFile.xlsx + } + + $timer.TotalMilliseconds | Should -BeLessThan 3000 + } + + It "Should be able to open, read and close as seperate actions".PadRight(90) { + $timer = Measure-Command { + $excel = Open-ExcelPackage $PSScriptRoot\Simple.xlsx + $data = Import-Excel -ExcelPackage $excel + Close-ExcelPackage -ExcelPackage $excel -NoSave} + $timer.TotalMilliseconds | Should -BeLessThan 2100 + $data.count | Should -Be 2 + $data[0].p1 | Should -Be "a" + $data[1].p1 | Should -Be "b" + } + + It "Should take Paths from parameter".PadRight(90) { + $data = Import-Excel -Path (Get-ChildItem -Path $PSScriptRoot -Filter "TestData?.xlsx").FullName + $data.count | Should -Be 4 + $data[0].cola | Should -Be 1 + $data[2].cola | Should -Be 5 + } + + It "Should take Paths from pipeline".PadRight(90) { + $data = (Get-ChildItem -Path $PSScriptRoot -Filter "TestData?.xlsx").FullName | Import-Excel + $data.count | Should -Be 4 + $data[0].cola | Should -Be 1 + $data[2].cola | Should -Be 5 + } + + It "Should support PipelineVariable".PadRight(90) { + $data = Import-Excel $PSScriptRoot\Simple.xlsx -PipelineVariable 'Pv' | ForEach-Object { $Pv.p1 } + $data.count | Should -Be 2 + $data[0] | Should -Be "a" + $data[1] | Should -Be "b" + } +} \ No newline at end of file diff --git a/UnitTests/ImportExcelTests/Simple.xlsx b/__tests__/ImportExcelTests/Simple.xlsx similarity index 100% rename from UnitTests/ImportExcelTests/Simple.xlsx rename to __tests__/ImportExcelTests/Simple.xlsx diff --git a/__tests__/ImportExcelTests/TestData1.xlsx b/__tests__/ImportExcelTests/TestData1.xlsx new file mode 100644 index 00000000..7f554adb Binary files /dev/null and b/__tests__/ImportExcelTests/TestData1.xlsx differ diff --git a/__tests__/ImportExcelTests/TestData2.xlsx b/__tests__/ImportExcelTests/TestData2.xlsx new file mode 100644 index 00000000..fd799670 Binary files /dev/null and b/__tests__/ImportExcelTests/TestData2.xlsx differ diff --git a/__tests__/ImportExcelTests/TestImportOnly.tests.ps1 b/__tests__/ImportExcelTests/TestImportOnly.tests.ps1 new file mode 100644 index 00000000..c0a1387e --- /dev/null +++ b/__tests__/ImportExcelTests/TestImportOnly.tests.ps1 @@ -0,0 +1,6 @@ +Param() +Describe "Module" -Tag "TestImportOnly" { + It "Should import without error" { + { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force -ErrorAction Stop } | Should -Not -Throw + } +} diff --git a/__tests__/ImportExcelTests/construction.xlsx b/__tests__/ImportExcelTests/construction.xlsx new file mode 100644 index 00000000..befd778d Binary files /dev/null and b/__tests__/ImportExcelTests/construction.xlsx differ diff --git a/__tests__/ImportExcelTests/rows05.xlsx b/__tests__/ImportExcelTests/rows05.xlsx new file mode 100644 index 00000000..3f54f30c Binary files /dev/null and b/__tests__/ImportExcelTests/rows05.xlsx differ diff --git a/__tests__/ImportExcelTests/rows10.xlsx b/__tests__/ImportExcelTests/rows10.xlsx new file mode 100644 index 00000000..0ca23b91 Binary files /dev/null and b/__tests__/ImportExcelTests/rows10.xlsx differ diff --git a/__tests__/ImportExcelTests/yearlySales.xlsx b/__tests__/ImportExcelTests/yearlySales.xlsx new file mode 100644 index 00000000..d30993a1 Binary files /dev/null and b/__tests__/ImportExcelTests/yearlySales.xlsx differ diff --git a/__tests__/InputItemParameter.tests.ps1 b/__tests__/InputItemParameter.tests.ps1 new file mode 100644 index 00000000..35d3b9b3 --- /dev/null +++ b/__tests__/InputItemParameter.tests.ps1 @@ -0,0 +1,192 @@ +# [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')] +# Param() +# Describe "Exporting with -Inputobject, table handling, Send-SQL-Data. Checking Import -asText" { +# BeforeAll { +# $path = "TestDrive:\Results.xlsx" +# $path2 = "TestDrive:\Results2.xlsx" +# Remove-Item -Path $path,$path2 -ErrorAction SilentlyContinue +# if (Test-path "$PSScriptRoot\Samples\Samples.ps1") {. "$PSScriptRoot\Samples\Samples.ps1"} +# $results = ((Get-Process) + (Get-Process -id $PID)) | Select-Object -last 10 -Property Name, cpu, pm, handles, StartTime +# $DataTable = [System.Data.DataTable]::new('Test') +# $null = $DataTable.Columns.Add('Name') +# $null = $DataTable.Columns.Add('CPU', [double]) +# $null = $DataTable.Columns.Add('PM', [Long]) +# $null = $DataTable.Columns.Add('Handles', [Int]) +# $null = $DataTable.Columns.Add('StartTime', [DateTime]) +# Send-SQLDataToExcel -path $path -DataTable $DataTable -WorkSheetname Sheet4 -force -TableName "Data" -WarningVariable WVOne -WarningAction SilentlyContinue +# Send-SQLDataToExcel -path $path -DataTable ([System.Data.DataTable]::new('Test2')) -WorkSheetname Sheet5 -force -WarningVariable wvTwo -WarningAction SilentlyContinue +# foreach ($r in $results) { +# $null = $DataTable.Rows.Add($r.name, $r.CPU, $R.PM, $r.Handles, $r.StartTime) +# } +# $NowPkg = Export-Excel -InputObject $DataTable -PassThru +# $NowPath1 = $NowPkg.File.FullName +# Close-ExcelPackage $NowPkg +# $NowPkg = Export-Excel -InputObject $DataTable -PassThru -table:$false +# $NowPath2 = $NowPkg.File.FullName +# Close-ExcelPackage $NowPkg +# Export-Excel -Path $path -InputObject $results -WorksheetName Sheet1 -RangeName "Whole" +# Export-Excel -Path $path -InputObject $DataTable -WorksheetName Sheet2 -AutoNameRange +# Send-SQLDataToExcel -path $path -DataTable $DataTable -WorkSheetname Sheet3 -TableName "Data" -WarningVariable WVThree -WarningAction SilentlyContinue + +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet1 -Append +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet1 -Append + +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet2 -Append -TableName "FirstLot" -TableStyle light7 +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet2 -Append + +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet3 -Append +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet3 -Append -TableName "SecondLot" + +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet4 -Append +# Send-SQLDataToExcel -Path $path2 -DataTable $DataTable -WorksheetName Sheet4 -Append -TableStyle Dark5 + + +# $excel = Open-ExcelPackage $path +# $sheet = $excel.Sheet1 +# } +# Context "Array of processes" { +# it "Put the correct rows and columns into the sheet " { +# $sheet.Dimension.Rows | Should -Be ($results.Count + 1) +# $sheet.Dimension.Columns | Should -Be 5 +# $sheet.cells["A1"].Value | Should -Be "Name" +# $sheet.cells["E1"].Value | Should -Be "StartTime" +# $sheet.cells["A3"].Value | Should -Be $results[1].Name +# } +# it "Created a range for the whole sheet " { +# $sheet.Names[0].Name | Should -Be "Whole" +# $sheet.Names[0].Start.Address | Should -Be "A1" +# $sheet.Names[0].End.row | Should -Be ($results.Count + 1) +# $sheet.Names[0].End.Column | Should -Be 5 +# } +# it "Formatted date fields with date type " { +# $sheet.Cells["E11"].Style.Numberformat.NumFmtID | Should -Be 22 +# } +# } +# $sheet = $excel.Sheet2 +# Context "Table of processes" { +# it "Put the correct rows and columns into the sheet " { +# $sheet.Dimension.Rows | Should -Be ($results.Count + 1) +# $sheet.Dimension.Columns | Should -Be 5 +# $sheet.cells["A1"].Value | Should -Be "Name" +# $sheet.cells["E1"].Value | Should -Be "StartTime" +# $sheet.cells["A3"].Value | Should -Be $results[1].Name +# } +# it "Created named ranges for each column " { +# $sheet.Names.count | Should -Be 5 +# $sheet.Names[0].Name | Should -Be "Name" +# $sheet.Names[1].Start.Address | Should -Be "B2" +# $sheet.Names[2].End.row | Should -Be ($results.Count + 1) +# $sheet.Names[3].End.Column | Should -Be 4 +# $sheet.Names[4].Start.Column | Should -Be 5 +# } +# it "Formatted date fields with date type " { +# $sheet.Cells["E11"].Style.Numberformat.NumFmtID | Should -Be 22 +# } +# } + +# Context "'Now' Mode behavior" { +# $NowPkg = Open-ExcelPackage $NowPath1 +# $sheet = $NowPkg.Sheet1 +# it "Formatted data as a table by default " { +# $sheet.Tables.Count | Should -Be 1 +# } +# Close-ExcelPackage -NoSave $NowPkg +# Remove-Item $NowPath1 +# $NowPkg = Open-ExcelPackage $NowPath2 +# $sheet = $NowPkg.Sheet1 +# it "Did not data as a table when table:`$false was used " { +# $sheet.Tables.Count | Should -Be 0 +# } +# Close-ExcelPackage -NoSave $NowPkg +# Remove-Item $NowPath2 +# } +# $sheet = $excel.Sheet3 +# Context "Table of processes via Send-SQLDataToExcel" { +# it "Put the correct data rows and columns into the sheet " { +# $sheet.Dimension.Rows | Should -Be ($results.Count + 1) +# $sheet.Dimension.Columns | Should -Be 5 +# $sheet.cells["A1"].Value | Should -Be "Name" +# $sheet.cells["E1"].Value | Should -Be "StartTime" +# $sheet.cells["A3"].Value | Should -Be $results[1].Name +# } +# it "Created a table " { +# $sheet.Tables.count | Should -Be 1 +# $sheet.Tables[0].Columns[4].name | Should -Be "StartTime" +# } +# it "Formatted date fields with date type " { +# $sheet.Cells["E11"].Style.Numberformat.NumFmtID | Should -Be 22 +# } +# it "Handled two data tables with the same name " { +# $sheet.Tables[0].Name | Should -Be "Data_" +# $wvThree[0] | Should -Match "is not unique" +# } +# } +# $Sheet = $excel.Sheet4 +# Context "Zero-row Data Table sent with Send-SQLDataToExcel -Force" { +# it "Raised a warning and put the correct data headers into the sheet " { +# $sheet.Dimension.Rows | Should -Be 1 +# $sheet.Dimension.Columns | Should -Be 5 +# $sheet.cells["A1"].Value | Should -Be "Name" +# $sheet.cells["E1"].Value | Should -Be "StartTime" +# $sheet.cells["A3"].Value | Should -BeNullOrEmpty +# $wvone[0] | Should -Match "Zero" +# } +# it "Applied table formatting " { +# $sheet.Tables.Count | Should -Be 1 +# $sheet.Tables[0].Name | Should -Be "Data" +# } + + +# } +# $Sheet = $excel.Sheet5 +# Context "Zero-column Data Table handled by Send-SQLDataToExcel -Force" { +# it "Created a blank Sheet and raised a warning " { +# $sheet.Dimension | Should -BeNullOrEmpty +# $wvTwo | Should -Not -BeNullOrEmpty +# } + +# } +# Close-ExcelPackage $excel +# $excel = Open-ExcelPackage $path2 +# Context "Send-SQLDataToExcel -append works correctly" { +# it "Works without table settings " { +# $excel.sheet1.Dimension.Address | Should -Be "A1:E21" +# $excel.sheet1.cells[1,1].value | Should -Be "Name" +# $excel.sheet1.cells[12,1].value | Should -Be $excel.sheet1.cells[2,1].value +# $excel.sheet1.Tables.count | Should -Be 0 +# } +# it "Extends an existing table when appending " { +# $excel.sheet2.Dimension.Address | Should -Be "A1:E21" +# $excel.sheet2.cells[1,2].value | Should -Be "CPU" +# $excel.sheet2.cells[13,2].value | Should -Be $excel.sheet2.cells[3,2].value +# $excel.sheet2.Tables.count | Should -Be 1 +# $excel.sheet2.Tables[0].name | Should -Be "FirstLot" +# $excel.sheet2.Tables[0].StyleName | Should -Be "TableStyleLight7" +# } +# it "Creates a new table by name when appending " { +# $excel.sheet3.cells[1,3].value | Should -Be "PM" +# $excel.sheet3.cells[14,3].value | Should -Be $excel.sheet3.cells[4,3].value +# $excel.sheet3.Tables.count | Should -Be 1 +# $excel.sheet3.Tables[0].name | Should -Be "SecondLot" +# $excel.sheet3.Tables[0].StyleName | Should -Be "TableStyleMedium6" +# } +# it "Creates a new table by style when appending " { +# $excel.sheet4.cells[1,4].value | Should -Be "Handles" +# $excel.sheet4.cells[15,4].value | Should -Be $excel.sheet4.cells[5,4].value +# $excel.sheet4.Tables.count | Should -Be 1 +# $excel.sheet4.Tables[0].name | Should -Be "Table1" +# $excel.sheet4.Tables[0].StyleName | Should -Be "TableStyleDark5" +# } +# } + +# Close-ExcelPackage $excel +# Context "Import As Text returns text values" { +# $x = Import-excel $path -WorksheetName sheet3 -AsText StartTime,hand* | Select-Object -last 1 +# it "Had fields of type string, not date or int, where specified as ASText " { +# $x.Handles.GetType().Name | Should -Be "String" +# $x.StartTime.GetType().Name | Should -Be "String" +# $x.CPU.GetType().Name | Should -Not -Be "String" +# } +# } + +# } \ No newline at end of file diff --git a/__tests__/Join-Worksheet.tests.ps1 b/__tests__/Join-Worksheet.tests.ps1 new file mode 100644 index 00000000..ee3c1b97 --- /dev/null +++ b/__tests__/Join-Worksheet.tests.ps1 @@ -0,0 +1,203 @@ +#Requires -Modules Pester +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +param() +Describe "Join Worksheet part 1" { + BeforeAll { + $data1 = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price,Total + 12001,Nails,37,3.99,147.63 + 12002,Hammer,5,12.10,60.5 + 12003,Saw,12,15.37,184.44 + 12010,Drill,20,8,160 + 12011,Crowbar,7,23.48,164.36 +"@ + $data2 = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price,Total + 12001,Nails,53,3.99,211.47 + 12002,Hammer,6,12.10,72.60 + 12003,Saw,10,15.37,153.70 + 12010,Drill,10,8,80 + 12012,Pliers,2,14.99,29.98 +"@ + $data3 = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price,Total + 12001,Nails,20,3.99,79.80 + 12002,Hammer,2,12.10,24.20 + 12010,Drill,11,8,88 + 12012,Pliers,3,14.99,44.97 +"@ + + . "$PSScriptRoot\Samples\Samples.ps1" + $path = "TestDrive:\test.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + $data1 | Export-Excel -Path $path -WorkSheetname Oxford + $data2 | Export-Excel -Path $path -WorkSheetname Abingdon + $data3 | Export-Excel -Path $path -WorkSheetname Banbury + $ptdef = New-PivotTableDefinition -PivotTableName "SummaryPivot" -PivotRows "Store" -PivotColumns "Product" -PivotData @{"Total" = "SUM" } -IncludePivotChart -ChartTitle "Sales Breakdown" -ChartType ColumnStacked -ChartColumn 10 + Join-Worksheet -Path $path -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "SummaryTable" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2, 1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -TitleBackgroundColor ([System.Drawing.Color]::AliceBlue) -PivotTableDefinition $ptdef + + $excel = Export-Excel -path $path -WorkSheetname SummaryPivot -Activate -NoTotalsInPivot -PivotDataToColumn -HideSheet * -UnHideSheet "Total", "SummaryPivot" -PassThru + # Open-ExcelPackage -Path $path + + $ws = $excel.Workbook.Worksheets["Total"] + $pt = $excel.Workbook.Worksheets["SummaryPivot"].pivottables[0] + $pc = $excel.Workbook.Worksheets["SummaryPivot"].Drawings[0] + } + Context "Export-Excel setting spreadsheet visibility" { + it "Hid the worksheets " { + $excel.Workbook.Worksheets["Oxford"].Hidden | Should -Be 'Hidden' + $excel.Workbook.Worksheets["Banbury"].Hidden | Should -Be 'Hidden' + $excel.Workbook.Worksheets["Abingdon"].Hidden | Should -Be 'Hidden' + } + it "Un-hid two of the worksheets " { + $excel.Workbook.Worksheets["Total"].Hidden | Should -Be 'Visible' + $excel.Workbook.Worksheets["SummaryPivot"].Hidden | Should -Be 'Visible' + } + it "Activated the correct worksheet " { + Set-ItResult -Pending -Because "Bug in EPPLus 4.5" + $excel.Workbook.worksheets["SummaryPivot"].View.TabSelected | Should -Be $true + $excel.Workbook.worksheets["Total"].View.TabSelected | Should -Be $false + } + + } + Context "Merging 3 blocks" { + it "Created sheet of the right size with a title and a table " { + $ws.Dimension.Address | Should -Be "A1:F16" + $ws.Tables[0].Address.Address | Should -Be "A2:F16" + $ws.Cells["A1"].Value | Should -Be "Store Sales Summary" + $ws.Cells["A1"].Style.Font.Size | Should -Be 14 + $ws.Cells["A1"].Style.Font.Bold | Should -Be $True + $ws.Cells["A1"].Style.Fill.BackgroundColor.Rgb | Should -Be "FFF0F8FF" + $ws.Cells["A1"].Style.Fill.PatternType.ToString() | Should -Be "Solid" + $ws.Tables[0].StyleName | Should -Be "TableStyleLight1" + $ws.Cells["A2:F2"].Style.Font.Bold | Should -Be $True + } + it "Added a from column with the right heading " { + $ws.Cells["F2" ].Value | Should -Be "Store" + $ws.Cells["F3" ].Value | Should -Be "Oxford" + $ws.Cells["F8" ].Value | Should -Be "Abingdon" + $ws.Cells["F13"].Value | Should -Be "Banbury" + } + it "Filled in the data " { + $ws.Cells["C3" ].Value | Should -Be $data1[0].quantity + $ws.Cells["C8" ].Value | Should -Be $data2[0].quantity + $ws.Cells["C13"].Value | Should -Be $data3[0].quantity + } + it "Created the pivot table " { + $pt | Should -Not -BeNullOrEmpty + $pt.StyleName | Should -Be "PivotStyleMedium9" + $pt.RowFields[0].Name | Should -Be "Store" + $pt.ColumnFields[0].name | Should -Be "Product" + $pt.DataFields[0].name | Should -Be "Sum of Total" + $pc.ChartType | Should -Be "ColumnStacked" + $pc.Title.text | Should -Be "Sales Breakdown" + } + } +} + +# Describe "Join Worksheet part 2" -Tags JoinWorksheetPart2 -Skip { +# BeforeAll { +# if (-not (Get-command Get-CimInstance -ErrorAction SilentlyContinue)) { +# Function Get-CimInstance { +# param ($classname , $namespace) +# Import-Clixml "$PSScriptRoot\$classname.xml" +# } +# } +# } +# BeforeEach { +# $path = "TestDrive:\Test.xlsx" +# Remove-item -Path $path -ErrorAction SilentlyContinue +# #switched to CIM objects so test runs on V6+ +# Get-CimInstance -ClassName win32_logicaldisk | +# Select-Object -Property DeviceId, VolumeName, Size, Freespace | +# Export-Excel -Path $path -WorkSheetname Volumes -NumberFormat "0,000" +# Get-CimInstance -Namespace root/StandardCimv2 -class MSFT_NetAdapter | +# Select-Object -Property Name, InterfaceDescription, MacAddress, LinkSpeed | +# Export-Excel -Path $path -WorkSheetname NetAdapters + +# Join-Worksheet -Path $path -HideSource -WorkSheetName Summary -NoHeader -LabelBlocks -AutoSize -Title "Summary" -TitleBold -TitleSize 22 +# $excel = Open-ExcelPackage -Path $path +# $ws = $excel.Workbook.Worksheets["Summary"] +# } +# Context "Bringing 3 Unlinked blocks onto one page" { +# it "Hid the source worksheets " { +# $excel.Workbook.Worksheets[1].Hidden.tostring() | Should -Be "Hidden" +# $excel.Workbook.Worksheets[2].Hidden.tostring() | Should -Be "Hidden" +# } +# it "Created the Summary sheet with title, and block labels, and copied the correct data " { +# $ws.Cells["A1"].Value | Should -Be "Summary" +# $ws.Cells["A2"].Value | Should -Be $excel.Workbook.Worksheets[1].name +# $ws.Cells["A3"].Value | Should -Be $excel.Workbook.Worksheets[1].Cells["A1"].value +# $ws.Cells["A4"].Value | Should -Be $excel.Workbook.Worksheets[1].Cells["A2"].value +# $ws.Cells["B4"].Value | Should -Be $excel.Workbook.Worksheets[1].Cells["B2"].value +# $nextRow = $excel.Workbook.Worksheets[1].Dimension.Rows + 3 +# $ws.Cells["A$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].name +# $nextRow ++ +# $ws.Cells["A$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].Cells["A1"].value +# $nextRow ++ +# $ws.Cells["A$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].Cells["A2"].value +# $ws.Cells["B$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].Cells["B2"].value +# } +# } +# } + +Describe "Join Worksheet part 2" -Tags JoinWorksheetPart2 { + BeforeEach { + $Sales = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price,Total + 12001,Nails,37,3.99,147.63 + 12002,Hammer,5,12.10,60.5 + 12003,Saw,12,15.37,184.44 + 12010,Drill,20,8,159 + 12011,Crowbar,7,23.48,164.36 +"@ + + $SalesInfo = ConvertFrom-Csv -InputObject @" + ID,SalesId + 12001,100 + 12002,101 + 12003,102 + 12010,103 + 12011,104 +"@ + + $xlfile = "TestDrive:\Test.xlsx" + Remove-Item $xlfile -ErrorAction SilentlyContinue + + $Sales | Export-Excel $xlfile -WorksheetName Sales + $SalesInfo | Export-Excel $xlfile -WorksheetName SalesInfo + + $excel = Join-Worksheet -Path $xlfile -WorkSheetName Summary -PassThru -HideSource -NoHeader -LabelBlocks -AutoSize -Title "Summary" -TitleBold -TitleSize 22 + $ws = $excel.Workbook.Worksheets["Summary"] + } + + AfterEach { + Close-ExcelPackage $excel + } + + Context "Bringing 3 Unlinked blocks onto one page" { + It "Tests hiding the source worksheets" { + $excel.Workbook.Worksheets.Count | Should -Be 3 + $excel.Workbook.Worksheets[1].Hidden.ToString() | Should -Be "Hidden" + $excel.Workbook.Worksheets[2].Hidden.ToString() | Should -Be "Hidden" + } + + It "Tests creating the Summary sheet with title, and block labels, and copied the correct data " { + $ws.Cells["A1"].Value | Should -Be "Summary" + $ws.Cells["A2"].Value | Should -Be $excel.Workbook.Worksheets[1].name + $ws.Cells["A3"].Value | Should -Be $excel.Workbook.Worksheets[1].Cells["A1"].value + $ws.Cells["A4"].Value | Should -Be $excel.Workbook.Worksheets[1].Cells["A2"].value + $ws.Cells["B4"].Value | Should -Be $excel.Workbook.Worksheets[1].Cells["B2"].value + + $nextRow = $excel.Workbook.Worksheets[1].Dimension.Rows + 3 + $ws.Cells["A$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].name + + $nextRow++ + $ws.Cells["A$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].Cells["A1"].value + + $nextRow++ + $ws.Cells["A$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].Cells["A2"].value + $ws.Cells["B$NextRow"].Value | Should -Be $excel.Workbook.Worksheets[2].Cells["B2"].value + } + } +} \ No newline at end of file diff --git a/__tests__/MSFT_NetAdapter.xml b/__tests__/MSFT_NetAdapter.xml new file mode 100644 index 00000000..10c0f9a6 --- /dev/null +++ b/__tests__/MSFT_NetAdapter.xml @@ -0,0 +1,1056 @@ + + + + Microsoft.Management.Infrastructure.CimInstance#root/StandardCimv2/MSFT_NetAdapter + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_NetworkPort + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_LogicalPort + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_LogicalDevice + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_EnabledLogicalElement + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_LogicalElement + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_ManagedSystemElement + Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/CIM_ManagedElement + Microsoft.Management.Infrastructure.CimInstance#MSFT_NetAdapter + Microsoft.Management.Infrastructure.CimInstance#CIM_NetworkPort + Microsoft.Management.Infrastructure.CimInstance#CIM_LogicalPort + Microsoft.Management.Infrastructure.CimInstance#CIM_LogicalDevice + Microsoft.Management.Infrastructure.CimInstance#CIM_EnabledLogicalElement + Microsoft.Management.Infrastructure.CimInstance#CIM_LogicalElement + Microsoft.Management.Infrastructure.CimInstance#CIM_ManagedSystemElement + Microsoft.Management.Infrastructure.CimInstance#CIM_ManagedElement + Microsoft.Management.Infrastructure.CimInstance + System.Object + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{EABBFFBE-8343-4C69-9EF2-D58081F91769}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {EABBFFBE-8343-4C69-9EF2-D58081F91769} + + + + + WiFi + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {EABBFFBE-8343-4C69-9EF2-D58081F91769} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + 52000000 + + 1500 + + false + + + + System.String[] + System.Array + System.Object + + + B4AE2BD10C3A + + + + + B4AE2BD10C3A + 0 + + false + PCI\VEN_11AB&DEV_2B38&SUBSYS_045E0004 + true + \Device\{EABBFFBE-8343-4C69-9EF2-D58081F91769} + true + 2020-01-21 + 132240384000000000 + Marvell AVASTAR Wireless-AC Network Controller + 6 + 50 + \SystemRoot\System32\drivers\mrvlpcie8897.sys + Marvell Semiconductors, Inc. + 15.68.17018.116 + false + true + false + + + System.UInt32[] + System.Array + System.Object + + + 12 + + + false + 1 + Marvell AVASTAR Wireless-AC Network Controller + {EABBFFBE-8343-4C69-9EF2-D58081F91769} + 24 + wireless_32768 + 1 + 71 + false + + 1 + 1 + 1 + 0 + 1500 + 16 + 9 + 19985273102270464 + 32768 + false + false + false + false + false + PCI\VEN_11AB&DEV_2B38&SUBSYS_045E0004&REV_00\4&1a5036a5&0&00EB + false + 52000000 + 2 + 52000000 + false + + false + + + + + + System.Collections.ArrayList + System.Object + + + + + CIM_ManagedElement + ROOT/StandardCimv2 + FLATFISH + 1377625085 + <CLASS NAME="CIM_ManagedElement"><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Core::CoreElements</VALUE></QUALIFIER><PROPERTY NAME="Caption" TYPE="string"><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>64</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Description" TYPE="string"></PROPERTY><PROPERTY NAME="ElementName" TYPE="string"></PROPERTY><PROPERTY NAME="InstanceID" TYPE="string"></PROPERTY></CLASS> + + + + + CIM_ManagedSystemElement + ROOT/StandardCimv2 + FLATFISH + 1377600653 + <CLASS NAME="CIM_ManagedSystemElement" SUPERCLASS="CIM_ManagedElement"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Core::CoreElements</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><PROPERTY NAME="CommunicationStatus" TYPE="uint16"><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>..</VALUE><VALUE>0x8000..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="DetailedStatus" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.PrimaryStatus</VALUE><VALUE>CIM_ManagedSystemElement.HealthState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>..</VALUE><VALUE>0x8000..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="HealthState" TYPE="uint16"><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>5</VALUE><VALUE>10</VALUE><VALUE>15</VALUE><VALUE>20</VALUE><VALUE>25</VALUE><VALUE>30</VALUE><VALUE>..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="InstallDate" TYPE="datetime"></PROPERTY><PROPERTY NAME="Name" TYPE="string"><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>1024</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="OperatingStatus" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.EnabledState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>..</VALUE><VALUE>0x8000..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="OperationalStatus" TYPE="uint16"><QUALIFIER NAME="ArrayType" TYPE="string" OVERRIDABLE="false"><VALUE>Indexed</VALUE></QUALIFIER><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_ManagedSystemElement.StatusDescriptions</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>..</VALUE><VALUE>0x8000..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="PrimaryStatus" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_ManagedSystemElement.DetailedStatus</VALUE><VALUE>CIM_ManagedSystemElement.HealthState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>..</VALUE><VALUE>0x8000..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="Status" TYPE="string"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_ManagedSystemElement.OperationalStatus</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>10</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>OK</VALUE><VALUE>Error</VALUE><VALUE>Degraded</VALUE><VALUE>Unknown</VALUE><VALUE>Pred Fail</VALUE><VALUE>Starting</VALUE><VALUE>Stopping</VALUE><VALUE>Service</VALUE><VALUE>Stressed</VALUE><VALUE>NonRecover</VALUE><VALUE>No Contact</VALUE><VALUE>Lost Comm</VALUE><VALUE>Stopped</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="StatusDescriptions" TYPE="string"><QUALIFIER NAME="ArrayType" TYPE="string" OVERRIDABLE="false"><VALUE>Indexed</VALUE></QUALIFIER><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_ManagedSystemElement.OperationalStatus</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY></CLASS> + + + + + CIM_LogicalElement + ROOT/StandardCimv2 + FLATFISH + 1377604813 + <CLASS NAME="CIM_LogicalElement" SUPERCLASS="CIM_ManagedSystemElement"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Core::CoreElements</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER></CLASS> + + + + + CIM_EnabledLogicalElement + ROOT/StandardCimv2 + FLATFISH + 1377628989 + <CLASS NAME="CIM_EnabledLogicalElement" SUPERCLASS="CIM_LogicalElement"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Core::CoreElements</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><PROPERTY.ARRAY NAME="AvailableRequestedStates" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestStateChange</VALUE><VALUE>CIM_EnabledLogicalElementCapabilities.RequestedStatesSupported</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>..</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="EnabledDefault" TYPE="uint16"><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>9</VALUE><VALUE>..</VALUE><VALUE>32768..65535</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="write" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><VALUE>2</VALUE></PROPERTY><PROPERTY NAME="EnabledState" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.OtherEnabledState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11..32767</VALUE><VALUE>32768..65535</VALUE></VALUE.ARRAY></QUALIFIER><VALUE>5</VALUE></PROPERTY><PROPERTY NAME="OtherEnabledState" TYPE="string"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.EnabledState</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="RequestedState" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.EnabledState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>..</VALUE><VALUE>32768..65535</VALUE></VALUE.ARRAY></QUALIFIER><VALUE>12</VALUE></PROPERTY><PROPERTY NAME="TimeOfLastStateChange" TYPE="datetime"></PROPERTY><PROPERTY NAME="TransitioningToState" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestStateChange</VALUE><VALUE>CIM_EnabledLogicalElement.RequestedState</VALUE><VALUE>CIM_EnabledLogicalElement.EnabledState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>..</VALUE></VALUE.ARRAY></QUALIFIER><VALUE>12</VALUE></PROPERTY><METHOD NAME="RequestStateChange" TYPE="uint32"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestedState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>..</VALUE><VALUE>4096</VALUE><VALUE>4097</VALUE><VALUE>4098</VALUE><VALUE>4099</VALUE><VALUE>4100..32767</VALUE><VALUE>32768..65535</VALUE></VALUE.ARRAY></QUALIFIER><PARAMETER NAME="RequestedState" TYPE="uint16"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestedState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>..</VALUE><VALUE>32768..65535</VALUE></VALUE.ARRAY></QUALIFIER></PARAMETER><PARAMETER NAME="TimeoutPeriod" TYPE="datetime"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>2</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER.REFERENCE NAME="Job" REFERENCECLASS="CIM_ConcreteJob"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>1</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER.REFERENCE></METHOD></CLASS> + + + + + CIM_LogicalDevice + ROOT/StandardCimv2 + FLATFISH + 1320694093 + <CLASS NAME="CIM_LogicalDevice" SUPERCLASS="CIM_EnabledLogicalElement"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Core::Device</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><PROPERTY.ARRAY NAME="AdditionalAvailability" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalDevice.Availability</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>19</VALUE><VALUE>20</VALUE><VALUE>21</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="Availability" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalDevice.AdditionalAvailability</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>19</VALUE><VALUE>20</VALUE><VALUE>21</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="CreationClassName" TYPE="string"><QUALIFIER NAME="key" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>256</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DeviceID" TYPE="string"><QUALIFIER NAME="key" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>64</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ErrorCleared" TYPE="boolean"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_ManagedSystemElement.OperationalStatus</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="ErrorDescription" TYPE="string"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_DeviceErrorData.ErrorDescription</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="IdentifyingDescriptions" TYPE="string"><QUALIFIER NAME="ArrayType" TYPE="string" OVERRIDABLE="false"><VALUE>Indexed</VALUE></QUALIFIER><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalDevice.OtherIdentifyingInfo</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="LastErrorCode" TYPE="uint32"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_DeviceErrorData.LastErrorCode</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="MaxQuiesceTime" TYPE="uint64"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>No value</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="OtherIdentifyingInfo" TYPE="string" ARRAYSIZE="256"><QUALIFIER NAME="ArrayType" TYPE="string" OVERRIDABLE="false"><VALUE>Indexed</VALUE></QUALIFIER><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>256</VALUE></QUALIFIER><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalDevice.IdentifyingDescriptions</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY><PROPERTY.ARRAY NAME="PowerManagementCapabilities" TYPE="uint16"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_PowerManagementCapabilities.PowerCapabilities</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="PowerManagementSupported" TYPE="boolean"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_PowerManagementCapabilities</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="PowerOnHours" TYPE="uint64"><QUALIFIER NAME="Counter" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="StatusInfo" TYPE="uint16"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.EnabledState</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="SystemCreationClassName" TYPE="string"><QUALIFIER NAME="key" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>256</VALUE></QUALIFIER><QUALIFIER NAME="Propagated" TYPE="string" OVERRIDABLE="false"><VALUE>CIM_System.CreationClassName</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="SystemName" TYPE="string"><QUALIFIER NAME="key" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>256</VALUE></QUALIFIER><QUALIFIER NAME="Propagated" TYPE="string" OVERRIDABLE="false"><VALUE>CIM_System.Name</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="TotalPowerOnHours" TYPE="uint64"><QUALIFIER NAME="Counter" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><METHOD NAME="SetPowerState" TYPE="uint32"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_PowerManagementService.SetPowerState</VALUE></VALUE.ARRAY></QUALIFIER><PARAMETER NAME="PowerState" TYPE="uint16"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE></VALUE.ARRAY></QUALIFIER></PARAMETER><PARAMETER NAME="Time" TYPE="datetime"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>1</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Reset" TYPE="uint32"></METHOD><METHOD NAME="EnableDevice" TYPE="uint32"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestStateChange</VALUE></VALUE.ARRAY></QUALIFIER><PARAMETER NAME="Enabled" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="OnlineDevice" TYPE="uint32"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestStateChange</VALUE></VALUE.ARRAY></QUALIFIER><PARAMETER NAME="Online" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="QuiesceDevice" TYPE="uint32"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_EnabledLogicalElement.RequestStateChange</VALUE></VALUE.ARRAY></QUALIFIER><PARAMETER NAME="Quiesce" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="SaveProperties" TYPE="uint32"></METHOD><METHOD NAME="RestoreProperties" TYPE="uint32"></METHOD></CLASS> + + + + + CIM_LogicalPort + ROOT/StandardCimv2 + FLATFISH + 1350059837 + <CLASS NAME="CIM_LogicalPort" SUPERCLASS="CIM_LogicalDevice"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Device::Ports</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><PROPERTY NAME="MaxSpeed" TYPE="uint64"><QUALIFIER NAME="PUnit" TYPE="string"><VALUE>bit / second</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="OtherPortType" TYPE="string"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalPort.PortType</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="PortType" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_NetworkPort.OtherNetworkPortType</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3..15999</VALUE><VALUE>16000..65535</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="RequestedSpeed" TYPE="uint64"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalPort.Speed</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="PUnit" TYPE="string"><VALUE>bit / second</VALUE></QUALIFIER><QUALIFIER NAME="write" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Speed" TYPE="uint64"><QUALIFIER NAME="PUnit" TYPE="string"><VALUE>bit / second</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="UsageRestriction" TYPE="uint16"><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY></CLASS> + + + + + CIM_NetworkPort + ROOT/StandardCimv2 + FLATFISH + 1350049693 + <CLASS NAME="CIM_NetworkPort" SUPERCLASS="CIM_LogicalPort"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Device::Ports</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><PROPERTY NAME="Speed" TYPE="uint64"><QUALIFIER NAME="PUnit" TYPE="string"><VALUE>bit / second</VALUE></QUALIFIER><QUALIFIER NAME="Override" TYPE="string" TOSUBCLASS="false"><VALUE>Speed</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ActiveMaximumTransmissionUnit" TYPE="uint64"><QUALIFIER NAME="PUnit" TYPE="string"><VALUE>byte</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="AutoSense" TYPE="boolean"></PROPERTY><PROPERTY NAME="FullDuplex" TYPE="boolean"></PROPERTY><PROPERTY NAME="LinkTechnology" TYPE="uint16"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_NetworkPort.OtherLinkTechnology</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="NetworkAddresses" TYPE="string" ARRAYSIZE="64"><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>64</VALUE></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="OtherLinkTechnology" TYPE="string"><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_NetworkPort.LinkTechnology</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="OtherNetworkPortType" TYPE="string"><QUALIFIER NAME="Deprecated" TYPE="string" TOSUBCLASS="false"><VALUE.ARRAY><VALUE>CIM_NetworkPort.OtherPortType</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="ModelCorrespondence" TYPE="string"><VALUE.ARRAY><VALUE>CIM_LogicalPort.PortType</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="PermanentAddress" TYPE="string"><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>64</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="PortNumber" TYPE="uint16"></PROPERTY><PROPERTY NAME="SupportedMaximumTransmissionUnit" TYPE="uint64"><QUALIFIER NAME="PUnit" TYPE="string"><VALUE>byte</VALUE></QUALIFIER></PROPERTY></CLASS> + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + <CLASS NAME="MSFT_NetAdapter" SUPERCLASS="CIM_NetworkPort"><QUALIFIER NAME="UMLPackagePath" TYPE="string"><VALUE>CIM::Device::Ports</VALUE></QUALIFIER><QUALIFIER NAME="dynamic" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="locale" TYPE="sint32" TOSUBCLASS="false"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="provider" TYPE="string"><VALUE>NetAdapterCim</VALUE></QUALIFIER><PROPERTY NAME="AdminLocked" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ComponentID" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ConnectorPresent" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DeviceName" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DeviceWakeUpEnable" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverDate" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverDateData" TYPE="uint64"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverDescription" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverMajorNdisVersion" TYPE="uint8"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverMinorNdisVersion" TYPE="uint8"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverName" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverProvider" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriverVersionString" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="EndPointInterface" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="HardwareInterface" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Hidden" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="HigherLayerInterfaceIndices" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="IMFilter" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceAdminStatus" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceDescription" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceGuid" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceIndex" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceName" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceOperationalStatus" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="InterfaceType" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="iSCSIInterface" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="LowerLayerInterfaceIndices" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="MajorDriverVersion" TYPE="uint16"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="MediaConnectState" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="MediaDuplexState" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="MinorDriverVersion" TYPE="uint16"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="MtuSize" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="NdisMedium" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>19</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="NdisPhysicalMedium" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>19</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="NetLuid" TYPE="uint64"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="NetLuidIndex" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="NotUserRemovable" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="OperationalStatusDownDefaultPortNotAuthenticated" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="OperationalStatusDownInterfacePaused" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="OperationalStatusDownLowPowerState" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="OperationalStatusDownMediaDisconnected" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="PnPDeviceID" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="PromiscuousMode" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ReceiveLinkSpeed" TYPE="uint64"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="State" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="TransmitLinkSpeed" TYPE="uint64"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Virtual" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="VlanID" TYPE="uint16"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="write" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="WdmInterface" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><METHOD NAME="Enable" TYPE="uint32"><QUALIFIER NAME="implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER NAME="CmdletOutput" TYPE="string"><QUALIFIER NAME="EmbeddedInstance" TYPE="string"><VALUE>MSFT_NetAdapter</VALUE></QUALIFIER><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Disable" TYPE="uint32"><QUALIFIER NAME="implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER NAME="CmdletOutput" TYPE="string"><QUALIFIER NAME="EmbeddedInstance" TYPE="string"><VALUE>MSFT_NetAdapter</VALUE></QUALIFIER><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Restart" TYPE="uint32"><QUALIFIER NAME="implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER NAME="CmdletOutput" TYPE="string"><QUALIFIER NAME="EmbeddedInstance" TYPE="string"><VALUE>MSFT_NetAdapter</VALUE></QUALIFIER><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Lock" TYPE="uint32"><QUALIFIER NAME="implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER NAME="CmdletOutput" TYPE="string"><QUALIFIER NAME="EmbeddedInstance" TYPE="string"><VALUE>MSFT_NetAdapter</VALUE></QUALIFIER><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Unlock" TYPE="uint32"><QUALIFIER NAME="implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER NAME="CmdletOutput" TYPE="string"><QUALIFIER NAME="EmbeddedInstance" TYPE="string"><VALUE>MSFT_NetAdapter</VALUE></QUALIFIER><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Rename" TYPE="uint32"><QUALIFIER NAME="implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER NAME="NewName" TYPE="string"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="In" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER NAME="CmdletOutput" TYPE="string"><QUALIFIER NAME="EmbeddedInstance" TYPE="string"><VALUE>MSFT_NetAdapter</VALUE></QUALIFIER><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>1</VALUE></QUALIFIER><QUALIFIER NAME="Out" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD></CLASS> + + + + + + + + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{E50C149F-EACF-48C4-A901-E4A5C1D25DCE}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {E50C149F-EACF-48C4-A901-E4A5C1D25DCE} + + + + + Ethernet 3 + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {E50C149F-EACF-48C4-A901-E4A5C1D25DCE} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + + + 1500 + + + + + + + 5882A899DC1F + + + + + 5882A899DC1F + 0 + + false + USB\VID_045E&PID_07C6&REV_3000 + true + \Device\{E50C149F-EACF-48C4-A901-E4A5C1D25DCE} + true + 2019-06-04 + 132040800000000000 + Surface Ethernet Adapter + 6 + 40 + \SystemRoot\System32\DriverStore\FileRepository\msux64w10.inf_amd64_1f233e36981f33bd\msux64w10.sys + Surface + 10.12.604.2019 + false + true + false + + + + 28 + + + false + 1 + Surface Ethernet Adapter + {E50C149F-EACF-48C4-A901-E4A5C1D25DCE} + 21 + ethernet_32772 + 2 + 6 + false + + 10 + 2 + 0 + 34 + 1500 + 0 + 14 + 1689399683186688 + 32772 + false + false + false + false + true + USB\VID_045E&PID_07C6\000001000000 + true + + 2 + + false + + true + + + + + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + + + + + + + + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{CDC88A91-293E-4B2C-AEC2-D60F89D1DB8C}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {CDC88A91-293E-4B2C-AEC2-D60F89D1DB8C} + + + + + Bluetooth Network Connection + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {CDC88A91-293E-4B2C-AEC2-D60F89D1DB8C} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + 3000000 + + 1500 + + true + + + + + B4AE2BD10C3B + + + + + B4AE2BD10C3B + 0 + + false + BTH\MS_BTHPAN + false + \Device\{CDC88A91-293E-4B2C-AEC2-D60F89D1DB8C} + false + 2006-06-21 + 127953216000000000 + Bluetooth Device (Personal Area Network) + 6 + 30 + \SystemRoot\System32\drivers\bthpan.sys + Microsoft + 10.0.19041.1 + false + false + false + + false + 1 + Bluetooth Device (Personal Area Network) + {CDC88A91-293E-4B2C-AEC2-D60F89D1DB8C} + 19 + ethernet_32770 + 2 + 6 + false + + 0 + 2 + 2 + 0 + 1500 + 0 + 10 + 1689399649632256 + 32770 + false + false + false + false + true + BTH\MS_BTHPAN\6&e3528ed&0&2 + false + 3000000 + 2 + 3000000 + true + + true + + + + + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + + + + + + + + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{C39E98D7-DB6C-4509-9E68-36369B652EC3}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {C39E98D7-DB6C-4509-9E68-36369B652EC3} + + + + + vEthernet (nat) + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {C39E98D7-DB6C-4509-9E68-36369B652EC3} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + 10000000000 + + 1500 + + + + + + + 00155D1ECE3F + + + + + 00155D1ECE3F + 0 + + false + vms_mp + false + \Device\{C39E98D7-DB6C-4509-9E68-36369B652EC3} + false + 2006-06-21 + 127953216000000000 + Hyper-V Virtual Ethernet Adapter + + + \SystemRoot\System32\drivers\VmsProxyHNic.sys + Microsoft + 10.0.19041.1 + false + false + false + + + + 38 + + + false + 1 + Hyper-V Virtual Ethernet Adapter #3 + {C39E98D7-DB6C-4509-9E68-36369B652EC3} + 37 + ethernet_32778 + 1 + 6 + false + + + + 54 + + + + 1 + 0 + + 1500 + 0 + 0 + 1689399783849984 + 32778 + true + false + false + false + false + ROOT\VMS_MP\0002 + false + 10000000000 + 2 + 10000000000 + true + + false + + + + + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + + + + + + + + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{B01AB642-6C1D-4CB5-9F4C-F926862A0166}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {B01AB642-6C1D-4CB5-9F4C-F926862A0166} + + + + + vEthernet (Default Switch) + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {B01AB642-6C1D-4CB5-9F4C-F926862A0166} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + 10000000000 + + 1500 + + + + + + + 00155DA8007A + + + + + 00155DA8007A + 0 + + false + vms_mp + false + \Device\{B01AB642-6C1D-4CB5-9F4C-F926862A0166} + false + 2006-06-21 + 127953216000000000 + Hyper-V Virtual Ethernet Adapter + + + \SystemRoot\System32\drivers\VmsProxyHNic.sys + Microsoft + 10.0.19041.1 + false + false + false + + + + 32 + + + false + 1 + Hyper-V Virtual Ethernet Adapter + {B01AB642-6C1D-4CB5-9F4C-F926862A0166} + 31 + ethernet_32777 + 1 + 6 + false + + + + 54 + + + + 1 + 0 + + 1500 + 0 + 0 + 1689399767072768 + 32777 + true + false + false + false + false + ROOT\VMS_MP\0000 + false + 10000000000 + 2 + 10000000000 + true + + false + + + + + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + + + + + + + + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{8E56A068-79F4-418D-A52D-9E0E210BB928}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {8E56A068-79F4-418D-A52D-9E0E210BB928} + + + + + vEthernet (WSL) + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {8E56A068-79F4-418D-A52D-9E0E210BB928} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + 10000000000 + + 1500 + + + + + + + 00155D493D76 + + + + + 00155D493D76 + 0 + + false + vms_mp + false + \Device\{8E56A068-79F4-418D-A52D-9E0E210BB928} + false + 2006-06-21 + 127953216000000000 + Hyper-V Virtual Ethernet Adapter + + + \SystemRoot\System32\drivers\VmsProxyHNic.sys + Microsoft + 10.0.19041.1 + false + false + false + + + + 61 + + + false + 1 + Hyper-V Virtual Ethernet Adapter #4 + {8E56A068-79F4-418D-A52D-9E0E210BB928} + 60 + ethernet_32784 + 1 + 6 + false + + + + 46 + + + + 1 + 0 + + 1500 + 0 + 0 + 1689399884513280 + 32784 + true + false + false + false + false + ROOT\VMS_MP\0003 + false + 10000000000 + 2 + 10000000000 + true + + false + + + + + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + + + + + + + + + MSFT_NetAdapter (CreationClassName = "MSFT_NetAdapter", DeviceID = "{4F19B550-1149-46F1-A5DB-3D8DECAED5BB}", SystemCreationClassName = "CIM_NetworkPort", SystemName = "FLATFISH") + + + + + {4F19B550-1149-46F1-A5DB-3D8DECAED5BB} + + + + + vEthernet (New Virtual Switch) + + + + + + + 2 + 5 + + 12 + + 12 + + + MSFT_NetAdapter + {4F19B550-1149-46F1-A5DB-3D8DECAED5BB} + + + + + + + + + + + CIM_NetworkPort + FLATFISH + + + + + + 10000000000 + + 1500 + + + + + + + 5882A899DC1F + + + + + 5882A899DC1F + 0 + + false + vms_mp + false + \Device\{4F19B550-1149-46F1-A5DB-3D8DECAED5BB} + false + 2006-06-21 + 127953216000000000 + Hyper-V Virtual Ethernet Adapter + + + \SystemRoot\System32\drivers\VmsProxyHNic.sys + Microsoft + 10.0.19041.1 + false + false + false + + + + 30 + + + false + 1 + Hyper-V Virtual Ethernet Adapter #2 + {4F19B550-1149-46F1-A5DB-3D8DECAED5BB} + 8 + ethernet_32780 + 2 + 6 + false + + + + 55 + + + + 2 + 0 + + 1500 + 0 + 0 + 1689399817404416 + 32780 + true + false + false + false + true + ROOT\VMS_MP\0001 + false + 10000000000 + 2 + 10000000000 + true + + false + + + + + + + + + MSFT_NetAdapter + root/StandardCimv2 + FLATFISH + 1326860669 + + + + + + + \ No newline at end of file diff --git a/__tests__/Mockservices.xml b/__tests__/Mockservices.xml new file mode 100644 index 00000000..fd4d52aa --- /dev/null +++ b/__tests__/Mockservices.xml @@ -0,0 +1,26460 @@ + + + + System.Service.ServiceController#StartupType + System.Service.ServiceController#BinaryPathName + System.Service.ServiceController#DelayedAutoStart + System.Service.ServiceController#Description + System.Service.ServiceController#UserName + System.ServiceProcess.ServiceController + System.ComponentModel.Component + System.MarshalByRefObject + System.Object + + AarSvc_9164d + + false + false + false + Agent Activation Runtime_9164d + + + System.ServiceProcess.ServiceController[] + System.Array + System.Object + + + + . + AarSvc_9164d + + + + + + + System.ServiceProcess.ServiceStartMode + System.Enum + System.ValueType + System.Object + + Manual + 3 + + + + System.ServiceProcess.ServiceControllerStatus + System.Enum + System.ValueType + System.Object + + Stopped + 1 + + + + System.ServiceProcess.ServiceType + System.Enum + System.ValueType + System.Object + + 224 + 224 + + + + + + + Runtime for activating conversational agent applications + false + C:\WINDOWS\system32\svchost.exe -k AarSvcGroup -p + + + Microsoft.PowerShell.Commands.ServiceStartupType + System.Enum + System.ValueType + System.Object + + Manual + 3 + + AarSvc_9164d + + + + + + AdobeUpdateService + + false + false + true + AdobeUpdateService + + . + AdobeUpdateService + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + + false + "C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\ElevationManager\AdobeUpdateService.exe" + + + Automatic + 2 + + AdobeUpdateService + + + + + + AGMService + + false + true + true + Adobe Genuine Monitor Service + + . + AGMService + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Adobe Genuine Monitor Service + false + "C:\Program Files (x86)\Common Files\Adobe\AdobeGCClient\AGMService.exe" + + + Automatic + 2 + + AGMService + + + + + + AGSService + + false + true + true + Adobe Genuine Software Integrity Service + + . + AGSService + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Adobe Genuine Software Integrity Service + false + "C:\Program Files (x86)\Common Files\Adobe\AdobeGCClient\AGSService.exe" + + + Automatic + 2 + + AGSService + + + + + + AJRouter + + false + false + false + AllJoyn Router Service + + . + AJRouter + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Routes AllJoyn messages for the local AllJoyn clients. If this service is stopped the AllJoyn clients that do not have their own bundled routers will be unable to run. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + AJRouter + + + + + + ALG + + false + false + false + Application Layer Gateway Service + + . + ALG + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Provides support for 3rd party protocol plug-ins for Internet Connection Sharing + false + C:\WINDOWS\System32\alg.exe + + + Manual + 3 + + ALG + + + + + + AppIDSvc + + false + false + false + Application Identity + + + + + + System.ServiceProcess.ServiceController + System.ComponentModel.Component + System.MarshalByRefObject + System.Object + + applockerfltr + + false + false + false + Smartlocker Filter Driver + + . + applockerfltr + + + + FltMgr + AppID + AppIDSvc + + + Manual + Stopped + KernelDriver + + + + + applockerfltr + + + + + + . + AppIDSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + AppID + + false + false + false + AppID Driver + + + + applockerfltr + AppIDSvc + + + . + AppID + + + + FltMgr + + + Manual + Stopped + KernelDriver + + + + + AppID + + + + + + CryptSvc + + false + true + true + Cryptographic Services + + + + applockerfltr + AppIDSvc + + + . + CryptSvc + + + + RpcSs + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + CryptSvc + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT Authority\LocalService + Determines and verifies the identity of an application. Disabling this service will prevent AppLocker from being enforced. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + AppIDSvc + + + + + + Appinfo + + false + false + true + Application Information + + . + Appinfo + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + ProfSvc + + false + true + true + User Profile Service + + + + XblGameSave + TokenBroker + UserManager + shpamsvc + NaturalAuthentication + Appinfo + + + . + ProfSvc + + + + RpcSs + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + ProfSvc + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Facilitates the running of interactive applications with additional administrative privileges. If this service is stopped, users will be unable to launch applications with the additional administrative privileges they may require to perform desired user tasks. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + Appinfo + + + + + + AppMgmt + + false + false + false + Application Management + + . + AppMgmt + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Processes installation, removal and enumeration requests for software deployed through Group Policy. If the service is disabled, users will be unable to install, remove or enumerate software deployed through Group Policy. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + AppMgmt + + + + + + AppReadiness + + false + false + false + App Readiness + + . + AppReadiness + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Gets apps ready for use the first time a user signs in to this PC and when adding new apps. + false + C:\WINDOWS\System32\svchost.exe -k AppReadiness -p + + + Manual + 3 + + AppReadiness + + + + + + AppVClient + + false + false + false + Microsoft App-V Client + + . + AppVClient + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + netprofm + + false + false + true + Network List Service + + + + NcdAutoSetup + AppVClient + + + . + netprofm + + + + RpcSs + nlasvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + netprofm + + + + + + AppvVfs + + false + false + false + AppvVfs + + + + AppVClient + + + . + AppvVfs + + + + FltMgr + AppvVemgr + + + Manual + Stopped + FileSystemDriver + + + + + AppvVfs + + + + + + AppvStrm + + false + false + false + AppVStrm + + + + AppVClient + + + . + AppvStrm + + + + FltMgr + + + Manual + Stopped + FileSystemDriver + + + + + AppvStrm + + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Manages App-V users and virtual applications + false + C:\WINDOWS\system32\AppVClient.exe + + + Disabled + 4 + + AppVClient + + + + + + AppXSvc + + false + true + true + AppX Deployment Service (AppXSVC) + + . + AppXSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + staterepository + + false + true + true + State Repository Service + + + + LxssManager + AppXSvc + + + . + staterepository + + + + rpcss + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + staterepository + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides infrastructure support for deploying Store applications. This service is started on demand and if disabled Store applications will not be deployed to the system, and may not function properly. + false + C:\WINDOWS\system32\svchost.exe -k wsappx -p + + + Manual + 3 + + AppXSvc + + + + + + aspnet_state + + false + false + false + ASP.NET State Service + + . + aspnet_state + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Provides support for out-of-process session states for ASP.NET. If this service is stopped, out-of-process requests will not be processed. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\aspnet_state.exe + + + Manual + 3 + + aspnet_state + + + + + + AssignedAccessManagerSvc + + false + false + false + AssignedAccessManager Service + + . + AssignedAccessManagerSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + AssignedAccessManager Service supports kiosk experience in Windows. + false + C:\WINDOWS\system32\svchost.exe -k AssignedAccessManagerSvc + + + Manual + 3 + + AssignedAccessManagerSvc + + + + + + AudioEndpointBuilder + + false + false + true + Windows Audio Endpoint Builder + + + + + + AarSvc_9164d + + false + false + false + Agent Activation Runtime_9164d + + . + AarSvc_9164d + + + + + Manual + Stopped + 224 + + + + + AarSvc_9164d + + + + + + AarSvc + + false + false + false + Agent Activation Runtime + + . + AarSvc + + + + Audiosrv + + + Manual + Stopped + 96 + + + + + AarSvc + + + + + + Audiosrv + + false + false + true + Windows Audio + + + + AarSvc_9164d + AarSvc + + + . + Audiosrv + + + + AudioEndpointBuilder + RpcSs + + + Automatic + Running + Win32OwnProcess + + + + + Audiosrv + + + + + + . + AudioEndpointBuilder + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Manages audio devices for the Windows Audio service. If this service is stopped, audio devices and effects will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Automatic + 2 + + AudioEndpointBuilder + + + + + + Audiosrv + + false + false + true + Windows Audio + + + + + + AarSvc_9164d + + false + false + false + Agent Activation Runtime_9164d + + . + AarSvc_9164d + + + + + Manual + Stopped + 224 + + + + + AarSvc_9164d + + + + + + AarSvc + + false + false + false + Agent Activation Runtime + + . + AarSvc + + + + Audiosrv + + + Manual + Stopped + 96 + + + + + AarSvc + + + + + + . + Audiosrv + + + + + + AudioEndpointBuilder + + false + false + true + Windows Audio Endpoint Builder + + + + AarSvc_9164d + AarSvc + Audiosrv + + + . + AudioEndpointBuilder + + + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + AudioEndpointBuilder + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Manages audio for Windows-based programs. If this service is stopped, audio devices and effects will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Automatic + 2 + + Audiosrv + + + + + + autotimesvc + + false + false + false + Cellular Time + + . + autotimesvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + This service sets time based on NITZ messages from a Mobile Network + false + C:\WINDOWS\system32\svchost.exe -k autoTimeSvc + + + Manual + 3 + + autotimesvc + + + + + + AxInstSV + + false + false + false + ActiveX Installer (AxInstSV) + + . + AxInstSV + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides User Account Control validation for the installation of ActiveX controls from the Internet and enables management of ActiveX control installation based on Group Policy settings. This service is started on demand and if disabled the installation of ActiveX controls will behave according to default browser settings. + false + C:\WINDOWS\system32\svchost.exe -k AxInstSVGroup + + + Manual + 3 + + AxInstSV + + + + + + BcastDVRUserService_9164d + + false + false + false + GameDVR and Broadcast User Service_9164d + + . + BcastDVRUserService_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 240 + 240 + + + + + + + This user service is used for Game Recordings and Live Broadcasts + false + C:\WINDOWS\system32\svchost.exe -k BcastDVRUserService + + + Manual + 3 + + BcastDVRUserService_9164d + + + + + + BDESVC + + false + false + true + BitLocker Drive Encryption Service + + . + BDESVC + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + localSystem + BDESVC hosts the BitLocker Drive Encryption service. BitLocker Drive Encryption provides secure startup for the operating system, as well as full volume encryption for OS, fixed or removable volumes. This service allows BitLocker to prompt users for various actions related to their volumes when mounted, and unlocks volumes automatically without user interaction. Additionally, it stores recovery information to Active Directory, if available, and, if necessary, ensures the most recent recovery certificates are used. Stopping or disabling the service would prevent users from leveraging this functionality. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + BDESVC + + + + + + BFE + + false + false + true + Base Filtering Engine + . + BFE + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + The Base Filtering Engine (BFE) is a service that manages firewall and Internet Protocol security (IPsec) policies and implements user mode filtering. Stopping or disabling the BFE service will significantly reduce the security of the system. It will also result in unpredictable behavior in IPsec management and firewall applications. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetworkFirewall -p + + + Automatic + 2 + + BFE + + + + + + BITS + + false + false + false + Background Intelligent Transfer Service + + . + BITS + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Transfers files in the background using idle network bandwidth. If the service is disabled, then any applications that depend on BITS, such as Windows Update or MSN Explorer, will be unable to automatically download programs and other information. + true + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + BITS + + + + + + BluetoothUserService_9164d + + false + false + true + Bluetooth User Support Service_9164d + + . + BluetoothUserService_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 240 + 240 + + + + + + + The Bluetooth user service supports proper functionality of Bluetooth features relevant to each user session. + false + C:\WINDOWS\system32\svchost.exe -k BthAppGroup -p + + + Manual + 3 + + BluetoothUserService_9164d + + + + + + BrokerInfrastructure + + false + false + false + Background Tasks Infrastructure Service + . + BrokerInfrastructure + + + + + + RpcEptMapper + + false + false + false + RPC Endpoint Mapper + . + RpcEptMapper + + + + + Automatic + Running + Win32ShareProcess + + + + + RpcEptMapper + + + + + + DcomLaunch + + false + false + false + DCOM Server Process Launcher + . + DcomLaunch + + + + + Automatic + Running + Win32ShareProcess + + + + + DcomLaunch + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Windows infrastructure service that controls which background tasks can run on the system. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Automatic + 2 + + BrokerInfrastructure + + + + + + BrYNSvc + + true + false + true + BrYNSvc + + . + BrYNSvc + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + + false + "C:\Program Files (x86)\Browny02\BrYNSvc.exe" + + + Manual + 3 + + BrYNSvc + + + + + + BTAGService + + false + false + true + Bluetooth Audio Gateway Service + + . + BTAGService + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Service supporting the audio gateway role of the Bluetooth Handsfree Profile. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted + + + Manual + 3 + + BTAGService + + + + + + BthAvctpSvc + + false + false + true + AVCTP service + + . + BthAvctpSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + This is Audio Video Control Transport Protocol service + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + BthAvctpSvc + + + + + + bthserv + + false + true + true + Bluetooth Support Service + + + + + + BluetoothUserService_9164d + + false + false + true + Bluetooth User Support Service_9164d + + . + BluetoothUserService_9164d + + + + + Manual + Running + 240 + + + + + BluetoothUserService_9164d + + + + + + BluetoothUserService + + false + false + false + Bluetooth User Support Service + + . + BluetoothUserService + + + + bthserv + rpcss + + + Manual + Stopped + 96 + + + + + BluetoothUserService + + + + + + . + bthserv + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + The Bluetooth service supports discovery and association of remote Bluetooth devices. Stopping or disabling this service may cause already installed Bluetooth devices to fail to operate properly and prevent new devices from being discovered or associated. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + bthserv + + + + + + c2wts + + false + false + false + Claims to Windows Token Service + + . + c2wts + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Service to convert claims based identities to windows identities + false + C:\Program Files\Windows Identity Foundation\v3.5\c2wtshost.exe + + + Manual + 3 + + c2wts + + + + + + camsvc + + false + true + true + Capability Access Manager Service + + . + camsvc + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides facilities for managing UWP apps access to app capabilities as well as checking an app's access to specific app capabilities + false + C:\WINDOWS\system32\svchost.exe -k appmodel -p + + + Manual + 3 + + camsvc + + + + + + CaptureService_9164d + + false + false + false + CaptureService_9164d + + . + CaptureService_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + Enables optional screen capture functionality for applications that call the Windows.Graphics.Capture API. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + CaptureService_9164d + + + + + + cbdhsvc_9164d + + false + false + true + Clipboard User Service_9164d + + . + cbdhsvc_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 240 + 240 + + + + + + + This user service is used for Clipboard scenarios + false + C:\WINDOWS\system32\svchost.exe -k ClipboardSvcGroup -p + + + Manual + 3 + + cbdhsvc_9164d + + + + + + CDPSvc + + false + false + true + Connected Devices Platform Service + + . + CDPSvc + + + + + + ncbservice + + false + false + true + Network Connection Broker + + + + CDPSvc + + + . + ncbservice + + + + RpcSS + tcpip + BrokerInfrastructure + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + ncbservice + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + Tcpip + + false + false + true + TCP/IP Protocol Driver + + + + WinNat + NetBT + tdx + tcpipreg + Tcpip6 + PolicyAgent + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Ndu + CDPSvc + NcbService + IPNAT + NcaSvc + iphlpsvc + IpFilterDriver + debugregsvc + + + . + Tcpip + + + + + Boot + Running + KernelDriver + + + + + Tcpip + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + This service is used for Connected Devices Platform scenarios + true + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + AutomaticDelayedStart + 10 + + CDPSvc + + + + + + CDPUserSvc_9164d + + false + false + true + Connected Devices Platform User Service_9164d + + . + CDPUserSvc_9164d + + + + + + + Automatic + 2 + + + + Running + 4 + + + + 240 + 240 + + + + + + + This user service is used for Connected Devices Platform scenarios + false + C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup + + + Automatic + 2 + + CDPUserSvc_9164d + + + + + + CertPropSvc + + false + true + true + Certificate Propagation + + . + CertPropSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Copies user certificates and root certificates from smart cards into the current user's certificate store, detects when a smart card is inserted into a smart card reader, and, if needed, installs the smart card Plug and Play minidriver. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs + + + Manual + 3 + + CertPropSvc + + + + + + ClickToRunSvc + + false + true + true + Microsoft Office Click-to-Run Service + + . + ClickToRunSvc + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + ‪Manages resource coordination, background streaming, and system integration of Microsoft Office products and their related updates. This service is required to run during the use of any Microsoft Office program, during initial streaming installation and all subsequent updates.‬ + false + "C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe" /service + + + Automatic + 2 + + ClickToRunSvc + + + + + + ClipSVC + + false + true + true + Client License Service (ClipSVC) + + . + ClipSVC + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides infrastructure support for the Microsoft Store. This service is started on demand and if disabled applications bought using Windows Store will not behave correctly. + false + C:\WINDOWS\System32\svchost.exe -k wsappx -p + + + Manual + 3 + + ClipSVC + + + + + + com.docker.service + + false + true + true + Docker Desktop Service + + . + com.docker.service + + + + + + LanmanServer + + false + false + true + Server + + + + com.docker.service + + + . + LanmanServer + + + + SamSS + Srv2 + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + LanmanServer + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + + false + "C:\Program Files\Docker\Docker\com.docker.service" + + + Automatic + 2 + + com.docker.service + + + + + + COMSysApp + + false + false + false + COM+ System Application + + . + COMSysApp + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + EventSystem + + false + false + true + COM+ Event System + + + + COMSysApp + SENS + + + . + EventSystem + + + + rpcss + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + EventSystem + + + + + + SENS + + false + false + true + System Event Notification Service + + + + COMSysApp + + + . + SENS + + + + EventSystem + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + SENS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Manages the configuration and tracking of Component Object Model (COM)+-based components. If the service is stopped, most COM+-based components will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\dllhost.exe /Processid:{02D4B3F1-FD88-11D1-960D-00805FC79235} + + + Manual + 3 + + COMSysApp + + + + + + ConsentUxUserSvc_9164d + + false + false + false + ConsentUX_9164d + + . + ConsentUxUserSvc_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + Allows ConnectUX and PC Settings to Connect and Pair with WiFi displays and Bluetooth devices. + false + C:\WINDOWS\system32\svchost.exe -k DevicesFlow + + + Manual + 3 + + ConsentUxUserSvc_9164d + + + + + + CoreMessagingRegistrar + + false + false + false + CoreMessaging + + . + CoreMessagingRegistrar + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Manages communication between system components. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetwork -p + + + Automatic + 2 + + CoreMessagingRegistrar + + + + + + cphs + + false + false + true + Intel(R) Content Protection HECI Service + + . + cphs + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Intel(R) Content Protection HECI Service - enables communication with the Content Protection FW + false + C:\WINDOWS\System32\DriverStore\FileRepository\64gh6293.inf_amd64_22fd8f9659edd17f\IntelCpHeciSvc.exe + + + Manual + 3 + + cphs + + + + + + cplspcon + + false + false + true + Intel(R) Content Protection HDCP Service + + . + cplspcon + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Intel(R) Content Protection HDCP Service - enables communication with Content Protection HDCP HW + false + C:\WINDOWS\System32\DriverStore\FileRepository\64gh6293.inf_amd64_22fd8f9659edd17f\IntelCpHDCPSvc.exe + + + Automatic + 2 + + cplspcon + + + + + + CredentialEnrollmentManagerUserSvc_9164d + + false + false + false + CredentialEnrollmentManagerUserSvc_9164d + + . + CredentialEnrollmentManagerUserSvc_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 208 + 208 + + + + + + + Credential Enrollment Manager + false + C:\WINDOWS\system32\CredentialEnrollmentManager.exe + + + Manual + 3 + + CredentialEnrollmentManagerUserSvc_9164d + + + + + + CryptSvc + + false + true + true + Cryptographic Services + + + + + + applockerfltr + + false + false + false + Smartlocker Filter Driver + + . + applockerfltr + + + + FltMgr + AppID + AppIDSvc + + + Manual + Stopped + KernelDriver + + + + + applockerfltr + + + + + + AppIDSvc + + false + false + false + Application Identity + + + + applockerfltr + + + . + AppIDSvc + + + + RpcSs + AppID + CryptSvc + + + Manual + Stopped + Win32ShareProcess + + + + + AppIDSvc + + + + + + . + CryptSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\NetworkService + Provides three management services: Catalog Database Service, which confirms the signatures of Windows files and allows new programs to be installed; Protected Root Service, which adds and removes Trusted Root Certification Authority certificates from this computer; and Automatic Root Certificate Update Service, which retrieves root certificates from Windows Update and enable scenarios such as SSL. If this service is stopped, these management services will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k NetworkService -p + + + Automatic + 2 + + CryptSvc + + + + + + CscService + + false + false + false + Offline Files + + . + CscService + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The Offline Files service performs maintenance activities on the Offline Files cache, responds to user logon and logoff events, implements the internals of the public API, and dispatches interesting events to those interested in Offline Files activities and changes in cache state. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + CscService + + + + + + DcomLaunch + + false + false + false + DCOM Server Process Launcher + . + DcomLaunch + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The DCOMLAUNCH service launches COM and DCOM servers in response to object activation requests. If this service is stopped or disabled, programs using COM or DCOM will not function properly. It is strongly recommended that you have the DCOMLAUNCH service running. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Automatic + 2 + + DcomLaunch + + + + + + debugregsvc + + false + false + false + debugregsvc + + . + debugregsvc + + + + + + Dnscache + + false + false + false + DNS Client + + + + RemoteAccess + RasMan + NcaSvc + debugregsvc + + + . + Dnscache + + + + nsi + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Dnscache + + + + + + Tcpip + + false + false + true + TCP/IP Protocol Driver + + + + WinNat + NetBT + tdx + tcpipreg + Tcpip6 + PolicyAgent + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Ndu + CDPSvc + NcbService + IPNAT + NcaSvc + iphlpsvc + IpFilterDriver + debugregsvc + + + . + Tcpip + + + + + Boot + Running + KernelDriver + + + + + Tcpip + + + + + + + + Automatic + 2 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides helper APIs to enable device discovery and debugging over the network + false + C:\WINDOWS\System32\svchost.exe -k DevToolsGroup + + + Automatic + 2 + + debugregsvc + + + + + + defragsvc + + false + false + false + Optimise drives + + . + defragsvc + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + Helps the computer run more efficiently by optimising files on storage drives. + false + C:\WINDOWS\system32\svchost.exe -k defragsvc + + + Manual + 3 + + defragsvc + + + + + + DeveloperToolsService + + false + false + false + Developer Tools Service + + . + DeveloperToolsService + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Enables scenarios for remote UWP application deployment and debugging + false + C:\WINDOWS\System32\DeveloperToolsSvc.exe + + + Manual + 3 + + DeveloperToolsService + + + + + + DeviceAssociationBrokerSvc_9164d + + false + false + false + DeviceAssociationBroker_9164d + + . + DeviceAssociationBrokerSvc_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + Enables apps to pair devices + false + C:\WINDOWS\system32\svchost.exe -k DevicesFlow -p + + + Manual + 3 + + DeviceAssociationBrokerSvc_9164d + + + + + + DeviceAssociationService + + false + true + true + Device Association Service + + . + DeviceAssociationService + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables pairing between the system and wired or wireless devices. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Automatic + 2 + + DeviceAssociationService + + + + + + DeviceInstall + + false + false + false + Device Install Service + + . + DeviceInstall + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Enables a computer to recognize and adapt to hardware changes with little or no user input. Stopping or disabling this service will result in system instability. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Manual + 3 + + DeviceInstall + + + + + + DevicePickerUserSvc_9164d + + false + false + false + DevicePicker_9164d + + . + DevicePickerUserSvc_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + This user service is used for managing the Miracast, DLNA and DIAL UI + false + C:\WINDOWS\system32\svchost.exe -k DevicesFlow + + + Manual + 3 + + DevicePickerUserSvc_9164d + + + + + + DevicesFlowUserSvc_9164d + + false + false + false + DevicesFlow_9164d + + . + DevicesFlowUserSvc_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + Allows ConnectUX and PC Settings to Connect and Pair with WiFi displays and Bluetooth devices. + false + C:\WINDOWS\system32\svchost.exe -k DevicesFlow + + + Manual + 3 + + DevicesFlowUserSvc_9164d + + + + + + DevQueryBroker + + false + true + true + DevQuery Background Discovery Broker + + . + DevQueryBroker + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables apps to discover devices with a backgroud task + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + DevQueryBroker + + + + + + Dhcp + + false + true + true + DHCP Client + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + BFE + dnscache + NSI + iphlpsvc + + + Manual + Stopped + Win32OwnProcess, Win32ShareProcess + + + + + NcaSvc + + + + + + iphlpsvc + + false + false + true + IP Helper + + + + NcaSvc + + + . + iphlpsvc + + + + RpcSS + winmgmt + tcpip + nsi + WinHttpAutoProxySvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + iphlpsvc + + + + + + WinHttpAutoProxySvc + + false + true + false + WinHTTP Web Proxy Auto-Discovery Service + + + + NcaSvc + iphlpsvc + + + . + WinHttpAutoProxySvc + + + + Dhcp + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + WinHttpAutoProxySvc + + + + + + NcdAutoSetup + + false + false + true + Network Connected Devices Auto-Setup + + . + NcdAutoSetup + + + + netprofm + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + NcdAutoSetup + + + + + + AppVClient + + false + false + false + Microsoft App-V Client + + . + AppVClient + + + + RpcSS + netprofm + AppvVfs + AppvStrm + + + Disabled + Stopped + Win32OwnProcess + + + + + AppVClient + + + + + + netprofm + + false + false + true + Network List Service + + + + NcdAutoSetup + AppVClient + + + . + netprofm + + + + RpcSs + nlasvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + netprofm + + + + + + NlaSvc + + false + false + true + Network Location Awareness + + + + NcdAutoSetup + AppVClient + netprofm + + + . + NlaSvc + + + + NSI + RpcSs + TcpIp + Dhcp + Eventlog + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NlaSvc + + + + + + . + Dhcp + + + + + + NSI + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + NSI + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NSI + + + + + + Afd + + false + false + true + Ancillary Function Driver for Winsock + + + + lmhosts + RemoteAccess + RasMan + NcaSvc + debugregsvc + Dnscache + iphlpsvc + WinHttpAutoProxySvc + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Dhcp + + + . + Afd + + + + + System + Running + KernelDriver + + + + + Afd + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\LocalService + Registers and updates IP addresses and DNS records for this computer. If this service is stopped, this computer will not receive dynamic IP addresses and DNS updates. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Automatic + 2 + + Dhcp + + + + + + diagnosticshub.standardcollector.service + + false + false + false + Microsoft (R) Diagnostics Hub Standard Collector Service + + . + diagnosticshub.standardcollector.service + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Diagnostics Hub Standard Collector Service. When running, this service collects real time ETW events and processes them. + false + C:\WINDOWS\system32\DiagSvcs\DiagnosticsHub.StandardCollector.Service.exe + + + Manual + 3 + + diagnosticshub.standardcollector.service + + + + + + diagsvc + + false + false + false + Diagnostic Execution Service + + . + diagsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Executes diagnostic actions for troubleshooting support + false + C:\WINDOWS\System32\svchost.exe -k diagnostics + + + Manual + 3 + + diagsvc + + + + + + DiagTrack + + false + true + true + Connected User Experiences and Telemetry + + . + DiagTrack + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + The Connected User Experiences and Telemetry service enables features that support in-application and connected user experiences. Additionally, this service manages the event driven collection and transmission of diagnostic and usage information (used to improve the experience and quality of the Windows Platform) when the diagnostics and usage privacy option settings are enabled under Feedback and Diagnostics. + false + C:\WINDOWS\System32\svchost.exe -k utcsvc -p + + + Automatic + 2 + + DiagTrack + + + + + + DispBrokerDesktopSvc + + false + false + true + Display Policy Service + + . + DispBrokerDesktopSvc + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Manages the connection and configuration of local and remote displays + true + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + AutomaticDelayedStart + 10 + + DispBrokerDesktopSvc + + + + + + DisplayEnhancementService + + false + false + true + Display Enhancement Service + + . + DisplayEnhancementService + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + A service for managing display enhancement such as brightness control. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + DisplayEnhancementService + + + + + + DmEnrollmentSvc + + false + false + false + Device Management Enrollment Service + + . + DmEnrollmentSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Performs Device Enrollment Activities for Device Management + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + DmEnrollmentSvc + + + + + + dmwappushservice + + false + false + false + Device Management Wireless Application Protocol (WAP) Push message Routing Service + + . + dmwappushservice + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Routes Wireless Application Protocol (WAP) Push messages received by the device and synchronizes Device Management sessions + true + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + dmwappushservice + + + + + + Dnscache + + false + false + false + DNS Client + + + + + + RemoteAccess + + false + false + false + Routing and Remote Access + + . + RemoteAccess + + + + RpcSS + Bfe + RasMan + Http + + + Disabled + Stopped + Win32ShareProcess + + + + + RemoteAccess + + + + + + RasMan + + false + true + true + Remote Access Connection Manager + + + + RemoteAccess + + + . + RasMan + + + + SstpSvc + DnsCache + + + Automatic + Running + Win32ShareProcess + + + + + RasMan + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + BFE + dnscache + NSI + iphlpsvc + + + Manual + Stopped + Win32OwnProcess, Win32ShareProcess + + + + + NcaSvc + + + + + + debugregsvc + + false + false + false + debugregsvc + + . + debugregsvc + + + + Dnscache + Tcpip + + + Automatic + Stopped + Win32OwnProcess + + + + + debugregsvc + + + + + + . + Dnscache + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + nsi + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nsi + + + + + + Afd + + false + false + true + Ancillary Function Driver for Winsock + + + + lmhosts + RemoteAccess + RasMan + NcaSvc + debugregsvc + Dnscache + iphlpsvc + WinHttpAutoProxySvc + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Dhcp + + + . + Afd + + + + + System + Running + KernelDriver + + + + + Afd + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\NetworkService + The DNS Client service (dnscache) caches Domain Name System (DNS) names and registers the full computer name for this computer. If the service is stopped, DNS names will continue to be resolved. However, the results of DNS name queries will not be cached and the computer's name will not be registered. If the service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k NetworkService -p + + + Automatic + 2 + + Dnscache + + + + + + docker + + false + true + true + Docker Engine + + . + docker + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + + false + "C:\Program Files\Docker\Docker\resources\dockerd.exe" --run-service --service-name docker -G docker-users --config-file C:\ProgramData\DockerDesktop\tmp-d4w\daemon.json + + + Automatic + 2 + + docker + + + + + + DoSvc + + false + false + true + Delivery Optimization + + . + DoSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\NetworkService + Performs content delivery optimization tasks + true + C:\WINDOWS\System32\svchost.exe -k NetworkService -p + + + AutomaticDelayedStart + 10 + + DoSvc + + + + + + dot3svc + + false + false + false + Wired AutoConfig + + . + dot3svc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + Ndisuio + + false + false + true + NDIS Usermode I/O Protocol + + + + wlpasvc + WwanSvc + WlanSvc + dot3svc + + + . + Ndisuio + + + + + Manual + Running + KernelDriver + + + + + Ndisuio + + + + + + Eaphost + + false + false + false + Extensible Authentication Protocol + + + + dot3svc + + + . + Eaphost + + + + RPCSS + KeyIso + + + Manual + Stopped + Win32ShareProcess + + + + + Eaphost + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + localSystem + The Wired AutoConfig (DOT3SVC) service is responsible for performing IEEE 802.1X authentication on Ethernet interfaces. If your current wired network deployment enforces 802.1X authentication, the DOT3SVC service should be configured to run for establishing Layer 2 connectivity and/or providing access to network resources. Wired networks that do not enforce 802.1X authentication are unaffected by the DOT3SVC service. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + dot3svc + + + + + + DPS + + false + true + true + Diagnostic Policy Service + + . + DPS + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + The Diagnostic Policy Service enables problem detection, troubleshooting and resolution for Windows components. If this service is stopped, diagnostics will no longer function. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNoNetwork -p + + + Automatic + 2 + + DPS + + + + + + DsmSvc + + false + false + false + Device Setup Manager + + . + DsmSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables the detection, download and installation of device-related software. If this service is disabled, devices may be configured with outdated software, and may not work correctly. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + DsmSvc + + + + + + DsSvc + + false + false + true + Data Sharing Service + + . + DsSvc + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides data brokering between applications. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + DsSvc + + + + + + DusmSvc + + false + false + true + Data Usage + + . + DusmSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT Authority\LocalService + Network data usage, data limit, restrict background data, metered networks. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Automatic + 2 + + DusmSvc + + + + + + Eaphost + + false + false + false + Extensible Authentication Protocol + + + + + + dot3svc + + false + false + false + Wired AutoConfig + + . + dot3svc + + + + RpcSs + Ndisuio + Eaphost + + + Manual + Stopped + Win32ShareProcess + + + + + dot3svc + + + + + + . + Eaphost + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + KeyIso + + false + false + true + CNG Key Isolation + + + + XboxNetApiSvc + dot3svc + Eaphost + + + . + KeyIso + + + + RpcSs + + + Manual + Running + Win32ShareProcess + + + + + KeyIso + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + localSystem + The Extensible Authentication Protocol (EAP) service provides network authentication in such scenarios as 802.1x wired and wireless, VPN, and Network Access Protection (NAP). EAP also provides application programming interfaces (APIs) that are used by network access clients, including wireless and VPN clients, during the authentication process. If you disable this service, this computer is prevented from accessing networks that require EAP authentication. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + Eaphost + + + + + + edgeupdate + + false + false + false + Microsoft Edge Update Service (edgeupdate) + + . + edgeupdate + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Automatic + 2 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Keeps your Microsoft software up to date. If this service is disabled or stopped, your Microsoft software will not be kept up to date, meaning security vulnerabilities that may arise cannot be fixed and features may not work. This service uninstalls itself when there is no Microsoft software using it. + true + "C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" /svc + + + AutomaticDelayedStart + 10 + + edgeupdate + + + + + + edgeupdatem + + false + false + false + Microsoft Edge Update Service (edgeupdatem) + + . + edgeupdatem + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Keeps your Microsoft software up to date. If this service is disabled or stopped, your Microsoft software will not be kept up to date, meaning security vulnerabilities that may arise cannot be fixed and features may not work. This service uninstalls itself when there is no Microsoft software using it. + true + "C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" /medsvc + + + Manual + 3 + + edgeupdatem + + + + + + EFS + + false + false + false + Encrypting File System (EFS) + + . + EFS + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides the core file encryption technology used to store encrypted files on NTFS file system volumes. If this service is stopped or disabled, applications will be unable to access encrypted files. + false + C:\WINDOWS\System32\lsass.exe + + + Manual + 3 + + EFS + + + + + + embeddedmode + + false + false + false + Embedded Mode + + . + embeddedmode + + + + + + BrokerInfrastructure + + false + false + false + Background Tasks Infrastructure Service + . + BrokerInfrastructure + + + + RpcEptMapper + DcomLaunch + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BrokerInfrastructure + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The Embedded Mode service enables scenarios related to Background Applications. Disabling this service will prevent Background Applications from being activated. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + embeddedmode + + + + + + EntAppSvc + + false + false + false + Enterprise App Management Service + + . + EntAppSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Enables enterprise application management. + false + C:\WINDOWS\system32\svchost.exe -k appmodel -p + + + Manual + 3 + + EntAppSvc + + + + + + EventLog + + false + true + true + Windows Event Log + + + + + + Wecsvc + + false + false + false + Windows Event Collector + + . + Wecsvc + + + + HTTP + Eventlog + + + Manual + Stopped + Win32ShareProcess + + + + + Wecsvc + + + + + + SurfaceUsbHubFwUpdateService + + false + true + true + Surface USB Hub Firmware Update Service + + . + SurfaceUsbHubFwUpdateService + + + + EventLog + + + Automatic + Running + Win32ShareProcess + + + + + SurfaceUsbHubFwUpdateService + + + + + + NcdAutoSetup + + false + false + true + Network Connected Devices Auto-Setup + + . + NcdAutoSetup + + + + netprofm + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + NcdAutoSetup + + + + + + AppVClient + + false + false + false + Microsoft App-V Client + + . + AppVClient + + + + RpcSS + netprofm + AppvVfs + AppvStrm + + + Disabled + Stopped + Win32OwnProcess + + + + + AppVClient + + + + + + netprofm + + false + false + true + Network List Service + + + + NcdAutoSetup + AppVClient + + + . + netprofm + + + + RpcSs + nlasvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + netprofm + + + + + + NlaSvc + + false + false + true + Network Location Awareness + + + + NcdAutoSetup + AppVClient + netprofm + + + . + NlaSvc + + + + NSI + RpcSs + TcpIp + Dhcp + Eventlog + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NlaSvc + + + + + + . + EventLog + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + This service manages events and event logs. It supports logging events, querying events, subscribing to events, archiving event logs, and managing event metadata. It can display events in both XML and plain text format. Stopping this service may compromise security and reliability of the system. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Automatic + 2 + + EventLog + + + + + + EventSystem + + false + false + true + COM+ Event System + + + + + + COMSysApp + + false + false + false + COM+ System Application + + . + COMSysApp + + + + RpcSs + EventSystem + SENS + + + Manual + Stopped + Win32OwnProcess + + + + + COMSysApp + + + + + + SENS + + false + false + true + System Event Notification Service + + + + COMSysApp + + + . + SENS + + + + EventSystem + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + SENS + + + + + + . + EventSystem + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Supports System Event Notification Service (SENS), which provides automatic distribution of events to subscribing Component Object Model (COM) components. If the service is stopped, SENS will close and will not be able to provide logon and logoff notifications. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Automatic + 2 + + EventSystem + + + + + + Fax + + false + false + false + Fax + + . + Fax + + + + + + TapiSrv + + false + false + false + Telephony + + + + Fax + + + . + TapiSrv + + + + RpcSs + + + Manual + Stopped + Win32ShareProcess + + + + + TapiSrv + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + Spooler + + false + false + true + Print Spooler + + + + Fax + + + . + Spooler + + + + RPCSS + http + + + Automatic + Running + Win32OwnProcess, InteractiveProcess + + + + + Spooler + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Enables you to send and receive faxes, using fax resources available on this computer or on the network. + false + C:\WINDOWS\system32\fxssvc.exe + + + Manual + 3 + + Fax + + + + + + fdPHost + + false + false + true + Function Discovery Provider Host + + + + + + FDResPub + + false + true + true + Function Discovery Resource Publication + + . + FDResPub + + + + RpcSs + http + fdphost + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + FDResPub + + + + + + . + fdPHost + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + http + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + http + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + http + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + The FDPHOST service hosts the Function Discovery (FD) network discovery providers. These FD providers supply network discovery services for the Simple Services Discovery Protocol (SSDP) and Web Services – Discovery (WS-D) protocol. Stopping or disabling the FDPHOST service will disable network discovery for these protocols when using FD. When this service is unavailable, network services using FD and relying on these discovery protocols will be unable to find network devices or resources. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + fdPHost + + + + + + FDResPub + + false + true + true + Function Discovery Resource Publication + + . + FDResPub + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + http + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + http + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + http + + + + + + fdphost + + false + false + true + Function Discovery Provider Host + + + + FDResPub + + + . + fdphost + + + + RpcSs + http + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + fdphost + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Publishes this computer and resources attached to this computer so they can be discovered over the network. If this service is stopped, network resources will no longer be published and they will not be discovered by other computers on the network. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -p + + + Manual + 3 + + FDResPub + + + + + + fhsvc + + false + true + true + File History Service + + . + fhsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Protects user files from accidental loss by copying them to a backup location + true + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + AutomaticDelayedStart + 10 + + fhsvc + + + + + + FileSyncHelper + + false + false + true + FileSyncHelper + + . + FileSyncHelper + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Helper service for OneDrive + false + "C:\Program Files (x86)\Microsoft OneDrive\20.169.0823.0008\FileSyncHelper.exe" + + + Manual + 3 + + FileSyncHelper + + + + + + FontCache + + false + true + true + Windows Font Cache Service + + . + FontCache + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Optimizes performance of applications by caching commonly used font data. Applications will start this service if it is not already running. It can be disabled, though doing so will degrade application performance. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Automatic + 2 + + FontCache + + + + + + FontCache3.0.0.0 + + false + false + false + Windows Presentation Foundation Font Cache 3.0.0.0 + + . + FontCache3.0.0.0 + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT Authority\LocalService + Optimizes performance of Windows Presentation Foundation (WPF) applications by caching commonly used font data. WPF applications will start this service if it is not already running. It can be disabled, though doing so will degrade the performance of WPF applications. + false + C:\WINDOWS\Microsoft.Net\Framework64\v3.0\WPF\PresentationFontCache.exe + + + Manual + 3 + + FontCache3.0.0.0 + + + + + + FrameServer + + false + false + false + Windows Camera Frame Server + + . + FrameServer + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables multiple clients to access video frames from camera devices. + false + C:\WINDOWS\System32\svchost.exe -k Camera + + + Manual + 3 + + FrameServer + + + + + + gpsvc + + false + false + true + Group Policy Client + + . + gpsvc + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + Mup + + false + false + true + Mup + + + + UmRdpService + RDPDR + LxssManagerUser_9164d + LxssManagerUser + P9Rdr + SessionEnv + Netlogon + LanmanWorkstation + mrxsmb20 + mrxsmb + WebClient + MRxDAV + CSC + rdbss + gpsvc + Dfsc + + + . + Mup + + + + + Boot + Running + FileSystemDriver + + + + + Mup + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + The service is responsible for applying settings configured by administrators for the computer and users through the Group Policy component. If the service is disabled, the settings will not be applied and applications and components will not be manageable through Group Policy. Any components or applications that depend on the Group Policy component might not be functional if the service is disabled. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + gpsvc + + + + + + GraphicsPerfSvc + + false + false + false + GraphicsPerfSvc + + . + GraphicsPerfSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Graphics performance monitor service + false + C:\WINDOWS\System32\svchost.exe -k GraphicsPerfSvcGroup + + + Manual + 3 + + GraphicsPerfSvc + + + + + + HgClientService + + false + false + false + Host Guardian Client Service + + . + HgClientService + + + + + + Winmgmt + + true + true + true + Windows Management Instrumentation + + + + vmms + NcaSvc + iphlpsvc + HgClientService + + + . + Winmgmt + + + + RPCSS + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Winmgmt + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides abstraction of Host Guardian artifacts. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + HgClientService + + + + + + hidserv + + false + true + true + Human Interface Device Service + + . + hidserv + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Activates and maintains the use of hot buttons on keyboards, remote controls and other multimedia devices. It is recommended that you keep this service running. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + hidserv + + + + + + hns + + false + false + true + Host Network Service + + . + hns + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + nsi + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nsi + + + + + + vfpext + + false + false + true + Microsoft Azure VFP Switch Extension + + + + hns + + + . + vfpext + + + + + System + Running + KernelDriver + + + + + vfpext + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides support for Windows Virtual Networks. + false + C:\WINDOWS\system32\svchost.exe -k NetSvcs -p + + + Manual + 3 + + hns + + + + + + HvHost + + false + true + true + HV Host Service + + . + HvHost + + + + + + hvservice + + false + false + true + Hypervisor/Virtual Machine Support Driver + + + + HvHost + + + . + hvservice + + + + + Manual + Running + KernelDriver + + + + + hvservice + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides an interface for the Hyper-V hypervisor to provide per-partition performance counters to the host operating system. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + HvHost + + + + + + icssvc + + false + false + false + Windows Mobile Hotspot Service + + . + icssvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + wcmsvc + + false + true + true + Windows Connection Manager + + + + WlanSvc + icssvc + + + . + wcmsvc + + + + RpcSs + NSI + + + Automatic + Running + Win32OwnProcess + + + + + wcmsvc + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT Authority\LocalService + Provides the ability to share a mobile data connection with another device. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + icssvc + + + + + + IKEEXT + + false + false + false + IKE and AuthIP IPsec Keying Modules + + + + + + XboxNetApiSvc + + false + false + false + Xbox Live Networking Service + + . + XboxNetApiSvc + + + + BFE + mpssvc + IKEEXT + KeyIso + + + Manual + Stopped + Win32ShareProcess + + + + + XboxNetApiSvc + + + + + + . + IKEEXT + + + + + + BFE + + false + false + true + Base Filtering Engine + . + BFE + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BFE + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + nsi + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nsi + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The IKEEXT service hosts the Internet Key Exchange (IKE) and Authenticated Internet Protocol (AuthIP) keying modules. These keying modules are used for authentication and key exchange in Internet Protocol security (IPsec). Stopping or disabling the IKEEXT service will disable IKE and AuthIP key exchange with peer computers. IPsec is typically configured to use IKE or AuthIP; therefore, stopping or disabling the IKEEXT service might result in an IPsec failure and might compromise the security of the system. It is strongly recommended that you have the IKEEXT service running. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + IKEEXT + + + + + + InstallService + + false + false + true + Microsoft Store Install Service + + . + InstallService + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides infrastructure support for the Microsoft Store. This service is started on demand, and if disabled then installations will not function properly. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + InstallService + + + + + + Intel(R) Capability Licensing Service TCP IP Interface + + false + false + false + Intel(R) Capability Licensing Service TCP IP Interface + + . + Intel(R) Capability Licensing Service TCP IP Interface + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Version: 1.56.87.0 + false + C:\WINDOWS\System32\DriverStore\FileRepository\iclsclient.inf_amd64_1244e13de260a91d\lib\SocketHeciServer.exe + + + Manual + 3 + + Intel(R) Capability Licensing Service TCP IP Interface + + + + + + Intel(R) TPM Provisioning Service + + false + false + false + Intel(R) TPM Provisioning Service + + . + Intel(R) TPM Provisioning Service + + + + + + + Automatic + 2 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Version: 1.56.87.0 + false + C:\WINDOWS\System32\DriverStore\FileRepository\iclsclient.inf_amd64_1244e13de260a91d\lib\TPMProvisioningService.exe + + + Automatic + 2 + + Intel(R) TPM Provisioning Service + + + + + + IntelAudioService + + false + false + false + Intel(R) Audio Service + + . + IntelAudioService + + + + + + + Automatic + 2 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + + false + C:\WINDOWS\system32\cAVS\Intel(R) Audio Service\IntelAudioService.exe + + + Automatic + 2 + + IntelAudioService + + + + + + iphlpsvc + + false + false + true + IP Helper + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + BFE + dnscache + NSI + iphlpsvc + + + Manual + Stopped + Win32OwnProcess, Win32ShareProcess + + + + + NcaSvc + + + + + + . + iphlpsvc + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + winmgmt + + true + true + true + Windows Management Instrumentation + + + + vmms + NcaSvc + iphlpsvc + HgClientService + + + . + winmgmt + + + + RPCSS + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + winmgmt + + + + + + tcpip + + false + false + true + TCP/IP Protocol Driver + + + + WinNat + NetBT + tdx + tcpipreg + Tcpip6 + PolicyAgent + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Ndu + CDPSvc + NcbService + IPNAT + NcaSvc + iphlpsvc + IpFilterDriver + debugregsvc + + + . + tcpip + + + + + Boot + Running + KernelDriver + + + + + tcpip + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + nsi + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nsi + + + + + + WinHttpAutoProxySvc + + false + true + false + WinHTTP Web Proxy Auto-Discovery Service + + + + NcaSvc + iphlpsvc + + + . + WinHttpAutoProxySvc + + + + Dhcp + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + WinHttpAutoProxySvc + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides tunnel connectivity using IPv6 transition technologies (6to4, ISATAP, Port Proxy, and Teredo), and IP-HTTPS. If this service is stopped, the computer will not have the enhanced connectivity benefits that these technologies offer. + false + C:\WINDOWS\System32\svchost.exe -k NetSvcs -p + + + Automatic + 2 + + iphlpsvc + + + + + + IpxlatCfgSvc + + false + false + false + IP Translation Configuration Service + + . + IpxlatCfgSvc + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + nsi + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nsi + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Configures and enables translation from v4 to v6 and vice versa + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + IpxlatCfgSvc + + + + + + KeyIso + + false + false + true + CNG Key Isolation + + + + + + XboxNetApiSvc + + false + false + false + Xbox Live Networking Service + + . + XboxNetApiSvc + + + + BFE + mpssvc + IKEEXT + KeyIso + + + Manual + Stopped + Win32ShareProcess + + + + + XboxNetApiSvc + + + + + + dot3svc + + false + false + false + Wired AutoConfig + + . + dot3svc + + + + RpcSs + Ndisuio + Eaphost + + + Manual + Stopped + Win32ShareProcess + + + + + dot3svc + + + + + + Eaphost + + false + false + false + Extensible Authentication Protocol + + + + dot3svc + + + . + Eaphost + + + + RPCSS + KeyIso + + + Manual + Stopped + Win32ShareProcess + + + + + Eaphost + + + + + + . + KeyIso + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The CNG key isolation service is hosted in the LSA process. The service provides key process isolation to private keys and associated cryptographic operations as required by the Common Criteria. The service stores and uses long-lived keys in a secure process complying with Common Criteria requirements. + false + C:\WINDOWS\system32\lsass.exe + + + Manual + 3 + + KeyIso + + + + + + KtmRm + + false + false + false + KtmRm for Distributed Transaction Coordinator + + . + KtmRm + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + SamSS + + false + false + false + Security Accounts Manager + + + + MSDTC + com.docker.service + LanmanServer + KtmRm + + + . + SamSS + + + + RPCSS + + + Automatic + Running + Win32ShareProcess + + + + + SamSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\NetworkService + Coordinates transactions between the Distributed Transaction Coordinator (MSDTC) and the Kernel Transaction Manager (KTM). If it is not needed, it is recommended that this service remain stopped. If it is needed, both MSDTC and KTM will start this service automatically. If this service is disabled, any MSDTC transaction interacting with a Kernel Resource Manager will fail and any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k NetworkServiceAndNoImpersonation -p + + + Manual + 3 + + KtmRm + + + + + + LanmanServer + + false + false + true + Server + + + + + + com.docker.service + + false + true + true + Docker Desktop Service + + . + com.docker.service + + + + LanmanServer + + + Automatic + Running + Win32OwnProcess + + + + + com.docker.service + + + + + + . + LanmanServer + + + + + + SamSS + + false + false + false + Security Accounts Manager + + + + MSDTC + com.docker.service + LanmanServer + KtmRm + + + . + SamSS + + + + RPCSS + + + Automatic + Running + Win32ShareProcess + + + + + SamSS + + + + + + Srv2 + + false + false + true + Server SMB 2.xxx Driver + + + + com.docker.service + LanmanServer + + + . + Srv2 + + + + srvnet + + + Manual + Running + FileSystemDriver + + + + + Srv2 + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Supports file, print, and named-pipe sharing over the network for this computer. If this service is stopped, these functions will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + LanmanServer + + + + + + LanmanWorkstation + + true + false + true + Workstation + + + + + + SessionEnv + + false + false + true + Remote Desktop Configuration + + . + SessionEnv + + + + RPCSS + LanmanWorkstation + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + SessionEnv + + + + + + Netlogon + + false + false + false + Netlogon + + . + Netlogon + + + + LanmanWorkstation + + + Manual + Stopped + Win32ShareProcess + + + + + Netlogon + + + + + + . + LanmanWorkstation + + + + + + Bowser + + false + false + true + Browser + + + + SessionEnv + Netlogon + LanmanWorkstation + + + . + Bowser + + + + + Manual + Running + FileSystemDriver + + + + + Bowser + + + + + + MRxSmb20 + + false + false + true + SMB 2.0 MiniRedirector + + + + SessionEnv + Netlogon + LanmanWorkstation + + + . + MRxSmb20 + + + + mrxsmb + + + Manual + Running + FileSystemDriver + + + + + MRxSmb20 + + + + + + NSI + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + NSI + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NSI + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\NetworkService + Creates and maintains client network connections to remote servers using the SMB protocol. If this service is stopped, these connections will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k NetworkService -p + + + Automatic + 2 + + LanmanWorkstation + + + + + + lfsvc + + false + false + true + Geolocation Service + + . + lfsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + This service monitors the current location of the system and manages geofences (a geographical location with associated events). If you turn off this service, applications will be unable to use or receive notifications for geolocation or geofences. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + lfsvc + + + + + + LicenseManager + + false + false + true + Windows License Manager Service + + . + LicenseManager + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\LocalService + Provides infrastructure support for the Microsoft Store. This service is started on demand and if disabled then content acquired through the Microsoft Store will not function properly. + false + C:\WINDOWS\System32\svchost.exe -k LocalService -p + + + Manual + 3 + + LicenseManager + + + + + + lltdsvc + + false + false + false + Link-Layer Topology Discovery Mapper + + . + lltdsvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + lltdio + + false + false + true + Link-Layer Topology Discovery Mapper I/O Driver + + + + QWAVE + lltdsvc + + + . + lltdio + + + + + Automatic + Running + KernelDriver + + + + + lltdio + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Creates a Network Map, consisting of PC and device topology (connectivity) information, and metadata describing each PC and device. If this service is disabled, the Network Map will not function properly. + false + C:\WINDOWS\System32\svchost.exe -k LocalService -p + + + Manual + 3 + + lltdsvc + + + + + + lmhosts + + false + false + true + TCP/IP NetBIOS Helper + + . + lmhosts + + + + + + Afd + + false + false + true + Ancillary Function Driver for Winsock + + + + lmhosts + RemoteAccess + RasMan + NcaSvc + debugregsvc + Dnscache + iphlpsvc + WinHttpAutoProxySvc + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Dhcp + + + . + Afd + + + + + System + Running + KernelDriver + + + + + Afd + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Provides support for the NetBIOS over TCP/IP (NetBT) service and NetBIOS name resolution for clients on the network, therefore enabling users to share files, print, and log on to the network. If this service is stopped, these functions might be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + lmhosts + + + + + + LSM + + false + false + false + Local Session Manager + + . + LSM + + + + + + RpcEptMapper + + false + false + false + RPC Endpoint Mapper + . + RpcEptMapper + + + + + Automatic + Running + Win32ShareProcess + + + + + RpcEptMapper + + + + + + DcomLaunch + + false + false + false + DCOM Server Process Launcher + . + DcomLaunch + + + + + Automatic + Running + Win32ShareProcess + + + + + DcomLaunch + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Core Windows Service that manages local user sessions. Stopping or disabling this service will result in system instability. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Automatic + 2 + + LSM + + + + + + LxpSvc + + false + false + false + Language Experience Service + + . + LxpSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides infrastructure support for deploying and configuring localized Windows resources. This service is started on demand and, if disabled, additional Windows languages will not be deployed to the system, and Windows may not function properly. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs + + + Manual + 3 + + LxpSvc + + + + + + LxssManager + + false + false + true + LxssManager + + . + LxssManager + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + staterepository + + false + true + true + State Repository Service + + + + LxssManager + AppXSvc + + + . + staterepository + + + + rpcss + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + staterepository + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + The LXSS Manager service supports running native ELF binaries. The service provides the infrastructure necessary for ELF binaries to run on Windows. If the service is stopped or disabled, those binaries will no longer run. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + LxssManager + + + + + + LxssManagerUser_9164d + + false + false + false + LxssManagerUser_9164d + + . + LxssManagerUser_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + The LXSS Manager service supports running native ELF binaries. The service provides the infrastructure necessary for ELF binaries to run on Windows. If the service is stopped or disabled, those binaries will no longer run. + false + C:\WINDOWS\system32\svchost.exe -k LxssManagerUser -p + + + Manual + 3 + + LxssManagerUser_9164d + + + + + + MapsBroker + + false + false + false + Downloaded Maps Manager + + . + MapsBroker + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Automatic + 2 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Windows service for application access to downloaded maps. This service is started on-demand by applications accessing downloaded maps. Disabling this service will prevent apps from accessing maps. + true + C:\WINDOWS\System32\svchost.exe -k NetworkService -p + + + AutomaticDelayedStart + 10 + + MapsBroker + + + + + + MessagingService_9164d + + false + false + false + MessagingService_9164d + + . + MessagingService_9164d + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + 224 + 224 + + + + + + + Service supporting text messaging and related functionality. + false + C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup + + + Manual + 3 + + MessagingService_9164d + + + + + + MicrosoftEdgeDevElevationService + + false + false + false + Microsoft Edge Dev Elevation Service + + . + MicrosoftEdgeDevElevationService + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Keeps Microsoft Edge Dev up to update. If this service is disabled, the application will not be kept up to date. + false + "C:\Program Files (x86)\Microsoft\Edge Dev\Application\88.0.702.0\elevation_service.exe" + + + Manual + 3 + + MicrosoftEdgeDevElevationService + + + + + + MicrosoftEdgeElevationService + + false + false + false + Microsoft Edge Elevation Service + + . + MicrosoftEdgeElevationService + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Keeps Microsoft Edge up to update. If this service is disabled, the application will not be kept up to date. + false + "C:\Program Files (x86)\Microsoft\Edge\Application\87.0.664.41\elevation_service.exe" + + + Manual + 3 + + MicrosoftEdgeElevationService + + + + + + MixedRealityOpenXRSvc + + false + false + false + Windows Mixed Reality OpenXR Service + + . + MixedRealityOpenXRSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Enables Mixed Reality OpenXR runtime functionality + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + MixedRealityOpenXRSvc + + + + + + mpssvc + + false + false + false + Windows Defender Firewall + . + mpssvc + + + + + + mpsdrv + + false + false + true + Windows Defender Firewall Authorization Driver + . + mpsdrv + + + + + Manual + Running + KernelDriver + + + + + mpsdrv + + + + + + bfe + + false + false + true + Base Filtering Engine + . + bfe + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + bfe + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + NT Authority\LocalService + Windows Defender Firewall helps to protect your computer by preventing unauthorised users from gaining access to your computer through the Internet or a network. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetworkFirewall -p + + + Automatic + 2 + + mpssvc + + + + + + MSDTC + + false + false + false + Distributed Transaction Coordinator + + . + MSDTC + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + SamSS + + false + false + false + Security Accounts Manager + + + + MSDTC + com.docker.service + LanmanServer + KtmRm + + + . + SamSS + + + + RPCSS + + + Automatic + Running + Win32ShareProcess + + + + + SamSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Coordinates transactions that span multiple resource managers, such as databases, message queues, and file systems. If this service is stopped, these transactions will fail. If this service is disabled, any services that explicitly depend on it will fail to start. + true + C:\WINDOWS\System32\msdtc.exe + + + Manual + 3 + + MSDTC + + + + + + MSiSCSI + + false + false + false + Microsoft iSCSI Initiator Service + + . + MSiSCSI + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Manages Internet SCSI (iSCSI) sessions from this computer to remote iSCSI target devices. If this service is stopped, this computer will not be able to login or access iSCSI targets. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + MSiSCSI + + + + + + msiserver + + false + false + false + Windows Installer + + . + msiserver + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Adds, modifies and removes applications provided as a Windows Installer or APPX package (*.msi, *.msp, *.appx). If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\msiexec.exe /V + + + Manual + 3 + + msiserver + + + + + + NaturalAuthentication + + false + false + false + Natural Authentication + + . + NaturalAuthentication + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + ProfSvc + + false + true + true + User Profile Service + + + + XblGameSave + TokenBroker + UserManager + shpamsvc + NaturalAuthentication + Appinfo + + + . + ProfSvc + + + + RpcSs + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + ProfSvc + + + + + + Schedule + + false + true + true + Task Scheduler + + + + NaturalAuthentication + + + . + Schedule + + + + RPCSS + SystemEventsBroker + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Schedule + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Signal aggregator service, that evaluates signals based on time, network, geolocation, bluetooth and cdf factors. Supported features are Device Unlock, Dynamic Lock and Dynamo MDM policies + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + NaturalAuthentication + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + + + BFE + + false + false + true + Base Filtering Engine + . + BFE + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BFE + + + + + + dnscache + + false + false + false + DNS Client + + + + RemoteAccess + RasMan + NcaSvc + debugregsvc + + + . + dnscache + + + + nsi + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + dnscache + + + + + + NSI + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + NSI + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NSI + + + + + + iphlpsvc + + false + false + true + IP Helper + + + + NcaSvc + + + . + iphlpsvc + + + + RpcSS + winmgmt + tcpip + nsi + WinHttpAutoProxySvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + iphlpsvc + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides DirectAccess status notification for UI components + false + C:\WINDOWS\System32\svchost.exe -k NetSvcs -p + + + Manual + 3 + + NcaSvc + + + + + + NcbService + + false + false + true + Network Connection Broker + + + + + + CDPSvc + + false + false + true + Connected Devices Platform Service + + . + CDPSvc + + + + ncbservice + RpcSS + Tcpip + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + CDPSvc + + + + + + . + NcbService + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + tcpip + + false + false + true + TCP/IP Protocol Driver + + + + WinNat + NetBT + tdx + tcpipreg + Tcpip6 + PolicyAgent + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Ndu + CDPSvc + NcbService + IPNAT + NcaSvc + iphlpsvc + IpFilterDriver + debugregsvc + + + . + tcpip + + + + + Boot + Running + KernelDriver + + + + + tcpip + + + + + + BrokerInfrastructure + + false + false + false + Background Tasks Infrastructure Service + . + BrokerInfrastructure + + + + RpcEptMapper + DcomLaunch + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BrokerInfrastructure + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Brokers connections that allow Windows Store Apps to receive notifications from the internet. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + NcbService + + + + + + NcdAutoSetup + + false + false + true + Network Connected Devices Auto-Setup + + . + NcdAutoSetup + + + + + + netprofm + + false + false + true + Network List Service + + + + NcdAutoSetup + AppVClient + + + . + netprofm + + + + RpcSs + nlasvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + netprofm + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Network Connected Devices Auto-Setup service monitors and installs qualified devices that connect to a qualified network. Stopping or disabling this service will prevent Windows from discovering and installing qualified network connected devices automatically. Users can still manually add network connected devices to a PC through the user interface. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNoNetwork -p + + + Manual + 3 + + NcdAutoSetup + + + + + + Netlogon + + false + false + false + Netlogon + + . + Netlogon + + + + + + LanmanWorkstation + + true + false + true + Workstation + + + + SessionEnv + Netlogon + + + . + LanmanWorkstation + + + + Bowser + MRxSmb20 + NSI + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + LanmanWorkstation + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Maintains a secure channel between this computer and the domain controller for authenticating users and services. If this service is stopped, the computer may not authenticate users and services and the domain controller cannot register DNS records. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\lsass.exe + + + Manual + 3 + + Netlogon + + + + + + Netman + + false + false + false + Network Connections + + . + Netman + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + nsi + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nsi + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Manages objects in the Network and Dial-Up Connections folder, in which you can view both local area network and remote connections. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + Netman + + + + + + netprofm + + false + false + true + Network List Service + + + + + + NcdAutoSetup + + false + false + true + Network Connected Devices Auto-Setup + + . + NcdAutoSetup + + + + netprofm + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + NcdAutoSetup + + + + + + AppVClient + + false + false + false + Microsoft App-V Client + + . + AppVClient + + + + RpcSS + netprofm + AppvVfs + AppvStrm + + + Disabled + Stopped + Win32OwnProcess + + + + + AppVClient + + + + + + . + netprofm + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + nlasvc + + false + false + true + Network Location Awareness + + + + NcdAutoSetup + AppVClient + netprofm + + + . + nlasvc + + + + NSI + RpcSs + TcpIp + Dhcp + Eventlog + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + nlasvc + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Identifies the networks the computer has connected to, collects and stores properties for these networks, and notifies applications when these properties change. + false + C:\WINDOWS\System32\svchost.exe -k LocalService -p + + + Manual + 3 + + netprofm + + + + + + NetSetupSvc + + false + false + false + Network Setup Service + + . + NetSetupSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + The Network Setup Service manages the installation of network drivers and permits the configuration of low-level network settings. If this service is stopped, any driver installations that are in progress may be cancelled. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + NetSetupSvc + + + + + + NetTcpPortSharing + + false + false + false + Net.Tcp Port Sharing Service + + . + NetTcpPortSharing + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Provides ability to share TCP ports over the net.tcp protocol. + false + C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\SMSvcHost.exe + + + Disabled + 4 + + NetTcpPortSharing + + + + + + NgcCtnrSvc + + false + false + true + Microsoft Passport Container + . + NgcCtnrSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Manages local user identity keys used to authenticate the user to identity providers, as well as TPM virtual smart cards. If this service is disabled, local user identity keys and TPM virtual smart cards will not be accessible. It is recommended that you do not reconfigure this service. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + NgcCtnrSvc + + + + + + NgcSvc + + false + false + true + Microsoft Passport + . + NgcSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides process isolation for cryptographic keys used to provide authentication to a user’s associated identity providers. If this service is disabled, all uses and management of these keys will not be available, which includes machine log-on and single sign-on for apps and websites. This service starts and stops automatically. It is recommended that you do not reconfigure this service. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + NgcSvc + + + + + + NlaSvc + + false + false + true + Network Location Awareness + + + + + + NcdAutoSetup + + false + false + true + Network Connected Devices Auto-Setup + + . + NcdAutoSetup + + + + netprofm + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + NcdAutoSetup + + + + + + AppVClient + + false + false + false + Microsoft App-V Client + + . + AppVClient + + + + RpcSS + netprofm + AppvVfs + AppvStrm + + + Disabled + Stopped + Win32OwnProcess + + + + + AppVClient + + + + + + netprofm + + false + false + true + Network List Service + + + + NcdAutoSetup + AppVClient + + + . + netprofm + + + + RpcSs + nlasvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + netprofm + + + + + + . + NlaSvc + + + + + + NSI + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + NSI + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NSI + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + TcpIp + + false + false + true + TCP/IP Protocol Driver + + + + WinNat + NetBT + tdx + tcpipreg + Tcpip6 + PolicyAgent + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Ndu + CDPSvc + NcbService + IPNAT + NcaSvc + iphlpsvc + IpFilterDriver + debugregsvc + + + . + TcpIp + + + + + Boot + Running + KernelDriver + + + + + TcpIp + + + + + + Dhcp + + false + true + true + DHCP Client + + + + NcaSvc + iphlpsvc + WinHttpAutoProxySvc + NcdAutoSetup + AppVClient + netprofm + NlaSvc + + + . + Dhcp + + + + NSI + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Dhcp + + + + + + Eventlog + + false + true + true + Windows Event Log + + + + Wecsvc + SurfaceUsbHubFwUpdateService + NcdAutoSetup + AppVClient + netprofm + NlaSvc + + + . + Eventlog + + + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Eventlog + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\NetworkService + Collects and stores configuration information for the network and notifies programs when this information is modified. If this service is stopped, configuration information might be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k NetworkService -p + + + Automatic + 2 + + NlaSvc + + + + + + nsi + + false + false + true + Network Store Interface Service + + + + + + WlanSvc + + false + true + true + WLAN AutoConfig + + . + WlanSvc + + + + nativewifip + RpcSs + Ndisuio + wcmsvc + + + Automatic + Running + Win32OwnProcess + + + + + WlanSvc + + + + + + icssvc + + false + false + false + Windows Mobile Hotspot Service + + . + icssvc + + + + RpcSs + wcmsvc + + + Manual + Stopped + Win32ShareProcess + + + + + icssvc + + + + + + Wcmsvc + + false + true + true + Windows Connection Manager + + + + WlanSvc + icssvc + + + . + Wcmsvc + + + + RpcSs + NSI + + + Automatic + Running + Win32OwnProcess + + + + + Wcmsvc + + + + + + upnphost + + false + false + false + UPnP Device Host + + . + upnphost + + + + SSDPSRV + HTTP + + + Manual + Stopped + Win32ShareProcess + + + + + upnphost + + + + + + SSDPSRV + + false + true + true + SSDP Discovery + + + + upnphost + + + . + SSDPSRV + + + + HTTP + NSI + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + SSDPSRV + + + + + + NcdAutoSetup + + false + false + true + Network Connected Devices Auto-Setup + + . + NcdAutoSetup + + + + netprofm + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + NcdAutoSetup + + + + + + AppVClient + + false + false + false + Microsoft App-V Client + + . + AppVClient + + + + RpcSS + netprofm + AppvVfs + AppvStrm + + + Disabled + Stopped + Win32OwnProcess + + + + + AppVClient + + + + + + netprofm + + false + false + true + Network List Service + + + + NcdAutoSetup + AppVClient + + + . + netprofm + + + + RpcSs + nlasvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + netprofm + + + + + + NlaSvc + + false + false + true + Network Location Awareness + + + + NcdAutoSetup + AppVClient + netprofm + + + . + NlaSvc + + + + NSI + RpcSs + TcpIp + Dhcp + Eventlog + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NlaSvc + + + + + + Netman + + false + false + false + Network Connections + + . + Netman + + + + RpcSs + nsi + + + Manual + Stopped + Win32ShareProcess + + + + + Netman + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + BFE + dnscache + NSI + iphlpsvc + + + Manual + Stopped + Win32OwnProcess, Win32ShareProcess + + + + + NcaSvc + + + + + + SessionEnv + + false + false + true + Remote Desktop Configuration + + . + SessionEnv + + + + RPCSS + LanmanWorkstation + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + SessionEnv + + + + + + Netlogon + + false + false + false + Netlogon + + . + Netlogon + + + + LanmanWorkstation + + + Manual + Stopped + Win32ShareProcess + + + + + Netlogon + + + + + + LanmanWorkstation + + true + false + true + Workstation + + + + SessionEnv + Netlogon + + + . + LanmanWorkstation + + + + Bowser + MRxSmb20 + NSI + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + LanmanWorkstation + + + + + + IpxlatCfgSvc + + false + false + false + IP Translation Configuration Service + + . + IpxlatCfgSvc + + + + nsi + + + Manual + Stopped + Win32ShareProcess + + + + + IpxlatCfgSvc + + + + + + iphlpsvc + + false + false + true + IP Helper + + + + NcaSvc + + + . + iphlpsvc + + + + RpcSS + winmgmt + tcpip + nsi + WinHttpAutoProxySvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + iphlpsvc + + + + + + XboxNetApiSvc + + false + false + false + Xbox Live Networking Service + + . + XboxNetApiSvc + + + + BFE + mpssvc + IKEEXT + KeyIso + + + Manual + Stopped + Win32ShareProcess + + + + + XboxNetApiSvc + + + + + + IKEEXT + + false + false + false + IKE and AuthIP IPsec Keying Modules + + + + XboxNetApiSvc + + + . + IKEEXT + + + + BFE + nsi + + + Manual + Stopped + Win32ShareProcess + + + + + IKEEXT + + + + + + hns + + false + false + true + Host Network Service + + . + hns + + + + RpcSs + nsi + vfpext + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + hns + + + + + + RemoteAccess + + false + false + false + Routing and Remote Access + + . + RemoteAccess + + + + RpcSS + Bfe + RasMan + Http + + + Disabled + Stopped + Win32ShareProcess + + + + + RemoteAccess + + + + + + RasMan + + false + true + true + Remote Access Connection Manager + + + + RemoteAccess + + + . + RasMan + + + + SstpSvc + DnsCache + + + Automatic + Running + Win32ShareProcess + + + + + RasMan + + + + + + debugregsvc + + false + false + false + debugregsvc + + . + debugregsvc + + + + Dnscache + Tcpip + + + Automatic + Stopped + Win32OwnProcess + + + + + debugregsvc + + + + + + Dnscache + + false + false + false + DNS Client + + + + RemoteAccess + RasMan + NcaSvc + debugregsvc + + + . + Dnscache + + + + nsi + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Dnscache + + + + + + WinHttpAutoProxySvc + + false + true + false + WinHTTP Web Proxy Auto-Discovery Service + + + + NcaSvc + iphlpsvc + + + . + WinHttpAutoProxySvc + + + + Dhcp + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + WinHttpAutoProxySvc + + + + + + Dhcp + + false + true + true + DHCP Client + + + + NcaSvc + iphlpsvc + WinHttpAutoProxySvc + NcdAutoSetup + AppVClient + netprofm + NlaSvc + + + . + Dhcp + + + + NSI + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Dhcp + + + + + + . + nsi + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + nsiproxy + + false + false + true + NSI Proxy Service Driver + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + nsi + + + . + nsiproxy + + + + + System + Running + KernelDriver + + + + + nsiproxy + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\LocalService + This service delivers network notifications (e.g. interface addition/deleting etc) to user mode clients. Stopping this service will cause loss of network connectivity. If this service is disabled, any other services that explicitly depend on this service will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Automatic + 2 + + nsi + + + + + + nvagent + + false + true + true + Network Virtualization Service + + . + nvagent + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides network virtualization services. + false + C:\WINDOWS\system32\svchost.exe -k NetSvcs + + + Manual + 3 + + nvagent + + + + + + NVDisplay.ContainerLocalSystem + + false + true + true + NVIDIA Display Container LS + + . + NVDisplay.ContainerLocalSystem + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Container service for NVIDIA root features + false + "C:\Program Files\NVIDIA Corporation\Display.NvContainer\NVDisplay.Container.exe" -s NVDisplay.ContainerLocalSystem -f "C:\ProgramData\NVIDIA\NVDisplay.ContainerLocalSystem.log" -l 3 -d "C:\Program Files\NVIDIA Corporation\Display.NvContainer\plugins\LocalSystem" -r -p 30000 + + + Automatic + 2 + + NVDisplay.ContainerLocalSystem + + + + + + NvTelemetryContainer + + false + true + true + NVIDIA Telemetry Container + + . + NvTelemetryContainer + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Container service for NVIDIA Telemetry + false + "C:\Program Files (x86)\NVIDIA Corporation\NvTelemetry\NvTelemetryContainer.exe" -s NvTelemetryContainer -f "C:\ProgramData\NVIDIA\NvTelemetryContainer.log" -l 3 -d "C:\Program Files (x86)\NVIDIA Corporation\NvTelemetry\plugins" -r + + + Automatic + 2 + + NvTelemetryContainer + + + + + + OneDrive Updater Service + + false + false + false + OneDrive Updater Service + + . + OneDrive Updater Service + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Keeps your OneDrive up to date. + false + "C:\Program Files (x86)\Microsoft OneDrive\20.169.0823.0008\OneDriveUpdaterService.exe" + + + Manual + 3 + + OneDrive Updater Service + + + + + + OneSyncSvc_9164d + + false + false + true + Sync Host_9164d + + . + OneSyncSvc_9164d + + + + + + + Automatic + 2 + + + + Running + 4 + + + + 224 + 224 + + + + + + + This service synchronizes mail, contacts, calendar and various other user data. Mail and other applications dependent on this functionality will not work properly when this service is not running. + true + C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup + + + AutomaticDelayedStart + 10 + + OneSyncSvc_9164d + + + + + + ose64 + + false + false + false + Office 64 Source Engine + + . + ose64 + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Saves installation files used for updates and repairs and is required for the downloading of Setup updates and Watson error reports. + false + "c:\Program Files\Common Files\Microsoft Shared\Source Engine\OSE.EXE" + + + Manual + 3 + + ose64 + + + + + + p2pimsvc + + false + false + false + Peer Networking Identity Manager + + + + + + PNRPAutoReg + + false + false + false + PNRP Machine Name Publication Service + + . + PNRPAutoReg + + + + pnrpsvc + + + Manual + Stopped + Win32ShareProcess + + + + + PNRPAutoReg + + + + + + p2psvc + + false + false + false + Peer Networking Grouping + + . + p2psvc + + + + p2pimsvc + PNRPSvc + + + Manual + Stopped + Win32ShareProcess + + + + + p2psvc + + + + + + PNRPsvc + + false + false + false + Peer Name Resolution Protocol + + + + PNRPAutoReg + p2psvc + + + . + PNRPsvc + + + + p2pimsvc + + + Manual + Stopped + Win32ShareProcess + + + + + PNRPsvc + + + + + + . + p2pimsvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Provides identity services for the Peer Name Resolution Protocol (PNRP) and Peer-to-Peer Grouping services. If disabled, the Peer Name Resolution Protocol (PNRP) and Peer-to-Peer Grouping services may not function, and some applications, such as HomeGroup and Remote Assistance, may not function correctly. + false + C:\WINDOWS\System32\svchost.exe -k LocalServicePeerNet + + + Manual + 3 + + p2pimsvc + + + + + + p2psvc + + false + false + false + Peer Networking Grouping + + . + p2psvc + + + + + + p2pimsvc + + false + false + false + Peer Networking Identity Manager + + + + PNRPAutoReg + p2psvc + PNRPsvc + + + . + p2pimsvc + + + + + Manual + Stopped + Win32ShareProcess + + + + + p2pimsvc + + + + + + PNRPSvc + + false + false + false + Peer Name Resolution Protocol + + + + PNRPAutoReg + p2psvc + + + . + PNRPSvc + + + + p2pimsvc + + + Manual + Stopped + Win32ShareProcess + + + + + PNRPSvc + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Enables multi-party communication using Peer-to-Peer Grouping. If disabled, some applications, such as HomeGroup, may not function. + false + C:\WINDOWS\System32\svchost.exe -k LocalServicePeerNet + + + Manual + 3 + + p2psvc + + + + + + PcaSvc + + false + true + true + Program Compatibility Assistant Service + + . + PcaSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + This service provides support for the Program Compatibility Assistant (PCA). PCA monitors programs installed and run by the user and detects known compatibility problems. If this service is stopped, PCA will not function properly. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + PcaSvc + + + + + + PeerDistSvc + + false + false + false + BranchCache + + . + PeerDistSvc + + + + + + http + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + http + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + http + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\NetworkService + This service caches network content from peers on the local subnet. + false + C:\WINDOWS\System32\svchost.exe -k PeerDist + + + Manual + 3 + + PeerDistSvc + + + + + + perceptionsimulation + + false + false + false + Windows Perception Simulation Service + + . + perceptionsimulation + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Enables spatial perception simulation, virtual camera management and spatial input simulation. + false + C:\WINDOWS\system32\PerceptionSimulation\PerceptionSimulationService.exe + + + Manual + 3 + + perceptionsimulation + + + + + + PerfHost + + false + false + false + Performance Counter DLL Host + + . + PerfHost + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Enables remote users and 64-bit processes to query performance counters provided by 32-bit DLLs. If this service is stopped, only local users and 32-bit processes will be able to query performance counters provided by 32-bit DLLs. + false + C:\WINDOWS\SysWow64\perfhost.exe + + + Manual + 3 + + PerfHost + + + + + + PhoneSvc + + false + false + true + Phone Service + + . + PhoneSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\LocalService + Manages the telephony state on the device + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + PhoneSvc + + + + + + PimIndexMaintenanceSvc_9164d + + false + false + true + Contact Data_9164d + + . + PimIndexMaintenanceSvc_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 224 + 224 + + + + + + + Indexes contact data for fast contact searching. If you stop or disable this service, contacts might be missing from your search results. + false + C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup + + + Manual + 3 + + PimIndexMaintenanceSvc_9164d + + + + + + pla + + false + false + false + Performance Logs & Alerts + . + pla + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Performance Logs and Alerts Collects performance data from local or remote computers based on preconfigured schedule parameters, then writes the data to a log or triggers an alert. If this service is stopped, performance information will not be collected. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNoNetwork -p + + + Manual + 3 + + pla + + + + + + PlugPlay + + false + true + true + Plug and Play + + . + PlugPlay + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables a computer to recognize and adapt to hardware changes with little or no user input. Stopping or disabling this service will result in system instability. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Manual + 3 + + PlugPlay + + + + + + PNRPAutoReg + + false + false + false + PNRP Machine Name Publication Service + + . + PNRPAutoReg + + + + + + pnrpsvc + + false + false + false + Peer Name Resolution Protocol + + + + PNRPAutoReg + p2psvc + + + . + pnrpsvc + + + + p2pimsvc + + + Manual + Stopped + Win32ShareProcess + + + + + pnrpsvc + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + This service publishes a machine name using the Peer Name Resolution Protocol. Configuration is managed via the netsh context 'p2p pnrp peer' + false + C:\WINDOWS\System32\svchost.exe -k LocalServicePeerNet + + + Manual + 3 + + PNRPAutoReg + + + + + + PNRPsvc + + false + false + false + Peer Name Resolution Protocol + + + + + + PNRPAutoReg + + false + false + false + PNRP Machine Name Publication Service + + . + PNRPAutoReg + + + + pnrpsvc + + + Manual + Stopped + Win32ShareProcess + + + + + PNRPAutoReg + + + + + + p2psvc + + false + false + false + Peer Networking Grouping + + . + p2psvc + + + + p2pimsvc + PNRPSvc + + + Manual + Stopped + Win32ShareProcess + + + + + p2psvc + + + + + + . + PNRPsvc + + + + + + p2pimsvc + + false + false + false + Peer Networking Identity Manager + + + + PNRPAutoReg + p2psvc + PNRPsvc + + + . + p2pimsvc + + + + + Manual + Stopped + Win32ShareProcess + + + + + p2pimsvc + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Enables serverless peer name resolution over the Internet using the Peer Name Resolution Protocol (PNRP). If disabled, some peer-to-peer and collaborative applications, such as Remote Assistance, may not function. + false + C:\WINDOWS\System32\svchost.exe -k LocalServicePeerNet + + + Manual + 3 + + PNRPsvc + + + + + + PolicyAgent + + false + true + true + IPsec Policy Agent + + . + PolicyAgent + + + + + + Tcpip + + false + false + true + TCP/IP Protocol Driver + + + + WinNat + NetBT + tdx + tcpipreg + Tcpip6 + PolicyAgent + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Ndu + CDPSvc + NcbService + IPNAT + NcaSvc + iphlpsvc + IpFilterDriver + debugregsvc + + + . + Tcpip + + + + + Boot + Running + KernelDriver + + + + + Tcpip + + + + + + bfe + + false + false + true + Base Filtering Engine + . + bfe + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + bfe + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\NetworkService + Internet Protocol security (IPsec) supports network-level peer authentication, data origin authentication, data integrity, data confidentiality (encryption), and replay protection. This service enforces IPsec policies created through the IP Security Policies snap-in or the command-line tool "netsh ipsec". If you stop this service, you may experience network connectivity issues if your policy requires that connections use IPsec. Also,remote management of Windows Defender Firewall is not available when this service is stopped. + false + C:\WINDOWS\system32\svchost.exe -k NetworkServiceNetworkRestricted -p + + + Manual + 3 + + PolicyAgent + + + + + + Power + + false + false + false + Power + + . + Power + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Manages power policy and power policy notification delivery. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Automatic + 2 + + Power + + + + + + PrintNotify + + false + false + false + Printer Extensions and Notifications + + . + PrintNotify + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess, InteractiveProcess + 288 + + + + + + LocalSystem + This service opens custom printer dialogue boxes and handles notifications from a remote print server or a printer. If you turn this service off, you won’t be able to see printer extensions or notifications. + false + C:\WINDOWS\system32\svchost.exe -k print + + + Manual + 3 + + PrintNotify + + + + + + PrintWorkflowUserSvc_9164d + + false + false + true + PrintWorkflow_9164d + + . + PrintWorkflowUserSvc_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 240 + 240 + + + + + + + Provides support for Print Workflow applications. If you turn off this service, you may not be able to print successfully. + false + C:\WINDOWS\system32\svchost.exe -k PrintWorkflow + + + Manual + 3 + + PrintWorkflowUserSvc_9164d + + + + + + ProfSvc + + false + true + true + User Profile Service + + + + + + XblGameSave + + false + false + false + Xbox Live Game Save + + . + XblGameSave + + + + UserManager + XblAuthManager + + + Manual + Stopped + Win32ShareProcess + + + + + XblGameSave + + + + + + TokenBroker + + false + false + true + Web Account Manager + + . + TokenBroker + + + + UserManager + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + TokenBroker + + + + + + UserManager + + false + false + true + User Manager + + + + XblGameSave + TokenBroker + + + . + UserManager + + + + RpcSs + ProfSvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + UserManager + + + + + + shpamsvc + + false + false + false + Shared PC Account Manager + + . + shpamsvc + + + + RpcSs + ProfSvc + + + Disabled + Stopped + Win32ShareProcess + + + + + shpamsvc + + + + + + NaturalAuthentication + + false + false + false + Natural Authentication + + . + NaturalAuthentication + + + + RpcSs + ProfSvc + Schedule + + + Manual + Stopped + Win32ShareProcess + + + + + NaturalAuthentication + + + + + + Appinfo + + false + false + true + Application Information + + . + Appinfo + + + + RpcSs + ProfSvc + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + Appinfo + + + + + + . + ProfSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + This service is responsible for loading and unloading user profiles. If this service is stopped or disabled, users will no longer be able to successfully sign in or sign out, apps might have problems getting to users' data, and components registered to receive profile event notifications won't receive them. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + ProfSvc + + + + + + PushToInstall + + false + false + false + Windows PushToInstall Service + + . + PushToInstall + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides infrastructure support for the Microsoft Store. This service is started automatically and if disabled then remote installations will not function properly. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + PushToInstall + + + + + + QWAVE + + false + false + false + Quality Windows Audio Video Experience + + . + QWAVE + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + psched + + false + false + true + QoS Packet Scheduler + + + + QWAVE + + + . + psched + + + + + System + Running + KernelDriver + + + + + psched + + + + + + QWAVEdrv + + false + false + false + QWAVE driver + + + + QWAVE + + + . + QWAVEdrv + + + + + Manual + Stopped + KernelDriver + + + + + QWAVEdrv + + + + + + LLTDIO + + false + false + true + Link-Layer Topology Discovery Mapper I/O Driver + + + + QWAVE + lltdsvc + + + . + LLTDIO + + + + + Automatic + Running + KernelDriver + + + + + LLTDIO + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Quality Windows Audio Video Experience (qWave) is a networking platform for Audio Video (AV) streaming applications on IP home networks. qWave enhances AV streaming performance and reliability by ensuring network quality-of-service (QoS) for AV applications. It provides mechanisms for admission control, run time monitoring and enforcement, application feedback, and traffic prioritization. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -p + + + Manual + 3 + + QWAVE + + + + + + RasAuto + + false + false + false + Remote Access Auto Connection Manager + + . + RasAuto + + + + + + RasAcd + + false + false + false + Remote Access Auto Connection Driver + + + + RasAuto + + + . + RasAcd + + + + + Manual + Stopped + KernelDriver + + + + + RasAcd + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + localSystem + Creates a connection to a remote network whenever a program references a remote DNS or NetBIOS name or address. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + RasAuto + + + + + + RasMan + + false + true + true + Remote Access Connection Manager + + + + + + RemoteAccess + + false + false + false + Routing and Remote Access + + . + RemoteAccess + + + + RpcSS + Bfe + RasMan + Http + + + Disabled + Stopped + Win32ShareProcess + + + + + RemoteAccess + + + + + + . + RasMan + + + + + + SstpSvc + + false + true + true + Secure Socket Tunneling Protocol Service + + + + RemoteAccess + RasMan + + + . + SstpSvc + + + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + SstpSvc + + + + + + DnsCache + + false + false + false + DNS Client + + + + RemoteAccess + RasMan + NcaSvc + debugregsvc + + + . + DnsCache + + + + nsi + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + DnsCache + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + localSystem + Manages dial-up and virtual private network (VPN) connections from this computer to the Internet or other remote networks. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs + + + Automatic + 2 + + RasMan + + + + + + RemoteAccess + + false + false + false + Routing and Remote Access + + . + RemoteAccess + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + Bfe + + false + false + true + Base Filtering Engine + . + Bfe + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + Bfe + + + + + + RasMan + + false + true + true + Remote Access Connection Manager + + + + RemoteAccess + + + . + RasMan + + + + SstpSvc + DnsCache + + + Automatic + Running + Win32ShareProcess + + + + + RasMan + + + + + + Http + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + Http + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + Http + + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + localSystem + Offers routing services to businesses in local area and wide area network environments. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs + + + Disabled + 4 + + RemoteAccess + + + + + + RemoteRegistry + + false + false + false + Remote Registry + + . + RemoteRegistry + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Enables remote users to modify registry settings on this computer. If this service is stopped, the registry can be modified only by users on this computer. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k localService -p + + + Disabled + 4 + + RemoteRegistry + + + + + + RetailDemo + + false + false + false + Retail Demo Service + + . + RetailDemo + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The Retail Demo service controls device activity while the device is in retail demo mode. + false + C:\WINDOWS\System32\svchost.exe -k rdxgroup + + + Manual + 3 + + RetailDemo + + + + + + RmSvc + + false + false + true + Radio Management Service + + . + RmSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Radio Management and Airplane Mode Service + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted + + + Manual + 3 + + RmSvc + + + + + + rpcapd + + false + false + false + Remote Packet Capture Protocol v.0 (experimental) + + . + rpcapd + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Allows to capture traffic on this machine from a remote machine. + false + "C:\Program Files (x86)\WinPcap\rpcapd.exe" -d -f "C:\Program Files (x86)\WinPcap\rpcapd.ini" + + + Manual + 3 + + rpcapd + + + + + + RpcEptMapper + + false + false + false + RPC Endpoint Mapper + . + RpcEptMapper + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\NetworkService + Resolves RPC interfaces identifiers to transport endpoints. If this service is stopped or disabled, programs using Remote Procedure Call (RPC) services will not function properly. + false + C:\WINDOWS\system32\svchost.exe -k RPCSS -p + + + Automatic + 2 + + RpcEptMapper + + + + + + RpcLocator + + false + false + false + Remote Procedure Call (RPC) Locator + + . + RpcLocator + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + In Windows 2003 and earlier versions of Windows, the Remote Procedure Call (RPC) Locator service manages the RPC name service database. In Windows Vista and later versions of Windows, this service does not provide any functionality and is present for application compatibility. + false + C:\WINDOWS\system32\locator.exe + + + Manual + 3 + + RpcLocator + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + + + RpcEptMapper + + false + false + false + RPC Endpoint Mapper + . + RpcEptMapper + + + + + Automatic + Running + Win32ShareProcess + + + + + RpcEptMapper + + + + + + DcomLaunch + + false + false + false + DCOM Server Process Launcher + . + DcomLaunch + + + + + Automatic + Running + Win32ShareProcess + + + + + DcomLaunch + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\NetworkService + The RPCSS service is the Service Control Manager for COM and DCOM servers. It performs object activations requests, object exporter resolutions and distributed garbage collection for COM and DCOM servers. If this service is stopped or disabled, programs using COM or DCOM will not function properly. It is strongly recommended that you have the RPCSS service running. + false + C:\WINDOWS\system32\svchost.exe -k rpcss -p + + + Automatic + 2 + + RpcSs + + + + + + SamSs + + false + false + false + Security Accounts Manager + + + + + + MSDTC + + false + false + false + Distributed Transaction Coordinator + + . + MSDTC + + + + RPCSS + SamSS + + + Manual + Stopped + Win32OwnProcess + + + + + MSDTC + + + + + + com.docker.service + + false + true + true + Docker Desktop Service + + . + com.docker.service + + + + LanmanServer + + + Automatic + Running + Win32OwnProcess + + + + + com.docker.service + + + + + + LanmanServer + + false + false + true + Server + + + + com.docker.service + + + . + LanmanServer + + + + SamSS + Srv2 + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + LanmanServer + + + + + + KtmRm + + false + false + false + KtmRm for Distributed Transaction Coordinator + + . + KtmRm + + + + RPCSS + SamSS + + + Manual + Stopped + Win32ShareProcess + + + + + KtmRm + + + + + + . + SamSs + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + The startup of this service signals other services that the Security Accounts Manager (SAM) is ready to accept requests. Disabling this service will prevent other services in the system from being notified when the SAM is ready, which may in turn cause those services to fail to start correctly. This service should not be disabled. + false + C:\WINDOWS\system32\lsass.exe + + + Automatic + 2 + + SamSs + + + + + + SCardSvr + + false + false + false + Smart Card + + . + SCardSvr + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Manages access to smart cards read by this computer. If this service is stopped, this computer will be unable to read smart cards. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation + + + Manual + 3 + + SCardSvr + + + + + + ScDeviceEnum + + false + false + false + Smart Card Device Enumeration Service + + . + ScDeviceEnum + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Creates software device nodes for all smart card readers accessible to a given session. If this service is disabled, WinRT APIs will not be able to enumerate smart card readers. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted + + + Manual + 3 + + ScDeviceEnum + + + + + + Schedule + + false + true + true + Task Scheduler + + + + + + NaturalAuthentication + + false + false + false + Natural Authentication + + . + NaturalAuthentication + + + + RpcSs + ProfSvc + Schedule + + + Manual + Stopped + Win32ShareProcess + + + + + NaturalAuthentication + + + + + + . + Schedule + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + SystemEventsBroker + + false + false + true + System Events Broker + . + SystemEventsBroker + + + + RpcEptMapper + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + SystemEventsBroker + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables a user to configure and schedule automated tasks on this computer. The service also hosts multiple Windows system-critical tasks. If this service is stopped or disabled, these tasks will not be run at their scheduled times. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + Schedule + + + + + + SCPolicySvc + + false + false + false + Smart Card Removal Policy + + . + SCPolicySvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Allows the system to be configured to lock the user desktop upon smart card removal. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs + + + Manual + 3 + + SCPolicySvc + + + + + + SDRSVC + + false + false + false + Windows Backup + + . + SDRSVC + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + Provides Windows Backup and Restore capabilities. + false + C:\WINDOWS\system32\svchost.exe -k SDRSVC + + + Manual + 3 + + SDRSVC + + + + + + seclogon + + true + false + true + Secondary Log-on + + . + seclogon + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables starting processes under alternate credentials. If this service is stopped, this type of log-on access will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + seclogon + + + + + + SecurityHealthService + + false + false + false + Windows Security Service + + . + SecurityHealthService + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Windows Security Service handles unified device protection and health information + false + C:\WINDOWS\system32\SecurityHealthService.exe + + + Manual + 3 + + SecurityHealthService + + + + + + SEMgrSvc + + false + false + true + Payments and NFC/SE Manager + + . + SEMgrSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Manages payments and Near Field Communication (NFC) based secure elements. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + SEMgrSvc + + + + + + SENS + + false + false + true + System Event Notification Service + + + + + + COMSysApp + + false + false + false + COM+ System Application + + . + COMSysApp + + + + RpcSs + EventSystem + SENS + + + Manual + Stopped + Win32OwnProcess + + + + + COMSysApp + + + + + + . + SENS + + + + + + EventSystem + + false + false + true + COM+ Event System + + + + COMSysApp + SENS + + + . + EventSystem + + + + rpcss + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + EventSystem + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Monitors system events and notifies subscribers to COM+ Event System of these events. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + SENS + + + + + + Sense + + false + false + false + Windows Defender Advanced Threat Protection Service + + . + Sense + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Windows Defender Advanced Threat Protection service helps protect against advanced threats by monitoring and reporting security events that happen on the computer. + false + "C:\Program Files\Windows Defender Advanced Threat Protection\MsSense.exe" + + + Manual + 3 + + Sense + + + + + + SensorDataService + + false + false + false + Sensor Data Service + + . + SensorDataService + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Delivers data from a variety of sensors + false + C:\WINDOWS\System32\SensorDataService.exe + + + Manual + 3 + + SensorDataService + + + + + + SensorService + + false + false + true + Sensor Service + + . + SensorService + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + A service for sensors that manages different sensors' functionality. Manages Simple Device Orientation (SDO) and History for sensors. Loads the SDO sensor that reports device orientation changes. If this service is stopped or disabled, the SDO sensor will not be loaded and so auto-rotation will not occur. History collection from Sensors will also be stopped. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + SensorService + + + + + + SensrSvc + + false + true + true + Sensor Monitoring Service + + . + SensrSvc + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Monitors various sensors in order to expose data and adapt to system and user state. If this service is stopped or disabled, the display brightness will not adapt to lighting conditions. Stopping this service may affect other system functionality and features as well. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -p + + + Manual + 3 + + SensrSvc + + + + + + SessionEnv + + false + false + true + Remote Desktop Configuration + + . + SessionEnv + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + LanmanWorkstation + + true + false + true + Workstation + + + + SessionEnv + Netlogon + + + . + LanmanWorkstation + + + + Bowser + MRxSmb20 + NSI + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + LanmanWorkstation + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + localSystem + Remote Desktop Configuration service (RDCS) is responsible for all Remote Desktop Services and Remote Desktop related configuration and session maintenance activities that require SYSTEM context. These include per-session temporary folders, RD themes, and RD certificates. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + SessionEnv + + + + + + SgrmBroker + + false + true + false + System Guard Runtime Monitor Broker + + . + SgrmBroker + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Monitors and attests to the integrity of the Windows platform. + true + C:\WINDOWS\system32\SgrmBroker.exe + + + AutomaticDelayedStart + 10 + + SgrmBroker + + + + + + SharedAccess + + false + false + true + Internet Connection Sharing (ICS) + + . + SharedAccess + + + + + + BFE + + false + false + true + Base Filtering Engine + . + BFE + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BFE + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides network address translation, addressing, name resolution and/or intrusion prevention services for a home or small office network. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + SharedAccess + + + + + + SharedRealitySvc + + false + false + false + Spatial Data Service + + . + SharedRealitySvc + + + + + + RpcSS + + false + false + false + Remote Procedure Call (RPC) + . + RpcSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + This service is used for Spatial Perception scenarios + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + SharedRealitySvc + + + + + + ShellHWDetection + + false + false + true + Shell Hardware Detection + + . + ShellHWDetection + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides notifications for AutoPlay hardware events. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + ShellHWDetection + + + + + + shpamsvc + + false + false + false + Shared PC Account Manager + + . + shpamsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + ProfSvc + + false + true + true + User Profile Service + + + + XblGameSave + TokenBroker + UserManager + shpamsvc + NaturalAuthentication + Appinfo + + + . + ProfSvc + + + + RpcSs + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + ProfSvc + + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Manages profiles and accounts on a SharedPC configured device + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Disabled + 4 + + shpamsvc + + + + + + smphost + + false + false + false + Microsoft Storage Spaces SMP + + . + smphost + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Host service for the Microsoft Storage Spaces management provider. If this service is stopped or disabled, Storage Spaces cannot be managed. + false + C:\WINDOWS\System32\svchost.exe -k smphost + + + Manual + 3 + + smphost + + + + + + SmsRouter + + false + false + false + Microsoft Windows SMS Router Service. + . + SmsRouter + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\LocalService + Routes messages based on rules to appropriate clients. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + SmsRouter + + + + + + SNMPTRAP + + false + false + false + SNMP Trap + + . + SNMPTRAP + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Receives trap messages generated by local or remote Simple Network Management Protocol (SNMP) agents and forwards the messages to SNMP management programs running on this computer. If this service is stopped, SNMP-based programs on this computer will not receive SNMP trap messages. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\snmptrap.exe + + + Manual + 3 + + SNMPTRAP + + + + + + spectrum + + false + false + false + Windows Perception Service + + . + spectrum + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Enables spatial perception, spatial input, and holographic rendering. + false + C:\WINDOWS\system32\spectrum.exe + + + Manual + 3 + + spectrum + + + + + + Spooler + + false + false + true + Print Spooler + + + + + + Fax + + false + false + false + Fax + + . + Fax + + + + TapiSrv + RpcSs + Spooler + + + Manual + Stopped + Win32OwnProcess + + + + + Fax + + + + + + . + Spooler + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + http + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + http + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + http + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, InteractiveProcess + 272 + + + + + + LocalSystem + This service spools print jobs and handles interaction with the printer. If you turn off this service, you won’t be able to print or see your printers. + false + C:\WINDOWS\System32\spoolsv.exe + + + Automatic + 2 + + Spooler + + + + + + sppsvc + + false + false + false + Software Protection + + . + sppsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Enables the download, installation and enforcement of digital licenses for Windows and Windows applications. If the service is disabled, the operating system and licensed applications may run in a notification mode. It is strongly recommended that you not disable the Software Protection service. + true + C:\WINDOWS\system32\sppsvc.exe + + + AutomaticDelayedStart + 10 + + sppsvc + + + + + + SQLWriter + + false + true + true + SQL Server VSS Writer + + . + SQLWriter + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides the interface to backup/restore Microsoft SQL server through the Windows VSS infrastructure. + false + "C:\Program Files\Microsoft SQL Server\90\Shared\sqlwriter.exe" + + + Automatic + 2 + + SQLWriter + + + + + + SSDPSRV + + false + true + true + SSDP Discovery + + + + + + upnphost + + false + false + false + UPnP Device Host + + . + upnphost + + + + SSDPSRV + HTTP + + + Manual + Stopped + Win32ShareProcess + + + + + upnphost + + + + + + . + SSDPSRV + + + + + + HTTP + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + HTTP + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + HTTP + + + + + + NSI + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + NSI + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NSI + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Discovers networked devices and services that use the SSDP discovery protocol, such as UPnP devices. Also announces SSDP devices and services running on the local computer. If this service is stopped, SSDP-based devices will not be discovered. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -p + + + Manual + 3 + + SSDPSRV + + + + + + ssh-agent + + false + false + false + OpenSSH Authentication Agent + + . + ssh-agent + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Agent to hold private keys used for public key authentication. + false + C:\WINDOWS\System32\OpenSSH\ssh-agent.exe + + + Disabled + 4 + + ssh-agent + + + + + + sshd + + false + false + false + OpenSSH SSH Server + + + + + + SshdBroker + + false + false + false + SshdBroker + + . + SshdBroker + + + + Sshd + + + Manual + Stopped + Win32ShareProcess + + + + + SshdBroker + + + + + + . + sshd + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + SSH protocol based service to provide secure encrypted communications between two untrusted hosts over an insecure network. + false + C:\WINDOWS\System32\OpenSSH\sshd.exe + + + Manual + 3 + + sshd + + + + + + SshdBroker + + false + false + false + SshdBroker + + . + SshdBroker + + + + + + Sshd + + false + false + false + OpenSSH SSH Server + + + + SshdBroker + + + . + Sshd + + + + + Manual + Stopped + Win32OwnProcess + + + + + Sshd + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + + false + C:\WINDOWS\system32\svchost.exe -k SshBrokerGroup + + + Manual + 3 + + SshdBroker + + + + + + SstpSvc + + false + true + true + Secure Socket Tunneling Protocol Service + + + + + + RemoteAccess + + false + false + false + Routing and Remote Access + + . + RemoteAccess + + + + RpcSS + Bfe + RasMan + Http + + + Disabled + Stopped + Win32ShareProcess + + + + + RemoteAccess + + + + + + RasMan + + false + true + true + Remote Access Connection Manager + + + + RemoteAccess + + + . + RasMan + + + + SstpSvc + DnsCache + + + Automatic + Running + Win32ShareProcess + + + + + RasMan + + + + + + . + SstpSvc + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\LocalService + Provides support for the Secure Socket Tunneling Protocol (SSTP) to connect to remote computers using VPN. If this service is disabled, users will not be able to use SSTP to access remote servers. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + SstpSvc + + + + + + StateRepository + + false + true + true + State Repository Service + + + + + + LxssManager + + false + false + true + LxssManager + + . + LxssManager + + + + RPCSS + staterepository + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + LxssManager + + + + + + AppXSvc + + false + true + true + AppX Deployment Service (AppXSVC) + + . + AppXSvc + + + + rpcss + staterepository + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + AppXSvc + + + + + + . + StateRepository + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides required infrastructure support for the application model. + false + C:\WINDOWS\system32\svchost.exe -k appmodel -p + + + Manual + 3 + + StateRepository + + + + + + stisvc + + true + true + true + Windows Image Acquisition (WIA) + + . + stisvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT Authority\LocalService + Provides image acquisition services for scanners and cameras + false + C:\WINDOWS\system32\svchost.exe -k imgsvc + + + Automatic + 2 + + stisvc + + + + + + StorSvc + + false + false + true + Storage Service + + . + StorSvc + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides enabling services for storage settings and external storage expansion + true + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + AutomaticDelayedStart + 10 + + StorSvc + + + + + + SurfaceDtxService + + false + true + true + Surface DTX Service + + . + SurfaceDtxService + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides support specific for Surface Hardware + false + C:\WINDOWS\system32\SurfaceDtxService.exe + + + Automatic + 2 + + SurfaceDtxService + + + + + + SurfaceService + + false + true + true + Surface Integration Service + + . + SurfaceService + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides support specific for Surface Hardware + true + C:\WINDOWS\system32\SurfaceService.exe + + + AutomaticDelayedStart + 10 + + SurfaceService + + + + + + SurfaceUsbHubFwUpdateService + + false + true + true + Surface USB Hub Firmware Update Service + + . + SurfaceUsbHubFwUpdateService + + + + + + EventLog + + false + true + true + Windows Event Log + + + + Wecsvc + SurfaceUsbHubFwUpdateService + NcdAutoSetup + AppVClient + netprofm + NlaSvc + + + . + EventLog + + + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + EventLog + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides support for Surface USB Hub Firmware + false + C:\WINDOWS\System32\SurfaceUsbHubFwUpdateService.exe + + + Automatic + 2 + + SurfaceUsbHubFwUpdateService + + + + + + svsvc + + false + false + false + Spot Verifier + + . + svsvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Verifies potential file system corruptions. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + svsvc + + + + + + swprv + + false + false + false + Microsoft Software Shadow Copy Provider + + . + swprv + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Manages software-based volume shadow copies taken by the Volume Shadow Copy service. If this service is stopped, software-based volume shadow copies cannot be managed. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\System32\svchost.exe -k swprv + + + Manual + 3 + + swprv + + + + + + SysMain + + false + true + true + SysMain + + . + SysMain + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + fileinfo + + false + false + true + File Information FS MiniFilter + + + + SysMain + + + . + fileinfo + + + + FltMgr + + + Boot + Running + FileSystemDriver + + + + + fileinfo + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Maintains and improves system performance over time. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Automatic + 2 + + SysMain + + + + + + SystemEventsBroker + + false + false + true + System Events Broker + . + SystemEventsBroker + + + + + + RpcEptMapper + + false + false + false + RPC Endpoint Mapper + . + RpcEptMapper + + + + + Automatic + Running + Win32ShareProcess + + + + + RpcEptMapper + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Coordinates execution of background work for WinRT application. If this service is stopped or disabled, then background work might not be triggered. + false + C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p + + + Automatic + 2 + + SystemEventsBroker + + + + + + TabletInputService + + false + false + false + Touch Keyboard and Handwriting Panel Service + + . + TabletInputService + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables Touch Keyboard and Handwriting Panel pen and ink functionality + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Automatic + 2 + + TabletInputService + + + + + + TapiSrv + + false + false + false + Telephony + + + + + + Fax + + false + false + false + Fax + + . + Fax + + + + TapiSrv + RpcSs + Spooler + + + Manual + Stopped + Win32OwnProcess + + + + + Fax + + + + + + . + TapiSrv + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\NetworkService + Provides Telephony API (TAPI) support for programs that control telephony devices on the local computer and, through the LAN, on servers that are also running the service. + false + C:\WINDOWS\System32\svchost.exe -k NetworkService -p + + + Manual + 3 + + TapiSrv + + + + + + TermService + + false + true + true + Remote Desktop Services + + + + + + UmRdpService + + false + true + true + Remote Desktop Services UserMode Port Redirector + + . + UmRdpService + + + + TermService + RDPDR + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + UmRdpService + + + + + + . + TermService + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT Authority\NetworkService + Allows users to connect interactively to a remote computer. Remote Desktop and Remote Desktop Session Host Server depend on this service. To prevent remote use of this computer, clear the checkboxes on the Remote tab of the System properties control panel item. + false + C:\WINDOWS\System32\svchost.exe -k NetworkService + + + Manual + 3 + + TermService + + + + + + Themes + + false + false + true + Themes + + . + Themes + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides user experience theme management. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + Themes + + + + + + TieringEngineService + + false + false + false + Storage Tiers Management + + . + TieringEngineService + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + Optimizes the placement of data in storage tiers on all tiered storage spaces in the system. + false + C:\WINDOWS\system32\TieringEngineService.exe + + + Manual + 3 + + TieringEngineService + + + + + + TimeBrokerSvc + + false + false + true + Time Broker + . + TimeBrokerSvc + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Coordinates execution of background work for WinRT application. If this service is stopped or disabled, then background work might not be triggered. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + TimeBrokerSvc + + + + + + TokenBroker + + false + false + true + Web Account Manager + + . + TokenBroker + + + + + + UserManager + + false + false + true + User Manager + + + + XblGameSave + TokenBroker + + + . + UserManager + + + + RpcSs + ProfSvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + UserManager + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + This service is used by Web Account Manager to provide single-sign-on to apps and services. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + TokenBroker + + + + + + TrkWks + + false + true + true + Distributed Link Tracking Client + + . + TrkWks + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Maintains links between NTFS files within a computer or across computers in a network. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Automatic + 2 + + TrkWks + + + + + + TroubleshootingSvc + + false + false + false + Recommended Troubleshooting Service + + . + TroubleshootingSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Enables automatic mitigation for known problems by applying recommended troubleshooting. If stopped, your device will not get recommended troubleshooting for problems on your device. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + TroubleshootingSvc + + + + + + TrustedInstaller + + false + false + false + Windows Modules Installer + + . + TrustedInstaller + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + Enables installation, modification, and removal of Windows updates and optional components. If this service is disabled, install or uninstall of Windows updates might fail for this computer. + false + C:\WINDOWS\servicing\TrustedInstaller.exe + + + Manual + 3 + + TrustedInstaller + + + + + + tzautoupdate + + false + false + false + Auto Time Zone Updater + + . + tzautoupdate + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Automatically sets the system time zone. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Disabled + 4 + + tzautoupdate + + + + + + UdkUserSvc_9164d + + false + false + true + Udk User Service_9164d + + . + UdkUserSvc_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 240 + 240 + + + + + + + Shell components service + false + C:\WINDOWS\system32\svchost.exe -k UdkSvcGroup + + + Manual + 3 + + UdkUserSvc_9164d + + + + + + UevAgentService + + false + false + false + User Experience Virtualization Service + + . + UevAgentService + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides support for application and OS settings roaming + false + C:\WINDOWS\system32\AgentService.exe + + + Disabled + 4 + + UevAgentService + + + + + + UmRdpService + + false + true + true + Remote Desktop Services UserMode Port Redirector + + . + UmRdpService + + + + + + TermService + + false + true + true + Remote Desktop Services + + + + UmRdpService + + + . + TermService + + + + RPCSS + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + TermService + + + + + + RDPDR + + false + false + true + Remote Desktop Device Redirector Driver + + + + UmRdpService + + + . + RDPDR + + + + RDBSS + + + Manual + Running + KernelDriver + + + + + RDPDR + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + localSystem + Allows the redirection of Printers/Drives/Ports for RDP connections + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + UmRdpService + + + + + + UnistoreSvc_9164d + + false + false + true + User Data Storage_9164d + + + + + + UserDataSvc_9164d + + false + false + true + User Data Access_9164d + + . + UserDataSvc_9164d + + + + + Manual + Running + 224 + + + + + UserDataSvc_9164d + + + + + + PimIndexMaintenanceSvc_9164d + + false + false + true + Contact Data_9164d + + . + PimIndexMaintenanceSvc_9164d + + + + + Manual + Running + 224 + + + + + PimIndexMaintenanceSvc_9164d + + + + + + . + UnistoreSvc_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 224 + 224 + + + + + + + Handles storage of structured user data, including contact info, calendars, messages and other content. If you stop or disable this service, apps that use this data might not work correctly. + false + C:\WINDOWS\System32\svchost.exe -k UnistackSvcGroup + + + Manual + 3 + + UnistoreSvc_9164d + + + + + + upnphost + + false + false + false + UPnP Device Host + + . + upnphost + + + + + + SSDPSRV + + false + true + true + SSDP Discovery + + + + upnphost + + + . + SSDPSRV + + + + HTTP + NSI + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + SSDPSRV + + + + + + HTTP + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + HTTP + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + HTTP + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Allows UPnP devices to be hosted on this computer. If this service is stopped, any hosted UPnP devices will stop functioning and no additional hosted devices can be added. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -p + + + Manual + 3 + + upnphost + + + + + + UserDataSvc_9164d + + false + false + true + User Data Access_9164d + + . + UserDataSvc_9164d + + + + + + + Manual + 3 + + + + Running + 4 + + + + 224 + 224 + + + + + + + Provides apps with access to structured user data, including contact info, calendars, messages and other content. If you stop or disable this service, apps that use this data might not work correctly. + false + C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup + + + Manual + 3 + + UserDataSvc_9164d + + + + + + UserManager + + false + false + true + User Manager + + + + + + XblGameSave + + false + false + false + Xbox Live Game Save + + . + XblGameSave + + + + UserManager + XblAuthManager + + + Manual + Stopped + Win32ShareProcess + + + + + XblGameSave + + + + + + TokenBroker + + false + false + true + Web Account Manager + + . + TokenBroker + + + + UserManager + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + TokenBroker + + + + + + . + UserManager + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + ProfSvc + + false + true + true + User Profile Service + + + + XblGameSave + TokenBroker + UserManager + shpamsvc + NaturalAuthentication + Appinfo + + + . + ProfSvc + + + + RpcSs + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + ProfSvc + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + User Manager provides the runtime components required for multi-user interaction. If this service is stopped, some applications may not operate correctly. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + UserManager + + + + + + UsoSvc + + false + true + true + Update Orchestrator Service + + . + UsoSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Manages Windows Updates. If stopped, your devices will not be able to download and install the latest updates. + true + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + AutomaticDelayedStart + 10 + + UsoSvc + + + + + + VacSvc + + false + false + false + Volumetric Audio Compositor Service + + . + VacSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Hosts spatial analysis for Mixed Reality audio simulation. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + VacSvc + + + + + + VaultSvc + + false + true + true + Credential Manager + + . + VaultSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides secure storage and retrieval of credentials to users, applications and security service packages. + false + C:\WINDOWS\system32\lsass.exe + + + Manual + 3 + + VaultSvc + + + + + + vds + + false + false + false + Virtual Disk + + . + vds + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides management services for disks, volumes, file systems, and storage arrays. + false + C:\WINDOWS\System32\vds.exe + + + Manual + 3 + + vds + + + + + + vmcompute + + false + false + true + Hyper-V Host Compute Service + + . + vmcompute + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + wcifs + + false + false + true + Windows Container Isolation + + + + vmcompute + + + . + wcifs + + + + FltMgr + + + Automatic + Running + FileSystemDriver + + + + + wcifs + + + + + + hvsocketcontrol + + false + false + true + hvsocketcontrol + + + + vmcompute + + + . + hvsocketcontrol + + + + + Manual + Running + KernelDriver + + + + + hvsocketcontrol + + + + + + condrv + + false + false + true + Console Driver + + + + vmcompute + + + . + condrv + + + + + Manual + Running + KernelDriver + + + + + condrv + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides support for running Windows Containers and Virtual Machines. + false + C:\WINDOWS\system32\vmcompute.exe + + + Manual + 3 + + vmcompute + + + + + + vmicguestinterface + + false + false + false + Hyper-V Guest Service Interface + + . + vmicguestinterface + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides an interface for the Hyper-V host to interact with specific services running inside the virtual machine. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + vmicguestinterface + + + + + + vmicheartbeat + + false + false + false + Hyper-V Heartbeat Service + + . + vmicheartbeat + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Monitors the state of this virtual machine by reporting a heartbeat at regular intervals. This service helps you identify running virtual machines that have stopped responding. + false + C:\WINDOWS\system32\svchost.exe -k ICService -p + + + Manual + 3 + + vmicheartbeat + + + + + + vmickvpexchange + + false + false + false + Hyper-V Data Exchange Service + + . + vmickvpexchange + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides a mechanism to exchange data between the virtual machine and the operating system running on the physical computer. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + vmickvpexchange + + + + + + vmicrdv + + false + false + false + Hyper-V Remote Desktop Virtualization Service + + . + vmicrdv + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides a platform for communication between the virtual machine and the operating system running on the physical computer. + false + C:\WINDOWS\system32\svchost.exe -k ICService -p + + + Manual + 3 + + vmicrdv + + + + + + vmicshutdown + + false + false + false + Hyper-V Guest Shutdown Service + + . + vmicshutdown + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides a mechanism to shut down the operating system of this virtual machine from the management interfaces on the physical computer. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + vmicshutdown + + + + + + vmictimesync + + false + false + false + Hyper-V Time Synchronization Service + + . + vmictimesync + + + + + + VmGid + + false + false + false + Microsoft Hyper-V Guest Infrastructure Driver + + + + vmictimesync + + + . + VmGid + + + + + Manual + Stopped + KernelDriver + + + + + VmGid + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Synchronizes the system time of this virtual machine with the system time of the physical computer. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + vmictimesync + + + + + + vmicvmsession + + false + false + false + Hyper-V PowerShell Direct Service + + . + vmicvmsession + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Provides a mechanism to manage virtual machine with PowerShell via VM session without a virtual network. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + vmicvmsession + + + + + + vmicvss + + false + false + false + Hyper-V Volume Shadow Copy Requestor + + . + vmicvss + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Coordinates the communications that are required to use Volume Shadow Copy Service to back up applications and data on this virtual machine from the operating system on the physical computer. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + vmicvss + + + + + + vmms + + false + false + true + Hyper-V Virtual Machine Management + + . + vmms + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + WINMGMT + + true + true + true + Windows Management Instrumentation + + + + vmms + NcaSvc + iphlpsvc + HgClientService + + + . + WINMGMT + + + + RPCSS + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + WINMGMT + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Management service for Hyper-V, provides service to run multiple virtual machines. + false + C:\WINDOWS\system32\vmms.exe + + + Automatic + 2 + + vmms + + + + + + VSS + + false + false + false + Volume Shadow Copy + + . + VSS + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Manages and implements Volume Shadow Copies used for backup and other purposes. If this service is stopped, shadow copies will be unavailable for backup and the backup may fail. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\vssvc.exe + + + Manual + 3 + + VSS + + + + + + W32Time + + false + false + false + Windows Time + + . + W32Time + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalService + + + Manual + 3 + + W32Time + + + + + + WaaSMedicSvc + + false + false + false + Windows Update Medic Service + + . + WaaSMedicSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables remediation and protection of Windows Update components. + false + C:\WINDOWS\system32\svchost.exe -k wusvcs -p + + + Manual + 3 + + WaaSMedicSvc + + + + + + WalletService + + false + false + false + WalletService + + . + WalletService + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Hosts objects used by clients of the wallet + false + C:\WINDOWS\System32\svchost.exe -k appmodel -p + + + Manual + 3 + + WalletService + + + + + + WarpJITSvc + + false + false + false + WarpJITSvc + + . + WarpJITSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT Authority\LocalService + Provides a JIT out of process service for WARP when running with ACG enabled. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted + + + Manual + 3 + + WarpJITSvc + + + + + + wbengine + + false + false + false + Block Level Backup Engine Service + + . + wbengine + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + The WBENGINE service is used by Windows Backup to perform backup and recovery operations. If this service is stopped by a user, it may cause the currently running backup or recovery operation to fail. Disabling this service may disable backup and recovery operations using Windows Backup on this computer. + false + "C:\WINDOWS\system32\wbengine.exe" + + + Manual + 3 + + wbengine + + + + + + WbioSrvc + + false + false + true + Windows Biometric Service + + . + WbioSrvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + The Windows biometric service gives client applications the ability to capture, compare, manipulate, and store biometric data without gaining direct access to any biometric hardware or samples. The service is hosted in a privileged SVCHOST process. + false + C:\WINDOWS\system32\svchost.exe -k WbioSvcGroup + + + Automatic + 2 + + WbioSrvc + + + + + + Wcmsvc + + false + true + true + Windows Connection Manager + + + + + + WlanSvc + + false + true + true + WLAN AutoConfig + + . + WlanSvc + + + + nativewifip + RpcSs + Ndisuio + wcmsvc + + + Automatic + Running + Win32OwnProcess + + + + + WlanSvc + + + + + + icssvc + + false + false + false + Windows Mobile Hotspot Service + + . + icssvc + + + + RpcSs + wcmsvc + + + Manual + Stopped + Win32ShareProcess + + + + + icssvc + + + + + + . + Wcmsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + NSI + + false + false + true + Network Store Interface Service + + + + WlanSvc + icssvc + Wcmsvc + upnphost + SSDPSRV + NcdAutoSetup + AppVClient + netprofm + NlaSvc + Netman + NcaSvc + SessionEnv + Netlogon + LanmanWorkstation + IpxlatCfgSvc + iphlpsvc + XboxNetApiSvc + IKEEXT + hns + RemoteAccess + RasMan + debugregsvc + Dnscache + WinHttpAutoProxySvc + Dhcp + + + . + NSI + + + + rpcss + nsiproxy + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + NSI + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT Authority\LocalService + Makes automatic connect/disconnect decisions based on the network connectivity options currently available to the PC and enables management of network connectivity based on Group Policy settings. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Automatic + 2 + + Wcmsvc + + + + + + wcncsvc + + false + false + false + Windows Connect Now - Config Registrar + + . + wcncsvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + WCNCSVC hosts the Windows Connect Now Configuration, which is Microsoft's Implementation of the Wireless Protected Setup (WPS) protocol. This is used to configure Wireless LAN settings for an Access Point (AP) or a Wireless Device. The service is started programmatically as needed. + false + C:\WINDOWS\System32\svchost.exe -k LocalServiceAndNoImpersonation -p + + + Manual + 3 + + wcncsvc + + + + + + WdiServiceHost + + false + true + true + Diagnostic Service Host + + . + WdiServiceHost + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + The Diagnostic Service Host is used by the Diagnostic Policy Service to host diagnostics that need to run in a Local Service context. If this service is stopped, any diagnostics that depend on it will no longer function. + false + C:\WINDOWS\System32\svchost.exe -k LocalService -p + + + Manual + 3 + + WdiServiceHost + + + + + + WdiSystemHost + + false + true + true + Diagnostic System Host + + . + WdiSystemHost + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + The Diagnostic System Host is used by the Diagnostic Policy Service to host diagnostics that need to run in a Local System context. If this service is stopped, any diagnostics that depend on it will no longer function. + false + C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + WdiSystemHost + + + + + + WdNisSvc + + false + false + true + Microsoft Defender Antivirus Network Inspection Service + + . + WdNisSvc + + + + + + WdNisDrv + + false + false + true + Microsoft Defender Antivirus Network Inspection System Driver + + + + WdNisSvc + + + . + WdNisDrv + + + + BFE + + + Manual + Running + KernelDriver + + + + + WdNisDrv + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\LocalService + Helps guard against intrusion attempts targeting known and newly discovered vulnerabilities in network protocols + false + "C:\ProgramData\Microsoft\Windows Defender\platform\4.18.2010.7-0\NisSrv.exe" + + + Manual + 3 + + WdNisSvc + + + + + + WebClient + + false + false + true + WebClient + + . + WebClient + + + + + + MRxDAV + + false + false + true + WebDav Client Redirector Driver + + + + WebClient + + + . + MRxDAV + + + + rdbss + + + Manual + Running + FileSystemDriver + + + + + MRxDAV + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + Enables Windows-based programs to create, access, and modify Internet-based files. If this service is stopped, these functions will not be available. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k LocalService -p + + + Manual + 3 + + WebClient + + + + + + WebManagement + + false + false + false + Web Management + + . + WebManagement + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Disabled + 4 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Web-based device management service + false + C:\WINDOWS\system32\WebManagement.exe + + + Disabled + 4 + + WebManagement + + + + + + Wecsvc + + false + false + false + Windows Event Collector + + . + Wecsvc + + + + + + HTTP + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + HTTP + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + HTTP + + + + + + Eventlog + + false + true + true + Windows Event Log + + + + Wecsvc + SurfaceUsbHubFwUpdateService + NcdAutoSetup + AppVClient + netprofm + NlaSvc + + + . + Eventlog + + + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Eventlog + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\NetworkService + This service manages persistent subscriptions to events from remote sources that support WS-Management protocol. This includes Windows Vista event logs, hardware and IPMI-enabled event sources. The service stores forwarded events in a local Event Log. If this service is stopped or disabled event subscriptions cannot be created and forwarded events cannot be accepted. + false + C:\WINDOWS\system32\svchost.exe -k NetworkService -p + + + Manual + 3 + + Wecsvc + + + + + + WEPHOSTSVC + + false + false + false + Windows Encryption Provider Host Service + + . + WEPHOSTSVC + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Windows Encryption Provider Host Service brokers encryption related functionalities from 3rd Party Encryption Providers to processes that need to evaluate and apply EAS policies. Stopping this will compromise EAS compliancy checks that have been established by the connected Mail Accounts + false + C:\WINDOWS\system32\svchost.exe -k WepHostSvcGroup + + + Manual + 3 + + WEPHOSTSVC + + + + + + wercplsupport + + false + false + false + Problem Reports Control Panel Support + + . + wercplsupport + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + localSystem + This service provides support for viewing, sending and deletion of system-level problem reports for the Problem Reports control panel. + false + C:\WINDOWS\System32\svchost.exe -k netsvcs -p + + + Manual + 3 + + wercplsupport + + + + + + WerSvc + + false + false + false + Windows Error Reporting Service + + . + WerSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + Allows errors to be reported when programs stop working or responding and allows existing solutions to be delivered. Also allows logs to be generated for diagnostic and repair services. If this service is stopped, error reporting might not work correctly and results of diagnostic services and repairs might not be displayed. + false + C:\WINDOWS\System32\svchost.exe -k WerSvcGroup + + + Manual + 3 + + WerSvc + + + + + + WFDSConMgrSvc + + false + false + false + Wi-Fi Direct Services Connection Manager Service + + . + WFDSConMgrSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + Manages connections to wireless services, including wireless display and docking. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + WFDSConMgrSvc + + + + + + WiaRpc + + false + false + false + Still Image Acquisition Events + + . + WiaRpc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Launches applications associated with still image acquisition events. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + WiaRpc + + + + + + WinDefend + + false + true + true + Microsoft Defender Antivirus Service + + . + WinDefend + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Helps protect users from malware and other potentially unwanted software + false + "C:\ProgramData\Microsoft\Windows Defender\platform\4.18.2010.7-0\MsMpEng.exe" + + + Automatic + 2 + + WinDefend + + + + + + WinHttpAutoProxySvc + + false + true + false + WinHTTP Web Proxy Auto-Discovery Service + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + BFE + dnscache + NSI + iphlpsvc + + + Manual + Stopped + Win32OwnProcess, Win32ShareProcess + + + + + NcaSvc + + + + + + iphlpsvc + + false + false + true + IP Helper + + + + NcaSvc + + + . + iphlpsvc + + + + RpcSS + winmgmt + tcpip + nsi + WinHttpAutoProxySvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + iphlpsvc + + + + + + . + WinHttpAutoProxySvc + + + + + + Dhcp + + false + true + true + DHCP Client + + + + NcaSvc + iphlpsvc + WinHttpAutoProxySvc + NcdAutoSetup + AppVClient + netprofm + NlaSvc + + + . + Dhcp + + + + NSI + Afd + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + Dhcp + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + WinHTTP implements the client HTTP stack and provides developers with a Win32 API and COM Automation component for sending HTTP requests and receiving responses. In addition, WinHTTP provides support for auto-discovering a proxy configuration via its implementation of the Web Proxy Auto-Discovery (WPAD) protocol. + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + WinHttpAutoProxySvc + + + + + + Winmgmt + + true + true + true + Windows Management Instrumentation + + + + + + vmms + + false + false + true + Hyper-V Virtual Machine Management + + . + vmms + + + + RPCSS + WINMGMT + + + Automatic + Running + Win32OwnProcess + + + + + vmms + + + + + + NcaSvc + + false + false + false + Network Connectivity Assistant + + . + NcaSvc + + + + BFE + dnscache + NSI + iphlpsvc + + + Manual + Stopped + Win32OwnProcess, Win32ShareProcess + + + + + NcaSvc + + + + + + iphlpsvc + + false + false + true + IP Helper + + + + NcaSvc + + + . + iphlpsvc + + + + RpcSS + winmgmt + tcpip + nsi + WinHttpAutoProxySvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + iphlpsvc + + + + + + HgClientService + + false + false + false + Host Guardian Client Service + + . + HgClientService + + + + Winmgmt + + + Manual + Stopped + Win32ShareProcess + + + + + HgClientService + + + + + + . + Winmgmt + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + localSystem + Provides a common interface and object model to access management information about operating system, devices, applications and services. If this service is stopped, most Windows-based software will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + Winmgmt + + + + + + WinRM + + false + true + true + Windows Remote Management (WS-Management) + + . + WinRM + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + HTTP + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + HTTP + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + HTTP + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\NetworkService + Windows Remote Management (WinRM) service implements the WS-Management protocol for remote management. WS-Management is a standard web services protocol used for remote software and hardware management. The WinRM service listens on the network for WS-Management requests and processes them. The WinRM Service needs to be configured with a listener using winrm.cmd command line tool or through Group Policy in order for it to listen over the network. The WinRM service provides access to WMI data and enables event collection. Event collection and subscription to events require that the service is running. WinRM messages use HTTP and HTTPS as transports. The WinRM service does not depend on IIS but is preconfigured to share a port with IIS on the same machine. The WinRM service reserves the /wsman URL prefix. To prevent conflicts with IIS, administrators should ensure that any websites hosted on IIS do not use the /wsman URL prefix. + true + C:\WINDOWS\System32\svchost.exe -k NetworkService -p + + + AutomaticDelayedStart + 10 + + WinRM + + + + + + wisvc + + false + true + true + Windows Insider Service + + . + wisvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides infrastructure support for the Windows Insider Programme. This service must remain enabled for the Windows Insider Programme to work. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + wisvc + + + + + + WlanSvc + + false + true + true + WLAN AutoConfig + + . + WlanSvc + + + + + + nativewifip + + false + false + true + NativeWiFi Filter + + + + WlanSvc + + + . + nativewifip + + + + + Manual + Running + KernelDriver + + + + + nativewifip + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + Ndisuio + + false + false + true + NDIS Usermode I/O Protocol + + + + wlpasvc + WwanSvc + WlanSvc + dot3svc + + + . + Ndisuio + + + + + Manual + Running + KernelDriver + + + + + Ndisuio + + + + + + wcmsvc + + false + true + true + Windows Connection Manager + + + + WlanSvc + icssvc + + + . + wcmsvc + + + + RpcSs + NSI + + + Automatic + Running + Win32OwnProcess + + + + + wcmsvc + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + The WLANSVC service provides the logic required to configure, discover, connect to and disconnect from a wireless local area network (WLAN) as defined by IEEE 802.11 standards. It also contains the logic to turn your computer into a software access point so that other devices or computers can connect to your computer wirelessly using a WLAN adapter that can support this. Stopping or disabling the WLANSVC service will make all WLAN adapters on your computer inaccessible from the Windows networking UI. It is strongly recommended that you have the WLANSVC service running if your computer has a WLAN adapter. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Automatic + 2 + + WlanSvc + + + + + + wlidsvc + + false + false + true + Microsoft Account Sign-in Assistant + + . + wlidsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables user sign-in through Microsoft account identity services. If this service is stopped, users will not be able to logon to the computer with their Microsoft account. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + wlidsvc + + + + + + wlpasvc + + false + false + false + Local Profile Assistant Service + + . + wlpasvc + + + + + + WwanSvc + + false + false + false + WWAN AutoConfig + + + + wlpasvc + + + . + WwanSvc + + + + RpcSs + NdisUio + + + Manual + Stopped + Win32ShareProcess + + + + + WwanSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT Authority\LocalService + This service provides profile management for subscriber identity modules + false + C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p + + + Manual + 3 + + wlpasvc + + + + + + WManSvc + + false + false + false + Windows Management Service + + . + WManSvc + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + Performs management including Provisioning and Enrollment activities + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + WManSvc + + + + + + wmiApSrv + + false + false + false + WMI Performance Adapter + + . + wmiApSrv + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + localSystem + Provides performance library information from Windows Management Instrumentation (WMI) providers to clients on the network. This service only runs when Performance Data Helper is activated. + false + C:\WINDOWS\system32\wbem\WmiApSrv.exe + + + Manual + 3 + + wmiApSrv + + + + + + WMPNetworkSvc + + false + false + false + Windows Media Player Network Sharing Service + + . + WMPNetworkSvc + + + + + + http + + false + false + true + HTTP Service + + + + WMPNetworkSvc + WinRM + Wecsvc + upnphost + SSDPSRV + Fax + Spooler + RemoteAccess + PeerDistSvc + FDResPub + fdPHost + + + . + http + + + + MsQuic + + + Manual + Running + KernelDriver + + + + + http + + + + + + WSearch + + false + true + true + Windows Search + + + + workfolderssvc + WMPNetworkSvc + + + . + WSearch + + + + RPCSS + BrokerInfrastructure + + + Automatic + Running + Win32OwnProcess + + + + + WSearch + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + NT AUTHORITY\NetworkService + Shares Windows Media Player libraries with other networked players and media devices using Universal Plug and Play + false + "C:\Program Files\Windows Media Player\wmpnetwk.exe" + + + Manual + 3 + + WMPNetworkSvc + + + + + + workfolderssvc + + false + false + false + Work Folders + + . + workfolderssvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + wsearch + + false + true + true + Windows Search + + + + workfolderssvc + WMPNetworkSvc + + + . + wsearch + + + + RPCSS + BrokerInfrastructure + + + Automatic + Running + Win32OwnProcess + + + + + wsearch + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + NT AUTHORITY\LocalService + This service syncs files with the Work Folders server, enabling you to use the files on any of the PCs and devices on which you've set up Work Folders. + false + C:\WINDOWS\System32\svchost.exe -k LocalService -p + + + Manual + 3 + + workfolderssvc + + + + + + WpcMonSvc + + false + false + false + Parental Controls + + . + WpcMonSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Enforces parental controls for child accounts in Windows. If this service is stopped or disabled, parental controls may not be enforced. + false + C:\WINDOWS\system32\svchost.exe -k LocalService + + + Manual + 3 + + WpcMonSvc + + + + + + WPDBusEnum + + false + false + false + Portable Device Enumerator Service + + . + WPDBusEnum + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enforces group policy for removable mass-storage devices. Enables applications such as Windows Media Player and Image Import Wizard to transfer and synchronize content using removable mass-storage devices. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted + + + Manual + 3 + + WPDBusEnum + + + + + + WpnService + + false + false + true + Windows Push Notifications System Service + + . + WpnService + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + This service runs in session 0 and hosts the notification platform and connection provider which handles the connection between the device and WNS server. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Automatic + 2 + + WpnService + + + + + + WpnUserService_9164d + + false + false + true + Windows Push Notifications User Service_9164d + + . + WpnUserService_9164d + + + + + + + Automatic + 2 + + + + Running + 4 + + + + 240 + 240 + + + + + + + This service hosts the Windows notification platform which provides support for local and push notifications. Supported notifications are tile, toast and raw. + false + C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup + + + Automatic + 2 + + WpnUserService_9164d + + + + + + wscsvc + + false + true + true + Security Center + + . + wscsvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + NT AUTHORITY\LocalService + The WSCSVC (Windows Security Center) service monitors and reports security health settings on the computer. The health settings include firewall (on/off), antivirus (on/off/out of date), antispyware (on/off/out of date), Windows Update (automatically/manually download and install updates), User Account Control (on/off), and Internet settings (recommended/not recommended). The service provides COM APIs for independent software vendors to register and record the state of their products to the Security Center service. The Security and Maintenance UI uses the service to provide systray alerts and a graphical view of the security health states in the Security and Maintenance control panel. Network Access Protection (NAP) uses the service to report the security health states of clients to the NAP Network Policy Server to make network quarantine decisions. The service also has a public API that allows external consumers to programmatically retrieve the aggregated security health state of the system. + true + C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p + + + AutomaticDelayedStart + 10 + + wscsvc + + + + + + WSearch + + false + true + true + Windows Search + + + + + + workfolderssvc + + false + false + false + Work Folders + + . + workfolderssvc + + + + RpcSs + wsearch + + + Manual + Stopped + Win32ShareProcess + + + + + workfolderssvc + + + + + + WMPNetworkSvc + + false + false + false + Windows Media Player Network Sharing Service + + . + WMPNetworkSvc + + + + http + WSearch + + + Manual + Stopped + Win32OwnProcess + + + + + WMPNetworkSvc + + + + + + . + WSearch + + + + + + RPCSS + + false + false + false + Remote Procedure Call (RPC) + . + RPCSS + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RPCSS + + + + + + BrokerInfrastructure + + false + false + false + Background Tasks Infrastructure Service + . + BrokerInfrastructure + + + + RpcEptMapper + DcomLaunch + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BrokerInfrastructure + + + + + + + + Automatic + 2 + + + + Running + 4 + + + + Win32OwnProcess + 16 + + + + + + LocalSystem + Provides content indexing, property caching, and search results for files, e-mail, and other content. + true + C:\WINDOWS\system32\SearchIndexer.exe /Embedding + + + AutomaticDelayedStart + 10 + + WSearch + + + + + + wuauserv + + false + false + true + Windows Update + + . + wuauserv + + + + + + rpcss + + false + false + false + Remote Procedure Call (RPC) + . + rpcss + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + rpcss + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Enables the detection, download and installation of updates for Windows and other programs. If this service is disabled, users of this computer will not be able to use Windows Update or its automatic updating feature, and programs will not be able to use the Windows Update Agent (WUA) API. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + wuauserv + + + + + + WwanSvc + + false + false + false + WWAN AutoConfig + + + + + + wlpasvc + + false + false + false + Local Profile Assistant Service + + . + wlpasvc + + + + WwanSvc + RpcSs + + + Manual + Stopped + Win32ShareProcess + + + + + wlpasvc + + + + + + . + WwanSvc + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + NdisUio + + false + false + true + NDIS Usermode I/O Protocol + + + + wlpasvc + WwanSvc + WlanSvc + dot3svc + + + . + NdisUio + + + + + Manual + Running + KernelDriver + + + + + NdisUio + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + localSystem + This service manages mobile broadband (GSM & CDMA) data card/embedded module adapters and connections by auto-configuring the networks. It is strongly recommended that this service be kept running for best user experience of mobile broadband devices. + false + C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p + + + Manual + 3 + + WwanSvc + + + + + + XblAuthManager + + false + false + true + Xbox Live Auth Manager + + + + + + XblGameSave + + false + false + false + Xbox Live Game Save + + . + XblGameSave + + + + UserManager + XblAuthManager + + + Manual + Stopped + Win32ShareProcess + + + + + XblGameSave + + + + + + . + XblAuthManager + + + + + + RpcSs + + false + false + false + Remote Procedure Call (RPC) + . + RpcSs + + + + RpcEptMapper + DcomLaunch + + + Automatic + Running + Win32ShareProcess + + + + + RpcSs + + + + + + + + Manual + 3 + + + + Running + 4 + + + + Win32OwnProcess, Win32ShareProcess + 48 + + + + + + LocalSystem + Provides authentication and authorisation services for interacting with Xbox Live. If this service is stopped, some applications may not operate correctly. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + XblAuthManager + + + + + + XblGameSave + + false + false + false + Xbox Live Game Save + + . + XblGameSave + + + + + + UserManager + + false + false + true + User Manager + + + + XblGameSave + TokenBroker + + + . + UserManager + + + + RpcSs + ProfSvc + + + Automatic + Running + Win32OwnProcess, Win32ShareProcess + + + + + UserManager + + + + + + XblAuthManager + + false + false + true + Xbox Live Auth Manager + + + + XblGameSave + + + . + XblAuthManager + + + + RpcSs + + + Manual + Running + Win32OwnProcess, Win32ShareProcess + + + + + XblAuthManager + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + This service syncs save data for Xbox Live save enabled games. If this service is stopped, game save data will not upload to or download from Xbox Live. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + XblGameSave + + + + + + XboxGipSvc + + false + false + false + Xbox Accessory Management Service + + . + XboxGipSvc + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + This service manages connected Xbox Accessories. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + XboxGipSvc + + + + + + XboxNetApiSvc + + false + false + false + Xbox Live Networking Service + + . + XboxNetApiSvc + + + + + + BFE + + false + false + true + Base Filtering Engine + . + BFE + + + + RpcSs + + + Automatic + Running + Win32ShareProcess + + + + + BFE + + + + + + mpssvc + + false + false + false + Windows Defender Firewall + . + mpssvc + + + + mpsdrv + bfe + + + Automatic + Running + Win32ShareProcess + + + + + mpssvc + + + + + + IKEEXT + + false + false + false + IKE and AuthIP IPsec Keying Modules + + + + XboxNetApiSvc + + + . + IKEEXT + + + + BFE + nsi + + + Manual + Stopped + Win32ShareProcess + + + + + IKEEXT + + + + + + KeyIso + + false + false + true + CNG Key Isolation + + + + XboxNetApiSvc + dot3svc + Eaphost + + + . + KeyIso + + + + RpcSs + + + Manual + Running + Win32ShareProcess + + + + + KeyIso + + + + + + + + Manual + 3 + + + + Stopped + 1 + + + + Win32ShareProcess + 32 + + + + + + LocalSystem + This service supports the Windows.Networking.XboxLive application programming interface. + false + C:\WINDOWS\system32\svchost.exe -k netsvcs -p + + + Manual + 3 + + XboxNetApiSvc + + + + \ No newline at end of file diff --git a/__tests__/New-ConditionalFormattingIconSet.tests.ps1 b/__tests__/New-ConditionalFormattingIconSet.tests.ps1 new file mode 100644 index 00000000..685f20bd --- /dev/null +++ b/__tests__/New-ConditionalFormattingIconSet.tests.ps1 @@ -0,0 +1,66 @@ +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +Describe "Test New Conditional Formatting IconSet" -Tag ConditionalFormattingIconSet { + BeforeEach { + $xlFilename = "TestDrive:\ConditionalFormattingIconSet.xlsx" + Remove-Item $xlFilename -ErrorAction SilentlyContinue + + $data = ConvertFrom-Csv @" +Region,State,Other,Units,Price,InStock +West,Texas,1,927,923.71,1 +North,Tennessee,3,466,770.67,0 +East,Florida,0,1520,458.68,1 +East,Maine,1,1828,661.24,0 +West,Virginia,1,465,053.58,1 +North,Missouri,1,436,235.67,1 +South,Kansas,0,214,992.47,1 +North,North Dakota,1,789,640.72,0 +South,Delaware,-1,712,508.55,1 +"@ + } + + It "Should set ThreeIconSet" { + # $cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly + $cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols + + $data | Export-Excel $xlFilename -ConditionalFormat $cfi1 + $actual = Import-Excel $xlFilename + $actual.count | Should -Be 9 + + $xl = Open-ExcelPackage $xlFilename + $xl.Workbook.Worksheets.Count | Should -Be 1 + $targetSheet = $xl.Workbook.Worksheets[1] + + $targetSheet.Name | Should -Be "Sheet1" + $targetSheet.ConditionalFormatting.Count | Should -Be 1 + $targetSheet.ConditionalFormatting[0].Type | Should -Be "ThreeIconSet" + $targetSheet.ConditionalFormatting[0].IconSet | Should -Be "Symbols" + $targetSheet.ConditionalFormatting[0].Reverse | Should -BeFalse + $targetSheet.ConditionalFormatting[0].ShowValue | Should -BeTrue + + Close-ExcelPackage $xl -NoSave + } + + It "Should set ThreeIconSet with ShowOnlyIcon" { + $cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly + + $data | Export-Excel $xlFilename -ConditionalFormat $cfi1 + $actual = Import-Excel $xlFilename + $actual.count | Should -Be 9 + + $xl = Open-ExcelPackage $xlFilename + $xl.Workbook.Worksheets.Count | Should -Be 1 + $targetSheet = $xl.Workbook.Worksheets[1] + + $targetSheet.Name | Should -Be "Sheet1" + $targetSheet.ConditionalFormatting.Count | Should -Be 1 + $targetSheet.ConditionalFormatting[0].Type | Should -Be "ThreeIconSet" + $targetSheet.ConditionalFormatting[0].IconSet | Should -Be "Symbols" + $targetSheet.ConditionalFormatting[0].Reverse | Should -BeFalse + $targetSheet.ConditionalFormatting[0].ShowValue | Should -BeFalse + + Close-ExcelPackage $xl -NoSave + } +} \ No newline at end of file diff --git a/__tests__/Open-ExcelPackage.tests.ps1 b/__tests__/Open-ExcelPackage.tests.ps1 new file mode 100644 index 00000000..1056bcb2 --- /dev/null +++ b/__tests__/Open-ExcelPackage.tests.ps1 @@ -0,0 +1,39 @@ +#Requires -Modules Pester + +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +<# +Methods +------- +Dispose +Equals +GetAsByteArray +GetHashCode +GetType +Load +Save +SaveAs +ToString + +Properties +---------- + +Compatibility +Compression +DoAdjustDrawings +Encryption +File +Package +Stream +Workbook +#> + +Describe "Test Open Excel Package" -Tag Open-ExcelPackage { + It "Should handle opening a workbook with Worksheet Names that will cause errors" { + $xlFilename = "$PSScriptRoot\UnsupportedWorkSheetNames.xlsx" + + { Open-ExcelPackage -Path $xlFilename -ErrorAction Stop } | Should -Not -Throw + } +} \ No newline at end of file diff --git a/__tests__/PasswordProtection.tests.ps1 b/__tests__/PasswordProtection.tests.ps1 new file mode 100644 index 00000000..66e79769 --- /dev/null +++ b/__tests__/PasswordProtection.tests.ps1 @@ -0,0 +1,31 @@ + + +Describe "Password Support" { + if ($PSVersionTable.PSVersion.Major -GT 5) { + It "Password Supported" { + Set-ItResult -Pending -Because "Can't test passwords on V6 and later" + } + return + } + Context "Password protected sheet" { + BeforeAll { + $password = "YouMustRememberThis" + $path = "TestDrive:\Test.xlsx" + Remove-Item $path -ErrorAction SilentlyContinue + Get-Service | Select-Object -First 10 | Export-excel -password $password -Path $Path -DisplayPropertySet + } + it "Threw an error when the password was omitted " { + {Open-ExcelPackage -Path $path } | Should -Throw + } + it "Was able to append when the password was included " { + {Get-Service | Select-Object -First 10 | + Export-excel -password $password -Path $Path -Append } | Should -Not -Throw + } + it "Kept the password on the file when it was saved " { + {Import-Excel $Path } | Should -Throw + } + it "Could read the file when the password was included " { + (Import-excel $path -Password $password).count | Should -Be 20 + } + } +} diff --git a/__tests__/Path.tests.ps1 b/__tests__/Path.tests.ps1 new file mode 100644 index 00000000..71838841 --- /dev/null +++ b/__tests__/Path.tests.ps1 @@ -0,0 +1,39 @@ +Describe "Test reading relative paths" { + BeforeAll { + $script:xlfileName = "TestR.xlsx" + If ([String]::IsNullOrEmpty($PWD)) { $PWD = $PSScriptRoot } + @{data = 1 } | Export-Excel (Join-Path $PWD "TestR.xlsx") + } + + AfterAll { + Remove-Item (Join-Path $PWD "$($script:xlfileName)") + } + + It "Should read local file".PadRight(90) { + $actual = Import-Excel -Path ".\$($script:xlfileName)" + $actual | Should -Not -Be $null + $actual.Count | Should -Be 1 + } + + It "Should read with pwd".PadRight(90) { + $actual = Import-Excel -Path (Join-Path $PWD "$($script:xlfileName)") + $actual | Should -Not -Be $null + } + + It "Should read with just a file name and resolve to cwd".PadRight(90) { + $actual = Import-Excel -Path "$($script:xlfileName)" + $actual | Should -Not -Be $null + } + + It "Should fail for not found".PadRight(90) { + { Import-Excel -Path "ExcelFileDoesNotExist.xlsx" } | Should -Throw "'ExcelFileDoesNotExist.xlsx' file not found" + } + + It "Should fail for xls extension".PadRight(90) { + { Import-Excel -Path "ExcelFileDoesNotExist.xls" } | Should -Throw "Import-Excel does not support reading this extension type .xls" + } + + It "Should fail for xlsxs extension".PadRight(90) { + { Import-Excel -Path "ExcelFileDoesNotExist.xlsxs" } | Should -Throw "Import-Excel does not support reading this extension type .xlsxs" + } +} \ No newline at end of file diff --git a/__tests__/ProtectWorksheet.tests.ps1 b/__tests__/ProtectWorksheet.tests.ps1 new file mode 100644 index 00000000..b1791788 --- /dev/null +++ b/__tests__/ProtectWorksheet.tests.ps1 @@ -0,0 +1,36 @@ +Describe "Setting worksheet protection " { + BeforeAll { + $path = "TestDrive:\test.xlsx" + Remove-Item -path $path -ErrorAction SilentlyContinue + $excel = ConvertFrom-Csv @" +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 + +"@ | Export-Excel -Path $path -WorksheetName Sheet1 -PassThru + + $ws = $excel.sheet1 + + Set-WorksheetProtection -Worksheet $ws -IsProtected -BlockEditObject -AllowFormatRows -UnLockAddress "1:1" + + Close-ExcelPackage -ExcelPackage $excel + $excel = Open-ExcelPackage -Path $path + $ws = $ws = $excel.sheet1 + } + it "Turned on protection for the sheet " { + $ws.Protection.IsProtected | Should -Be $true + } + it "Set sheet-wide protection options " { + $ws.Protection.AllowEditObject | Should -Be $false + $ws.Protection.AllowFormatRows | Should -Be $true + $ws.cells["a2"].Style.Locked | Should -Be $true + } + it "Unprotected some cells " { + $ws.cells["a1"].Style.Locked | Should -Be $false + } +} + diff --git a/__tests__/RangePassing.Tests.ps1 b/__tests__/RangePassing.Tests.ps1 new file mode 100644 index 00000000..0d44121a --- /dev/null +++ b/__tests__/RangePassing.Tests.ps1 @@ -0,0 +1,124 @@ +#Requires -Modules Pester +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '', Justification = 'Testing for presence of alias')] +param() + +describe "Consistent passing of ranges." { + BeforeAll { + $path = "TestDrive:\test.xlsx" + # if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) { + Function Get-Service { Import-Clixml $PSScriptRoot\Mockservices.xml } + # } + } + Context "Conditional Formatting" { + it "accepts named ranges, cells['name'], worksheet + Name, worksheet + column " { + Remove-Item -path $path -ErrorAction SilentlyContinue + $excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -AutoNameRange -Title "Services on $Env:COMPUTERNAME" + { Add-ConditionalFormatting $excel.Services.Names["Status"] -StrikeThru -RuleType ContainsText -ConditionValue "Stopped" } | Should -Not -Throw + $excel.Services.ConditionalFormatting.Count | Should -Be 1 + { Add-ConditionalFormatting $excel.Services.Cells["Name"] -Italic -RuleType ContainsText -ConditionValue "SVC" } | Should -Not -Throw + $excel.Services.ConditionalFormatting.Count | Should -Be 2 + $warnvar = $null + Add-ConditionalFormatting $excel.Services.Column(3) ` + -underline -RuleType ContainsText -ConditionValue "Windows" -WarningVariable warnvar -WarningAction SilentlyContinue + $warnvar | Should -Not -BeNullOrEmpty + $excel.Services.ConditionalFormatting.Count | Should -Be 2 + $warnvar = $null + Add-ConditionalFormatting $excel.Services.Column(3) -Worksheet $excel.Services` + -underline -RuleType ContainsText -ConditionValue "Windows" -WarningVariable warnvar -WarningAction SilentlyContinue + $warnvar | Should -BeNullOrEmpty + $excel.Services.ConditionalFormatting.Count | Should -Be 3 + { Add-ConditionalFormatting "Status" -Worksheet $excel.Services ` + -ForeGroundColor ([System.Drawing.Color]::Green) -RuleType ContainsText -ConditionValue "Running" } | Should -Not -Throw + $excel.Services.ConditionalFormatting.Count | Should -Be 4 + Close-ExcelPackage -NoSave $excel + } + + it "accepts table, table.Address and worksheet + 'C:C' " { + $excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME" + { Add-ConditionalFormatting $excel.Services.Tables[0] ` + -Italic -RuleType ContainsText -ConditionValue "Svc" } | Should -Not -Throw + $excel.Services.ConditionalFormatting.Count | Should -Be 1 + { Add-ConditionalFormatting $excel.Services.Tables["ServiceTable"].Address ` + -Bold -RuleType ContainsText -ConditionValue "windows" } | Should -Not -Throw + $excel.Services.ConditionalFormatting.Count | Should -Be 2 + { Add-ConditionalFormatting -Worksheet $excel.Services -Address "a:a" ` + -RuleType ContainsText -ConditionValue "stopped" -ForeGroundColor ([System.Drawing.Color]::Red) } | Should -Not -Throw + $excel.Services.ConditionalFormatting.Count | Should -Be 3 + Close-ExcelPackage -NoSave $excel + } + } + + Context "Formating (Set-ExcelRange or its alias Set-Format) " { + it "accepts Named Range, cells['Name'], cells['A1:Z9'], row, Worksheet + 'A1:Z9'" { + $excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME" + { Set-format $excel.Services.Names["serviceRange"] -Bold } | Should -Not -Throw + $excel.Services.cells["B2"].Style.Font.Bold | Should -Be $true + { Set-ExcelRange -Range $excel.Services.Cells["serviceRange"] -italic:$true } | Should -Not -Throw + $excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true + { Set-format $excel.Services.Row(4) -underline -Bold:$false } | Should -Not -Throw + $excel.Services.cells["A4"].Style.Font.UnderLine | Should -Be $true + $excel.Services.cells["A4"].Style.Font.Bold | Should -Not -Be $true + { Set-ExcelRange $excel.Services.Cells["A3:B3"] -StrikeThru } | Should -Not -Throw + $excel.Services.cells["B3"].Style.Font.Strike | Should -Be $true + { Set-ExcelRange -Worksheet $excel.Services -Range "A5:B6" -FontSize 8 } | Should -Not -Throw + $excel.Services.cells["A5"].Style.Font.Size | Should -Be 8 + Close-ExcelPackage -NoSave $excel + } + + it "Accepts Table, Table.Address , worksheet + Name, Column," { + $excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoNameRange -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME" + { Set-ExcelRange $excel.Services.Tables[0] -Italic } | Should -Not -Throw + $excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true + { Set-format $excel.Services.Tables["ServiceTable"].Address -Underline } | Should -Not -Throw + $excel.Services.cells["C3"].Style.Font.UnderLine | Should -Be $true + { Set-ExcelRange -Worksheet $excel.Services -Range "Name" -Bold } | Should -Not -Throw + $excel.Services.cells["B4"].Style.Font.Bold | Should -Be $true + { $excel.Services.Column(3) | Set-ExcelRange -FontColor ([System.Drawing.Color]::Red) } | Should -Not -Throw + $excel.Services.cells["C4"].Style.Font.Color.Rgb | Should -Be "FFFF0000" + Close-ExcelPackage -NoSave $excel + } + + } + + Context "PivotTables" { + it "Accepts Named range, .Cells['Name'], name&Worksheet, cells['A1:Z9'], worksheet&'A1:Z9' " { + $excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME" + $ws = $excel.Workbook.Worksheets[1] #can get a worksheet by name or index - starting at 1 + $end = $ws.Dimension.End.Address + #can get a named ranged by name or index - starting at zero + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt0 -SourceRange $ws.Names[0]` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt0"] | Should -Not -BeNullOrEmpty + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.Names["servicerange"]` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty + #Can specify the range for a pivot as NamedRange or Table or TableAddress or Worksheet + "A1:Z10" or worksheet + RangeName, or worksheet.cells["A1:Z10"] or worksheet.cells["RangeName"] + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange "servicerange" -SourceWorkSheet $ws ` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt3 -SourceRange $ws.cells["servicerange"]` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt3"] | Should -Not -BeNullOrEmpty + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt4 -SourceRange $ws.cells["A2:$end"]` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt4"] | Should -Not -BeNullOrEmpty + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt5 -SourceRange "A2:$end" -SourceWorkSheet $ws ` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt5"] | Should -Not -BeNullOrEmpty + Close-ExcelPackage -NoSave $excel + } + it "Accepts Table, Table.Addres " { + $excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME" + $ws = $excel.Workbook.Worksheets["Services"] #can get a worksheet by name or index - starting at 1 + #Can get a table by name or -stating at zero. Can specify the range for a pivot as or Table or TableAddress + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.tables["servicetable"]` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty + { Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange $ws.tables[0].Address ` + -PivotRows Status -PivotData Name } | Should -Not -Throw + $excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty + Close-ExcelPackage -NoSave $excel + } + } +} \ No newline at end of file diff --git a/__tests__/Read-Clipboard.tests.ps1 b/__tests__/Read-Clipboard.tests.ps1 new file mode 100644 index 00000000..152a9fe8 --- /dev/null +++ b/__tests__/Read-Clipboard.tests.ps1 @@ -0,0 +1,90 @@ +#Requires -Modules Pester +# if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { +Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force +# } +Describe "Read Clipboard" -Tag "Read-Clipboard" { + + It 'Should return $null if it cannot detect data format on the clipboard' { + $testData = 'abc' + $actual = ReadClipboardImpl $testData + $actual.Count | Should -Be 0 + $actual | Should -BeNullOrEmpty + } + + It 'Should return converted csv data' { + $testData = @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +"@ + $actual = ReadClipboardImpl $testData + $actual.count | Should -Be 3 + } + + It 'Should return converted tab delimited data' { + $testData = @" +YEAR PRESIDENT FIRST LADY VICE PRESIDENT +2021- Joseph R. Biden Jill Biden Kamala Harris +2017-2021 Donald J. Trump Melania Trump Mike Pence +2009-2017 Barack Obama Michelle Obama Joseph R. Biden +"@ + $actual = ReadClipboardImpl $testData + $actual.count | Should -Be 3 + } + + It 'Should return converted json data' { + $testData = @" +[ +{ + "YEAR": "2021-", + "PRESIDENT": "Joseph R. Biden", + "FIRST LADY": "Jill Biden", + "VICE PRESIDENT": "Kamala Harris" +}, +{ + "YEAR": "2017-2021", + "PRESIDENT": "Donald J. Trump", + "FIRST LADY": "Melania Trump", + "VICE PRESIDENT": "Mike Pence" +}, +{ + "YEAR": "2009-2017", + "PRESIDENT": "Barack Obama", + "FIRST LADY": "Michelle Obama", + "VICE PRESIDENT": "Joseph R. Biden" +} +] +"@ + $actual = ReadClipboardImpl $testData + $actual.count | Should -Be 3 + } + + It 'Should return converted "|" delimited data' { + $testData = @" +Region|State|Units|Price +West|Texas|927|923.71 +North|Tennessee|466|770.67 +East|Florida|520|458.68 +"@ + $actual = ReadClipboardImpl $testData -Delimiter '|' + $actual.count | Should -Be 3 + } + + It 'Should return converted data with headers' { + $testData = @" +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +"@ + + $actual = ReadClipboardImpl $testData -Header 'P1', 'P2', 'p3', 'P4' + $actual.count | Should -Be 3 + + $propertyNames = $actual[0].psobject.Properties.Name + $propertyNames[0] | Should -BeExactly 'P1' + $propertyNames[1] | Should -BeExactly 'P2' + $propertyNames[2] | Should -BeExactly 'p3' + $propertyNames[3] | Should -BeExactly 'P4' + } +} \ No newline at end of file diff --git a/__tests__/Read-OleDbDataTests/Invoke-ExcelQuery.Tests.ps1 b/__tests__/Read-OleDbDataTests/Invoke-ExcelQuery.Tests.ps1 new file mode 100644 index 00000000..e79f96dc --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Invoke-ExcelQuery.Tests.ps1 @@ -0,0 +1,46 @@ +#Requires -Modules Pester +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +$skip = $false +if ($IsLinux -or $IsMacOS) { + $skip = $true + Write-Warning "Invoke-ExcelQuery: Linux and MacOs are not supported. Skipping tests." +}else{ + try { + if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") { + $skip = $true + Write-Warning "Invoke-ExcelQuery: Microsoft.ACE.OLEDB.12.0 provider not found. Skipping tests." + } + } + catch { + $skip = $true + Write-Warning "Invoke-ExcelQuery: Calls to System.Data.OleDb failed. Skipping tests." + } +} + + +Describe "Invoke-ExcelQuery" -Tag "Invoke-ExcelQuery" { + $PSDefaultParameterValues = @{ 'It:Skip' = $skip } + BeforeAll { + $tfp = "$PSScriptRoot\Read-OleDbData.xlsx" + } + Context "Basic Checks" { + It "Should have a valid Test file" { + Test-Path $tfp | Should -Be $true + } + It "Should have the Read-OleDbData command loaded" { + (Get-Command Read-OleDbData -ErrorAction SilentlyContinue) -ne $null | Should -Be $true + } + It "Should have the Invoke-ExcelQuery command loaded" { + (Get-Command Invoke-ExcelQuery -ErrorAction SilentlyContinue) -ne $null | Should -Be $true + } + } + Context "Sheet1`$A1" { + It "Should return 1 result with a value of 1" { + $Results = Invoke-ExcelQuery $tfp "select ROUND(F1) as [A1] from [sheet1`$A1:A1]" + @($Results).length + $Results.A1 | Should -Be 2 + } + } +} diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.TestA.sql b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestA.sql new file mode 100644 index 00000000..576c6afd --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestA.sql @@ -0,0 +1,4 @@ +select + ROUND(F1) as [A1] +from + [sheet3$A1:A1] \ No newline at end of file diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.TestB.sql b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestB.sql new file mode 100644 index 00000000..9334b90d --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestB.sql @@ -0,0 +1,7 @@ +select ROUND(F1) as [A1] from [sheet1$A1:A1] +union all select ROUND(F1) as [A1] from [sheet2$A1:A1] +union all select ROUND(F1) as [A1] from [sheet3$A1:A1] +union all select ROUND(F1) as [A1] from [sheet4$A1:A1] +union all select ROUND(F1) as [A1] from [sheet5$A1:A1] +union all select ROUND(F1) as [A1] from [sheet6$A1:A1] +union all select ROUND(F1) as [A1] from [sheet7$A1:A1] \ No newline at end of file diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.TestC.sql b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestC.sql new file mode 100644 index 00000000..9e3f5f79 --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestC.sql @@ -0,0 +1,4 @@ +select + * +from + [sheet1$A1:E10] diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.TestD.sql b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestD.sql new file mode 100644 index 00000000..efb169c2 --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestD.sql @@ -0,0 +1,10 @@ +select top 1 + 'All A1s' as [A1], + F1 as [Sheet1], + (select F1 FROM [sheet2$a1:a1]) as [Sheet2], + (select F1 FROM [sheet3$a1:a1]) as [Sheet3], + (select F1 FROM [sheet4$a1:a1]) as [Sheet4], + (select F1 FROM [sheet5$a1:a1]) as [Sheet5], + (select F1 FROM [sheet6$a1:a1]) as [Sheet6], + (select F1 FROM [sheet7$a1:a1]) as [Sheet7] +FROM [sheet1$a1:a1] \ No newline at end of file diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.TestE.sql b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestE.sql new file mode 100644 index 00000000..bd98cfae --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Read-OleDbData.TestE.sql @@ -0,0 +1,31 @@ +select top 1 + 'All A1s Start from Sheet1' as [A1], + F1 as [Sheet1], + (select F1 FROM [sheet2$a1:a1]) as [Sheet2], + (select F1 FROM [sheet3$a1:a1]) as [Sheet3], + (select F1 FROM [sheet4$a1:a1]) as [Sheet4] +FROM [sheet1$a1:a1] +UNION ALL +select top 1 + 'All A1s Start from Sheet2' as [A1], + (select F1 FROM [sheet1$a1:a1]) as [Sheet1], + F1 as [Sheet2], + (select F1 FROM [sheet3$a1:a1]) as [Sheet3], + (select F1 FROM [sheet4$a1:a1]) as [Sheet4] +FROM [sheet2$a1:a1] +UNION ALL +select top 1 + 'All A1s Start from Sheet3' as [A1], + (select F1 FROM [sheet1$a1:a1]) as [Sheet1], + (select F1 FROM [sheet2$a1:a1]) as [Sheet2], + F1 as [Sheet3], + (select F1 FROM [sheet4$a1:a1]) as [Sheet4] +FROM [sheet3$a1:a1] +UNION ALL +select top 1 + 'All A1s Start from Sheet4' as [A1], + (select F1 FROM [sheet1$a1:a1]) as [Sheet1], + (select F1 FROM [sheet2$a1:a1]) as [Sheet2], + (select F1 FROM [sheet3$a1:a1]) as [Sheet3], + F1 as [Sheet4] +FROM [sheet4$a1:a1] diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.Tests.ps1 b/__tests__/Read-OleDbDataTests/Read-OleDbData.Tests.ps1 new file mode 100644 index 00000000..7a9ef5cf --- /dev/null +++ b/__tests__/Read-OleDbDataTests/Read-OleDbData.Tests.ps1 @@ -0,0 +1,92 @@ +#Requires -Modules Pester +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +$skip = $false +if ($IsLinux -or $IsMacOS) { + $skip = $true + Write-Warning "Read-OleDbData: Linux and MacOs are not supported. Skipping tests." +}else{ + try { + if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") { + $skip = $true + Write-Warning "Read-OleDbData: Microsoft.ACE.OLEDB.12.0 provider not found. Skipping tests." + } + } + catch { + $skip = $true + Write-Warning "Read-OleDbData: Calls to System.Data.OleDb failed. Skipping tests." + } +} +Describe "Read-OleDbData" -Tag "Read-OleDbData" { + $PSDefaultParameterValues = @{ 'It:Skip' = $skip } + BeforeAll { + $scriptPath = $PSScriptRoot + $tfp = "$scriptPath\Read-OleDbData.xlsx" + $cs = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$tfp;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" + } + Context "Basic Tests" { + It "Should have a valid Test file" { + Test-Path $tfp | Should -Be $true + } + It "Should have the Read-OleDbData command loaded" { + (Get-Command Read-OleDbData -ErrorAction SilentlyContinue) -ne $null | Should -Be $true + } + It "Should be able to open spreadsheet" { + $null = Read-OleDbData -ConnectionString $cs -SqlStatement "select 1" + $true | Should -Be $true + } + It "Should return PSCustomObject for single result" { + #multiple records will come back as Object[], but not going to test for that + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement "select 1" + $Results.GetType().Name | Should -Be 'PSCustomObject' + } + } + Context "Sheet1`$A1" { + It "Should return 1 result with a value of 1" { + $sql = "select ROUND(F1) as [A1] from [sheet1`$A1:A1]" + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement $sql + @($Results).length + $Results.A1 | Should -Be 2 + } + } + Context "Sheet2`$A1" { + It "Should return 1 result with value of 2" { + $sql = "select ROUND(F1) as [A1] from [sheet2`$A1:A1]" + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement $sql + @($Results).length + $Results.A1 | Should -Be 3 + } + } + Context "Sheet3`$A1, Sql from file" { + It "Should return 1 result with value of 3" { + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement (Get-Content "$scriptPath\Read-OleDbData.TestA.sql" -raw) + @($Results).length + $Results.A1 | Should -Be 4 + } + } + Context "Sheets[1-7]`$A1, Sql from file" { + It "Should return 7 result with where sum values 1-6 = value 7" { + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement (Get-Content "$scriptPath\Read-OleDbData.TestB.sql" -raw) + $a = $Results.A1 + $a.length + ($a[0..5] | Measure-Object -sum).sum | Should -Be (7 + $a[6]) + } + } + Context "Sheet1`$:A1:E10, Sql from file" { + #note, this spreadsheet doesn't have the fields populated other than A1, so it will, correctly, return only one value + It "Should return 1 result with value of 1" { + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement (Get-Content "$scriptPath\Read-OleDbData.TestC.sql" -raw) + @($Results).length + $Results.F1 | Should -Be 2 + } + } + Context "When Read-OleDbData.xlsx, select a1 from all sheets as a single record, and sql is in a file" { + It "should return one row with 8 columns" { + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement (Get-Content "$scriptPath\Read-OleDbData.TestD.sql" -raw) + @($Results).length + @($Results.psobject.Properties).length | Should -Be 9 + } + } + Context "When Read-OleDbData.xlsx, select a1 from all sheets as a single record multiple times to create a range, and sql is in a file" { + It "should return 4 records with 5 columns" { + $Results = Read-OleDbData -ConnectionString $cs -SqlStatement (Get-Content "$scriptPath\Read-OleDbData.TestE.sql" -raw) + @($Results).length + @($Results[0].psobject.Properties).length | Should -Be 9 + } + } +} \ No newline at end of file diff --git a/__tests__/Read-OleDbDataTests/Read-OleDbData.xlsx b/__tests__/Read-OleDbDataTests/Read-OleDbData.xlsx new file mode 100644 index 00000000..5458ccfb Binary files /dev/null and b/__tests__/Read-OleDbDataTests/Read-OleDbData.xlsx differ diff --git a/__tests__/Remove-WorkSheet.tests.ps1 b/__tests__/Remove-WorkSheet.tests.ps1 new file mode 100644 index 00000000..ca660b63 --- /dev/null +++ b/__tests__/Remove-WorkSheet.tests.ps1 @@ -0,0 +1,79 @@ +#Requires -Modules Pester +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} +Describe "Remove Worksheet" { + Context "Remove a worksheet output" { + BeforeEach { + # Create three sheets + $data = ConvertFrom-Csv @" +Name,Age +Jane,10 +John,20 +"@ + $xlFile1 = "TestDrive:\RemoveWorsheet1.xlsx" + Remove-Item $xlFile1 -ErrorAction SilentlyContinue + + $data | Export-Excel -Path $xlFile1 -WorksheetName Target1 + $data | Export-Excel -Path $xlFile1 -WorksheetName Target2 + $data | Export-Excel -Path $xlFile1 -WorksheetName Target3 + $data | Export-Excel -Path $xlFile1 -WorksheetName Sheet1 + + $xlFile2 = "TestDrive:\RemoveWorsheet2.xlsx" + Remove-Item $xlFile2 -ErrorAction SilentlyContinue + + $data | Export-Excel -Path $xlFile2 -WorksheetName Target1 + $data | Export-Excel -Path $xlFile2 -WorksheetName Target2 + $data | Export-Excel -Path $xlFile2 -WorksheetName Target3 + $data | Export-Excel -Path $xlFile2 -WorksheetName Sheet1 + } + + it "Should throw about the Path".PadRight(87) { + {Remove-Worksheet} | Should -Throw 'Remove-Worksheet requires the and Excel file' + } + + it "Should delete Target2".PadRight(87) { + Remove-Worksheet -Path $xlFile1 -WorksheetName Target2 + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should -Be 3 + $actual[0].Name | Should -Be "Target1" + $actual[1].Name | Should -Be "Target3" + $actual[2].Name | Should -Be "Sheet1" + } + + it "Should delete Sheet1".PadRight(87) { + Remove-Worksheet -Path $xlFile1 + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should -Be 3 + $actual[0].Name | Should -Be "Target1" + $actual[1].Name | Should -Be "Target2" + $actual[2].Name | Should -Be "Target3" + } + + it "Should delete multiple sheets".PadRight(87) { + Remove-Worksheet -Path $xlFile1 -WorksheetName Target1, Sheet1 + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should -Be 2 + $actual[0].Name | Should -Be "Target2" + $actual[1].Name | Should -Be "Target3" + } + + it "Should delete sheet from multiple workbooks".PadRight(87) { + + Get-ChildItem "TestDrive:\RemoveWorsheet*.xlsx" | Remove-Worksheet + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should -Be 3 + $actual[0].Name | Should -Be "Target1" + $actual[1].Name | Should -Be "Target2" + $actual[2].Name | Should -Be "Target3" + } + } +} \ No newline at end of file diff --git a/__tests__/Samples/Get-CimInstanceDisk.xml b/__tests__/Samples/Get-CimInstanceDisk.xml new file mode 100644 index 00000000..9c9d5786 Binary files /dev/null and b/__tests__/Samples/Get-CimInstanceDisk.xml differ diff --git a/__tests__/Samples/Get-CimInstanceNetAdapter.xml b/__tests__/Samples/Get-CimInstanceNetAdapter.xml new file mode 100644 index 00000000..27db7a49 Binary files /dev/null and b/__tests__/Samples/Get-CimInstanceNetAdapter.xml differ diff --git a/__tests__/Samples/Get-Process.xml b/__tests__/Samples/Get-Process.xml new file mode 100644 index 00000000..763098df Binary files /dev/null and b/__tests__/Samples/Get-Process.xml differ diff --git a/__tests__/Samples/Get-Service.xml b/__tests__/Samples/Get-Service.xml new file mode 100644 index 00000000..d8181a52 Binary files /dev/null and b/__tests__/Samples/Get-Service.xml differ diff --git a/__tests__/Samples/Samples.ps1 b/__tests__/Samples/Samples.ps1 new file mode 100644 index 00000000..0d14446c --- /dev/null +++ b/__tests__/Samples/Samples.ps1 @@ -0,0 +1,53 @@ +if ($IsLinux -or $IsMacOS) { + if (-not (Get-Command 'Get-Service' -ErrorAction SilentlyContinue)) { + function Get-Service { + Import-Clixml -Path (Join-Path $PSScriptRoot Get-Service.xml) + } + } + if (-not (Get-Command 'Get-CimInstance' -ErrorAction SilentlyContinue)) { + function Get-CimInstance { + param ( + $ClassName, + $Namespace, + $class + ) + if ($ClassName -eq 'win32_logicaldisk') { + Import-Clixml -Path (Join-Path $PSScriptRoot Get-CimInstanceDisk.xml) + } + elseif ($class -eq 'MSFT_NetAdapter') { + Import-Clixml -Path (Join-Path $PSScriptRoot Get-CimInstanceNetAdapter.xml) + } + } + } + function Get-Process { + param ( + $Name, + $Id + ) + if (-not $Name) { + if ($Id) { + (Import-Clixml -Path (Join-Path $PSScriptRoot Get-Process.xml))[0] + } + else { + Import-Clixml -Path (Join-Path $PSScriptRoot Get-Process.xml) + } + } + } +} + +<# Creating the samples +Get-Service | Select-Object -First 30 | Export-Clixml -Path Get-Service.xml + +$Disk = Get-CimInstance -ClassName win32_logicaldisk | Select-Object -Property DeviceId,VolumeName, Size,Freespace +$Disk | Export-Clixml -Path Get-CimInstanceDisk.xml + +$NetAdapter = Get-CimInstance -Namespace root/StandardCimv2 -class MSFT_NetAdapter | Select-Object -Property Name, InterfaceDescription, MacAddress, LinkSpeed +$NetAdapter | Export-Clixml -Path Get-CimInstanceNetAdapter.xml + +$Process = Get-Process | Where-Object { $_.StartTime -and $_.StartInfo -and $_.Modules -and $_.Company -notlike '*Microsoft*' } | Select-Object -first 20 +$Process | Export-Clixml -Path $Path +$Process = Import-Clixml -Path $Path +$Process | foreach {$_.Threads = 'System.Diagnostics.ProcessThreadCollection'} +$Process | foreach {$_.Modules = 'System.Diagnostics.ProcessThreadCollection'} +$Process | Export-Clixml -Path $Path +#> \ No newline at end of file diff --git a/__tests__/Set-CellComment.tests.ps1 b/__tests__/Set-CellComment.tests.ps1 new file mode 100644 index 00000000..c952eee8 --- /dev/null +++ b/__tests__/Set-CellComment.tests.ps1 @@ -0,0 +1,44 @@ +if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) { + Import-Module $PSScriptRoot\..\ImportExcel.psd1 +} + +Describe "Test setting comment on cells in different ways" -Tag SetCellComment { + BeforeAll { + $data = ConvertFrom-Csv @" +OrderId,Category,Sales,Quantity,Discount +1,Cosmetics,744.01,07,0.7 +2,Grocery,349.13,25,0.3 +3,Apparels,535.11,88,0.2 +4,Electronics,524.69,60,0.1 +5,Electronics,439.10,41,0.0 +6,Apparels,56.84,54,0.8 +7,Electronics,326.66,97,0.7 +8,Cosmetics,17.25,74,0.6 +9,Grocery,199.96,39,0.4 +10,Grocery,731.77,20,0.3 +"@ + + $Excel = $data | Export-Excel -PassThru + $ws = $Excel.Workbook.Worksheets | Select-Object -First 1 + } + + AfterAll { + Close-ExcelPackage $Excel + } + + It "Should add comments to multiple cells".PadRight(87) { + Set-CellComment -Range "A1" -Worksheet $ws -Text "This was added with a single cell range" + Set-CellComment -Range "A2:C2" -Worksheet $ws -Text "This was added with a multiple cell range" + Set-CellComment -ColumnLetter A -Row 3 -Worksheet $ws -Text "This was added using a column letter and rownumber" + Set-CellComment -ColumnNumber 1 -Row 4 -Worksheet $ws -Text "This was added using a column number and row number" + + Set-CellComment -Range "B2" -Worksheet $ws -Text "This demonstrates an overwrite of a previously set comment" + + $ws.Cells["A1"].Comment.Text | Should -BeExactly "This was added with a single cell range" + $ws.Cells["A2"].Comment.Text | Should -BeExactly "This was added with a multiple cell range" + $ws.Cells["B2"].Comment.Text | Should -BeExactly "This demonstrates an overwrite of a previously set comment" + $ws.Cells["C2"].Comment.Text | Should -BeExactly "This was added with a multiple cell range" + $ws.Cells["A3"].Comment.Text | Should -BeExactly "This was added using a column letter and rownumber" + $ws.Cells["A4"].Comment.Text | Should -BeExactly "This was added using a column number and row number" + } +} \ No newline at end of file diff --git a/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 new file mode 100644 index 00000000..59c99089 --- /dev/null +++ b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 @@ -0,0 +1,428 @@ + + +Describe "Number format expansion and setting" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + + $data = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price + 12001,Nails,37,3.99 + 12002,Hammer,5,12.10 + 12003,Saw,12,15.37 + 12010,Drill,20,8 + 12011,Crowbar,7,23.48 +"@ + + $DriverData = convertFrom-CSv @" + Name,Wikipage,DateOfBirth + Fernando Alonso,/wiki/Fernando_Alonso,1981-07-29 + Jenson Button,/wiki/Jenson_Button,1980-01-19 + Kimi Räikkönen,/wiki/Kimi_R%C3%A4ikk%C3%B6nen,1979-10-17 + Lewis Hamilton,/wiki/Lewis_Hamilton,1985-01-07 + Nico Rosberg,/wiki/Nico_Rosberg,1985-06-27 + Sebastian Vettel,/wiki/Sebastian_Vettel,1987-07-03 +"@ | ForEach-Object { $_.DateOfBirth = [datetime]$_.DateofBirth; $_ } + } + + Context "Expand-NumberFormat function" { + It "Expanded named number formats as expected " { + $r = [regex]::Escape([cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol) + Expand-NumberFormat 'Currency' | Should -Match "^[$r\(\)\[\] RED0#\?\-;,.]+$" + Expand-NumberFormat 'Number' | Should -Be "0.00" + Expand-NumberFormat 'Percentage' | Should -Be "0.00%" + Expand-NumberFormat 'Scientific' | Should -Be "0.00E+00" + Expand-NumberFormat 'Fraction' | Should -Be "# ?/?" + Expand-NumberFormat 'Short Date' | Should -Be "mm-dd-yy" + Expand-NumberFormat 'Short Time' | Should -Be "h:mm" + Expand-NumberFormat 'Long Time' | Should -Be "h:mm:ss" + Expand-NumberFormat 'Date-Time' | Should -Be "m/d/yy h:mm" + Expand-NumberFormat 'Text' | Should -Be "@" + } + } + Context "Apply-NumberFormat" { + BeforeAll { + Remove-Item -Path $path -ErrorAction SilentlyContinue + $n = [datetime]::Now.ToOADate() + + $excel = 1..32 | ForEach-Object { $n } | Export-Excel -Path $path -show -WorksheetName s2 -PassThru + $ws = $excel.Workbook.Worksheets[1] + Set-ExcelRange -Worksheet $ws -Range "A1" -numberFormat 'General' + Set-ExcelRange -Worksheet $ws -Range "A2" -numberFormat 'Number' + Set-ExcelRange -Worksheet $ws -Range "A3" -numberFormat 'Percentage' + Set-ExcelRange -Worksheet $ws -Range "A4" -numberFormat 'Scientific' + Set-ExcelRange -Worksheet $ws -Range "A5" -numberFormat 'Fraction' + Set-ExcelRange -Worksheet $ws -Range "A6" -numberFormat 'Short Date' + Set-ExcelRange -Worksheet $ws -Range "A7" -numberFormat 'Short Time' + Set-ExcelRange -Worksheet $ws -Range "A8" -numberFormat 'Long Time' + Set-ExcelRange -Worksheet $ws -Range "A9" -numberFormat 'Date-Time' + Set-ExcelRange -Worksheet $ws -Range "A10" -numberFormat 'Currency' + Set-ExcelRange -Worksheet $ws -Range "A11" -numberFormat 'Text' + Set-ExcelRange -Worksheet $ws -Range "A12" -numberFormat 'h:mm AM/PM' + Set-ExcelRange -Worksheet $ws -Range "A13" -numberFormat 'h:mm:ss AM/PM' + Set-ExcelRange -Worksheet $ws -Range "A14" -numberFormat 'mm:ss' + Set-ExcelRange -Worksheet $ws -Range "A15" -numberFormat '[h]:mm:ss' + Set-ExcelRange -Worksheet $ws -Range "A16" -numberFormat 'mmss.0' + Set-ExcelRange -Worksheet $ws -Range "A17" -numberFormat 'd-mmm-yy' + Set-ExcelRange -Worksheet $ws -Range "A18" -numberFormat 'd-mmm' + Set-ExcelRange -Worksheet $ws -Range "A19" -numberFormat 'mmm-yy' + Set-ExcelRange -Worksheet $ws -Range "A20" -numberFormat '0' + Set-ExcelRange -Worksheet $ws -Range "A21" -numberFormat '0.00' + Set-ExcelRange -Address $ws.Cells[ "A22"] -NumberFormat '#,##0' + Set-ExcelRange -Address $ws.Cells[ "A23"] -NumberFormat '#,##0.00' + Set-ExcelRange -Address $ws.Cells[ "A24"] -NumberFormat '#,' + Set-ExcelRange -Address $ws.Cells[ "A25"] -NumberFormat '#.0,,' + Set-ExcelRange -Address $ws.Cells[ "A26"] -NumberFormat '0%' + Set-ExcelRange -Address $ws.Cells[ "A27"] -NumberFormat '0.00%' + Set-ExcelRange -Address $ws.Cells[ "A28"] -NumberFormat '0.00E+00' + Set-ExcelRange -Address $ws.Cells[ "A29"] -NumberFormat '# ?/?' + Set-ExcelRange -Address $ws.Cells[ "A30"] -NumberFormat '# ??/??' + Set-ExcelRange -Address $ws.Cells[ "A31"] -NumberFormat '@' + + Close-ExcelPackage -ExcelPackage $excel + + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Workbook.Worksheets[1] + } + + It "Set formats which translate to the correct format ID " { + $ws.Cells[ 1, 1].Style.Numberformat.NumFmtID | Should -Be 0 # Set as General + $ws.Cells[20, 1].Style.Numberformat.NumFmtID | Should -Be 1 # Set as 0 + $ws.Cells[ 2, 1].Style.Numberformat.NumFmtID | Should -Be 2 # Set as "Number" + $ws.Cells[21, 1].Style.Numberformat.NumFmtID | Should -Be 2 # Set as 0.00 + $ws.Cells[22, 1].Style.Numberformat.NumFmtID | Should -Be 3 # Set as #,##0 + $ws.Cells[23, 1].Style.Numberformat.NumFmtID | Should -Be 4 # Set as #,##0.00 + $ws.Cells[26, 1].Style.Numberformat.NumFmtID | Should -Be 9 # Set as 0% + $ws.Cells[27, 1].Style.Numberformat.NumFmtID | Should -Be 10 # Set as 0.00% + $ws.Cells[ 3, 1].Style.Numberformat.NumFmtID | Should -Be 10 # Set as "Percentage" + $ws.Cells[28, 1].Style.Numberformat.NumFmtID | Should -Be 11 # Set as 0.00E+00 + $ws.Cells[ 4, 1].Style.Numberformat.NumFmtID | Should -Be 11 # Set as "Scientific" + $ws.Cells[ 5, 1].Style.Numberformat.NumFmtID | Should -Be 12 # Set as "Fraction" + $ws.Cells[29, 1].Style.Numberformat.NumFmtID | Should -Be 12 # Set as # ?/? + $ws.Cells[30, 1].Style.Numberformat.NumFmtID | Should -Be 13 # Set as # ??/? + $ws.Cells[ 6, 1].Style.Numberformat.NumFmtID | Should -Be 14 # Set as "Short date" + $ws.Cells[17, 1].Style.Numberformat.NumFmtID | Should -Be 15 # Set as d-mmm-yy + $ws.Cells[18, 1].Style.Numberformat.NumFmtID | Should -Be 16 # Set as d-mmm + $ws.Cells[19, 1].Style.Numberformat.NumFmtID | Should -Be 17 # Set as mmm-yy + $ws.Cells[12, 1].Style.Numberformat.NumFmtID | Should -Be 18 # Set as h:mm AM/PM + $ws.Cells[13, 1].Style.Numberformat.NumFmtID | Should -Be 19 # Set as h:mm:ss AM/PM + $ws.Cells[ 7, 1].Style.Numberformat.NumFmtID | Should -Be 20 # Set as "Short time" + $ws.Cells[ 8, 1].Style.Numberformat.NumFmtID | Should -Be 21 # Set as "Long time" + $ws.Cells[ 9, 1].Style.Numberformat.NumFmtID | Should -Be 22 # Set as "Date-time" + $ws.Cells[14, 1].Style.Numberformat.NumFmtID | Should -Be 45 # Set as mm:ss + $ws.Cells[15, 1].Style.Numberformat.NumFmtID | Should -Be 46 # Set as [h]:mm:ss + $ws.Cells[16, 1].Style.Numberformat.NumFmtID | Should -Be 47 # Set as mmss.0 + $ws.Cells[11, 1].Style.Numberformat.NumFmtID | Should -Be 49 # Set as "Text" + $ws.Cells[31, 1].Style.Numberformat.NumFmtID | Should -Be 49 # Set as @ + $ws.Cells[24, 1].Style.Numberformat.Format | Should -Be '#,' # Whole thousands + $ws.Cells[25, 1].Style.Numberformat.Format | Should -Be '#.0,,' # Millions + } + } +} + +Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + + $data = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price + 12001,Nails,37,3.99 + 12002,Hammer,5,12.10 + 12003,Saw,12,15.37 + 12010,Drill,20,8 + 12011,Crowbar,7,23.48 +"@ + + # Pester errors for countries with ',' as decimal separator + Foreach ($datarow in $data) { + $datarow.Price = [decimal]($datarow.Price) + } + + $DriverData = convertFrom-CSv @" + Name,Wikipage,DateOfBirth + Fernando Alonso,/wiki/Fernando_Alonso,1981-07-29 + Jenson Button,/wiki/Jenson_Button,1980-01-19 + Kimi Räikkönen,/wiki/Kimi_R%C3%A4ikk%C3%B6nen,1979-10-17 + Lewis Hamilton,/wiki/Lewis_Hamilton,1985-01-07 + Nico Rosberg,/wiki/Nico_Rosberg,1985-06-27 + Sebastian Vettel,/wiki/Sebastian_Vettel,1987-07-03 +"@ | ForEach-Object { $_.DateOfBirth = [datetime]$_.DateofBirth; $_ } + + Remove-Item -Path $path -ErrorAction SilentlyContinue + $excel = $data | Export-Excel -Path $path -AutoNameRange -PassThru + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "Total" -Value "=Quantity*Price" -NumberFormat "£#,###.00" -FontColor ([System.Drawing.Color]::Blue) -Bold -HorizontalAlignment Right -VerticalAlignment Top + $r = Set-ExcelRow -PassThru -Worksheet $ws -StartColumn 3 -BorderAround Thin -Italic -Underline -FontSize 14 -Value { "=sum($columnName`2:$columnName$endrow)" } -VerticalAlignment Bottom + Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].Cells["b3"] -HorizontalAlignment Right -VerticalAlignment Center -BorderAround Thick -BorderColor ([System.Drawing.Color]::Red) -StrikeThru + Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].Cells["c3"] -BorderColor ([System.Drawing.Color]::Red) -BorderTop DashDot -BorderLeft DashDotDot -BorderBottom Dashed -BorderRight Dotted + Set-ExcelRange -Worksheet $ws -Range "E3" -Bold:$false -FontShift Superscript -HorizontalAlignment Left + Set-ExcelRange -Worksheet $ws -Range "E1" -ResetFont -HorizontalAlignment General -FontName "Courier New" -fontSize 9 + Set-ExcelRange -Address $ws.Cells["E7"] -ResetFont -WrapText -BackgroundColor ([System.Drawing.Color]::AliceBlue) -BackgroundPattern DarkTrellis -PatternColor ([System.Drawing.Color]::Red) -NumberFormat "£#,###.00" + Set-ExcelRange -Address $ws.Column(1) -Width 0 + if (-not $env:NoAutoSize) { + Set-ExcelRange -Address $ws.Column(2) -AutoFit + Set-ExcelRange -Address $ws.Cells["E:E"] -AutoFit + } + #Test alias + Set-Format -Address $ws.row(5) -Height 0 + $rr = $r.row + Set-ExcelRange -Worksheet $ws -Range "B$rr" -Value "Total" + $BadHideWarnvar = $null + Set-ExcelRange -Worksheet $ws -Range "D$rr" -Formula "=E$rr/C$rr" -Hidden -WarningVariable "BadHideWarnvar" -WarningAction SilentlyContinue + $rr ++ + Set-ExcelRange -Worksheet $ws -Range "B$rr" -Value ([datetime]::Now) + Close-ExcelPackage $excel -Calculate + + + $excel = Open-ExcelPackage $path + $ws = $excel.Workbook.Worksheets["Sheet1"] + } + Context "Set-ExcelRow and Set-ExcelColumn" { + it "Set a row and a column to have zero width/height " { + $r | Should -Not -BeNullorEmpty + # $c | Should -Not -BeNullorEmpty ## can't see why but this test breaks in appveyor + $ws.Column(1).width | Should -Be 0 + $ws.Row(5).height | Should -Be 0 + } + it "Set a column formula, with numberformat, color, bold face and alignment " { + $ws.Cells["e2"].Formula | Should -Be "Quantity*Price" + $ws.Cells["e2"].Value | Should -Be 147.63 + $ws.Cells["e2"].Style.Font.Color.rgb | Should -Be "FF0000FF" + $ws.Cells["e2"].Style.Font.Bold | Should -Be $true + $ws.Cells["e2"].Style.Font.VerticalAlign | Should -Be "None" + $ws.Cells["e2"].Style.Numberformat.format | Should -Be "£#,###.00" + $ws.Cells["e2"].Style.HorizontalAlignment | Should -Be "Right" + } + } + Context "Other formatting" { + it "Trapped an attempt to hide a range instead of a Row/Column " { + $BadHideWarnvar | Should -Not -BeNullOrEmpty + } + it "Set and calculated a row formula with border font size and underline " { + $ws.Cells["b7"].Style.Border.Top.Style | Should -Be "None" + $ws.Cells["F7"].Style.Border.Top.Style | Should -Be "None" + $ws.Cells["C7"].Style.Border.Top.Style | Should -Be "Thin" + $ws.Cells["C7"].Style.Border.Bottom.Style | Should -Be "Thin" + $ws.Cells["C7"].Style.Border.Right.Style | Should -Be "None" + $ws.Cells["C7"].Style.Border.Left.Style | Should -Be "Thin" + $ws.Cells["E7"].Style.Border.Left.Style | Should -Be "None" + $ws.Cells["E7"].Style.Border.Right.Style | Should -Be "Thin" + $ws.Cells["C7"].Style.Font.size | Should -Be 14 + $ws.Cells["C7"].Formula | Should -Be "sum(C2:C6)" + $ws.Cells["C7"].value | Should -Be 81 + $ws.Cells["C7"].Style.Font.UnderLine | Should -Be $true + $ws.Cells["C6"].Style.Font.UnderLine | Should -Be $false + } + it "Set custom font, size, text-wrapping, alignment, superscript, border and Fill " { + $ws.Cells["b3"].Style.Border.Left.Color.Rgb | Should -Be "FFFF0000" + $ws.Cells["b3"].Style.Border.Left.Style | Should -Be "Thick" + $ws.Cells["b3"].Style.Border.Right.Style | Should -Be "Thick" + $ws.Cells["b3"].Style.Border.Top.Style | Should -Be "Thick" + $ws.Cells["b3"].Style.Border.Bottom.Style | Should -Be "Thick" + $ws.Cells["b3"].Style.Font.Strike | Should -Be $true + $ws.Cells["e1"].Style.Font.Color.Rgb | Should -Be "ff000000" + $ws.Cells["e1"].Style.Font.Bold | Should -Be $false + $ws.Cells["e1"].Style.Font.Name | Should -Be "Courier New" + $ws.Cells["e1"].Style.Font.Size | Should -Be 9 + $ws.Cells["e3"].Style.Font.VerticalAlign | Should -Be "Superscript" + $ws.Cells["e3"].Style.HorizontalAlignment | Should -Be "Left" + $ws.Cells["C6"].Style.WrapText | Should -Be $false + $ws.Cells["e7"].Style.WrapText | Should -Be $true + $ws.Cells["e7"].Style.Fill.BackgroundColor.Rgb | Should -Be "FFF0F8FF" + $ws.Cells["e7"].Style.Fill.PatternColor.Rgb | Should -Be "FFFF0000" + $ws.Cells["e7"].Style.Fill.PatternType | Should -Be "DarkTrellis" + } + } + + Context "Set-ExcelRange value setting " { + it "Inserted a formula " { + $ws.Cells["D7"].Formula | Should -Be "E7/C7" + } + it "Inserted a value " { + $ws.Cells["B7"].Value | Should -Be "Total" + } + it "Inserted a date with localized date-time format " { + $ws.Cells["B8"].Style.Numberformat.NumFmtID | Should -Be 22 + } + } + + Context "Set-ExcelColumn Value Setting" { + BeforeAll { + Remove-Item -Path $path -ErrorAction SilentlyContinue + + $excel = $DriverData | Export-Excel -PassThru -Path $path -AutoSize -AutoNameRange + $ws = $excel.Workbook.Worksheets[1] + + Set-ExcelColumn -Worksheet $ws -Heading "Link" -AutoSize -Value { "https://en.wikipedia.org" + $worksheet.Cells["B$Row"].value } + $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "NextBirthday" -Value { + $bmonth = $worksheet.Cells["C$Row"].value.month ; $bDay = $worksheet.Cells["C$Row"].value.day + $cMonth = [datetime]::Now.Month ; $cday = [datetime]::Now.day ; $cyear = [datetime]::Now.Year + if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))) { + [datetime]::new($cyear + 1, $bmonth, $bDay) + } + else { [datetime]::new($cyear, $bmonth, $bday) } + } + Set-ExcelColumn -Worksheet $ws -Heading "Age" -Value "=INT((NOW()-DateOfBirth)/365)" + # Test Piping column Numbers into Set excelColumn + 3, $c.ColumnMin | Set-ExcelColumn -Worksheet $ws -NumberFormat 'Short Date' -AutoSize + + 4..6 | Set-ExcelColumn -Worksheet $ws -AutoNameRange + + Close-ExcelPackage -ExcelPackage $excel -Calculate + $excel = Open-ExcelPackage $path + $ws = $excel.Workbook.Worksheets["Sheet1"] + } + It "Inserted Hyperlinks " { + $ws.Cells["D2"].Hyperlink | Should -Not -BeNullorEmpty + $ws.Cells["D2"].Style.Font.UnderLine | Should -Be $true + } + It "Inserted and formatted Dates " { + $ws.Cells["C2"].Value.GetType().name | Should -Be "DateTime" + $ws.Cells["C2"].Style.Numberformat.NumFmtID | Should -Be 14 + $ws.Cells["E2"].Value.GetType().name | Should -Be "DateTime" + $ws.Cells["E2"].Style.Numberformat.NumFmtID | Should -Be 14 + } + It "Inserted Formulas " { + $ws.Cells["F2"].Formula | Should -Not -BeNullorEmpty + } + It "Created Named ranges " { + $ws.Names.Count | Should -Be 6 + $ws.Names["Age"] | Should -Not -BeNullorEmpty + $ws.Names["Age"].Start.Column | Should -Be 6 + $ws.Names["Age"].Start.Row | Should -Be 2 + $ws.Names["Age"].End.Row | Should -Be 7 + $ws.names[0].name | Should -Be "Name" + $ws.Names[0].Start.Column | Should -Be 1 + $ws.Names[0].Start.Row | Should -Be 2 + } + + } +} + +Describe "Conditional Formatting" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + $data = Get-Process | Where-Object company | Select-Object company, name, pm, handles, *mem* + $cfmt = New-ConditionalFormattingIconSet -Range "c:c" -ConditionalFormat ThreeIconSet -IconType Arrows + $data | Export-Excel -path $Path -AutoSize -ConditionalFormat $cfmt + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Workbook.Worksheets[1] + } + Context "Using a pre-prepared 3 Arrows rule" { + it "Set the right type, IconSet and range " { + $ws.ConditionalFormatting[0].IconSet | Should -Be "Arrows" + $ws.ConditionalFormatting[0].Address.Address | Should -Be "c:c" + $ws.ConditionalFormatting[0].Type.ToString() | Should -Be "ThreeIconSet" + } + } + +} + +Describe "AutoNameRange data with a single property name" { + BeforeEach { + $path = "TestDrive:\test.xlsx" + $data2 = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price,Total + 12001,Nails,37,3.99,147.63 + 12002,Hammer,5,12.10,60.5 + 12003,Saw,12,15.37,184.44 + 12010,Drill,20,8,160 + 12011,Crowbar,7,23.48,164.36 + 12001,Nails,53,3.99,211.47 + 12002,Hammer,6,12.10,72.60 + 12003,Saw,10,15.37,153.70 + 12010,Drill,10,8,80 + 12012,Pliers,2,14.99,29.98 + 12001,Nails,20,3.99,79.80 + 12002,Hammer,2,12.10,24.20 + 12010,Drill,11,8,88 + 12012,Pliers,3,14.99,44.97 +"@ + $xlfile = "TestDrive:\testNamedRange.xlsx" + Remove-Item $xlfile -ErrorAction SilentlyContinue + } + + it "Should have a single item as a named range " { + $excel = ConvertFrom-Csv @" +Sold +1 +2 +3 +4 +"@ | Export-Excel $xlfile -PassThru -AutoNameRange + + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $ws.Names.Count | Should -Be 1 + $ws.Names[0].Name | Should -Be 'Sold' + } + + it "Should have a more than a single item as a named range " { + $excel = ConvertFrom-Csv @" +Sold,ID +1,a +2,b +3,c +4,d +"@ | Export-Excel $xlfile -PassThru -AutoNameRange + + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $ws.Names.Count | Should -Be 2 + $ws.Names[0].Name | Should -Be 'Sold' + $ws.Names[1].Name | Should -Be 'ID' + } +} + +Describe "Table Formatting" { + BeforeAll { + $path = "TestDrive:\test.xlsx" + $data2 = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price,Total + 12001,Nails,37,3.99,147.63 + 12002,Hammer,5,12.10,60.5 + 12003,Saw,12,15.37,184.44 + 12010,Drill,20,8,160 + 12011,Crowbar,7,23.48,164.36 + 12001,Nails,53,3.99,211.47 + 12002,Hammer,6,12.10,72.60 + 12003,Saw,10,15.37,153.70 + 12010,Drill,10,8,80 + 12012,Pliers,2,14.99,29.98 + 12001,Nails,20,3.99,79.80 + 12002,Hammer,2,12.10,24.20 + 12010,Drill,11,8,88 + 12012,Pliers,3,14.99,44.97 +"@ + $excel = $data2 | Export-excel -path $path -WorksheetName Hardware -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru + $ws = $excel.Workbook.Worksheets[1] + #test showfilter & TotalSettings + $Table = Add-ExcelTable -PassThru -Range $ws.Cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TableTotalSettings @{"Total" = "Sum"} -ShowFirstColumn -ShowFilter:$false + #test expnading named number formats + Set-ExcelColumn -Worksheet $ws -Column 4 -NumberFormat 'Currency' + Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency' + $PtDef = New-PivotTableDefinition -PivotTableName Totals -PivotRows Product -PivotData @{"Total" = "Sum"} -PivotNumberFormat Currency -PivotTotals None -PivotTableStyle Dark2 + Export-excel -ExcelPackage $excel -WorksheetName Hardware -PivotTableDefinition $PtDef + $excel = Open-ExcelPackage -Path $path + $ws1 = $excel.Workbook.Worksheets["Hardware"] + $ws2 = $excel.Workbook.Worksheets["Totals"] + } + Context "Setting and not clearing when Export-Excel touches the file again." { + it "Set the Table Options " { + $ws1.Tables[0].Address.Address | Should -Be "A1:E16" + $ws1.Tables[0].Name | Should -Be "HardwareTable" + $ws1.Tables[0].ShowFirstColumn | Should -Be $true + $ws1.Tables[0].ShowLastColumn | Should -Not -Be $true + $ws1.Tables[0].ShowTotal | Should -Be $true + $ws1.Tables[0].Columns["Total"].TotalsRowFunction | Should -Be "Sum" + $ws1.Tables[0].StyleName | Should -Be "TableStyleLight1" + $ws1.Cells["D4"].Style.Numberformat.Format | Should -Match ([regex]::Escape([cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol)) + $ws1.Cells["E5"].Style.Numberformat.Format | Should -Match ([regex]::Escape([cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol)) + } + it "Set the Pivot Options " { + $ws2.PivotTables[0].DataFields[0].Format | Should -Match ([regex]::Escape([cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol)) + $ws2.PivotTables[0].ColumGrandTotals | Should -Be $false + $ws2.PivotTables[0].StyleName | Should -Be "PivotStyleDark2" + } + } +} \ No newline at end of file diff --git a/__tests__/UnsupportedWorkSheetNames.xlsx b/__tests__/UnsupportedWorkSheetNames.xlsx new file mode 100644 index 00000000..b27620b1 Binary files /dev/null and b/__tests__/UnsupportedWorkSheetNames.xlsx differ diff --git a/__tests__/Validation.tests.ps1 b/__tests__/Validation.tests.ps1 new file mode 100644 index 00000000..22e96cbf --- /dev/null +++ b/__tests__/Validation.tests.ps1 @@ -0,0 +1,55 @@ +Describe "Data validation and protection" { + Context "Data Validation rules" { + BeforeAll { + $data = ConvertFrom-Csv -InputObject @" + ID,Product,Quantity,Price + 12001,Nails,37,3.99 + 12002,Hammer,5,12.10 + 12003,Saw,12,15.37 + 12010,Drill,20,8 + 12011,Crowbar,7,23.48 +"@ + $path = "TestDrive:\DataValidation.xlsx" + Remove-Item $path -ErrorAction SilentlyContinue + $excelPackage = $Data | Export-excel -WorksheetName "Sales" -path $path -PassThru + $excelPackage = @('Chisel', 'Crowbar', 'Drill', 'Hammer', 'Nails', 'Saw', 'Screwdriver', 'Wrench') | + Export-excel -ExcelPackage $excelPackage -WorksheetName Values -PassThru + + $VParams = @{Worksheet = $excelPackage.sales; ShowErrorMessage = $true; ErrorStyle = 'stop'; ErrorTitle = 'Invalid Data' } + Add-ExcelDataValidationRule @VParams -Range 'B2:B1001' -ValidationType List -Formula 'values!$a$1:$a$10' -ErrorBody "You must select an item from the list.`r`nYou can add to the list on the values page" #Bucket + Add-ExcelDataValidationRule @VParams -Range 'E2:E1001' -ValidationType Integer -Operator between -Value 0 -Value2 10000 -ErrorBody 'Quantity must be a whole number between 0 and 10000' + Close-ExcelPackage -ExcelPackage $excelPackage + + $excelPackage = Open-ExcelPackage -Path $path + $ws = $excelPackage.Sales + } + It "Created the expected number of rules " { + $ws.DataValidations.count | Should -Be 2 + } + It "Created a List validation rule against a range of Cells " { + $ws.DataValidations[0].ValidationType.Type.tostring() | Should -Be 'List' + $ws.DataValidations[0].Formula.ExcelFormula | Should -Be 'values!$a$1:$a$10' + $ws.DataValidations[0].Formula2 | Should -Benullorempty + } + It "Created an integer validation rule for values between X and Y " { + $ws.DataValidations[1].ValidationType.Type.tostring() | Should -Be 'Whole' + $ws.DataValidations[1].Formula.Value | Should -Be 0 + $ws.DataValidations[1].Formula2.value | Should -Not -Benullorempty + $ws.DataValidations[1].Operator.tostring() | Should -Be 'between' + } + It "Set Error behaviors for both rules " { + $ws.DataValidations[0].ErrorStyle.tostring() | Should -Be 'stop' + $ws.DataValidations[1].ErrorStyle.tostring() | Should -Be 'stop' + $ws.DataValidations[0].AllowBlank | Should -Be $true + $ws.DataValidations[1].AllowBlank | Should -Be $true + $ws.DataValidations[0].ShowErrorMessage | Should -Be $true + $ws.DataValidations[1].ShowErrorMessage | Should -Be $true + $ws.DataValidations[0].ErrorTitle | Should -Not -Benullorempty + $ws.DataValidations[1].ErrorTitle | Should -Not -Benullorempty + $ws.DataValidations[0].Error | Should -Not -Benullorempty + $ws.DataValidations[1].Error | Should -Not -Benullorempty + } + } + + +} \ No newline at end of file diff --git a/__tests__/testImportExcel.xlsx b/__tests__/testImportExcel.xlsx new file mode 100644 index 00000000..9f975792 Binary files /dev/null and b/__tests__/testImportExcel.xlsx differ diff --git a/__tests__/testImportExcelHeaderOnly.xlsx b/__tests__/testImportExcelHeaderOnly.xlsx new file mode 100644 index 00000000..dae67e22 Binary files /dev/null and b/__tests__/testImportExcelHeaderOnly.xlsx differ diff --git a/__tests__/testImportExcelImportColumns.xlsx b/__tests__/testImportExcelImportColumns.xlsx new file mode 100644 index 00000000..be83bff2 Binary files /dev/null and b/__tests__/testImportExcelImportColumns.xlsx differ diff --git a/__tests__/testRelative.xlsx b/__tests__/testRelative.xlsx new file mode 100644 index 00000000..14df5849 Binary files /dev/null and b/__tests__/testRelative.xlsx differ diff --git a/__tests__/win32_logicaldisk.xml b/__tests__/win32_logicaldisk.xml new file mode 100644 index 00000000..7685cfe4 --- /dev/null +++ b/__tests__/win32_logicaldisk.xml @@ -0,0 +1,252 @@ + + + + Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_LogicalDisk + Microsoft.Management.Infrastructure.CimInstance#ROOT/cimv2/CIM_LogicalDisk + Microsoft.Management.Infrastructure.CimInstance#ROOT/cimv2/CIM_StorageExtent + Microsoft.Management.Infrastructure.CimInstance#ROOT/cimv2/CIM_LogicalDevice + Microsoft.Management.Infrastructure.CimInstance#ROOT/cimv2/CIM_LogicalElement + Microsoft.Management.Infrastructure.CimInstance#ROOT/cimv2/CIM_ManagedSystemElement + Microsoft.Management.Infrastructure.CimInstance#Win32_LogicalDisk + Microsoft.Management.Infrastructure.CimInstance#CIM_LogicalDisk + Microsoft.Management.Infrastructure.CimInstance#CIM_StorageExtent + Microsoft.Management.Infrastructure.CimInstance#CIM_LogicalDevice + Microsoft.Management.Infrastructure.CimInstance#CIM_LogicalElement + Microsoft.Management.Infrastructure.CimInstance#CIM_ManagedSystemElement + Microsoft.Management.Infrastructure.CimInstance + System.Object + + Win32_LogicalDisk: C: (DeviceID = "C:") + + C: + Local Fixed Disk + + C: + + + + + Win32_LogicalDisk + C: + + + + + + + + Win32_ComputerSystem + FLATFISH + 0 + + + + + 17877114880 + 510653362176 + false + 3 + NTFS + 255 + 12 + + + + + false + true + + Local Disk + D470C5ED + + + + + + System.Collections.ArrayList + System.Object + + + + + CIM_ManagedSystemElement + ROOT/cimv2 + FLATFISH + 1335234525 + <CLASS NAME="CIM_ManagedSystemElement"><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="Locale" TYPE="sint32"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UUID" TYPE="string"><VALUE>{8502C517-5FBB-11D2-AAC1-006008C78BC7}</VALUE></QUALIFIER><PROPERTY NAME="Caption" TYPE="string"><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>64</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Description" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="InstallDate" TYPE="datetime"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>MIF.DMTF|ComponentID|001.5</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Name" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Status" TYPE="string"><QUALIFIER NAME="MaxLen" TYPE="sint32"><VALUE>10</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>OK</VALUE><VALUE>Error</VALUE><VALUE>Degraded</VALUE><VALUE>Unknown</VALUE><VALUE>Pred Fail</VALUE><VALUE>Starting</VALUE><VALUE>Stopping</VALUE><VALUE>Service</VALUE><VALUE>Stressed</VALUE><VALUE>NonRecover</VALUE><VALUE>No Contact</VALUE><VALUE>Lost Comm</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY></CLASS> + + + + + CIM_LogicalElement + ROOT/cimv2 + FLATFISH + 1335213213 + <CLASS NAME="CIM_LogicalElement" SUPERCLASS="CIM_ManagedSystemElement"><QUALIFIER NAME="Locale" TYPE="sint32"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UUID" TYPE="string"><VALUE>{8502C518-5FBB-11D2-AAC1-006008C78BC7}</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER></CLASS> + + + + + CIM_LogicalDevice + ROOT/cimv2 + FLATFISH + 1335222317 + <CLASS NAME="CIM_LogicalDevice" SUPERCLASS="CIM_LogicalElement"><QUALIFIER NAME="Locale" TYPE="sint32"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UUID" TYPE="string"><VALUE>{8502C529-5FBB-11D2-AAC1-006008C78BC7}</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PROPERTY NAME="Availability" TYPE="uint16"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>MIF.DMTF|Operational State|003.5</VALUE><VALUE>MIB.IETF|HOST-RESOURCES-MIB.hrDeviceStatus</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>19</VALUE><VALUE>20</VALUE><VALUE>21</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="ConfigManagerErrorCode" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="Schema" TYPE="string"><VALUE>Win32</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>0</VALUE><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE><VALUE>7</VALUE><VALUE>8</VALUE><VALUE>9</VALUE><VALUE>10</VALUE><VALUE>11</VALUE><VALUE>12</VALUE><VALUE>13</VALUE><VALUE>14</VALUE><VALUE>15</VALUE><VALUE>16</VALUE><VALUE>17</VALUE><VALUE>18</VALUE><VALUE>19</VALUE><VALUE>20</VALUE><VALUE>21</VALUE><VALUE>22</VALUE><VALUE>23</VALUE><VALUE>24</VALUE><VALUE>25</VALUE><VALUE>26</VALUE><VALUE>27</VALUE><VALUE>28</VALUE><VALUE>29</VALUE><VALUE>30</VALUE><VALUE>31</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="ConfigManagerUserConfig" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="Schema" TYPE="string"><VALUE>Win32</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="CreationClassName" TYPE="string"><QUALIFIER NAME="CIM_Key" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DeviceID" TYPE="string"><QUALIFIER NAME="CIM_Key" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ErrorCleared" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ErrorDescription" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="LastErrorCode" TYPE="uint32"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="PNPDeviceID" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="Schema" TYPE="string"><VALUE>Win32</VALUE></QUALIFIER></PROPERTY><PROPERTY.ARRAY NAME="PowerManagementCapabilities" TYPE="uint16"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY.ARRAY><PROPERTY NAME="PowerManagementSupported" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="StatusInfo" TYPE="uint16"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>MIF.DMTF|Operational State|003.3</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="SystemCreationClassName" TYPE="string"><QUALIFIER NAME="CIM_Key" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="Propagated" TYPE="string"><VALUE>CIM_System.CreationClassName</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="SystemName" TYPE="string"><QUALIFIER NAME="CIM_Key" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="Propagated" TYPE="string"><VALUE>CIM_System.Name</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><METHOD NAME="SetPowerState" TYPE="uint32"><PARAMETER NAME="PowerState" TYPE="uint16"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="IN" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="ValueMap" TYPE="string"><VALUE.ARRAY><VALUE>1</VALUE><VALUE>2</VALUE><VALUE>3</VALUE><VALUE>4</VALUE><VALUE>5</VALUE><VALUE>6</VALUE></VALUE.ARRAY></QUALIFIER></PARAMETER><PARAMETER NAME="Time" TYPE="datetime"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>1</VALUE></QUALIFIER><QUALIFIER NAME="IN" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="Reset" TYPE="uint32"></METHOD></CLASS> + + + + + CIM_StorageExtent + ROOT/cimv2 + FLATFISH + 1335220237 + <CLASS NAME="CIM_StorageExtent" SUPERCLASS="CIM_LogicalDevice"><QUALIFIER NAME="Locale" TYPE="sint32"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UUID" TYPE="string"><VALUE>{8502C538-5FBB-11D2-AAC1-006008C78BC7}</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PROPERTY NAME="Access" TYPE="uint16"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="BlockSize" TYPE="uint64"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>MIB.IETF|HOST-RESOURCES-MIB.hrStorageAllocationUnits</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ErrorMethodology" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="NumberOfBlocks" TYPE="uint64"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>MIB.IETF|HOST-RESOURCES-MIB.hrStorageSize</VALUE></VALUE.ARRAY></QUALIFIER></PROPERTY><PROPERTY NAME="Purpose" TYPE="string"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY></CLASS> + + + + + CIM_LogicalDisk + ROOT/cimv2 + FLATFISH + 1335229325 + <CLASS NAME="CIM_LogicalDisk" SUPERCLASS="CIM_StorageExtent"><QUALIFIER NAME="Locale" TYPE="sint32"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UUID" TYPE="string"><VALUE>{8502C539-5FBB-11D2-AAC1-006008C78BC7}</VALUE></QUALIFIER><QUALIFIER NAME="Abstract" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PROPERTY NAME="FreeSpace" TYPE="uint64"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Size" TYPE="uint64"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY></CLASS> + + + + + Win32_LogicalDisk + root/cimv2 + FLATFISH + 1323049133 + <CLASS NAME="Win32_LogicalDisk" SUPERCLASS="CIM_LogicalDisk"><QUALIFIER NAME="Locale" TYPE="sint32"><VALUE>1033</VALUE></QUALIFIER><QUALIFIER NAME="UUID" TYPE="string"><VALUE>{8502C4B7-5FBB-11D2-AAC1-006008C78BC7}</VALUE></QUALIFIER><QUALIFIER NAME="dynamic" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="provider" TYPE="string"><VALUE>CIMWin32</VALUE></QUALIFIER><QUALIFIER NAME="SupportsUpdate" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><PROPERTY NAME="DeviceID" TYPE="string"><QUALIFIER NAME="CIM_Key" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="key" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>WMI</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="Override" TYPE="string"><VALUE>DeviceId</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Compressed" TYPE="boolean"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|File System Functions|GetVolumeInformation|FS_VOL_IS_COMPRESSED</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="DriveType" TYPE="uint32"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|FileFunctions|GetDriveType</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="FileSystem" TYPE="string"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|File System Functions|GetVolumeInformation</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="MaximumComponentLength" TYPE="uint32"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|File System Functions|GetVolumeInformation</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="MediaType" TYPE="uint32"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|Device Input and Output Functions|DeviceIoControl</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="ProviderName" TYPE="string"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|Windows Networking Functions|WNetGetConnection</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="QuotasDisabled" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="QuotasIncomplete" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="QuotasRebuilding" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="SupportsDiskQuotas" TYPE="boolean"><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="SupportsFileBasedCompression" TYPE="boolean"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|File System Functions|GetVolumeInformation|FS_FILE_COMPRESSION</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="VolumeDirty" TYPE="boolean"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>FSCTL_IS_VOLUME_DIRTY</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="VolumeName" TYPE="string"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|File System Functions|GetVolumeInformation</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="write" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="VolumeSerialNumber" TYPE="string"><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Win32API|File System Functions|GetVolumeInformation</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="read" TYPE="boolean"><VALUE>true</VALUE></QUALIFIER></PROPERTY><METHOD NAME="Chkdsk" TYPE="uint32"><QUALIFIER NAME="Implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Fmifs.dll | Method ChkDskExRoutine</VALUE></VALUE.ARRAY></QUALIFIER><PARAMETER NAME="FixErrors" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER NAME="ForceDismount" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>3</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER NAME="OkToRunAtBootUp" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>5</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER NAME="RecoverBadSectors" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>4</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER NAME="SkipFolderCycle" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>2</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER><PARAMETER NAME="VigorousIndexCheck" TYPE="boolean"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>1</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER></METHOD><METHOD NAME="ScheduleAutoChk" TYPE="uint32"><QUALIFIER NAME="Implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Chkntfs.exe</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="Static" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER.ARRAY NAME="LogicalDisk" TYPE="string"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER.ARRAY></METHOD><METHOD NAME="ExcludeFromAutochk" TYPE="uint32"><QUALIFIER NAME="Implemented" TYPE="boolean" TOSUBCLASS="false"><VALUE>true</VALUE></QUALIFIER><QUALIFIER NAME="MappingStrings" TYPE="string"><VALUE.ARRAY><VALUE>Chkntfs.exe</VALUE></VALUE.ARRAY></QUALIFIER><QUALIFIER NAME="Static" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER><PARAMETER.ARRAY NAME="LogicalDisk" TYPE="string"><QUALIFIER NAME="ID" TYPE="sint32" OVERRIDABLE="false"><VALUE>0</VALUE></QUALIFIER><QUALIFIER NAME="in" TYPE="boolean" OVERRIDABLE="false"><VALUE>true</VALUE></QUALIFIER></PARAMETER.ARRAY></METHOD></CLASS> + + + + + + + + + Win32_LogicalDisk: D: (DeviceID = "D:") + + D: + Local Fixed Disk + + D: + + + + + Win32_LogicalDisk + D: + + + + + + + + Win32_ComputerSystem + FLATFISH + 0 + + + + + 124505268224 + 1000202272768 + false + 3 + NTFS + 255 + 12 + + + + + false + true + false + Samsung_T3 + 245C4248 + + + + + + + + + Win32_LogicalDisk + root/cimv2 + FLATFISH + 1323049133 + + + + + + + + + Win32_LogicalDisk: E: (DeviceID = "E:") + + E: + Removable Disk + + E: + + + + + Win32_LogicalDisk + E: + + + + + + + + Win32_ComputerSystem + FLATFISH + 0 + + + + + 5516288000 + 15824056320 + false + 2 + NTFS + 255 + + + + + + false + true + false + + 2645DC17 + + + + + + + + + Win32_LogicalDisk + root/cimv2 + FLATFISH + 1323049133 + + + + + + + \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 81131c96..00000000 Binary files a/appveyor.yml and /dev/null differ diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..f64f9141 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,149 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: + branches: + include: + - '*' + # - master + # - releases/* + paths: + exclude: + - README.md + - CHANGELOG.md + +jobs: + - job: Windows + pool: + vmImage: 'windows-latest' + + steps: + + # BEGIN - ACE support for Invoke-ExcelQuery testing + - task: Cache@2 + inputs: + key: v2 | "$(Agent.OS)" | ace + path: ace + cacheHitVar: CACHE_RESTORED + displayName: Cache ACE + + - bash: | + mkdir ./ace + curl -o ./ace/ace.exe https://download.microsoft.com/download/3/5/C/35C84C36-661A-44E6-9324-8786B8DBE231/accessdatabaseengine_X64.exe + displayName: 'Download ACE' + condition: ne(variables.CACHE_RESTORED, 'true') + + - powershell: Start-Process ./ace/ace.exe -Wait -ArgumentList "/quiet /passive /norestart" + displayName: 'Install ACE for Invoke-ExcelQuery testing' + # END - ACE support for Invoke-ExcelQuery testing + + - powershell: 'Install-Module -Name Pester -Force -SkipPublisherCheck' + displayName: 'Update Pester' + - powershell: './CI/CI.ps1 -Test' + displayName: 'Install and Test' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + + - powershell: './CI/CI.ps1 -Artifact' + displayName: 'Prepare Artifact' + - task: PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)' + artifact: 'Modules' + - powershell: './CI/CI.ps1 -Analyzer' + displayName: 'Invoke ScriptAnalyzer' + - task: PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.SourcesDirectory)' + artifact: 'Source' + + - job: WindowsPSCore + pool: + vmImage: 'windows-latest' + + steps: + + # BEGIN - ACE support for Invoke-ExcelQuery testing + - task: Cache@2 + inputs: + key: v2 | "$(Agent.OS)" | ace + path: ace + cacheHitVar: CACHE_RESTORED + displayName: Cache ACE + + - bash: | + mkdir ./ace + curl -o ./ace/ace.exe https://download.microsoft.com/download/3/5/C/35C84C36-661A-44E6-9324-8786B8DBE231/accessdatabaseengine_X64.exe + displayName: 'Download ACE' + condition: ne(variables.CACHE_RESTORED, 'true') + + - powershell: Start-Process ./ace/ace.exe -Wait -ArgumentList "/quiet /passive /norestart" + displayName: 'Install ACE for Invoke-ExcelQuery testing' + # END - ACE support for Invoke-ExcelQuery testing + + - pwsh: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - pwsh: './CI/CI.ps1 -Test' + displayName: 'Install and Test' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + + - job: Ubuntu + pool: + vmImage: 'ubuntu-latest' + + steps: + - powershell: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - powershell: './CI/CI.ps1 -Test' + displayName: 'Install and Test' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + + - job: macOS + pool: + vmImage: 'macOS-latest' + + steps: + - script: brew install mono-libgdiplus + displayName: 'Install mono-libgdiplus' + - powershell: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - powershell: './CI/CI.ps1 -Test' + displayName: 'Install and Test' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true + + - job: macOSNoDeps + pool: + vmImage: 'macOS-latest' + + steps: + - powershell: 'Install-Module -Name Pester -Force' + displayName: 'Update Pester' + - powershell: './CI/CI.ps1 -TestImportOnly' + displayName: 'Install and Test Import Only' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/TestResults*.xml' + failTaskOnFailedTests: true diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..eaa3abbb --- /dev/null +++ b/changelog.md @@ -0,0 +1,226 @@ +# 7.8.10 + +- Thank you https://github.com/evenmartinsen for the PR to fix the AV + +# 7.8.9 + +- Thanks to (Edward Miller)[https://github.com/edwardmiller-mesirow] for improving `ConvertTo-ExcelXlsx`and making it more robust + +# 7.8.8 + +- Fix the release + +# 7.8.7 + +- Thanks to [Phil Bossman](https://github.com/pbossman) for the PR and fixing this. + + Now, back again, you can type `Import-Excel .\yearlySales.xlsx`, press and get a list of the worksheets in the Excel file + + ![alt text](images/AutoCompleteSheetNames.png) + +# Infrastructure change + +- Thank you to [RipFence](https://github.com/RipFence) who asked how to place a chart on a different sheet from the data and then did a PR adding the example. +- added `ignore` so files checked into examples do not trigger a CI run + +# 7.8.6 + +- Thank you [John Boyne](https://github.com/kyllath) + - Add missing parameter aliases to align with caller/callee + +# 7.8.5 + +- Added `Get-ExcelFileSchema` to get the schema of an Excel file. +- This was added to support interacting with `ChatGPT`. Passing the schema to the `ChatGPT` via `PowerShellAI` let's you ask questions about the data including generating code based on the schema. + +```powershell +Get-ExcelFileSchema .\salesData.xlsx +``` + +```json +{ + "ExcelFile": "salesData.xlsx", + "WorksheetName": "Sheet1", + "Visible": true, + "Rows": 10, + "Columns": 4, + "Address": "A1:D10", + "Path": ".", + "PropertyNames": [ + "Region", + "State", + "Units", + "Price" + ] +} +``` + +# 7.8.x + +Thanks to [Thomas Hofkens](https://github.com/thkn-hofa) +- Added `-NoHyperLinkConversion` to `Export-Excel` to no convert data to hyperlinks. [#1316](https://github.com/dfinke/ImportExcel/issues/1316) + +# 7.8.4 + +- Add -ShowOnlyIcon to `New-ConditionalFormattingIconSet` does not show data in the cell, just the icon. Based on this discussion https://github.com/dfinke/ImportExcel/discussions/1340 + +# 7.8.3 + +Thanks [Thomas Hofkens](https://github.com/thkn-hofa) + +- Extended Export-Excel with parameter TableTotalSettings +- New Feature: Set-CellComment +- Fix Pester error for countries with ',' as decimal separator +- Fix Pester error for Windows PowerShell 5.1 + +# 7.8.2 + +- Fix docs [#1254](https://github.com/dfinke/ImportExcel/pull/1251)`Add-Worksheet` warning. Thank you [Wilson Stewart](https://github.com/WilsonStewart) +- Fix docs [#1251](https://github.com/dfinke/ImportExcel/pull/1251)`Add-Worksheet` warning. Thank you [Jeremiah Adams](https://github.com/JeremiahTheFirst) +- Fix docs [#1253](https://github.com/dfinke/ImportExcel/pull/1253) `convertfrom-exceltosqlinsert`. Thank you [Wes Stahler](https://github.com/stahler) +- Set Validate Range for rows to max rows available [#1273](https://github.com/dfinke/ImportExcel/pull/1273). Thank you [Stephen Brown](https://github.com/steve-daedilus) +- Extended Get-ExcelFileSummary to include more Visible -eq $true|$false + +# 7.8.1 + +- Fixed conditional formatting so it recognizes 'Top and Bottom' as a rule type. Thanks [g-pearl](https://github.com/g-pearl) +* Update open-excelpackage.md. Thanks [stahler](https://github.com/stahler) +- Added Group Column tests + + +# 7.8.0 +Thanks [James O'Neill](https://github.com/jhoneill) + +- Updated example Get-ModuleStats that extracts module statistics on the PowerShell Gallery. +- Added GroupNumericColumn and GroupDateColumn to New-PivotTableDefinition and Add-PivotTable. + +|GroupNumericColumn|GroupDateColumn| +|:---:|:---:| +|![](images/GroupNumericColumn.png)|![](images/GroupDateColumn.png)| + +# Example added + +Thank you [@kkazala](https://github.com/kkazala) + +- Added an example reading a sheet, extracting the `ConditionalFormatting` and generating the PowerShell statements so you can re-create them. +- Added an example showing `ConditionalFormatting` using the `RuleType` `Expression` with a formula + - [Highlight-DiffCells.ps1](https://github.dev/kkazala/ImportExcel/blob/b53881fd023c052da1acc7812511da223bb2e40c/Examples/ConditionalFormatting/Highlight-DiffCells.ps1) + +# 7.7.0 + +- Fix a bug with `-UnderLineType parameter is ignored in Set-ExcelColumn` [#1204](https://github.com/dfinke/ImportExcel/issues/1204) + +# 7.6.0 + +- **_[Under investigation]_** Fix -StartRow and -StartColumn being ignored. +- James O'Neill: + - Update Get-HtmlTable to support to use PowerHTML (maintained by [Justin Grote](https://twitter.com/JustinWGrote)). + - Added example to including a new function Import-ByColumn. Works like Import-Excel but with data in columns instead of the conventional rows. +- Update Import-HTML with better defaults +- Fixed example `Get-ModuleStats.ps1` which reads the PowerShell Gallery page and extracts the stats table + + +# v7.5.2 +- Changed the switch `-NotAsDictionary` to `-Raw`. Works with `-Worksheetname *` reads all the sheets in the xlsx file and returns an array. + +# v7.5.1 +- Fixed `Import-Excel` - Reset `EndRow` and `EndColumn` in the correct place. +# v7.5.0 +## Fixes + +- Importing multiple files with Import-Excel by pipeline uses only the first file for the row count https://github.com/dfinke/ImportExcel/issues/1172 + +## New Features + +- Import-Excel now supports importing multiple sheets. It can either return a dictionary of all sheets, or as a single array of all sheets combined. + - `Import-Excel $xlfile *` # reads all sheets, returns all data in a dictionary + - `Import-Excel $xlfile * -NotAsDictionary` # reads all sheets, returns all data in a single array +- Added helper functions. Useful for working with an Excel package via `Open-ExcelPackage` or `-PassThru` + - `Enable-ExcelAutoFilter` + - `Enable-ExcelAutofit` + - `Get-ExcelSheetDimensionAddress` + +# v7.4.2 + +- Thank you [James Mueller](https://github.com/jamesmmueller) Updated `ConvertFrom-ExcelToSQLInsert` to handle single quotes in the SQL statement. + +- Thank you to Josh Hendricks + - Add images to spreadsheets. [Check it out](https://github.com/dfinke/ImportExcel/tree/master/Examples/AddImage) + - Catch up with him on [GitHub](https://github.com/joshooaj) and [Twitter](https://twitter.com/joshooaj) for the idea + +# v7.4.1 + +- Implements: https://github.com/dfinke/ImportExcel/issues/1111 +- Refactored ReZip into separate function +- Deletes temp folder after rezipping +- Added -ReZip to `Close-ExcelPackage` + +# v7.4.0 + +- Thank you to [Max Goczall](https://github.com/muschebubusche) for this contribution! + - `ImportColumns` parameter added to `ImportExcel`. It is used to define which columns of the ExcelPackage should be imported. + +```powershell +Import-Excel -Path $xlFile -ImportColumns @(6,7,12,25,46) +``` + +# v7.3.1 + +- Added query Excel spreadsheets, with SQL queries! + +```powershell +$query = 'select F2 as [Category], F5 as [Discount], F5*2 as [DiscountPlus] from [sheet1$A2:E11]' + +Invoke-ExcelQuery .\testOleDb.xlsx $query +``` + +![](./images/SQL-Spreadsheet.png) + +## Result + +``` +Category Discount DiscountPlus +-------- -------- ------------ +Cosmetics 0.7 1.4 +Grocery 0.3 0.6 +Apparels 0.2 0.4 +Electronics 0.1 0.2 +Electronics 0 0 +Apparels 0.8 1.6 +Electronics 0.7 1.4 +Cosmetics 0.6 1.2 +Grocery 0.4 0.8 +Grocery 0.3 0.6 +``` + +- Thank you to Roy Ashbrook for the SQL query code. Catch up with Roy: + +|Media|Link| +|---|---| +|twitter|https://twitter.com/royashbrook +|github|https://github.com/royashbrook +|linkedin|https://linkedin.com/in/royashbrook +|blog|https://ashbrook.io + +# v7.3.0 + +- Fix throwing error when a Worksheet name collides with a method, or property name on the `OfficeOpenXml.ExcelPackage` package + +# v7.2.3 + +- Fix inline help, thank you [Wes Stahler](https://github.com/stahler) + +# v7.2.2 + +- Improved checks for Linux, Mac and PS 5.1 + +# v7.2.1 + +- Improve auto-detection of data on the clipboard + +# v7.2.0 + +- Added `Read-Clipboard` support for Windows. Read text from clipboard. It can read CSV or JSON. Plus, you can specify the delimiter and headers. + +### Check out the video + \ No newline at end of file diff --git a/charting/README.md b/charting/README.md new file mode 100644 index 00000000..db1e88b7 --- /dev/null +++ b/charting/README.md @@ -0,0 +1,2 @@ +# Charting + diff --git a/charting/barchart.md b/charting/barchart.md new file mode 100644 index 00000000..62173294 --- /dev/null +++ b/charting/barchart.md @@ -0,0 +1,131 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# BarChart + +## SYNOPSIS + +## SYNTAX + +```text +BarChart [[-targetData] ] [[-title] ] [[-ChartType] ] [-NoLegend] [-ShowCategory] + [-ShowPercent] [] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -ChartType + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -targetData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -title + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/charting/columnchart.md b/charting/columnchart.md new file mode 100644 index 00000000..ae07af48 --- /dev/null +++ b/charting/columnchart.md @@ -0,0 +1,131 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# ColumnChart + +## SYNOPSIS + +## SYNTAX + +```text +ColumnChart [[-targetData] ] [[-title] ] [[-ChartType] ] [-NoLegend] + [-ShowCategory] [-ShowPercent] [] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -ChartType + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -targetData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -title + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/charting/dochart.md b/charting/dochart.md new file mode 100644 index 00000000..4b49f658 --- /dev/null +++ b/charting/dochart.md @@ -0,0 +1,127 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# DoChart + +## SYNOPSIS + +## SYNTAX + +```text +DoChart [[-targetData] ] [[-title] ] [[-ChartType] ] [-NoLegend] [-ShowCategory] + [-ShowPercent] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -ChartType + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -targetData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -title + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/charting/linechart.md b/charting/linechart.md new file mode 100644 index 00000000..816305da --- /dev/null +++ b/charting/linechart.md @@ -0,0 +1,131 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: 'https://github.com/dfinke/ImportExcel' +schema: 2.0.0 +--- + +# LineChart + +## SYNOPSIS + +## SYNTAX + +```text +LineChart [[-targetData] ] [[-title] ] [[-ChartType] ] [-NoLegend] [-ShowCategory] + [-ShowPercent] [] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -ChartType + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -targetData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -title + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/charting/piechart.md b/charting/piechart.md new file mode 100644 index 00000000..2f19a6c9 --- /dev/null +++ b/charting/piechart.md @@ -0,0 +1,131 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# PieChart + +## SYNOPSIS + +## SYNTAX + +```text +PieChart [[-targetData] ] [[-title] ] [[-ChartType] ] [-NoLegend] [-ShowCategory] + [-ShowPercent] [] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -ChartType + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -targetData + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -title + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/compare-WorkSheet.ps1 b/compare-WorkSheet.ps1 deleted file mode 100644 index 8ee571eb..00000000 --- a/compare-WorkSheet.ps1 +++ /dev/null @@ -1,252 +0,0 @@ -Function Compare-WorkSheet { -<# - .Synopsis - Compares two worksheets with the same name in different files. - .Description - This command takes two file names, a worksheet name and a name for a key column. - It reads the worksheet from each file and decides the column names. - It builds as hashtable of the key column values and the rows they appear in - It then uses PowerShell's compare object command to compare the sheets (explicity checking all column names which have not been excluded) - For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison, - otherwise rows will be considered as different simply because they have different row numbers - We also add the name of the file in which the difference occurs. - If -BackgroundColor is specified the difference rows will be changed to that background. - .Example - Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | format-table - The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32_product to Export-Excel - The command compares the "products" pages in the two workbooks, but we don't want to register a differnce if if the software was installed on a - different date or from a different place, so Excluding Install* removes InstallDate and InstallSource. - This data doesn't have a "name" column" so we specify the "IdentifyingNumber" column as the key. - The results will be presented as a table. - .Example - compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -GridView - This time two workbooks contain the result of redirecting Get-WmiObject -Class win32_service to Export-Excel - Here the -Differencefile and -Referencefile parameter switches are assumed , and the default setting for -key ("Name") works for services - This will display the differences between the "services" sheets using a grid view - .Example - Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen - This version of the command outputs the differences between the "services" pages and also highlights any different rows in the spreadsheet files. - .Example - Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show - This builds on the previous example: this time Where two changed rows have the value in the "name" column (the default value for -key), - this version adds highlighting of the changed cells in red; and then opens the Excel file. - .Example - Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description" - This time the reference file and the difference file are the same file and two different sheets are used. Because the tests include the - machine name and time the test was run the command specifies a limited set of columns should be used. - .Example - Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent - The "General" page has a title and two unlabelled columns with a row forCPU, Memory, Domain, Disk and so on - So the command is instructed to starts at row 2 to skip the title and to name the columns: the first is "label" and the Second "Value"; - the label acts as the key. This time we interested the rows which are the same in both sheets, - and the result is displayed using grid view. Note that grid view works best when the number of columns is small. - .Example - Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray - This version of the previous command lightlights all the cells in lightgray and then sets the changed rows back to white; only - the unchanged rows are highlighted -#> -[cmdletbinding(DefaultParameterSetName)] - Param( - #First file to compare - [parameter(Mandatory=$true,Position=0)] - $Referencefile , - #Second file to compare - [parameter(Mandatory=$true,Position=1)] - $Differencefile , - #Name(s) of worksheets to compare. - $WorkSheetName = "Sheet1", - #Properties to include in the DIFF - supports wildcards, default is "*" - $Property = "*" , - #Properties to exclude from the the search - supports wildcards - $ExcludeProperty , - #Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. - [Parameter(ParameterSetName='B', Mandatory)] - [String[]]$Headername, - #Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet - [Parameter(ParameterSetName='C', Mandatory)] - [switch]$NoHeader, - #The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. - [int]$Startrow = 1, - #If specified, highlights all the cells - so you can make Equal cells one colour, and Diff cells another. - [System.Drawing.Color]$AllDataBackgroundColor, - #If specified, highlights the DIFF rows - [System.Drawing.Color]$BackgroundColor, - #If specified identifies the tabs which contain DIFF rows (ignored if -backgroundColor is omitted) - [System.Drawing.Color]$TabColor, - #Name of a column which is unique and will be used to add a row to the DIFF object, default is "Name" - $Key = "Name" , - #If specified, highlights the DIFF columns in rows which have the same key. - [System.Drawing.Color]$FontColor, - #If specified opens the Excel workbooks instead of outputting the diff to the console (unless -passthru is also specified) - [Switch]$Show, - #If specified, the command tries to the show the DIFF in a Gridview and not on the console. (unless-Passthru is also specified). This Works best with few columns selected, and requires a key - [switch]$GridView, - #If specified -Passthrough full set of diff data is returned without filtering to the specified properties - [Switch]$PassThru, - #If specified the result will include equal rows as well. By default only different rows are returned - [Switch]$IncludeEqual, - #If Specified the result includes only the rows where both are equal - [Switch]$ExcludeDifferent - ) - - #if the filenames don't resolve, give up now. - try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)} - Catch { Write-Warning -Message "Could not Resolve the filenames." ; return } - - #If we have one file , we mush have two different worksheet names. If we have two files we can a single string or two strings. - if ($onefile -and ( ($WorkSheetName.count -ne 2) -or $WorkSheetName[0] -eq $WorkSheetName[1] ) ) { - Write-Warning -Message "If both the Reference and difference file are the same then worksheet name must provide 2 different names" - return - } - if ($WorkSheetName.count -eq 2) {$worksheet1 = $WorkSheetName[0] ; $WorkSheet2 = $WorkSheetName[1]} - elseif ($WorkSheetName -is [string]) {$worksheet1 = $WorkSheet2 = $WorkSheetName} - else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return } - - $params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop } - foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}} - try { - $Sheet1 = Import-Excel -Path $Referencefile -WorksheetName $WorkSheet1 @params - $Sheet2 = Import-Excel -Path $Differencefile -WorksheetName $WorkSheet2 @Params - } - Catch {Write-Warning -Message "Could not read the worksheet from $Referencefile and/or $Differencefile." ; return } - - #Get Column headings and create a hash table of Name to column letter. - $headings = $Sheet1[-1].psobject.Properties.name # This preserves the sequence - using get-member would sort them alphabetically! - $headings | ForEach-Object -Begin {$columns = @{} ; $i=65 } -Process {$Columns[$_] = [char]($i ++) } - - #Make a list of property headings using the Property (default "*") and ExcludeProperty parameters - if ($Key -eq "Name" -and $NoHeader) {$key = "p1"} - $propList = @() - foreach ($p in $Property) {$propList += ($headings.where({$_ -like $p}) )} - foreach ($p in $ExcludeProperty) {$propList = $propList.where({$_ -notlike $p}) } - if (($headings -contains $key) -and ($propList -notcontains $Key)) {$propList += $Key} - $propList = $propList | Select-Object -Unique - if ($propList.Count -eq 0) {Write-Warning -Message "No Columns are selected with -Property = '$Property' and -excludeProperty = '$ExcludeProperty'." ; return} - - #Add RowNumber, Sheetname and file name to every row - $FirstDataRow = $startRow + 1 - if ($Headername -or $NoHeader) {$FirstDataRow -- } - $i = $FirstDataRow ; foreach ($row in $Sheet1) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++) - Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet1 - Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Referencefile} - $i = $FirstDataRow ; foreach ($row in $Sheet2) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++) - Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet2 - Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Differencefile} - - if ($ExcludeDifferent -and -not $IncludeEqual) {$IncludeEqual = $true} - #Do the comparison and add file,sheet and row to the result - these are prefixed with "_" to show they are added the addition will fail if the sheet has these properties so split the operations - $diff = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual:$IncludeEqual -ExcludeDifferent:$ExcludeDifferent | - Sort-Object -Property "_Row","File" - - #if BackgroundColor was specified, set it on extra or extra or changed rows - if ($diff -and $BackgroundColor) { - #Differences may only exist in one file. So gather the changes for each file; open the file, update each impacted row in the shee, save the file - $updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property "_File" - foreach ($file in $updates) { - try {$xl = Open-ExcelPackage -Path $file.name } - catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return} - if ($AllDataBackgroundColor) { - $file.Group._sheet | Sort-Object -Unique | ForEach-Object { - $ws = $xl.Workbook.Worksheets[$_] - if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address} - else {$range = "A" + ($startrow + 1) + ":" + $ws.dimension.end.address} - Set-Format -WorkSheet $ws -BackgroundColor $AllDataBackgroundColor -Range $Range - } - } - foreach ($row in $file.group) { - $ws = $xl.Workbook.Worksheets[$row._Sheet] - $range = $ws.Dimension -replace "\d+",$row._row - Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor - } - if ($TabColor) { - foreach ($tab in ($file.group._sheet | Select-Object -Unique)) { - $xl.Workbook.Worksheets[$tab].TabColor = $TabColor - } - } - $xl.save() ; $xl.Stream.Close() ; $xl.Dispose() - } - } - #if font colour was specified, set it on changed properties where the same key appears in both sheets. - if ($diff -and $FontColor -and ($propList -contains $Key) ) { - $updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | where {$_.count -eq 2} - if ($updates) { - $XL1 = Open-ExcelPackage -path $Referencefile - if ($oneFile ) {$xl2 = $xl1} - else {$xl2 = Open-ExcelPackage -path $Differencefile } - foreach ($u in $updates) { - foreach ($p in $propList) { - if($u.Group[0].$p -ne $u.Group[1].$p ) { - Set-Format -WorkSheet $xl1.Workbook.Worksheets[$u.Group[0]._sheet] -Range ($Columns[$p] + $u.Group[0]._Row) -FontColor $FontColor - Set-Format -WorkSheet $xl2.Workbook.Worksheets[$u.Group[1]._sheet] -Range ($Columns[$p] + $u.Group[1]._Row) -FontColor $FontColor - } - } - } - $xl1.Save() ; $xl1.Stream.Close() ; $xl1.Dispose() - if (-not $oneFile) {$xl2.Save() ; $xl2.Stream.Close() ; $xl2.Dispose()} - } - } - elseif ($diff -and $FontColor) {Write-Warning -Message "To match rows to set changed cells, you must specify -Key and it must match one of the included properties." } - - #if nothing was found write a message which wont be redirected - if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." } - - if ($show) { - Start-Process -FilePath $Referencefile - if (-not $oneFile) { Start-Process -FilePath $Differencefile } - if ($GridView) { Write-Warning -Message "-GridView is ignored when -Show is specified" } - } - elseif ($GridView -and $propList -contains $key) { - - - if ($IncludeEqual -and -not $ExcludeDifferent) { - $GroupedRows = $diff | Group-Object -Property $key - } - else { #to get the right now numbers on the grid we need to have all the rows. - $GroupedRows = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual | - Group-Object -Property $key - } - #Additions, deletions and unchanged rows will give a group of 1; changes will give a group of 2 . - - #If one sheet has extra rows we can get a single "==" result from compare, but with the row from the reference sheet - #but the row in the other sheet might so we will look up the row number from the key field build a hash table for that - $Sheet2 | ForEach-Object -Begin {$Rowhash = @{} } -Process {$Rowhash[$_.$key] = $_._row } - - $ExpandedDiff = ForEach ($g in $GroupedRows) { - #we're going to create a custom object from a hash table. We want the fields to be ordered - $hash = [ordered]@{} - foreach ($result IN $g.Group) { - # if result indicates equal or "in Reference" set the reference side row. If we did that on a previous result keep it. Otherwise set to "blank" - if ($result.sideindicator -ne "=>") {$hash["Row"] = $Rowhash[$g.Name] - #position the key as the next field (only appears once) - $Hash[$key] = $g.Name - #For all the other fields we care about create <=FieldName and/or =>FieldName - foreach ($p in $propList.Where({$_ -ne $key})) { - if ($result.SideIndicator -eq "==") {$hash[("=>$P")] = $hash[("<=$P")] =$result.$P} - else {$hash[($result.SideIndicator+$P)] =$result.$P} - } - } - [Pscustomobject]$hash - } - - #Sort by reference row number, and fill in any blanks in the difference-row column - $ExpandedDiff = $ExpandedDiff | Sort-Object -Property "row") {$ExpandedDiff[$i].">row" = $ExpandedDiff[$i-1].">row" } } - #Sort by difference row number, and fill in any blanks in the reference-row column - $ExpandedDiff = $ExpandedDiff | Sort-Object -Property ">row" - for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i]."row" } - elseif ( $IncludeEqual) {$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "row" } - else {$ExpandedDiff = $ExpandedDiff.where({$_.side -ne "=="}) | Sort-Object -Property "row" } - $ExpandedDiff | Update-FirstObjectProperties | Out-GridView -Title "Comparing $Referencefile::$worksheet1 (<=) with $Differencefile::$WorkSheet2 (=>)" - } - elseif ($GridView ) {Write-Warning -Message "To use -GridView you must specify -Key and it must match one of the included properties." } - elseif (-not $PassThru) {return ($diff | Select-Object -Property (@(@{n="_Side";e={$_.SideIndicator}},"_File" ,"_Sheet","_Row") + $propList))} - if ( $PassThru) {return $diff } -} \ No newline at end of file diff --git a/dashboard.xlsx b/dashboard.xlsx deleted file mode 100644 index 414a4d17..00000000 Binary files a/dashboard.xlsx and /dev/null differ diff --git a/en/ImportExcel-help.xml b/en/ImportExcel-help.xml new file mode 100644 index 00000000..69440b84 --- /dev/null +++ b/en/ImportExcel-help.xml @@ -0,0 +1,22749 @@ + + + + + Add-ConditionalFormatting + Add + ConditionalFormatting + + Adds conditional formatting to all or part of a worksheet. + + + + Conditional formatting allows Excel to: + * Mark cells with icons depending on their value + * Show a databar whose length indicates the value or a two or three color scale where the color indicates the relative value + * Change the color, font, or number format of cells which meet given criteria + + Add-ConditionalFormatting allows these parameters to be set; for fine tuning of the rules, the -PassThru switch will return the rule so that you can modify things which are specific to that type of rule, example, the values which correspond to each icon in an Icon-Set. + + + + Add-ConditionalFormatting + + Address + + A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] + + Object + + Object + + + None + + + RuleType + + A standard named-rule - Top / Bottom / Less than / Greater than / Contains etc. + + + AboveAverage + AboveOrEqualAverage + BelowAverage + BelowOrEqualAverage + AboveStdDev + BelowStdDev + Bottom + BottomPercent + Top + TopPercent + Last7Days + LastMonth + LastWeek + NextMonth + NextWeek + ThisMonth + ThisWeek + Today + Tomorrow + Yesterday + BeginsWith + Between + ContainsBlanks + ContainsErrors + ContainsText + DuplicateValues + EndsWith + Equal + Expression + GreaterThan + GreaterThanOrEqual + LessThan + LessThanOrEqual + NotBetween + NotContains + NotContainsBlanks + NotContainsErrors + NotContainsText + NotEqual + UniqueValues + ThreeColorScale + TwoColorScale + ThreeIconSet + FourIconSet + FiveIconSet + DataBar + + eExcelConditionalFormattingRuleType + + eExcelConditionalFormattingRuleType + + + None + + + ConditionValue + + A value for the condition (for example 2000 if the test is 'lessthan 2000'; Formulas should begin with "=" ) + + Object + + Object + + + None + + + ConditionValue2 + + A second value for the conditions like "Between X and Y" + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied + + ExcelWorksheet + + ExcelWorksheet + + + None + + + ForegroundColor + + Text color for matching objects + + Object + + Object + + + None + + + Reverse + + Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales + + + SwitchParameter + + + False + + + BackgroundColor + + Background color for matching items + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern for matching items + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + None + + + PatternColor + + Secondary color when a background pattern requires it + + Object + + Object + + + None + + + NumberFormat + + Sets the numeric format for matching items + + Object + + Object + + + None + + + Bold + + Put matching items in bold face + + + SwitchParameter + + + False + + + Italic + + Put matching items in italic + + + SwitchParameter + + + False + + + Underline + + Underline matching items + + + SwitchParameter + + + False + + + StrikeThru + + Strikethrough text of matching items + + + SwitchParameter + + + False + + + StopIfTrue + + Prevent the processing of subsequent rules + + + SwitchParameter + + + False + + + Priority + + Set the sequence for rule processing + + Int32 + + Int32 + + + 0 + + + PassThru + + If specified pass the rule back to the caller to allow additional customization. + + + SwitchParameter + + + False + + + + Add-ConditionalFormatting + + Address + + A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied + + ExcelWorksheet + + ExcelWorksheet + + + None + + + DataBarColor + + Color for databar type charts + + Object + + Object + + + None + + + Priority + + Set the sequence for rule processing + + Int32 + + Int32 + + + 0 + + + PassThru + + If specified pass the rule back to the caller to allow additional customization. + + + SwitchParameter + + + False + + + + Add-ConditionalFormatting + + Address + + A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied + + ExcelWorksheet + + ExcelWorksheet + + + None + + + ThreeIconsSet + + One of the three-icon set types (e.g. Traffic Lights) + + + Arrows + ArrowsGray + Flags + Signs + Symbols + Symbols2 + TrafficLights1 + TrafficLights2 + + eExcelconditionalFormatting3IconsSetType + + eExcelconditionalFormatting3IconsSetType + + + None + + + Reverse + + Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales + + + SwitchParameter + + + False + + + Priority + + Set the sequence for rule processing + + Int32 + + Int32 + + + 0 + + + PassThru + + If specified pass the rule back to the caller to allow additional customization. + + + SwitchParameter + + + False + + + + Add-ConditionalFormatting + + Address + + A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied + + ExcelWorksheet + + ExcelWorksheet + + + None + + + FourIconsSet + + A four-icon set name + + + Arrows + ArrowsGray + Rating + RedToBlack + TrafficLights + + eExcelconditionalFormatting4IconsSetType + + eExcelconditionalFormatting4IconsSetType + + + None + + + Reverse + + Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales + + + SwitchParameter + + + False + + + Priority + + Set the sequence for rule processing + + Int32 + + Int32 + + + 0 + + + PassThru + + If specified pass the rule back to the caller to allow additional customization. + + + SwitchParameter + + + False + + + + Add-ConditionalFormatting + + Address + + A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied + + ExcelWorksheet + + ExcelWorksheet + + + None + + + FiveIconsSet + + A five-icon set name + + + Arrows + ArrowsGray + Quarters + Rating + + eExcelconditionalFormatting5IconsSetType + + eExcelconditionalFormatting5IconsSetType + + + None + + + Reverse + + Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales + + + SwitchParameter + + + False + + + Priority + + Set the sequence for rule processing + + Int32 + + Int32 + + + 0 + + + PassThru + + If specified pass the rule back to the caller to allow additional customization. + + + SwitchParameter + + + False + + + + + + Address + + A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied + + ExcelWorksheet + + ExcelWorksheet + + + None + + + RuleType + + A standard named-rule - Top / Bottom / Less than / Greater than / Contains etc. + + eExcelConditionalFormattingRuleType + + eExcelConditionalFormattingRuleType + + + None + + + ForegroundColor + + Text color for matching objects + + Object + + Object + + + None + + + DataBarColor + + Color for databar type charts + + Object + + Object + + + None + + + ThreeIconsSet + + One of the three-icon set types (e.g. Traffic Lights) + + eExcelconditionalFormatting3IconsSetType + + eExcelconditionalFormatting3IconsSetType + + + None + + + FourIconsSet + + A four-icon set name + + eExcelconditionalFormatting4IconsSetType + + eExcelconditionalFormatting4IconsSetType + + + None + + + FiveIconsSet + + A five-icon set name + + eExcelconditionalFormatting5IconsSetType + + eExcelconditionalFormatting5IconsSetType + + + None + + + Reverse + + Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales + + SwitchParameter + + SwitchParameter + + + False + + + ConditionValue + + A value for the condition (for example 2000 if the test is 'lessthan 2000'; Formulas should begin with "=" ) + + Object + + Object + + + None + + + ConditionValue2 + + A second value for the conditions like "Between X and Y" + + Object + + Object + + + None + + + BackgroundColor + + Background color for matching items + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern for matching items + + ExcelFillStyle + + ExcelFillStyle + + + None + + + PatternColor + + Secondary color when a background pattern requires it + + Object + + Object + + + None + + + NumberFormat + + Sets the numeric format for matching items + + Object + + Object + + + None + + + Bold + + Put matching items in bold face + + SwitchParameter + + SwitchParameter + + + False + + + Italic + + Put matching items in italic + + SwitchParameter + + SwitchParameter + + + False + + + Underline + + Underline matching items + + SwitchParameter + + SwitchParameter + + + False + + + StrikeThru + + Strikethrough text of matching items + + SwitchParameter + + SwitchParameter + + + False + + + StopIfTrue + + Prevent the processing of subsequent rules + + SwitchParameter + + SwitchParameter + + + False + + + Priority + + Set the sequence for rule processing + + Int32 + + Int32 + + + 0 + + + PassThru + + If specified pass the rule back to the caller to allow additional customization. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru + Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b2:b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003" + Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled" + $excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern + $excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true + $excel.Save() ; $excel.Dispose() + + Here Export-Excel is called with the -PassThru parameter, so the ExcelPackage object representing Machines.XLSX is stored in $Excel.The desired worksheet is selected, and then columns" B" and "I" are conditionally formatted (excluding the top row) to show red text if they contain "2003" or "Disabled" respectively. + A fixed date format is then applied to columns D to G, and the top row is formatted. + Finally the workbook is saved and the Excel package object is closed. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $r = Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Range "B1:B100" -ThreeIconsSet Flags -Passthru + $r.Reverse = $true ; $r.Icon1.Type = "Num"; $r.Icon2.Type = "Num" ; $r.Icon2.value = 100 ; $r.Icon3.type = "Num" ;$r.Icon3.value = 1000 + + Again Export-Excel has been called with -PassThru leaving a package object in $Excel. + This time B1:B100 has been conditionally formatted with 3 icons, using the "Flags" Icon-Set. + Add-ConditionalFormatting does not provide accessto every option in the formatting rule, so -PassThru has been used and the rule is modified to apply the flags in reverse order, and transitions between flags are set to 100 and 1000. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red + + This time $sheet holds an ExcelWorkshseet object and databars are added to column D, excluding the top row. + + + + -------------------------- EXAMPLE 4 -------------------------- + PS\> Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue + + In this example a named range is used to select the cells where the condition should apply, and instead of specifying a sheet and range within the sheet as separate parameters, the cells where the format should apply are specified directly. + If a cell in the "FinishPosition" range is 1, then the text is turned to Bold & Purple. + This rule is moved to first in the priority list, and where cells have a value of 1, no other rules will be processed. + + + + -------------------------- EXAMPLE 5 -------------------------- + PS\> $excel = Get-ChildItem | Select-Object -Property Name,Length,LastWriteTime,CreationTime | Export-Excel "$env:temp\test43.xlsx" -PassThru -AutoSize + $ws = $excel.Workbook.Worksheets["Sheet1"] + $ws.Cells["E1"].Value = "SavedAt" + $ws.Cells["F1"].Value = [datetime]::Now + $ws.Cells["F1"].Style.Numberformat.Format = (Expand-NumberFormat -NumberFormat 'Date-Time') + $lastRow = $ws.Dimension.End.Row + Add-ConditionalFormatting -WorkSheet $ws -address "A2:A$Lastrow" -RuleType LessThan -ConditionValue "A" -ForeGroundColor Gray + Add-ConditionalFormatting -WorkSheet $ws -address "B2:B$Lastrow" -RuleType GreaterThan -ConditionValue 1000000 -NumberFormat '#,###,,.00"M"' + Add-ConditionalFormatting -WorkSheet $ws -address "C2:C$Lastrow" -RuleType GreaterThan -ConditionValue "=INT($F$1-7)" -ForeGroundColor Green -StopIfTrue + Add-ConditionalFormatting -WorkSheet $ws -address "D2:D$Lastrow" -RuleType Equal -ConditionValue "=C2" -ForeGroundColor Blue -StopIfTrue + Close-ExcelPackage -Show $excel + + The first few lines of code export a list of file and directory names, sizes and dates to a spreadsheet. + It puts the date of the export in cell F1. + The first Conditional format changes the color of files and folders that begin with a ".", "_" or anything else which sorts before "A". + The second Conditional format changes the Number format of numbers bigger than 1 million, for example 1,234,567,890 will dispay as "1,234.57M" + The third highlights datestamps of files less than a week old when the export was run; the = is necessary in the condition value otherwise the rule will look for the the text INT($F$1-7), and the cell address for the date is fixed using the standard Excel $ notation. + The final Conditional format looks for files which have not changed since they were created. Here the condition value is "=C2". The = sign means C2 is treated as a formula, not literal text. Unlike the file age, we want the cell used to change for each cell where the conditional format applies. + The first cell in the conditional format range is D2, which is compared against C2, then D3 is compared against C3 and so on. A common mistake is to include the title row in the range and accidentally apply conditional formatting to it, or to begin the range at row 2 but use row 1 as the starting point for comparisons. + + + + -------------------------- EXAMPLE 6 -------------------------- + PS\> Add-ConditionalFormatting $ws.Cells["B:B"] GreaterThan 10000000 -Fore Red -Stop -Pri 1 + + This version shows the shortest syntax - the Address, Ruletype, and Conditionvalue can be identified from their position, and ForegroundColor, StopIfTrue and Priority can all be shortend. + + + + + + Online Version: + + + + + + + Add-ExcelChart + Add + ExcelChart + + Creates a chart in an existing Excel worksheet. + + + + Creates a chart. + It is possible to configure the type of chart, the range of X values (labels) and Y values, the title, the legend, the ranges for both axes, the format and position of the axes. + Normally the command does not return anything, but if -passthru is specified the chart is returned so that it can be customized. + + + + Add-ExcelChart + + Worksheet + + An existing Sheet where the chart will be created. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + Title + + The title for the chart. + + String + + String + + + None + + + ChartType + + One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + ColumnStacked + + + ChartTrendLine + + + + + Exponential + Linear + Logarithmic + MovingAvgerage + Polynomial + Power + + eTrendLine[] + + eTrendLine[] + + + None + + + XRange + + The range of cells containing values for the X-Axis - usually labels. + + Object + + Object + + + None + + + YRange + + The range(s) of cells holding values for the Y-Axis - usually "data". + + Object + + Object + + + None + + + Width + + Width of the chart in Pixels; defaults to 500. + + Int32 + + Int32 + + + 500 + + + Height + + Height of the chart in Pixels; defaults to 350. + + Int32 + + Int32 + + + 350 + + + Row + + Row position of the top left corner of the chart. ) places at the top of the sheet, 1 below row 1 and so on. + + Int32 + + Int32 + + + 0 + + + RowOffSetPixels + + Offset to position the chart by a fraction of a row. + + Int32 + + Int32 + + + 10 + + + Column + + Column position of the top left corner of the chart; 0 places at the edge of the sheet 1 to the right of column A and so on. + + Int32 + + Int32 + + + 6 + + + ColumnOffSetPixels + + Offset to position the chart by a fraction of a column. + + Int32 + + Int32 + + + 5 + + + LegendPosition + + Location of the key, either left, right, top, bottom or TopRight. + + + Top + Left + Right + Bottom + TopRight + + eLegendPosition + + eLegendPosition + + + None + + + LegendSize + + Font size for the key. + + Object + + Object + + + None + + + LegendBold + + Sets the key in bold type. + + + SwitchParameter + + + False + + + NoLegend + + If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. + + + SwitchParameter + + + False + + + ShowCategory + + Attaches a category label, in charts which support this. + + + SwitchParameter + + + False + + + ShowPercent + + Attaches a percentage label, in charts which support this. + + + SwitchParameter + + + False + + + SeriesHeader + + Specify explicit name(s) for the data series, which will appear in the legend/key. The contents of a cell can be specified in the from =Sheet9!Z10 . + + String[] + + String[] + + + None + + + TitleBold + + Sets the title in bold face. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 0 + + + XAxisTitleText + + Specifies a title for the X-axis. + + String + + String + + + None + + + XAxisTitleBold + + Sets the X-axis title in bold face. + + + SwitchParameter + + + False + + + XAxisTitleSize + + Sets the font size for the axis title. + + Object + + Object + + + None + + + XAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers along the X-axis. + + String + + String + + + None + + + XMajorUnit + + Spacing for the major gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMinorUnit + + Spacing for the minor gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMaxValue + + Maximum value for the scale along the X-axis. + + Object + + Object + + + None + + + XMinValue + + Minimum value for the scale along the X-axis. + + Object + + Object + + + None + + + XAxisPosition + + Position for the X-axis (Top or Bottom). + + + Left + Bottom + Right + Top + + eAxisPosition + + eAxisPosition + + + None + + + YAxisTitleText + + Specifies a title for the Y-axis. + + String + + String + + + None + + + YAxisTitleBold + + Sets the Y-axis title in bold face. + + + SwitchParameter + + + False + + + YAxisTitleSize + + Sets the font size for the Y-axis title + + Object + + Object + + + None + + + YAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers on the Y-axis. + + String + + String + + + None + + + YMajorUnit + + Spacing for the major gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMinorUnit + + Spacing for the minor gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMaxValue + + Maximum value on the Y-axis. + + Object + + Object + + + None + + + YMinValue + + Minimum value on the Y-axis. + + Object + + Object + + + None + + + YAxisPosition + + Position for the Y-axis (Left or Right). + + + Left + Bottom + Right + Top + + eAxisPosition + + eAxisPosition + + + None + + + PassThru + + Add-Excel chart doesn't normally return anything, but if -PassThru is specified it returns the newly created chart to allow it to be fine tuned. + + + SwitchParameter + + + False + + + + Add-ExcelChart + + PivotTable + + Instead of specify X and Y ranges, get data from a PivotTable by passing a PivotTable Object. + + ExcelPivotTable + + ExcelPivotTable + + + None + + + Title + + The title for the chart. + + String + + String + + + None + + + ChartType + + One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + ColumnStacked + + + ChartTrendLine + + + + + Exponential + Linear + Logarithmic + MovingAvgerage + Polynomial + Power + + eTrendLine[] + + eTrendLine[] + + + None + + + XRange + + The range of cells containing values for the X-Axis - usually labels. + + Object + + Object + + + None + + + YRange + + The range(s) of cells holding values for the Y-Axis - usually "data". + + Object + + Object + + + None + + + Width + + Width of the chart in Pixels; defaults to 500. + + Int32 + + Int32 + + + 500 + + + Height + + Height of the chart in Pixels; defaults to 350. + + Int32 + + Int32 + + + 350 + + + Row + + Row position of the top left corner of the chart. ) places at the top of the sheet, 1 below row 1 and so on. + + Int32 + + Int32 + + + 0 + + + RowOffSetPixels + + Offset to position the chart by a fraction of a row. + + Int32 + + Int32 + + + 10 + + + Column + + Column position of the top left corner of the chart; 0 places at the edge of the sheet 1 to the right of column A and so on. + + Int32 + + Int32 + + + 6 + + + ColumnOffSetPixels + + Offset to position the chart by a fraction of a column. + + Int32 + + Int32 + + + 5 + + + LegendPosition + + Location of the key, either left, right, top, bottom or TopRight. + + + Top + Left + Right + Bottom + TopRight + + eLegendPosition + + eLegendPosition + + + None + + + LegendSize + + Font size for the key. + + Object + + Object + + + None + + + LegendBold + + Sets the key in bold type. + + + SwitchParameter + + + False + + + NoLegend + + If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. + + + SwitchParameter + + + False + + + ShowCategory + + Attaches a category label, in charts which support this. + + + SwitchParameter + + + False + + + ShowPercent + + Attaches a percentage label, in charts which support this. + + + SwitchParameter + + + False + + + SeriesHeader + + Specify explicit name(s) for the data series, which will appear in the legend/key. The contents of a cell can be specified in the from =Sheet9!Z10 . + + String[] + + String[] + + + None + + + TitleBold + + Sets the title in bold face. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 0 + + + XAxisTitleText + + Specifies a title for the X-axis. + + String + + String + + + None + + + XAxisTitleBold + + Sets the X-axis title in bold face. + + + SwitchParameter + + + False + + + XAxisTitleSize + + Sets the font size for the axis title. + + Object + + Object + + + None + + + XAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers along the X-axis. + + String + + String + + + None + + + XMajorUnit + + Spacing for the major gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMinorUnit + + Spacing for the minor gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMaxValue + + Maximum value for the scale along the X-axis. + + Object + + Object + + + None + + + XMinValue + + Minimum value for the scale along the X-axis. + + Object + + Object + + + None + + + XAxisPosition + + Position for the X-axis (Top or Bottom). + + + Left + Bottom + Right + Top + + eAxisPosition + + eAxisPosition + + + None + + + YAxisTitleText + + Specifies a title for the Y-axis. + + String + + String + + + None + + + YAxisTitleBold + + Sets the Y-axis title in bold face. + + + SwitchParameter + + + False + + + YAxisTitleSize + + Sets the font size for the Y-axis title + + Object + + Object + + + None + + + YAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers on the Y-axis. + + String + + String + + + None + + + YMajorUnit + + Spacing for the major gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMinorUnit + + Spacing for the minor gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMaxValue + + Maximum value on the Y-axis. + + Object + + Object + + + None + + + YMinValue + + Minimum value on the Y-axis. + + Object + + Object + + + None + + + YAxisPosition + + Position for the Y-axis (Left or Right). + + + Left + Bottom + Right + Top + + eAxisPosition + + eAxisPosition + + + None + + + PassThru + + Add-Excel chart doesn't normally return anything, but if -PassThru is specified it returns the newly created chart to allow it to be fine tuned. + + + SwitchParameter + + + False + + + + + + Worksheet + + An existing Sheet where the chart will be created. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + PivotTable + + Instead of specify X and Y ranges, get data from a PivotTable by passing a PivotTable Object. + + ExcelPivotTable + + ExcelPivotTable + + + None + + + Title + + The title for the chart. + + String + + String + + + None + + + ChartType + + One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". + + eChartType + + eChartType + + + ColumnStacked + + + ChartTrendLine + + + + eTrendLine[] + + eTrendLine[] + + + None + + + XRange + + The range of cells containing values for the X-Axis - usually labels. + + Object + + Object + + + None + + + YRange + + The range(s) of cells holding values for the Y-Axis - usually "data". + + Object + + Object + + + None + + + Width + + Width of the chart in Pixels; defaults to 500. + + Int32 + + Int32 + + + 500 + + + Height + + Height of the chart in Pixels; defaults to 350. + + Int32 + + Int32 + + + 350 + + + Row + + Row position of the top left corner of the chart. ) places at the top of the sheet, 1 below row 1 and so on. + + Int32 + + Int32 + + + 0 + + + RowOffSetPixels + + Offset to position the chart by a fraction of a row. + + Int32 + + Int32 + + + 10 + + + Column + + Column position of the top left corner of the chart; 0 places at the edge of the sheet 1 to the right of column A and so on. + + Int32 + + Int32 + + + 6 + + + ColumnOffSetPixels + + Offset to position the chart by a fraction of a column. + + Int32 + + Int32 + + + 5 + + + LegendPosition + + Location of the key, either left, right, top, bottom or TopRight. + + eLegendPosition + + eLegendPosition + + + None + + + LegendSize + + Font size for the key. + + Object + + Object + + + None + + + LegendBold + + Sets the key in bold type. + + SwitchParameter + + SwitchParameter + + + False + + + NoLegend + + If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. + + SwitchParameter + + SwitchParameter + + + False + + + ShowCategory + + Attaches a category label, in charts which support this. + + SwitchParameter + + SwitchParameter + + + False + + + ShowPercent + + Attaches a percentage label, in charts which support this. + + SwitchParameter + + SwitchParameter + + + False + + + SeriesHeader + + Specify explicit name(s) for the data series, which will appear in the legend/key. The contents of a cell can be specified in the from =Sheet9!Z10 . + + String[] + + String[] + + + None + + + TitleBold + + Sets the title in bold face. + + SwitchParameter + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 0 + + + XAxisTitleText + + Specifies a title for the X-axis. + + String + + String + + + None + + + XAxisTitleBold + + Sets the X-axis title in bold face. + + SwitchParameter + + SwitchParameter + + + False + + + XAxisTitleSize + + Sets the font size for the axis title. + + Object + + Object + + + None + + + XAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers along the X-axis. + + String + + String + + + None + + + XMajorUnit + + Spacing for the major gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMinorUnit + + Spacing for the minor gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMaxValue + + Maximum value for the scale along the X-axis. + + Object + + Object + + + None + + + XMinValue + + Minimum value for the scale along the X-axis. + + Object + + Object + + + None + + + XAxisPosition + + Position for the X-axis (Top or Bottom). + + eAxisPosition + + eAxisPosition + + + None + + + YAxisTitleText + + Specifies a title for the Y-axis. + + String + + String + + + None + + + YAxisTitleBold + + Sets the Y-axis title in bold face. + + SwitchParameter + + SwitchParameter + + + False + + + YAxisTitleSize + + Sets the font size for the Y-axis title + + Object + + Object + + + None + + + YAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers on the Y-axis. + + String + + String + + + None + + + YMajorUnit + + Spacing for the major gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMinorUnit + + Spacing for the minor gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMaxValue + + Maximum value on the Y-axis. + + Object + + Object + + + None + + + YMinValue + + Minimum value on the Y-axis. + + Object + + Object + + + None + + + YAxisPosition + + Position for the Y-axis (Left or Right). + + eAxisPosition + + eAxisPosition + + + None + + + PassThru + + Add-Excel chart doesn't normally return anything, but if -PassThru is specified it returns the newly created chart to allow it to be fine tuned. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.Drawing.Chart.ExcelChart + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $Excel = ConvertFrom-Csv @" + Product, City, Sales + Apple, London, 300 + Orange, London, 400 + Banana, London, 300 + Orange, Paris, 600 + Banana, Paris, 300 + Apple, New York, 1200 +"@ | Export-Excel -Path test.xlsx -PassThru + Add-ExcelChart -Worksheet $Excel.Workbook.Worksheets[1] -ChartType "Doughnut" -XRange "A2:B7" -YRange "C2:C7" -width 500 + Close-ExcelPackage -Show $Excel + + The first command expands a multi-line string into 6 rows of data which is exported to new Excel file; leaving an ExcelPackage object in $excel The second command adds a chart - the cell ranges are explicitly specified. + Note that the XRange (labels) is TWO columns wide and the chart will combine the name of the product and the name of the City to create the label. + The width of the chart is set explictly, the default legend is used and there is no Chart title. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $Excel = Invoke-Sum (Get-Process) Company Handles, PM, VirtualMemorySize | Export-Excel $path -AutoSize -ExcelChartDefinition $c -AutoNameRange -PassThru + Add-ExcelChart -Worksheet $Excel.Workbook.Worksheets[1] -Title "VM use" -ChartType PieExploded3D -XRange "Name" -YRange "VirtualMemorySize" -NoLegend -ShowCategory + Close-ExcelPackage $Excel -Show + + The first line exports information and creates named ranges for each column. + The Second line uses the ranges to specify a chart - the labels come from the range "Name" and the data from the range "VirtualMemorySize" + The chart is specified as a 3D exploded PIE chart, with a title of "VM Use" and instead of a legend the the pie slices are identified with a label. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> $Excel = Invoke-Sum (Get-Process) Company Handles, PM, VirtualMemorySize | Export-Excel test.xlsx -TableName Processes -PassThru + Add-ExcelChart -Worksheet $Excel.Workbook.Worksheets[1] -Title Stats -ChartType LineMarkersStacked -XRange "Processes[Name]" -YRange "Processes[PM]", "Processes[VirtualMemorySize]" -SeriesHeader 'PM', 'VMSize' + Close-ExcelPackage $Excel -Show + + The first line exports information to a table in new file; and captures the excel Package object in $Excel + The second line creates a chart on the first page of the work sheet, using the notation "TableName[ColumnnName]" to refer to the data, the labels come Name column in the table, and the data series from its PM and VirtualMemorySize columns. The display names for these in the header are set to 'PM' and 'VMSize'. + + + + -------------------------- EXAMPLE 4 -------------------------- + PS\> $excel = 0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -Path Text.xlsx -WorkSheetname SinX -PassThru +Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 \` + -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" \` + -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 \` + -SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPosition Bottom +Close-ExcelPackage $Excel -Show + + The first line puts numbers from 0 to 360 into a sheet, as the first column, and a formula to calculate the Sine of that number of number of degrees in the second column. It creates named-ranges for the two columns - "X" and "SinX" respectively + The Add-ExcelChart command adds a chart to that worksheet, specifying a line chart with the X values coming from named-range "X" and the Y values coming from named-range "SinX". The chart has a title, and is positioned to the right of column 2 and sized 800 pixels wide + The X-axis is labelled "Degrees", in bold 12 point type and runs from 0 to 361 with labels every 30, and minor tick marks every 10. Degrees are shown padded to 3 digits. + The Y-axis is labelled "Sine" and to allow some room above and below its scale runs from -1.25 to 1.25, and is marked off in units of 0.25 shown to two decimal places. + The key will for the chart will be at the bottom in 8 point bold type and the line will be named "Sin(x)". + + + + + + Online Version: + + + + + + + Add-ExcelDataValidationRule + Add + ExcelDataValidationRule + + Adds data validation to a range of cells + + + + Excel supports the validation of user input, and ranges of cells can be marked to only contain numbers, or date, or Text up to a particular length, or selections from a list. This command adds validation rules to a worksheet. + + + + Add-ExcelDataValidationRule + + Range + + The range of cells to be validate, for example, "B2:C100" + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the cells should be validated + + ExcelWorksheet + + ExcelWorksheet + + + None + + + ValidationType + + An option corresponding to a choice from the 'Allow' pull down on the settings page in the Excel dialog. "Any" means "any allowed" - in other words, no Validation + + Object + + Object + + + None + + + Operator + + The operator to apply to Decimal, Integer, TextLength, DateTime and time fields, for example "equal" or "between" + + + between + notBetween + equal + notEqual + lessThan + lessThanOrEqual + greaterThan + greaterThanOrEqual + + ExcelDataValidationOperator + + ExcelDataValidationOperator + + + Equal + + + Value + + For Decimal, Integer, TextLength, DateTime the [first] data value + + Object + + Object + + + None + + + Value2 + + When using the between operator, the second data value + + Object + + Object + + + None + + + Formula + + The [first] data value as a formula. Use absolute formulas $A$1 if (e.g.) you want all cells to check against the same list + + Object + + Object + + + None + + + Formula2 + + When using the between operator, the second data value as a formula + + Object + + Object + + + None + + + ValueSet + + When using the list validation type, a set of values (rather than refering to Sheet!B$2:B$100 ) + + Object + + Object + + + None + + + ShowErrorMessage + + Corresponds to the the 'Show Error alert ...' check box on error alert page in the Excel dialog + + + SwitchParameter + + + False + + + ErrorStyle + + Stop, Warning, or Infomation, corresponding to to the style setting in the Excel dialog + + + undefined + stop + warning + information + + ExcelDataValidationWarningStyle + + ExcelDataValidationWarningStyle + + + None + + + ErrorTitle + + The title for the message box corresponding to to the title setting in the Excel dialog + + String + + String + + + None + + + ErrorBody + + The error message corresponding to to the Error message setting in the Excel dialog + + String + + String + + + None + + + ShowPromptMessage + + Corresponds to the the 'Show Input message ...' check box on input message page in the Excel dialog + + + SwitchParameter + + + False + + + PromptBody + + The prompt message corresponding to to the Input message setting in the Excel dialog + + String + + String + + + None + + + PromptTitle + + The title for the message box corresponding to to the title setting in the Excel dialog + + String + + String + + + None + + + NoBlank + + By default the 'Ignore blank' option will be selected, unless NoBlank is sepcified. + + String + + String + + + None + + + + + + Range + + The range of cells to be validate, for example, "B2:C100" + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the cells should be validated + + ExcelWorksheet + + ExcelWorksheet + + + None + + + ValidationType + + An option corresponding to a choice from the 'Allow' pull down on the settings page in the Excel dialog. "Any" means "any allowed" - in other words, no Validation + + Object + + Object + + + None + + + Operator + + The operator to apply to Decimal, Integer, TextLength, DateTime and time fields, for example "equal" or "between" + + ExcelDataValidationOperator + + ExcelDataValidationOperator + + + Equal + + + Value + + For Decimal, Integer, TextLength, DateTime the [first] data value + + Object + + Object + + + None + + + Value2 + + When using the between operator, the second data value + + Object + + Object + + + None + + + Formula + + The [first] data value as a formula. Use absolute formulas $A$1 if (e.g.) you want all cells to check against the same list + + Object + + Object + + + None + + + Formula2 + + When using the between operator, the second data value as a formula + + Object + + Object + + + None + + + ValueSet + + When using the list validation type, a set of values (rather than refering to Sheet!B$2:B$100 ) + + Object + + Object + + + None + + + ShowErrorMessage + + Corresponds to the the 'Show Error alert ...' check box on error alert page in the Excel dialog + + SwitchParameter + + SwitchParameter + + + False + + + ErrorStyle + + Stop, Warning, or Infomation, corresponding to to the style setting in the Excel dialog + + ExcelDataValidationWarningStyle + + ExcelDataValidationWarningStyle + + + None + + + ErrorTitle + + The title for the message box corresponding to to the title setting in the Excel dialog + + String + + String + + + None + + + ErrorBody + + The error message corresponding to to the Error message setting in the Excel dialog + + String + + String + + + None + + + ShowPromptMessage + + Corresponds to the the 'Show Input message ...' check box on input message page in the Excel dialog + + SwitchParameter + + SwitchParameter + + + False + + + PromptBody + + The prompt message corresponding to to the Input message setting in the Excel dialog + + String + + String + + + None + + + PromptTitle + + The title for the message box corresponding to to the title setting in the Excel dialog + + String + + String + + + None + + + NoBlank + + By default the 'Ignore blank' option will be selected, unless NoBlank is sepcified. + + String + + String + + + None + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\>Add-ExcelDataValidationRule -WorkSheet $PlanSheet -Range 'E2:E1001' -ValidationType Integer -Operator between -Value 0 -Value2 100 \` + -ShowErrorMessage -ErrorStyle stop -ErrorTitle 'Invalid Data' -ErrorBody 'Percentage must be a whole number between 0 and 100' + + This defines a validation rule on cells E2-E1001; it is an integer rule and requires a number between 0 and 100. If a value is input with a fraction, negative number, or positive number &gt; 100 a stop dialog box appears. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\>Add-ExcelDataValidationRule -WorkSheet $PlanSheet -Range 'B2:B1001' -ValidationType List -Formula 'values!$a$2:$a$1000' + -ShowErrorMessage -ErrorStyle stop -ErrorTitle 'Invalid Data' -ErrorBody 'You must select an item from the list' + + This defines a list rule on Cells B2:1001, and the posible values are in a sheet named "values" at cells A2 to A1000 Blank cells in this range are ignored. + If $ signs were left out of the fomrmula B2 would be checked against A2-A1000, B3, against A3-A1001, B4 against A4-A1002 up to B1001 beng checked against A1001-A1999 + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\>Add-ExcelDataValidationRule -WorkSheet $PlanSheet -Range 'I2:N1001' -ValidationType List -ValueSet @('yes','YES','Yes') + -ShowErrorMessage -ErrorStyle stop -ErrorTitle 'Invalid Data' -ErrorBody "Select Yes or leave blank for no" + + Similar to the previous example but this time provides a value set; Excel comparisons are case sesnsitive, hence 3 versions of Yes. + + + + + + Online Version: + + + + + + + Add-ExcelName + Add + ExcelName + + Adds a named-range to an existing Excel worksheet. + + + + It is often helpful to be able to refer to sets of cells with a name rather than using their co-ordinates; Add-ExcelName sets up these names. + + + + Add-ExcelName + + Range + + The range of cells to assign as a name. + + ExcelRange + + ExcelRange + + + None + + + RangeName + + The name to assign to the range. If the name exists it will be updated to the new range. If no name is specified, the first cell in the range will be used as the name. + + String + + String + + + None + + + + + + Range + + The range of cells to assign as a name. + + ExcelRange + + ExcelRange + + + None + + + RangeName + + The name to assign to the range. If the name exists it will be updated to the new range. If no name is specified, the first cell in the range will be used as the name. + + String + + String + + + None + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $rangeName + + $WS is a worksheet, and $dataRange is a string describing a range of cells - for example "A1:Z10" - which will become a named range, using the name in $rangeName. + + + + + + Online Version: + + + + + + + Add-ExcelTable + Add + ExcelTable + + Adds Tables to Excel workbooks. + + + + Unlike named ranges, where the name only needs to be unique within a sheet, Table names must be unique in the workbook. + Tables carry formatting and by default have a filter. + The filter, header, totals, first and last column highlights can all be configured. + + + + Add-ExcelTable + + Range + + The range of cells to assign to a table. + + ExcelRange + + ExcelRange + + + None + + + TableName + + The name for the Table - this should be unqiue in the Workbook - auto generated names will be used if this is left empty. + + String + + String + + + None + + + TableStyle + + The Style for the table, by default "Medium6" is used + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + Medium6 + + + TableTotalSettings + + A HashTable in the form of either + - ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> - + + ColumnName = @{ + Function = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> + Comment = $HoverComment + } + + if specified, -ShowTotal is not needed. + + Hashtable + + Hashtable + + + None + + + ShowHeader + + By default the header row is shown - it can be turned off with -ShowHeader:$false. + + + SwitchParameter + + + False + + + ShowFilter + + By default the filter is enabled - it can be turned off with -ShowFilter:$false. + + + SwitchParameter + + + False + + + ShowTotal + + Show total adds a totals row. This does not automatically sum the columns but provides a drop-down in each to select sum, average etc + + + SwitchParameter + + + False + + + ShowFirstColumn + + Highlights the first column in bold. + + + SwitchParameter + + + False + + + ShowLastColumn + + Highlights the last column in bold. + + + SwitchParameter + + + False + + + ShowRowStripes + + By default the table formats show striped rows, the can be turned off with -ShowRowStripes:$false + + + SwitchParameter + + + False + + + ShowColumnStripes + + Turns on column stripes. + + + SwitchParameter + + + False + + + PassThru + + If -PassThru is specified, the table object will be returned to allow additional changes to be made. + + + SwitchParameter + + + False + + + + + + Range + + The range of cells to assign to a table. + + ExcelRange + + ExcelRange + + + None + + + TableName + + The name for the Table - this should be unqiue in the Workbook - auto generated names will be used if this is left empty. + + String + + String + + + None + + + TableStyle + + The Style for the table, by default "Medium6" is used + + TableStyles + + TableStyles + + + Medium6 + + + ShowHeader + + By default the header row is shown - it can be turned off with -ShowHeader:$false. + + SwitchParameter + + SwitchParameter + + + False + + + ShowFilter + + By default the filter is enabled - it can be turned off with -ShowFilter:$false. + + SwitchParameter + + SwitchParameter + + + False + + + ShowTotal + + Show total adds a totals row. This does not automatically sum the columns but provides a drop-down in each to select sum, average etc + + SwitchParameter + + SwitchParameter + + + False + + + TableTotalSettings + + A HashTable in the form of either + - ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> - + + ColumnName = @{ + Function = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> + Comment = $HoverComment + } + + if specified, -ShowTotal is not needed. + + Hashtable + + Hashtable + + + None + + + ShowFirstColumn + + Highlights the first column in bold. + + SwitchParameter + + SwitchParameter + + + False + + + ShowLastColumn + + Highlights the last column in bold. + + SwitchParameter + + SwitchParameter + + + False + + + ShowRowStripes + + By default the table formats show striped rows, the can be turned off with -ShowRowStripes:$false + + SwitchParameter + + SwitchParameter + + + False + + + ShowColumnStripes + + Turns on column stripes. + + SwitchParameter + + SwitchParameter + + + False + + + PassThru + + If -PassThru is specified, the table object will be returned to allow additional changes to be made. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.Table.ExcelTable + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName + + $WS is a worksheet, and $dataRange is a string describing a range of cells - for example "A1:Z10". This range which will become a table, named $TableName + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Add-ExcelTable -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName Musictable -ShowFilter:$false -ShowTotal -ShowFirstColumn + + Again $ws is a worksheet, range here is the whole of the active part of the worksheet. The table style and name are set, the filter is turned off, and a "Totals" row added, and first column is set in bold. + + + + + + Online Version: + + + + + + + Add-PivotTable + Add + PivotTable + + Adds a PivotTable (and optional PivotChart) to a workbook. + + + + If the PivotTable already exists, the source data will be updated. + + + + Add-PivotTable + + PivotTableName + + Name for the new PivotTable - this will be the name of a sheet in the Workbook. + + String + + String + + + None + + + Address + + By default, a PivotTable will be created on its own sheet, but it can be created on an existing sheet by giving the address where the top left corner of the table should go. (Allow two rows for the filter if one is used.) + + ExcelAddressBase + + ExcelAddressBase + + + None + + + ExcelPackage + + An Excel-package object for the workbook. + + Object + + Object + + + None + + + SourceWorkSheet + + Worksheet where the data is found. + + Object + + Object + + + None + + + SourceRange + + Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used. + + Object + + Object + + + None + + + PivotRows + + Fields to set as rows in the PivotTable. + + Object + + Object + + + None + + + PivotData + + A hash table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP. + + Object + + Object + + + None + + + PivotColumns + + Fields to set as columns in the PivotTable. + + Object + + Object + + + None + + + PivotFilter + + Fields to use to filter in the PivotTable. + + Object + + Object + + + None + + + PivotDataToColumn + + If there are multiple data items in a PivotTable, by default they are shown on separate rows; this switch makes them separate columns. + + + SwitchParameter + + + False + + + PivotTotals + + Define whether totals should be added to rows, columns neither, or both (the default is both). + + String + + String + + + Both + + + NoTotalsInPivot + + Included for compatibility - equivalent to -PivotTotals "None". + + + SwitchParameter + + + False + + + GroupDateRow + + The name of a row field which should be grouped by parts of the date/time (ignored if GroupDateRow is not specified) + + String + + String + + + None + + + GroupDateColumn + + The name of a Column field which should be grouped by parts of the date/time (ignored if GroupDateRow is not specified) + + String + + String + + + None + + + GroupDatePart + + The Part(s) of the date to use in the grouping (ignored if GroupDateRow is not specified) + + + Years + Quarters + Months + Days + Hours + Minutes + Seconds + + eDateGroupBy[] + + eDateGroupBy[] + + + None + + + GroupNumericRow + + The name of a row field which should be grouped by Number (e.g. 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericColumn + + The name of a Column field which should be grouped by Number (e.g. 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericMin + + The starting point for grouping + + Double + + Double + + + 0 + + + GroupNumericMax + + The endpoint for grouping + + Double + + Double + + + 1.79769313486232E+308 + + + GroupNumericInterval + + The interval for grouping + + Double + + Double + + + 100 + + + PivotNumberFormat + + Number format to apply to the data cells in the PivotTable. + + String + + String + + + None + + + PivotTableStyle + + Apply a table style to the PivotTable. + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + None + + + PivotChartDefinition + + Use a chart definition instead of specifying chart settings one by one. + + Object + + Object + + + None + + + Activate + + If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified. + + + SwitchParameter + + + False + + + PassThru + + Return the PivotTable so it can be customized. + + + SwitchParameter + + + False + + + + Add-PivotTable + + PivotTableName + + Name for the new PivotTable - this will be the name of a sheet in the Workbook. + + String + + String + + + None + + + Address + + By default, a PivotTable will be created on its own sheet, but it can be created on an existing sheet by giving the address where the top left corner of the table should go. (Allow two rows for the filter if one is used.) + + ExcelAddressBase + + ExcelAddressBase + + + None + + + ExcelPackage + + An Excel-package object for the workbook. + + Object + + Object + + + None + + + SourceWorkSheet + + Worksheet where the data is found. + + Object + + Object + + + None + + + SourceRange + + Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used. + + Object + + Object + + + None + + + PivotRows + + Fields to set as rows in the PivotTable. + + Object + + Object + + + None + + + PivotData + + A hash table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP. + + Object + + Object + + + None + + + PivotColumns + + Fields to set as columns in the PivotTable. + + Object + + Object + + + None + + + PivotFilter + + Fields to use to filter in the PivotTable. + + Object + + Object + + + None + + + PivotDataToColumn + + If there are multiple data items in a PivotTable, by default they are shown on separate rows; this switch makes them separate columns. + + + SwitchParameter + + + False + + + PivotTotals + + Define whether totals should be added to rows, columns neither, or both (the default is both). + + String + + String + + + Both + + + NoTotalsInPivot + + Included for compatibility - equivalent to -PivotTotals "None". + + + SwitchParameter + + + False + + + GroupDateRow + + The name of a row field which should be grouped by parts of the date/time (ignored if GroupDateRow is not specified) + + String + + String + + + None + + + GroupDateColumn + + The name of a Column field which should be grouped by parts of the date/time (ignored if GroupDateRow is not specified) + + String + + String + + + None + + + GroupDatePart + + The Part(s) of the date to use in the grouping (ignored if GroupDateRow is not specified) + + + Years + Quarters + Months + Days + Hours + Minutes + Seconds + + eDateGroupBy[] + + eDateGroupBy[] + + + None + + + GroupNumericRow + + The name of a row field which should be grouped by Number (e.g. 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericColumn + + The name of a Column field which should be grouped by Number (e.g. 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericMin + + The starting point for grouping + + Double + + Double + + + 0 + + + GroupNumericMax + + The endpoint for grouping + + Double + + Double + + + 1.79769313486232E+308 + + + GroupNumericInterval + + The interval for grouping + + Double + + Double + + + 100 + + + PivotNumberFormat + + Number format to apply to the data cells in the PivotTable. + + String + + String + + + None + + + PivotTableStyle + + Apply a table style to the PivotTable. + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + None + + + IncludePivotChart + + If specified, a chart will be included. + + + SwitchParameter + + + False + + + ChartTitle + + Optional title for the pivot chart, by default the title omitted. + + String + + String + + + None + + + ChartHeight + + Height of the chart in Pixels (400 by default). + + Int32 + + Int32 + + + 400 + + + ChartWidth + + Width of the chart in Pixels (600 by default). + + Int32 + + Int32 + + + 600 + + + ChartRow + + Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart (default is 0, chart starts at top edge of row 1). + + Int32 + + Int32 + + + 0 + + + ChartColumn + + Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart (default is 4, chart starts at left edge of column E). + + Int32 + + Int32 + + + 4 + + + ChartRowOffSetPixels + + Vertical offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartColumnOffSetPixels + + Horizontal offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartType + + Type of chart; defaults to "Pie". + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + Pie + + + NoLegend + + If specified hides the chart legend. + + + SwitchParameter + + + False + + + ShowCategory + + If specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type. + + + SwitchParameter + + + False + + + ShowPercent + + If specified attaches percentages to slices in a pie chart. + + + SwitchParameter + + + False + + + Activate + + If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified. + + + SwitchParameter + + + False + + + PassThru + + Return the PivotTable so it can be customized. + + + SwitchParameter + + + False + + + + + + PivotTableName + + Name for the new PivotTable - this will be the name of a sheet in the Workbook. + + String + + String + + + None + + + Address + + By default, a PivotTable will be created on its own sheet, but it can be created on an existing sheet by giving the address where the top left corner of the table should go. (Allow two rows for the filter if one is used.) + + ExcelAddressBase + + ExcelAddressBase + + + None + + + ExcelPackage + + An Excel-package object for the workbook. + + Object + + Object + + + None + + + SourceWorkSheet + + Worksheet where the data is found. + + Object + + Object + + + None + + + SourceRange + + Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used. + + Object + + Object + + + None + + + PivotRows + + Fields to set as rows in the PivotTable. + + Object + + Object + + + None + + + PivotData + + A hash table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP. + + Object + + Object + + + None + + + PivotColumns + + Fields to set as columns in the PivotTable. + + Object + + Object + + + None + + + PivotFilter + + Fields to use to filter in the PivotTable. + + Object + + Object + + + None + + + PivotDataToColumn + + If there are multiple data items in a PivotTable, by default they are shown on separate rows; this switch makes them separate columns. + + SwitchParameter + + SwitchParameter + + + False + + + PivotTotals + + Define whether totals should be added to rows, columns neither, or both (the default is both). + + String + + String + + + Both + + + NoTotalsInPivot + + Included for compatibility - equivalent to -PivotTotals "None". + + SwitchParameter + + SwitchParameter + + + False + + + GroupDateRow + + The name of a row field which should be grouped by parts of the date/time (ignored if GroupDateRow is not specified) + + String + + String + + + None + + + GroupDateColumn + + The name of a Column field which should be grouped by parts of the date/time (ignored if GroupDateRow is not specified) + + String + + String + + + None + + + GroupDatePart + + The Part(s) of the date to use in the grouping (ignored if GroupDateRow is not specified) + + eDateGroupBy[] + + eDateGroupBy[] + + + None + + + GroupNumericRow + + The name of a row field which should be grouped by Number (e.g. 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericColumn + + The name of a Column field which should be grouped by Number (e.g. 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericMin + + The starting point for grouping + + Double + + Double + + + 0 + + + GroupNumericMax + + The endpoint for grouping + + Double + + Double + + + 1.79769313486232E+308 + + + GroupNumericInterval + + The interval for grouping + + Double + + Double + + + 100 + + + PivotNumberFormat + + Number format to apply to the data cells in the PivotTable. + + String + + String + + + None + + + PivotTableStyle + + Apply a table style to the PivotTable. + + TableStyles + + TableStyles + + + None + + + PivotChartDefinition + + Use a chart definition instead of specifying chart settings one by one. + + Object + + Object + + + None + + + IncludePivotChart + + If specified, a chart will be included. + + SwitchParameter + + SwitchParameter + + + False + + + ChartTitle + + Optional title for the pivot chart, by default the title omitted. + + String + + String + + + None + + + ChartHeight + + Height of the chart in Pixels (400 by default). + + Int32 + + Int32 + + + 400 + + + ChartWidth + + Width of the chart in Pixels (600 by default). + + Int32 + + Int32 + + + 600 + + + ChartRow + + Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart (default is 0, chart starts at top edge of row 1). + + Int32 + + Int32 + + + 0 + + + ChartColumn + + Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart (default is 4, chart starts at left edge of column E). + + Int32 + + Int32 + + + 4 + + + ChartRowOffSetPixels + + Vertical offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartColumnOffSetPixels + + Horizontal offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartType + + Type of chart; defaults to "Pie". + + eChartType + + eChartType + + + Pie + + + NoLegend + + If specified hides the chart legend. + + SwitchParameter + + SwitchParameter + + + False + + + ShowCategory + + If specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type. + + SwitchParameter + + SwitchParameter + + + False + + + ShowPercent + + If specified attaches percentages to slices in a pie chart. + + SwitchParameter + + SwitchParameter + + + False + + + Activate + + If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified. + + SwitchParameter + + SwitchParameter + + + False + + + PassThru + + Return the PivotTable so it can be customized. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.Table.PivotTable.ExcelPivotTable + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $excel = Get-Service | Export-Excel -Path test.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName ServiceTable -Title "Services on $Env:COMPUTERNAME" + Add-PivotTable -ExcelPackage $excel -PivotTableName ServiceSummary -SourceRange $excel.Workbook.Worksheets\[1\].Tables\[0\].Address -PivotRows Status -PivotData Name -NoTotalsInPivot -Activate + Close-ExcelPackage $excel -Show + + This exports data to new workbook and creates a table with the data in it. + The Pivot table is added on its own page, the table created in the first command is used as the source for the PivotTable; which counts the service names in for each Status. + At the end the Pivot page is made active. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $chartdef = New-ExcelChartDefinition -Title "Gross and net by city and product" -ChartType ColumnClustered ` + -Column 11 -Width 500 -Height 360 -YMajorUnit 500 -YMinorUnit 100 -YAxisNumberformat "$#,##0" -LegendPosition Bottom + $excel = ConvertFrom-Csv @" +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 +"@ | Export-Excel -Path "test.xlsx" -TableStyle Medium13 -tablename "RawData" -PassThru + Add-PivotTable -PivotTableName Sales -Address $excel.Workbook.Worksheets[1].Cells["F1"] ` + -SourceWorkSheet $excel.Workbook.Worksheets[1] -PivotRows City -PivotColumns Product -PivotData @{Gross="Sum";Net="Sum"} ` + -PivotNumberFormat "$#,##0.00" -PivotTotals Both -PivotTableStyle Medium12 -PivotChartDefinition $chartdef + Close-ExcelPackage -show $excel + + This script starts by defining a chart. + Then it exports some data to an XLSX file and keeps the file open. + The next step is to add the pivot table, normally this would be on its own sheet in the workbook, but here -Address is specified to place it beside the data. + The Add-Pivot table is given the chart definition and told to create a tale using the City field to create rows, the Product field to create columns and the data should be the sum of the gross field and the sum of the net field; grand totals for both gross and net are included for rows (Cities) and columns (Products) and the data is explicitly formatted as a currency. + Note that in the chart definition the number format for the axis does not include any fraction part. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS> $excel = Convertfrom-csv @" +Location,OrderDate,quantity +Boston,1/1/2017,100 +New York,1/21/2017,200 +Boston,1/11/2017,300 +New York,1/9/2017,400 +Boston,1/18/2017,500 +Boston,2/1/2017,600 +New York,2/21/2017,700 +New York,2/11/2017,800 +Boston,2/9/2017,900 +Boston,2/18/2017,1000 +New York,1/1/2018,100 +Boston,1/21/2018,200 +New York,1/11/2018,300 +Boston,1/9/2018,400 +New York,1/18/2018,500 +Boston,2/1/2018,600 +Boston,2/21/2018,700 +New York,2/11/2018,800 +New York,2/9/2018,900 +Boston,2/18/2018,1000 +"@ | Select-Object -Property @{n="OrderDate";e={[datetime]::ParseExact($_.OrderDate,"M/d/yyyy",(Get-Culture))}}, + Location, Quantity | Export-Excel "test2.xlsx" -PassThru -AutoSize + Set-ExcelColumn -Worksheet $excel.sheet1 -Column 1 -NumberFormat 'Short Date' + $pt = Add-PivotTable -PassThru -PivotTableName "ByDate" -Address $excel.Sheet1.cells["F1"] -SourceWorkSheet $excel.Sheet1 -PivotRows location,orderdate -PivotData @{'quantity'='sum'} -GroupDateRow orderdate -GroupDatePart 'Months,Years' -PivotTotals None + $pt.RowFields[0].SubtotalTop=$false + $pt.RowFields[0].Compact=$false + Close-ExcelPackage $excel -Show + + Here the data contains dates formatted as strings using US format. + These are converted to DateTime objects before being exported to Excel; the "OrderDate" column is formatted with the local short-date style. + Then the PivotTable is added; it groups information by date and location, the date is split into years and then months. + No grand totals are displayed. + The Pivot table object is caught in a variable, and the "Location" column has its subtotal moved from the top to the bottom of each location section, and the "Compact" option is disabled to prevent "Year" moving into the same column as location. + Finally the workbook is saved and shown in Excel. + + + + + + Online Version: + + + + + + + Add-WorkSheet + Add + WorkSheet + + Adds a worksheet to an existing workbook. + + + + If the named worksheet already exists, the -Clearsheet parameter decides whether it should be deleted and a new one returned, or if not specified the existing sheet will be returned. + By default the sheet is created at the end of the work book, the -MoveXXXX switches allow the sheet to be [re]positioned at the start or before or after another sheet. + A new sheet will only be made the default sheet when excel opens if -Activate is specified. + + + + Add-WorkSheet + + ExcelPackage + + An object representing an Excel Package. + + ExcelPackage + + ExcelPackage + + + None + + + WorksheetName + + The name of the worksheet, 'Sheet1' by default. + + String + + String + + + None + + + ClearSheet + + If the worksheet already exists, by default it will returned, unless -ClearSheet is specified in which case it will be deleted and re-created. + + + SwitchParameter + + + False + + + MoveToStart + + If specified, the worksheet will be moved to the start of the workbook. + MoveToStart takes precedence over MoveToEnd, Movebefore and MoveAfter if more than one is specified. + + + SwitchParameter + + + False + + + MoveToEnd + + If specified, the worksheet will be moved to the end of the workbook. + (This is the default position for newly created sheets, but it can be used to move existing sheets.) + + + SwitchParameter + + + False + + + MoveBefore + + If specified, the worksheet will be moved before the nominated one (which can be an index starting from 1, or a name). + MoveBefore takes precedence over MoveAfter if both are specified. + + Object + + Object + + + None + + + MoveAfter + + If specified, the worksheet will be moved after the nominated one (which can be an index starting from 1, or a name or *). + If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + + Object + + Object + + + None + + + Activate + + If there is already content in the workbook the new sheet will not be active UNLESS Activate is specified. + + + SwitchParameter + + + False + + + CopySource + + If worksheet is provided as a copy source the new worksheet will be a copy of it. The source can be in the same workbook, or in a different file. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + NoClobber + + Ignored but retained for backwards compatibility. + + + SwitchParameter + + + False + + + + Add-WorkSheet + + ExcelWorkbook + + An Excel Workbook to which the Worksheet will be added - a Package contains one Workbook, so you can use whichever fits at the time. + + ExcelWorkbook + + ExcelWorkbook + + + None + + + WorksheetName + + The name of the worksheet, 'Sheet1' by default. + + String + + String + + + None + + + ClearSheet + + If the worksheet already exists, by default it will returned, unless -ClearSheet is specified in which case it will be deleted and re-created. + + + SwitchParameter + + + False + + + MoveToStart + + If specified, the worksheet will be moved to the start of the workbook. + MoveToStart takes precedence over MoveToEnd, Movebefore and MoveAfter if more than one is specified. + + + SwitchParameter + + + False + + + MoveToEnd + + If specified, the worksheet will be moved to the end of the workbook. + (This is the default position for newly created sheets, but it can be used to move existing sheets.) + + + SwitchParameter + + + False + + + MoveBefore + + If specified, the worksheet will be moved before the nominated one (which can be an index starting from 1, or a name). + MoveBefore takes precedence over MoveAfter if both are specified. + + Object + + Object + + + None + + + MoveAfter + + If specified, the worksheet will be moved after the nominated one (which can be an index starting from 1, or a name or *). + If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + + Object + + Object + + + None + + + Activate + + If there is already content in the workbook the new sheet will not be active UNLESS Activate is specified. + + + SwitchParameter + + + False + + + CopySource + + If worksheet is provided as a copy source the new worksheet will be a copy of it. The source can be in the same workbook, or in a different file. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + NoClobber + + Ignored but retained for backwards compatibility. + + + SwitchParameter + + + False + + + + + + ExcelPackage + + An object representing an Excel Package. + + ExcelPackage + + ExcelPackage + + + None + + + ExcelWorkbook + + An Excel Workbook to which the Worksheet will be added - a Package contains one Workbook, so you can use whichever fits at the time. + + ExcelWorkbook + + ExcelWorkbook + + + None + + + WorksheetName + + The name of the worksheet, 'Sheet1' by default. + + String + + String + + + None + + + ClearSheet + + If the worksheet already exists, by default it will returned, unless -ClearSheet is specified in which case it will be deleted and re-created. + + SwitchParameter + + SwitchParameter + + + False + + + MoveToStart + + If specified, the worksheet will be moved to the start of the workbook. + MoveToStart takes precedence over MoveToEnd, Movebefore and MoveAfter if more than one is specified. + + SwitchParameter + + SwitchParameter + + + False + + + MoveToEnd + + If specified, the worksheet will be moved to the end of the workbook. + (This is the default position for newly created sheets, but it can be used to move existing sheets.) + + SwitchParameter + + SwitchParameter + + + False + + + MoveBefore + + If specified, the worksheet will be moved before the nominated one (which can be an index starting from 1, or a name). + MoveBefore takes precedence over MoveAfter if both are specified. + + Object + + Object + + + None + + + MoveAfter + + If specified, the worksheet will be moved after the nominated one (which can be an index starting from 1, or a name or *). + If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + + Object + + Object + + + None + + + Activate + + If there is already content in the workbook the new sheet will not be active UNLESS Activate is specified. + + SwitchParameter + + SwitchParameter + + + False + + + CopySource + + If worksheet is provided as a copy source the new worksheet will be a copy of it. The source can be in the same workbook, or in a different file. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + NoClobber + + Ignored but retained for backwards compatibility. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.ExcelWorksheet + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $WorksheetActors = $ExcelPackage | Add-WorkSheet -WorkSheetname Actors + + $ExcelPackage holds an Excel package object (returned by Open-ExcelPackage, or Export-Excel -passthru). This command will add a sheet named 'Actors', or return the sheet if it exists, and the result is stored in $WorkSheetActors. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $WorksheetActors = Add-WorkSheet -ExcelPackage $ExcelPackage -WorkSheetname "Actors" -ClearSheet -MoveToStart + + This time the Excel package object is passed as a parameter instead of piped. + If the 'Actors' sheet already exists it is deleted and re-created. + The new sheet will be created last in the workbook, and -MoveToStart Moves it to the start. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> $null = Add-WorkSheet -ExcelWorkbook $wb -WorkSheetname $DestinationName -CopySource $sourceWs -Activate + + This time a workbook is used instead of a package, and a worksheet is copied - $SourceWs is a worksheet object, which can come from the same workbook or a different one. + Here the new copy of the data is made the active sheet when the workbook is opened. + + + + + + Online Version: + + + + + + + Close-ExcelPackage + Close + ExcelPackage + + Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file in Excel as required. + + + + When working with an ExcelPackage object, the Workbook is held in memory and not saved until the .Save() method of the package is called. + Close-ExcelPackage saves and disposes of the Package object. + It can be called with -NoSave to abandon the file without saving, with a new "SaveAs" filename, and/or with a password to protect the file. And -Show will open the file in Excel; -Calculate will try to update the workbook, although not everything can be recalculated + + + + Close-ExcelPackage + + ExcelPackage + + Package to close. + + ExcelPackage + + ExcelPackage + + + None + + + SaveAs + + Save file with a new name (ignored if -NoSave Specified). + + Object + + Object + + + None + + + Password + + Password to protect the file. + + String + + String + + + None + + + Show + + Open the file in Excel. + + + SwitchParameter + + + False + + + NoSave + + Abandon the file without saving. + + + SwitchParameter + + + False + + + Calculate + + Attempt to recalculation the workbook before saving + + + SwitchParameter + + + False + + + + + + ExcelPackage + + Package to close. + + ExcelPackage + + ExcelPackage + + + None + + + Show + + Open the file in Excel. + + SwitchParameter + + SwitchParameter + + + False + + + NoSave + + Abandon the file without saving. + + SwitchParameter + + SwitchParameter + + + False + + + SaveAs + + Save file with a new name (ignored if -NoSave Specified). + + Object + + Object + + + None + + + Password + + Password to protect the file. + + String + + String + + + None + + + Calculate + + Attempt to recalculation the workbook before saving + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + Close-ExcelPackage -show $excel + + $excel holds a package object, this saves the workbook and loads it into Excel. + + + + -------------------------- EXAMPLE 2 -------------------------- + Close-ExcelPackage -NoSave $excel + + $excel holds a package object, this disposes of it without writing it to disk. + + + + + + Online Version: + + + + + + + Compare-WorkSheet + Compare + WorkSheet + + Compares two worksheets and shows the differences. + + + + This command takes two file names, one or two worksheet names and a name for a "key" column. + It reads the worksheet from each file and decides the column names and builds a hashtable of the key-column values and the rows in which they appear. + It then uses PowerShell's Compare-Object command to compare the sheets (explicitly checking all the column names which have not been excluded). + For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison, otherwise identical rows at different positions in the file will not be considered a match. + We also add the name of the file and sheet in which the difference occurs. + If -BackgroundColor is specified the difference rows will be changed to that background in the orginal file. + + + + Compare-WorkSheet + + Referencefile + + First file to compare. + + Object + + Object + + + None + + + Differencefile + + Second file to compare. + + Object + + Object + + + None + + + WorkSheetName + + Name(s) of worksheets to compare. + + Object + + Object + + + Sheet1 + + + Property + + Properties to include in the comparison - supports wildcards, default is "*". + + Object + + Object + + + * + + + ExcludeProperty + + Properties to exclude from the comparison - supports wildcards. + + Object + + Object + + + None + + + Headername + + Specifies custom property names to use, instead of the values defined in the starting row of the sheet. + + String[] + + String[] + + + None + + + Startrow + + The row from where we start to import data: all rows above the start row are disregarded. By default, this is the first row. + + Int32 + + Int32 + + + 1 + + + AllDataBackgroundColor + + If specified, highlights all the cells - so you can make Equal cells one color, and Different cells another. + + Object + + Object + + + None + + + BackgroundColor + + If specified, highlights the rows with differences. + + Object + + Object + + + None + + + TabColor + + If specified identifies the tabs which contain difference rows (ignored if -BackgroundColor is omitted). + + Object + + Object + + + None + + + Key + + Name of a column which is unique and will be used to add a row to the DIFF object, defaults to "Name". + + Object + + Object + + + Name + + + FontColor + + If specified, highlights the DIFF columns in rows which have the same key. + + Object + + Object + + + None + + + Show + + If specified, opens the Excel workbooks instead of outputting the diff to the console (unless -PassThru is also specified). + + + SwitchParameter + + + False + + + GridView + + If specified, the command tries to the show the DIFF in a Grid-View and not on the console (unless-PassThru is also specified). This works best with few columns selected, and requires a key. + + + SwitchParameter + + + False + + + PassThru + + If specified a full set of DIFF data is returned without filtering to the specified properties. + + + SwitchParameter + + + False + + + IncludeEqual + + If specified the result will include equal rows as well. By default only different rows are returned. + + + SwitchParameter + + + False + + + ExcludeDifferent + + If specified, the result includes only the rows where both are equal. + + + SwitchParameter + + + False + + + + Compare-WorkSheet + + Referencefile + + First file to compare. + + Object + + Object + + + None + + + Differencefile + + Second file to compare. + + Object + + Object + + + None + + + WorkSheetName + + Name(s) of worksheets to compare. + + Object + + Object + + + Sheet1 + + + Property + + Properties to include in the comparison - supports wildcards, default is "*". + + Object + + Object + + + * + + + ExcludeProperty + + Properties to exclude from the comparison - supports wildcards. + + Object + + Object + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3 ...) instead of the using the values the starting row of the sheet. + + + SwitchParameter + + + False + + + Startrow + + The row from where we start to import data: all rows above the start row are disregarded. By default, this is the first row. + + Int32 + + Int32 + + + 1 + + + AllDataBackgroundColor + + If specified, highlights all the cells - so you can make Equal cells one color, and Different cells another. + + Object + + Object + + + None + + + BackgroundColor + + If specified, highlights the rows with differences. + + Object + + Object + + + None + + + TabColor + + If specified identifies the tabs which contain difference rows (ignored if -BackgroundColor is omitted). + + Object + + Object + + + None + + + Key + + Name of a column which is unique and will be used to add a row to the DIFF object, defaults to "Name". + + Object + + Object + + + Name + + + FontColor + + If specified, highlights the DIFF columns in rows which have the same key. + + Object + + Object + + + None + + + Show + + If specified, opens the Excel workbooks instead of outputting the diff to the console (unless -PassThru is also specified). + + + SwitchParameter + + + False + + + GridView + + If specified, the command tries to the show the DIFF in a Grid-View and not on the console (unless-PassThru is also specified). This works best with few columns selected, and requires a key. + + + SwitchParameter + + + False + + + PassThru + + If specified a full set of DIFF data is returned without filtering to the specified properties. + + + SwitchParameter + + + False + + + IncludeEqual + + If specified the result will include equal rows as well. By default only different rows are returned. + + + SwitchParameter + + + False + + + ExcludeDifferent + + If specified, the result includes only the rows where both are equal. + + + SwitchParameter + + + False + + + + + + Referencefile + + First file to compare. + + Object + + Object + + + None + + + Differencefile + + Second file to compare. + + Object + + Object + + + None + + + WorkSheetName + + Name(s) of worksheets to compare. + + Object + + Object + + + Sheet1 + + + Property + + Properties to include in the comparison - supports wildcards, default is "*". + + Object + + Object + + + * + + + ExcludeProperty + + Properties to exclude from the comparison - supports wildcards. + + Object + + Object + + + None + + + Headername + + Specifies custom property names to use, instead of the values defined in the starting row of the sheet. + + String[] + + String[] + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3 ...) instead of the using the values the starting row of the sheet. + + SwitchParameter + + SwitchParameter + + + False + + + Startrow + + The row from where we start to import data: all rows above the start row are disregarded. By default, this is the first row. + + Int32 + + Int32 + + + 1 + + + AllDataBackgroundColor + + If specified, highlights all the cells - so you can make Equal cells one color, and Different cells another. + + Object + + Object + + + None + + + BackgroundColor + + If specified, highlights the rows with differences. + + Object + + Object + + + None + + + TabColor + + If specified identifies the tabs which contain difference rows (ignored if -BackgroundColor is omitted). + + Object + + Object + + + None + + + Key + + Name of a column which is unique and will be used to add a row to the DIFF object, defaults to "Name". + + Object + + Object + + + Name + + + FontColor + + If specified, highlights the DIFF columns in rows which have the same key. + + Object + + Object + + + None + + + Show + + If specified, opens the Excel workbooks instead of outputting the diff to the console (unless -PassThru is also specified). + + SwitchParameter + + SwitchParameter + + + False + + + GridView + + If specified, the command tries to the show the DIFF in a Grid-View and not on the console (unless-PassThru is also specified). This works best with few columns selected, and requires a key. + + SwitchParameter + + SwitchParameter + + + False + + + PassThru + + If specified a full set of DIFF data is returned without filtering to the specified properties. + + SwitchParameter + + SwitchParameter + + + False + + + IncludeEqual + + If specified the result will include equal rows as well. By default only different rows are returned. + + SwitchParameter + + SwitchParameter + + + False + + + ExcludeDifferent + + If specified, the result includes only the rows where both are equal. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | Format-Table + + The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32_product to Export-Excel. + The command compares the "Products" pages in the two workbooks, but we don't want to register a difference if the software was installed on a different date or from a different place, and excluding Install* removes InstallDate and InstallSource. + This data doesn't have a "Name" column, so we specify the "IdentifyingNumber" column as the key. + The results will be presented as a table. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName Services -GridView + + This time two workbooks contain the result of redirecting the command Get-WmiObject -Class win32_service to Export-Excel. + Here the -Differencefile and -Referencefile parameter switches are assumed and the default setting for -Key ("Name") works for services. + This will display the differences between the "Services" sheets using a grid view + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen + + This version of the command outputs the differences between the "services" pages and highlights any different rows in the spreadsheet files. + + + + -------------------------- EXAMPLE 4 -------------------------- + PS\> Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show + + This example builds on the previous one: this time where two changed rows have the value in the "Name" column (the default value for -Key), this version adds highlighting of the changed cells in red; and then opens the Excel file. + + + + -------------------------- EXAMPLE 5 -------------------------- + PS\> Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description" + + This time the reference file and the difference file are the same file and two different sheets are used. + Because the tests include the machine name and time the test was run, the command specifies that a limited set of columns should be used. + + + + -------------------------- EXAMPLE 6 -------------------------- + PS\> Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent + + The "General" page in the two workbooks has a title and two unlabelled columns with a row each for CPU, Memory, Domain, Disk and so on. + So the command is told to start at row 2 in order to skip the title and given names for the columns: the first is "label" and the second "Value"; the label acts as the key. + This time we are interested in those rows which are the same in both sheets, and the result is displayed using grid view. + Note that grid view works best when the number of columns is small. + + + + -------------------------- EXAMPLE 7 -------------------------- + PS\>Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray + + This version of the previous command highlights all the cells in LightGray and then sets the changed rows back to white. + Only the unchanged rows are highlighted. + + + + + + Online Version: + + + + + + + Convert-ExcelRangeToImage + Convert + ExcelRangeToImage + + Gets the specified part of an Excel file and exports it as an image + + + + Excel allows charts to be exported directly to a file, but it can't do this with the rest of a sheet. To work round this, this function + * Opens a copy of Excel and loads a file + * Selects a worksheet and then a range of cells in that worksheet + * Copies the select to the clipboard + * Saves the clipboard contents as an image file (it will save as .JPG unless the file name ends .BMP or .PNG) + * Copies a single cell to the clipboard (to prevent the "you have put a lot in the clipboard" message appearing) + * Closes Excel + + Unlike most functions in the module it needs a local copy of Excel to be installed. EXAMPLES + + + + Convert-ExcelRangeToImage + + Path + + Path to the Excel file + + Object + + Object + + + None + + + WorkSheetname + + Worksheet name - if none is specified "Sheet1" will be assumed + + Object + + Object + + + Sheet1 + + + Range + + Range of cells within the sheet, e.g "A1:Z99" + + Object + + Object + + + None + + + Destination + + A bmp, png or jpg file where the result will be saved + + Object + + Object + + + "$pwd\temp.png" + + + Show + + If specified opens the image in the default viewer. + + + SwitchParameter + + + False + + + + + + Path + + Path to the Excel file + + Object + + Object + + + None + + + WorkSheetname + + Worksheet name - if none is specified "Sheet1" will be assumed + + Object + + Object + + + Sheet1 + + + Range + + Range of cells within the sheet, e.g "A1:Z99" + + Object + + Object + + + None + + + Destination + + A bmp, png or jpg file where the result will be saved + + Object + + Object + + + "$pwd\temp.png" + + + Show + + If specified opens the image in the default viewer. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + + Online Version: + + + + + + + ConvertFrom-ExcelSheet + ConvertFrom + ExcelSheet + + Exports Sheets from Excel Workbooks to CSV files. + + + + This command provides a convenient way to run Import-Excel @ImportParameters \| Select-Object @selectParameters \| export-Csv @ ExportParameters It can take the parameters -AsText , as used in Import-Excel, )Properties & -ExcludeProperties as used in Select-Object and -Append, -Delimiter and -Encoding as used in Export-CSV + + + + ConvertFrom-ExcelSheet + + Path + + The path to the .XLSX file which will be exported. + + String + + String + + + None + + + OutputPath + + The directory where the output file(s) will be created. The file name(s) will match the name of the workbook page which contained the data. + + String + + String + + + None + + + SheetName + + The name of a sheet to export, or a regular expression which is used to identify sheets + + String + + String + + + None + + + Encoding + + Sets the text encoding for the output data file; UTF8 bu default + + Encoding + + Encoding + + + None + + + Extension + + Sets the file extension for the exported data, defaults to CSV + + + .txt + .log + .csv + + String + + String + + + None + + + Delimiter + + Selects , or ; as the delimeter for the exported data - if not specified , is used by default. + + + ; + + + + String + + String + + + None + + + Property + + Specifies the properties to select. Wildcards are permitted - the default is "*". The value of the Property parameter can be a new calculated property, and follows the same pattern as Select-Item + + Object + + Object + + + None + + + ExcludeProperty + + Specifies the properties that to exclude from the export. Wildcards are permitted. This parameter is effective only when the command also includes the Property parameter. + + Object + + Object + + + None + + + AsText + + AsText allows selected columns to be returned as the text displayed in their cells, instead of their value. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Append + + Use this parameter to have the export add output to the end of the file. Without this parameter, the command replaces the file contents without warning. + + + SwitchParameter + + + False + + + + + + Append + + Use this parameter to have the export add output to the end of the file. Without this parameter, the command replaces the file contents without warning. + + SwitchParameter + + SwitchParameter + + + False + + + AsText + + AsText allows selected columns to be returned as the text displayed in their cells, instead of their value. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Delimiter + + Selects , or ; as the delimeter for the exported data - if not specified , is used by default. + + String + + String + + + None + + + Encoding + + Sets the text encoding for the output data file; UTF8 bu default + + Encoding + + Encoding + + + None + + + ExcludeProperty + + Specifies the properties that to exclude from the export. Wildcards are permitted. This parameter is effective only when the command also includes the Property parameter. + + Object + + Object + + + None + + + Extension + + Sets the file extension for the exported data, defaults to CSV + + String + + String + + + None + + + OutputPath + + The directory where the output file(s) will be created. The file name(s) will match the name of the workbook page which contained the data. + + String + + String + + + None + + + Path + + The path to the .XLSX file which will be exported. + + String + + String + + + None + + + Property + + Specifies the properties to select. Wildcards are permitted - the default is "*". The value of the Property parameter can be a new calculated property, and follows the same pattern as Select-Item + + Object + + Object + + + None + + + SheetName + + The name of a sheet to export, or a regular expression which is used to identify sheets + + String + + String + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> ConvertFrom-ExcelSheet Path .\__tests__\First10Races.xlsx -OutputPath .. -AsText GridPosition,date + + First10Races.xlsx contains information about Motor races. The race date and grid (starting) position are stored with custom formats. The command specifies the path to the file, and the directory to create the output file, and specifies that the columns "GridPosition" and "Date" should be treated as text to preserve their formatting + + + + -------------------------- Example 2 -------------------------- + PS C:\> ConvertFrom-ExcelSheet Path .\__tests__\First10Races.xlsx -OutputPath .. -AsText "GridPosition" -Property driver, @{n="date"; e={[datetime]::FromOADate($_.Date).tostring("#MM/dd/yyyy#")}} , FinishPosition, GridPosition + + This uses the same file as example 1. Because the race date has a custom format, it imports as a number, The requirement is to create a CSV file with the Driver, a specially formatted Date, FinishPostion and GridPostion (keeping its custom formatting). The command specifies the path to the file, and the directory to create the output file, specifies that the column "GridPosition" should be treated as text instead of a number, and the output properties should be Driver, a calculated "date" field, FinishPosition and GridPsition. FromOADate converts the dates used by Excel (Days since Jan 1 1900) to a datetime object. + + + + + + Online Version: + + + + + + + ConvertFrom-ExcelToSQLInsert + ConvertFrom + ExcelToSQLInsert + + Generate SQL insert statements from Excel spreadsheet. + + + + Generate SQL insert statements from Excel spreadsheet. + + + + ConvertFrom-ExcelToSQLInsert + + TableName + + Name of the target database table. + + Object + + Object + + + None + + + Path + + Path to an existing .XLSX file This parameter is passed to Import-Excel as is. + + Object + + Object + + + None + + + WorkSheetname + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. This parameter is passed to Import-Excel as is. + + Object + + Object + + + 1 + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 0 + + + Header + + Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. If you provide fewer header names than there is data in the worksheet, then only the data with a corresponding header name will be imported and the data without header name will be disregarded. If you provide more header names than there is data in the worksheet, then all data will be imported and all objects will have all the property names you defined in the header names. As such, the last properties will be blank as there is no data for them. + + String[] + + String[] + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. This switch is best used when you want to import the complete worksheet 'as is' and are not concerned with the property names. + + + SwitchParameter + + + False + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + ConvertEmptyStringsToNull + + If specified, cells without any data are replaced with NULL, instead of an empty string. This is to address behviors in certain DBMS where an empty string is insert as 0 for INT column, instead of a NULL value. + + + SwitchParameter + + + False + + + UseMSSQLSyntax + + + + + SwitchParameter + + + False + + + + + + TableName + + Name of the target database table. + + Object + + Object + + + None + + + Path + + Path to an existing .XLSX file This parameter is passed to Import-Excel as is. + + Object + + Object + + + None + + + WorkSheetname + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. This parameter is passed to Import-Excel as is. + + Object + + Object + + + 1 + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 0 + + + Header + + Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. If you provide fewer header names than there is data in the worksheet, then only the data with a corresponding header name will be imported and the data without header name will be disregarded. If you provide more header names than there is data in the worksheet, then all data will be imported and all objects will have all the property names you defined in the header names. As such, the last properties will be blank as there is no data for them. + + String[] + + String[] + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. This switch is best used when you want to import the complete worksheet 'as is' and are not concerned with the property names. + + SwitchParameter + + SwitchParameter + + + False + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + SwitchParameter + + SwitchParameter + + + False + + + ConvertEmptyStringsToNull + + If specified, cells without any data are replaced with NULL, instead of an empty string. This is to address behviors in certain DBMS where an empty string is insert as 0 for INT column, instead of a NULL value. + + SwitchParameter + + SwitchParameter + + + False + + + UseMSSQLSyntax + + + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + Generate SQL insert statements from Movies.xlsx file, leaving blank cells as empty strings: + +---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Sheet1 | +---------------------------------------------------------- +| A B C | +|1 Movie Name Year Rating | +|2 The Bodyguard 1992 9 | +|3 The Matrix 1999 8 | +|4 Skyfall 2012 9 | +|5 The Avengers 2012 | +---------------------------------------------------------- + +PS C:\> ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path 'C:\Movies.xlsx' +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Bodyguard', '1992', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Matrix', '1999', '8'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('Skyfall', '2012', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Avengers', '2012', ''); + + + + + + -------------------------- EXAMPLE 2 -------------------------- + Generate SQL insert statements from Movies.xlsx file, specify NULL instead of an empty string. + +---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Sheet1 | +---------------------------------------------------------- +| A B C | +|1 Movie Name Year Rating | +|2 The Bodyguard 1992 9 | +|3 The Matrix 1999 8 | +|4 Skyfall 2012 9 | +|5 The Avengers 2012 | +---------------------------------------------------------- + +PS C:\> ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path "C:\Movies.xlsx" -ConvertEmptyStringsToNull +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Bodyguard', '1992', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Matrix', '1999', '8'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('Skyfall', '2012', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Avengers', '2012', NULL); + + + + + + + + Online Version: + + + + + + + Copy-ExcelWorkSheet + Copy + ExcelWorkSheet + + Copies a worksheet between workbooks or within the same workbook. + + + + Copy-ExcelWorkSheet takes a Source object which is either a worksheet, or a package, Workbook or path, in which case the source worksheet can be specified by name or number (starting from 1). The destination worksheet can be explicitly named, or will follow the name of the source if no name is specified. The Destination workbook can be given as the path to an XLSx file, an ExcelPackage object or an ExcelWorkbook object. + + + + Copy-ExcelWorkSheet + + SourceObject + + An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data is found. + + Object + + Object + + + None + + + SourceWorkSheet + + Name or number (starting from 1) of the worksheet in the source workbook (defaults to 1). + + Object + + Object + + + 1 + + + DestinationWorkbook + + An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data should be copied. + + Object + + Object + + + None + + + DestinationWorksheet + + Name of the worksheet in the destination workbook; by default the same as the source worksheet's name. If the sheet exists it will be deleted and re-copied. + + Object + + Object + + + None + + + Show + + if the destination is an excel package or a path, launch excel and open the file on completion. + + + SwitchParameter + + + False + + + + + + SourceObject + + An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data is found. + + Object + + Object + + + None + + + SourceWorkSheet + + Name or number (starting from 1) of the worksheet in the source workbook (defaults to 1). + + Object + + Object + + + 1 + + + DestinationWorkbook + + An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data should be copied. + + Object + + Object + + + None + + + DestinationWorksheet + + Name of the worksheet in the destination workbook; by default the same as the source worksheet's name. If the sheet exists it will be deleted and re-copied. + + Object + + Object + + + None + + + Show + + if the destination is an excel package or a path, launch excel and open the file on completion. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + Copy-ExcelWorkSheet -SourceWorkbook Test1.xlsx -DestinationWorkbook Test2.xlsx + + This is the simplest version of the command: no source worksheet is specified so Copy-ExcelWorksheet uses the first sheet in the workbook No Destination sheet is specified so the new worksheet will be the same as the one which is being copied. + + + + -------------------------- EXAMPLE 2 -------------------------- + Copy-ExcelWorkSheet -SourceWorkbook Server1.xlsx -sourceWorksheet "Settings" -DestinationWorkbook Settings.xlsx -DestinationWorksheet "Server1" + + Here the Settings page from Server1's workbook is copied to the 'Server1" page of a "Settings" workbook. + + + + -------------------------- EXAMPLE 3 -------------------------- + $excel = Open-ExcelPackage .\test.xlsx + + C:\&gt; Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet "first" -DestinationWorkbook $excel -Show -DestinationWorksheet Duplicate This opens the workbook test.xlsx and copies the worksheet named "first" to a new worksheet named "Duplicate", because -Show is specified the file is saved and opened in Excel + + + + -------------------------- EXAMPLE 4 -------------------------- + $excel = Open-ExcelPackage .\test.xlsx + + C:\&gt; Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet 1 -DestinationWorkbook $excel -DestinationWorksheet Duplicate C:\&gt; Close-ExcelPackage $excel This is almost the same as the previous example, except source sheet is specified by position rather than name and because -Show is not specified, so other steps can be carried using the package object, at the end the file is saved by Close-ExcelPackage + + + + + + Online Version: + + + + + + + Expand-NumberFormat + Expand + NumberFormat + + Converts short names for number formats to the formatting strings used in Excel + + + + Where you can type a number format you can write, for example, 'Short-Date' and the module will translate it into the format string used by Excel. Some formats, like Short-Date, change when Excel loads (so date will use the local ordering of year, month and Day). Excel also changes how markers in the are presented different cultures "," is used in the format string to mean "local thousand seperator" but depending on the country "," or "." or " " may used as the thousand seperator. + + + + Expand-NumberFormat + + NumberFormat + + The format string to Expand + + Object + + Object + + + None + + + + + + NumberFormat + + The format string to Expand + + Object + + Object + + + None + + + + + + + System.String + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + Expand-NumberFormat percentage + + Returns "0.00%" + + + + -------------------------- EXAMPLE 2 -------------------------- + Expand-NumberFormat Currency + + Returns the currency format specified in the local regional settings, which may not be the same as Excel uses. + The regional settings set the currency symbol and then whether it is before or after the number and separated with a space or not; for negative numbers the number may be wrapped in parentheses or a - sign might appear before or after the number and symbol. + So this returns $\#,\#\#0.00;($\#,\#\#0.00) for English US, \#,\#\#0.00 €;€\#,\#\#0.00- for French. + Note some Eurozone countries write €1,23 and others 1,23€. In French the decimal point will be rendered as a "," and the thousand separator as a space. + + + + + + Online Version: + + + + + + + Export-Excel + Export + Excel + + Exports data to an Excel worksheet. + + + + Exports data to an Excel file and where possible tries to convert numbers in text fields so Excel recognizes them as numbers instead of text. After all: Excel is a spreadsheet program used for number manipulation and calculations. The parameter -NoNumberConversion * can be used if number conversion is not desired. + + + + Export-Excel + + Path + + Path to a new or existing .XLSX file. + + String + + String + + + None + + + TableTotalSettings + + A HashTable in the form of either + - ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> - + + ColumnName = @{ + Function = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> + Comment = $HoverComment + } + + if specified, -ShowTotal is not needed. + + Hashtable + + Hashtable + + + None + + + InputObject + + Date is usually piped into Export-Excel, but it also accepts data through the InputObject parameter + + Object + + Object + + + None + + + Calculate + + If specified, a recalculation of the worksheet will be requested before saving. + + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation; convenient for viewing the results instantly without having to search for the file first. + + + SwitchParameter + + + False + + + WorksheetName + + The name of a sheet within the workbook - "Sheet1" by default. + + String + + String + + + Sheet1 + + + Password + + Sets password protection on the workbook. + + String + + String + + + None + + + ClearSheet + + If specified Export-Excel will remove any existing worksheet with the selected name. + The default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place). + + + SwitchParameter + + + False + + + Append + + If specified data will be added to the end of an existing sheet, using the same column headings. + + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in the top left cell. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBold + + Sets the title in boldface type. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + IncludePivotTable + + Adds a PivotTable using the data in the worksheet. + + + SwitchParameter + + + False + + + PivotTableName + + If a PivotTable is created from command line parameters, specifies the name of the new sheet holding the pivot. Defaults to "WorksheetName-PivotTable". + + String + + String + + + None + + + PivotRows + + Name(s) of column(s) from the spreadsheet which will provide the Row name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotColumns + + Name(s) of columns from the spreadsheet which will provide the Column name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotData + + In a PivotTable created from command line parameters, the fields to use in the table body are given as a Hash-table in the form + ColumnName = Average\|Count\|CountNums\|Max\|Min\|Product\|None\|StdDev\|StdDevP\|Sum\|Var\|VarP. + + Object + + Object + + + None + + + PivotFilter + + Name(s) columns from the spreadsheet which will provide the Filter name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotDataToColumn + + If there are multiple datasets in a PivotTable, by default they are shown as separate rows under the given row heading; this switch makes them separate columns. + + + SwitchParameter + + + False + + + PivotTableDefinition + + Instead of describing a single PivotTable with multiple command-line parameters; you can use a HashTable in the form PivotTableName = Definition; + In this table Definition is itself a Hashtable with Sheet, PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values. The New-PivotTableDefinition command will create the definition from a command line. + + Hashtable + + Hashtable + + + None + + + IncludePivotChart + + Include a chart with the PivotTable - implies -IncludePivotTable. + + + SwitchParameter + + + False + + + ChartType + + The type for PivotChart (one of Excel's defined chart types). + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + Pie + + + NoLegend + + Exclude the legend from the PivotChart. + + + SwitchParameter + + + False + + + ShowCategory + + Add category labels to the PivotChart. + + + SwitchParameter + + + False + + + ShowPercent + + Add percentage labels to the PivotChart. + + + SwitchParameter + + + False + + + AutoSize + + Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell. + + + SwitchParameter + + + False + + + MaxAutoSizeRows + + Autosizing can be time consuming, so this sets a maximum number of rows to look at for the Autosize operation. Default is 1000; If 0 is specified ALL rows will be checked + + Object + + Object + + + 1000 + + + NoClobber + + Not used. Left in to avoid problems with older scripts, it may be removed in future versions. + + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the form RowNumber, ColumnNumber). + + Int32[] + + Int32[] + + + None + + + AutoFilter + + Enables the Excel filter on the complete header row, so users can easily sort, filter and/or search the data in the selected column. + + + SwitchParameter + + + False + + + BoldTopRow + + Makes the top row boldface. + + + SwitchParameter + + + False + + + NoHeader + + Specifies that field names should not be put at the top of columns. + + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + TableName + + Makes the data in the worksheet a table with a name, and applies a style to it. The name must not contain spaces. If the -Tablestyle parameter is specified without Tablename, "table1", "table2" etc. will be used. + + Object + + Object + + + None + + + TableStyle + + Selects the style for the named table - if the Tablename parameter is specified without giving a style, 'Medium6' is used as a default. + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + Medium6 + + + Barchart + + Creates a "quick" bar chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + PieChart + + Creates a "quick" pie chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + LineChart + + Creates a "quick" line chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + ColumnChart + + Creates a "quick" column chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + ExcelChartDefinition + + A hash-table containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-Pivot] charts. This can be created with the New-ExcelChartDefinition command. + + Object[] + + Object[] + + + None + + + HideSheet + + Name(s) of Sheet(s) to hide in the workbook, supports wildcards. If the selection would cause all sheets to be hidden, the sheet being worked on will be revealed. + + String[] + + String[] + + + None + + + UnHideSheet + + Name(s) of Sheet(s) to reveal in the workbook, supports wildcards. + + String[] + + String[] + + + None + + + MoveToStart + + If specified, the worksheet will be moved to the start of the workbook. + -MoveToStart takes precedence over -MoveToEnd, -Movebefore and -MoveAfter if more than one is specified. + + + SwitchParameter + + + False + + + MoveToEnd + + If specified, the worksheet will be moved to the end of the workbook. (This is the default position for newly created sheets, but the option can be specified to move existing sheets.) + + + SwitchParameter + + + False + + + MoveBefore + + If specified, the worksheet will be moved before the nominated one (which can be a position starting from 1, or a name). + -MoveBefore takes precedence over -MoveAfter if both are specified. + + Object + + Object + + + None + + + MoveAfter + + If specified, the worksheet will be moved after the nominated one (which can be a position starting from 1, or a name or *). + If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + + Object + + Object + + + None + + + KillExcel + + Closes Excel without stopping to ask if work should be saved - prevents errors writing to the file because Excel has it open. + + + SwitchParameter + + + False + + + AutoNameRange + + Makes each column a named range. + + + SwitchParameter + + + False + + + StartRow + + Row to start adding data. 1 by default. Row 1 will contain the title, if any is specifed. Then headers will appear (Unless -No header is specified) then the data appears. + + Int32 + + Int32 + + + 1 + + + StartColumn + + Column to start adding data - 1 by default. + + Int32 + + Int32 + + + 1 + + + PassThru + + If specified, Export-Excel returns an object representing the Excel package without saving the package first. To save, you must either use the Close-ExcelPackage command, or send the package object back to Export-Excel which will save and close the file, or use the object's .Save() or SaveAs() method. + + + SwitchParameter + + + False + + + Numberformat + + Formats all values that can be converted to a number to the format specified. For examples: + + '0' integer (not really needed unless you need to round numbers, Excel will use default cell properties). + '#' integer without displaying the number 0 in the cell. + '0.0' number with 1 decimal place. + '0.00' 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. + '0%' number with 2 decimal places and thousand-separator and money-symbol. + '[Blue]$#,##0.00;[Red]-$#,##0.00' + blue for positive numbers and red for negative numbers; Both proceeded by a '$' sign + + String + + String + + + General + + + ExcludeProperty + + Specifies properties which may exist in the target data but should not be placed on the worksheet. + + String[] + + String[] + + + None + + + NoAliasOrScriptPropeties + + Some objects in PowerShell duplicate existing properties by adding aliases, or have Script properties which may take a long time to return a value and slow the export down, if specified this option removes these properties + + + SwitchParameter + + + False + + + DisplayPropertySet + + Many (but not all) objects in PowerShell have a hidden property named psStandardmembers with a child property DefaultDisplayPropertySet ; this parameter reduces the properties exported to those in this set. + + + SwitchParameter + + + False + + + NoNumberConversion + + By default the command will convert all values to numbers if possible, but this isn't always desirable. -NoNumberConversion allows you to add exceptions for the conversion. + The only Wildcard allowed is * for all properties + + String[] + + String[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. When specific conditions are met the format is applied. + + Object[] + + Object[] + + + None + + + Style + + Takes style settings as a hash-table (which may be built with the New-ExcelStyle command) and applies them to the worksheet. If the hash-table contains a range the settings apply to the range, otherewise they apply to the whole sheet. + + Object[] + + Object[] + + + None + + + CellStyleSB + + A script block which is run at the end of the export to apply styles to cells (although it can be used for other purposes). The script block is given three paramaters; an object containing the current worksheet, the Total number of Rows and the number of the last column. + + ScriptBlock + + ScriptBlock + + + None + + + Activate + + If there is already content in the workbook, a new sheet will not be active UNLESS Activate is specified; when a PivotTable is created its sheet will be activated by this switch. + + + SwitchParameter + + + False + + + Now + + The -Now switch is a shortcut that automatically creates a temporary file, enables "AutoSize", "TableName" and "Show", and opens the file immediately. + + + SwitchParameter + + + False + + + ReturnRange + + If specified, Export-Excel returns the range of added cells in the format "A1:Z100". + + + SwitchParameter + + + False + + + PivotTotals + + By default, PivotTables have totals for each row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + + String + + String + + + Both + + + NoTotalsInPivot + + In a PivotTable created from command line parameters, prevents the addition of totals to rows and columns. + + + SwitchParameter + + + False + + + ReZip + + If specified, Export-Excel will expand the contents of the .XLSX file (which is multiple files in a zip archive) and rebuild it. + + + SwitchParameter + + + False + + + + Export-Excel + + TableTotalSettings + + A HashTable in the form of either + - ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> - + + ColumnName = @{ + Function = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> + Comment = $HoverComment + } + + if specified, -ShowTotal is not needed. + + Hashtable + + Hashtable + + + None + + + ExcelPackage + + An object representing an Excel Package - usually this is returned by specifying -PassThru allowing multiple commands to work on the same workbook without saving and reloading each time. + + ExcelPackage + + ExcelPackage + + + None + + + InputObject + + Date is usually piped into Export-Excel, but it also accepts data through the InputObject parameter + + Object + + Object + + + None + + + Calculate + + If specified, a recalculation of the worksheet will be requested before saving. + + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation; convenient for viewing the results instantly without having to search for the file first. + + + SwitchParameter + + + False + + + WorksheetName + + The name of a sheet within the workbook - "Sheet1" by default. + + String + + String + + + Sheet1 + + + Password + + Sets password protection on the workbook. + + String + + String + + + None + + + ClearSheet + + If specified Export-Excel will remove any existing worksheet with the selected name. + The default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place). + + + SwitchParameter + + + False + + + Append + + If specified data will be added to the end of an existing sheet, using the same column headings. + + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in the top left cell. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBold + + Sets the title in boldface type. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + IncludePivotTable + + Adds a PivotTable using the data in the worksheet. + + + SwitchParameter + + + False + + + PivotTableName + + If a PivotTable is created from command line parameters, specifies the name of the new sheet holding the pivot. Defaults to "WorksheetName-PivotTable". + + String + + String + + + None + + + PivotRows + + Name(s) of column(s) from the spreadsheet which will provide the Row name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotColumns + + Name(s) of columns from the spreadsheet which will provide the Column name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotData + + In a PivotTable created from command line parameters, the fields to use in the table body are given as a Hash-table in the form + ColumnName = Average\|Count\|CountNums\|Max\|Min\|Product\|None\|StdDev\|StdDevP\|Sum\|Var\|VarP. + + Object + + Object + + + None + + + PivotFilter + + Name(s) columns from the spreadsheet which will provide the Filter name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotDataToColumn + + If there are multiple datasets in a PivotTable, by default they are shown as separate rows under the given row heading; this switch makes them separate columns. + + + SwitchParameter + + + False + + + PivotTableDefinition + + Instead of describing a single PivotTable with multiple command-line parameters; you can use a HashTable in the form PivotTableName = Definition; + In this table Definition is itself a Hashtable with Sheet, PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values. The New-PivotTableDefinition command will create the definition from a command line. + + Hashtable + + Hashtable + + + None + + + IncludePivotChart + + Include a chart with the PivotTable - implies -IncludePivotTable. + + + SwitchParameter + + + False + + + ChartType + + The type for PivotChart (one of Excel's defined chart types). + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + Pie + + + NoLegend + + Exclude the legend from the PivotChart. + + + SwitchParameter + + + False + + + ShowCategory + + Add category labels to the PivotChart. + + + SwitchParameter + + + False + + + ShowPercent + + Add percentage labels to the PivotChart. + + + SwitchParameter + + + False + + + AutoSize + + Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell. + + + SwitchParameter + + + False + + + MaxAutoSizeRows + + Autosizing can be time consuming, so this sets a maximum number of rows to look at for the Autosize operation. Default is 1000; If 0 is specified ALL rows will be checked + + Object + + Object + + + 1000 + + + NoClobber + + Not used. Left in to avoid problems with older scripts, it may be removed in future versions. + + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the form RowNumber, ColumnNumber). + + Int32[] + + Int32[] + + + None + + + AutoFilter + + Enables the Excel filter on the complete header row, so users can easily sort, filter and/or search the data in the selected column. + + + SwitchParameter + + + False + + + BoldTopRow + + Makes the top row boldface. + + + SwitchParameter + + + False + + + NoHeader + + Specifies that field names should not be put at the top of columns. + + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + TableName + + Makes the data in the worksheet a table with a name, and applies a style to it. The name must not contain spaces. If the -Tablestyle parameter is specified without Tablename, "table1", "table2" etc. will be used. + + Object + + Object + + + None + + + TableStyle + + Selects the style for the named table - if the Tablename parameter is specified without giving a style, 'Medium6' is used as a default. + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + Medium6 + + + Barchart + + Creates a "quick" bar chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + PieChart + + Creates a "quick" pie chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + LineChart + + Creates a "quick" line chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + ColumnChart + + Creates a "quick" column chart using the first text column as labels and the first numeric column as values. + + + SwitchParameter + + + False + + + ExcelChartDefinition + + A hash-table containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-Pivot] charts. This can be created with the New-ExcelChartDefinition command. + + Object[] + + Object[] + + + None + + + HideSheet + + Name(s) of Sheet(s) to hide in the workbook, supports wildcards. If the selection would cause all sheets to be hidden, the sheet being worked on will be revealed. + + String[] + + String[] + + + None + + + UnHideSheet + + Name(s) of Sheet(s) to reveal in the workbook, supports wildcards. + + String[] + + String[] + + + None + + + MoveToStart + + If specified, the worksheet will be moved to the start of the workbook. + -MoveToStart takes precedence over -MoveToEnd, -Movebefore and -MoveAfter if more than one is specified. + + + SwitchParameter + + + False + + + MoveToEnd + + If specified, the worksheet will be moved to the end of the workbook. (This is the default position for newly created sheets, but the option can be specified to move existing sheets.) + + + SwitchParameter + + + False + + + MoveBefore + + If specified, the worksheet will be moved before the nominated one (which can be a position starting from 1, or a name). + -MoveBefore takes precedence over -MoveAfter if both are specified. + + Object + + Object + + + None + + + MoveAfter + + If specified, the worksheet will be moved after the nominated one (which can be a position starting from 1, or a name or *). + If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + + Object + + Object + + + None + + + KillExcel + + Closes Excel without stopping to ask if work should be saved - prevents errors writing to the file because Excel has it open. + + + SwitchParameter + + + False + + + AutoNameRange + + Makes each column a named range. + + + SwitchParameter + + + False + + + StartRow + + Row to start adding data. 1 by default. Row 1 will contain the title, if any is specifed. Then headers will appear (Unless -No header is specified) then the data appears. + + Int32 + + Int32 + + + 1 + + + StartColumn + + Column to start adding data - 1 by default. + + Int32 + + Int32 + + + 1 + + + PassThru + + If specified, Export-Excel returns an object representing the Excel package without saving the package first. To save, you must either use the Close-ExcelPackage command, or send the package object back to Export-Excel which will save and close the file, or use the object's .Save() or SaveAs() method. + + + SwitchParameter + + + False + + + Numberformat + + Formats all values that can be converted to a number to the format specified. For examples: + + '0' integer (not really needed unless you need to round numbers, Excel will use default cell properties). + '#' integer without displaying the number 0 in the cell. + '0.0' number with 1 decimal place. + '0.00' 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. + '0%' number with 2 decimal places and thousand-separator and money-symbol. + '[Blue]$#,##0.00;[Red]-$#,##0.00' + blue for positive numbers and red for negative numbers; Both proceeded by a '$' sign + + String + + String + + + General + + + ExcludeProperty + + Specifies properties which may exist in the target data but should not be placed on the worksheet. + + String[] + + String[] + + + None + + + NoAliasOrScriptPropeties + + Some objects in PowerShell duplicate existing properties by adding aliases, or have Script properties which may take a long time to return a value and slow the export down, if specified this option removes these properties + + + SwitchParameter + + + False + + + DisplayPropertySet + + Many (but not all) objects in PowerShell have a hidden property named psStandardmembers with a child property DefaultDisplayPropertySet ; this parameter reduces the properties exported to those in this set. + + + SwitchParameter + + + False + + + NoNumberConversion + + By default the command will convert all values to numbers if possible, but this isn't always desirable. -NoNumberConversion allows you to add exceptions for the conversion. + The only Wildcard allowed is * for all properties + + String[] + + String[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. When specific conditions are met the format is applied. + + Object[] + + Object[] + + + None + + + Style + + Takes style settings as a hash-table (which may be built with the New-ExcelStyle command) and applies them to the worksheet. If the hash-table contains a range the settings apply to the range, otherewise they apply to the whole sheet. + + Object[] + + Object[] + + + None + + + CellStyleSB + + A script block which is run at the end of the export to apply styles to cells (although it can be used for other purposes). The script block is given three paramaters; an object containing the current worksheet, the Total number of Rows and the number of the last column. + + ScriptBlock + + ScriptBlock + + + None + + + Activate + + If there is already content in the workbook, a new sheet will not be active UNLESS Activate is specified; when a PivotTable is created its sheet will be activated by this switch. + + + SwitchParameter + + + False + + + ReturnRange + + If specified, Export-Excel returns the range of added cells in the format "A1:Z100". + + + SwitchParameter + + + False + + + PivotTotals + + By default, PivotTables have totals for each row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + + String + + String + + + Both + + + NoTotalsInPivot + + In a PivotTable created from command line parameters, prevents the addition of totals to rows and columns. + + + SwitchParameter + + + False + + + ReZip + + If specified, Export-Excel will expand the contents of the .XLSX file (which is multiple files in a zip archive) and rebuild it. + + + SwitchParameter + + + False + + + + + + Path + + Path to a new or existing .XLSX file. + + String + + String + + + None + + + ExcelPackage + + An object representing an Excel Package - usually this is returned by specifying -PassThru allowing multiple commands to work on the same workbook without saving and reloading each time. + + ExcelPackage + + ExcelPackage + + + None + + + InputObject + + Date is usually piped into Export-Excel, but it also accepts data through the InputObject parameter + + Object + + Object + + + None + + + Calculate + + If specified, a recalculation of the worksheet will be requested before saving. + + SwitchParameter + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation; convenient for viewing the results instantly without having to search for the file first. + + SwitchParameter + + SwitchParameter + + + False + + + WorksheetName + + The name of a sheet within the workbook - "Sheet1" by default. + + String + + String + + + Sheet1 + + + Password + + Sets password protection on the workbook. + + String + + String + + + None + + + ClearSheet + + If specified Export-Excel will remove any existing worksheet with the selected name. + The default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place). + + SwitchParameter + + SwitchParameter + + + False + + + Append + + If specified data will be added to the end of an existing sheet, using the same column headings. + + SwitchParameter + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in the top left cell. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBold + + Sets the title in boldface type. + + SwitchParameter + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + IncludePivotTable + + Adds a PivotTable using the data in the worksheet. + + SwitchParameter + + SwitchParameter + + + False + + + PivotTableName + + If a PivotTable is created from command line parameters, specifies the name of the new sheet holding the pivot. Defaults to "WorksheetName-PivotTable". + + String + + String + + + None + + + PivotRows + + Name(s) of column(s) from the spreadsheet which will provide the Row name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotColumns + + Name(s) of columns from the spreadsheet which will provide the Column name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotData + + In a PivotTable created from command line parameters, the fields to use in the table body are given as a Hash-table in the form + ColumnName = Average\|Count\|CountNums\|Max\|Min\|Product\|None\|StdDev\|StdDevP\|Sum\|Var\|VarP. + + Object + + Object + + + None + + + PivotFilter + + Name(s) columns from the spreadsheet which will provide the Filter name(s) in a PivotTable created from command line parameters. + + String[] + + String[] + + + None + + + PivotDataToColumn + + If there are multiple datasets in a PivotTable, by default they are shown as separate rows under the given row heading; this switch makes them separate columns. + + SwitchParameter + + SwitchParameter + + + False + + + PivotTableDefinition + + Instead of describing a single PivotTable with multiple command-line parameters; you can use a HashTable in the form PivotTableName = Definition; + In this table Definition is itself a Hashtable with Sheet, PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values. The New-PivotTableDefinition command will create the definition from a command line. + + Hashtable + + Hashtable + + + None + + + IncludePivotChart + + Include a chart with the PivotTable - implies -IncludePivotTable. + + SwitchParameter + + SwitchParameter + + + False + + + ChartType + + The type for PivotChart (one of Excel's defined chart types). + + eChartType + + eChartType + + + Pie + + + NoLegend + + Exclude the legend from the PivotChart. + + SwitchParameter + + SwitchParameter + + + False + + + ShowCategory + + Add category labels to the PivotChart. + + SwitchParameter + + SwitchParameter + + + False + + + ShowPercent + + Add percentage labels to the PivotChart. + + SwitchParameter + + SwitchParameter + + + False + + + AutoSize + + Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell. + + SwitchParameter + + SwitchParameter + + + False + + + MaxAutoSizeRows + + Autosizing can be time consuming, so this sets a maximum number of rows to look at for the Autosize operation. Default is 1000; If 0 is specified ALL rows will be checked + + Object + + Object + + + 1000 + + + NoClobber + + Not used. Left in to avoid problems with older scripts, it may be removed in future versions. + + SwitchParameter + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + SwitchParameter + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + SwitchParameter + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + SwitchParameter + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the form RowNumber, ColumnNumber). + + Int32[] + + Int32[] + + + None + + + AutoFilter + + Enables the Excel filter on the complete header row, so users can easily sort, filter and/or search the data in the selected column. + + SwitchParameter + + SwitchParameter + + + False + + + BoldTopRow + + Makes the top row boldface. + + SwitchParameter + + SwitchParameter + + + False + + + NoHeader + + Specifies that field names should not be put at the top of columns. + + SwitchParameter + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + TableName + + Makes the data in the worksheet a table with a name, and applies a style to it. The name must not contain spaces. If the -Tablestyle parameter is specified without Tablename, "table1", "table2" etc. will be used. + + Object + + Object + + + None + + + TableStyle + + Selects the style for the named table - if the Tablename parameter is specified without giving a style, 'Medium6' is used as a default. + + TableStyles + + TableStyles + + + Medium6 + + + TableTotalSettings + + A HashTable in the form of either + - ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> - + + ColumnName = @{ + Function = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|<Custom Excel function starting with "="> + Comment = $HoverComment + } + + if specified, -ShowTotal is not needed. + + Hashtable + + Hashtable + + + None + + + Barchart + + Creates a "quick" bar chart using the first text column as labels and the first numeric column as values. + + SwitchParameter + + SwitchParameter + + + False + + + PieChart + + Creates a "quick" pie chart using the first text column as labels and the first numeric column as values. + + SwitchParameter + + SwitchParameter + + + False + + + LineChart + + Creates a "quick" line chart using the first text column as labels and the first numeric column as values. + + SwitchParameter + + SwitchParameter + + + False + + + ColumnChart + + Creates a "quick" column chart using the first text column as labels and the first numeric column as values. + + SwitchParameter + + SwitchParameter + + + False + + + ExcelChartDefinition + + A hash-table containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-Pivot] charts. This can be created with the New-ExcelChartDefinition command. + + Object[] + + Object[] + + + None + + + HideSheet + + Name(s) of Sheet(s) to hide in the workbook, supports wildcards. If the selection would cause all sheets to be hidden, the sheet being worked on will be revealed. + + String[] + + String[] + + + None + + + UnHideSheet + + Name(s) of Sheet(s) to reveal in the workbook, supports wildcards. + + String[] + + String[] + + + None + + + MoveToStart + + If specified, the worksheet will be moved to the start of the workbook. + -MoveToStart takes precedence over -MoveToEnd, -Movebefore and -MoveAfter if more than one is specified. + + SwitchParameter + + SwitchParameter + + + False + + + MoveToEnd + + If specified, the worksheet will be moved to the end of the workbook. (This is the default position for newly created sheets, but the option can be specified to move existing sheets.) + + SwitchParameter + + SwitchParameter + + + False + + + MoveBefore + + If specified, the worksheet will be moved before the nominated one (which can be a position starting from 1, or a name). + -MoveBefore takes precedence over -MoveAfter if both are specified. + + Object + + Object + + + None + + + MoveAfter + + If specified, the worksheet will be moved after the nominated one (which can be a position starting from 1, or a name or *). + If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + + Object + + Object + + + None + + + KillExcel + + Closes Excel without stopping to ask if work should be saved - prevents errors writing to the file because Excel has it open. + + SwitchParameter + + SwitchParameter + + + False + + + AutoNameRange + + Makes each column a named range. + + SwitchParameter + + SwitchParameter + + + False + + + StartRow + + Row to start adding data. 1 by default. Row 1 will contain the title, if any is specifed. Then headers will appear (Unless -No header is specified) then the data appears. + + Int32 + + Int32 + + + 1 + + + StartColumn + + Column to start adding data - 1 by default. + + Int32 + + Int32 + + + 1 + + + PassThru + + If specified, Export-Excel returns an object representing the Excel package without saving the package first. To save, you must either use the Close-ExcelPackage command, or send the package object back to Export-Excel which will save and close the file, or use the object's .Save() or SaveAs() method. + + SwitchParameter + + SwitchParameter + + + False + + + Numberformat + + Formats all values that can be converted to a number to the format specified. For examples: + + '0' integer (not really needed unless you need to round numbers, Excel will use default cell properties). + '#' integer without displaying the number 0 in the cell. + '0.0' number with 1 decimal place. + '0.00' 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. + '0%' number with 2 decimal places and thousand-separator and money-symbol. + '[Blue]$#,##0.00;[Red]-$#,##0.00' + blue for positive numbers and red for negative numbers; Both proceeded by a '$' sign + + String + + String + + + General + + + ExcludeProperty + + Specifies properties which may exist in the target data but should not be placed on the worksheet. + + String[] + + String[] + + + None + + + NoAliasOrScriptPropeties + + Some objects in PowerShell duplicate existing properties by adding aliases, or have Script properties which may take a long time to return a value and slow the export down, if specified this option removes these properties + + SwitchParameter + + SwitchParameter + + + False + + + DisplayPropertySet + + Many (but not all) objects in PowerShell have a hidden property named psStandardmembers with a child property DefaultDisplayPropertySet ; this parameter reduces the properties exported to those in this set. + + SwitchParameter + + SwitchParameter + + + False + + + NoNumberConversion + + By default the command will convert all values to numbers if possible, but this isn't always desirable. -NoNumberConversion allows you to add exceptions for the conversion. + The only Wildcard allowed is * for all properties + + String[] + + String[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. When specific conditions are met the format is applied. + + Object[] + + Object[] + + + None + + + Style + + Takes style settings as a hash-table (which may be built with the New-ExcelStyle command) and applies them to the worksheet. If the hash-table contains a range the settings apply to the range, otherewise they apply to the whole sheet. + + Object[] + + Object[] + + + None + + + CellStyleSB + + A script block which is run at the end of the export to apply styles to cells (although it can be used for other purposes). The script block is given three paramaters; an object containing the current worksheet, the Total number of Rows and the number of the last column. + + ScriptBlock + + ScriptBlock + + + None + + + Activate + + If there is already content in the workbook, a new sheet will not be active UNLESS Activate is specified; when a PivotTable is created its sheet will be activated by this switch. + + SwitchParameter + + SwitchParameter + + + False + + + Now + + The -Now switch is a shortcut that automatically creates a temporary file, enables "AutoSize", "TableName" and "Show", and opens the file immediately. + + SwitchParameter + + SwitchParameter + + + False + + + ReturnRange + + If specified, Export-Excel returns the range of added cells in the format "A1:Z100". + + SwitchParameter + + SwitchParameter + + + False + + + PivotTotals + + By default, PivotTables have totals for each row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + + String + + String + + + Both + + + NoTotalsInPivot + + In a PivotTable created from command line parameters, prevents the addition of totals to rows and columns. + + SwitchParameter + + SwitchParameter + + + False + + + ReZip + + If specified, Export-Excel will expand the contents of the .XLSX file (which is multiple files in a zip archive) and rebuild it. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.ExcelPackage + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Get-Process | Export-Excel .\Test.xlsx -show + + Export all the processes to the Excel file 'Test.xlsx' and open the file immediately. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> 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 numbers which use a thousand seperator and display to two decimal places. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> [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.xlsx" and tries to convert all values to numbers where possible except for "IPAddress" and "Number1", which are stored in the sheet 'as is', without being converted to a number. + + + + -------------------------- EXAMPLE 4 -------------------------- + PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> [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 5 -------------------------- + PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> 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 that will show cells with a value is greater than 525, with a background fill color of "LightPink" and the text in "DarkRed". + Where the condition is not met the color will be the default, black text on a white background. + + + + -------------------------- EXAMPLE 6 -------------------------- + PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> Get-Service | Select-Object -Property Name, Status, DisplayName, ServiceName | + Export-Excel @ExcelParams -ConditionalText $( + New-ConditionalText Stop DarkRed LightPink + New-ConditionalText Running Blue Cyan + ) + + Exports all services to an Excel sheet, setting a Conditional formatting rule that will set the background fill color to "LightPink" and the text color to "DarkRed" when the value contains the word "Stop". + If the value contains the word "Running" it will have a background fill color of "Cyan" and text colored 'Blue'. + If neither condition is met, the color will be the default, black text on a white background. + + + + -------------------------- EXAMPLE 7 -------------------------- + PS\> $r = Get-ChildItem C:\WINDOWS\system32 -File + +PS\> $TotalSettings = @{ + Name = "Count" + Extension = "=COUNTIF([Extension];`".exe`")" + Length = @{ + Function = "=SUMIF([Extension];`".exe`";[Length])" + Comment = "Sum of all exe sizes" + } + } + +PS\> $r | Export-Excel -TableName system32files -TableStyle Medium10 -TableTotalSettings $TotalSettings -Show + + Exports a list of files with a totals row with three calculated totals: + - Total count of names + - Count of files with the extension ".exe" + - Total size of all file with extension ".exe" and add a comment as to not be mistaken that is is the total size of all files + + + + -------------------------- EXAMPLE 8 -------------------------- + PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true + } +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> $Array = @() +PS\> $Obj1 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' +} + +PS\> $Obj2 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' +} + + PS\> $Obj3 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' + Member4 = 'Fourth' +} + +PS\> $Array = $Obj1, $Obj2, $Obj3 +PS\> $Array | Out-GridView -Title 'Not showing Member3 and Member4' +PS\> $Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorksheetName Numbers + + Updates the first object of the array by adding property 'Member3' and 'Member4'. Afterwards, all objects are exported to an Excel file and all column headers are visible. + + + + -------------------------- EXAMPLE 9 -------------------------- + PS\> Get-Process | Export-Excel .\test.xlsx -WorksheetName Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM + + + + + + -------------------------- EXAMPLE 10 -------------------------- + PS\> Get-Process | Export-Excel .\test.xlsx -WorksheetName Processes -ChartType PieExploded3D -IncludePivotChart -IncludePivotTable -Show -PivotRows Company -PivotData PM + + + + + + -------------------------- EXAMPLE 11 -------------------------- + PS\> Get-Service | Export-Excel 'c:\temp\test.xlsx' -Show -IncludePivotTable -PivotRows status -PivotData @{status='count'} + + + + + + -------------------------- EXAMPLE 12 -------------------------- + PS\> $pt = [ordered]@{} +PS\> $pt.pt1=@{ + SourceWorkSheet = 'Sheet1'; + PivotRows = 'Status' + PivotData = @{'Status'='count'} + IncludePivotChart = $true + ChartType = 'BarClustered3D' +} +PS\> $pt.pt2=@ + SourceWorkSheet = 'Sheet2'; + PivotRows = 'Company' + PivotData = @{'Company'='count'} + IncludePivotChart = $true + ChartType = 'PieExploded3D' +} +PS\> Remove-Item -Path .\test.xlsx +PS\> Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -AutoSize +PS\> Get-Process | Select-Object -Property Name,Company,Handles,CPU,VM | Export-Excel -Path .\test.xlsx -AutoSize -WorksheetName 'sheet2' +PS\> Export-Excel -Path .\test.xlsx -PivotTableDefinition $pt -Show + + This example defines two PivotTables. + Then it puts Service data on Sheet1 with one call to Export-Excel and Process Data on sheet2 with a second call to Export-Excel. + The third and final call adds the two PivotTables and opens the spreadsheet in Excel. + + + + -------------------------- EXAMPLE 13 -------------------------- + PS\> Remove-Item -Path .\test.xlsx +PS\> $excel = Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -PassThru +PS\> $excel.Workbook.Worksheets ["Sheet1"].Row(1).style.font.bold = $true +PS\> $excel.Workbook.Worksheets ["Sheet1"].Column(3 ).width = 29 +PS\> $excel.Workbook.Worksheets ["Sheet1"].Column(3 ).Style.wraptext = $true +PS\> $excel.Save() +PS\> $excel.Dispose() +PS\> Start-Process .\test.xlsx + + This example uses -PassThru. + It puts service information into sheet1 of the workbook and saves the ExcelPackage object in $Excel. + It then uses the package object to apply formatting, and then saves the workbook and disposes of the object, before loading the document in Excel. + Note: Other commands in the module remove the need to work directly with the package object in this way. + + + + -------------------------- EXAMPLE 14 -------------------------- + PS\> Remove-Item -Path .\test.xlsx -ErrorAction Ignore +PS\> $excel = Get-Process | Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | + Export-Excel -Path .\test.xlsx -ClearSheet -WorksheetName "Processes" -PassThru +PS\> $sheet = $excel.Workbook.Worksheets ["Processes"] +PS\> $sheet.Column(1) | Set-ExcelRange -Bold -AutoFit +PS\> $sheet.Column(2) | Set-ExcelRange -Width 29 -WrapText +PS\> $sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NFormat "#,###" +PS\> Set-ExcelRange -Address $sheet.Cells ["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" +PS\> Set-ExcelRange -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold +PS\> Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center +PS\> Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red +PS\> Add-ConditionalFormatting -WorkSheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red +PS\> foreach ($c in 5..9) {Set-ExcelRange -Address $sheet.Column($c) -AutoFit } +PS\> Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show + + This a more sophisticated version of the previous example showing different ways of using Set-ExcelRange, and also adding conditional formatting. + In the final command a PivotChart is added and the workbook is opened in Excel. + + + + -------------------------- EXAMPLE 15 -------------------------- + PS\> 0..360 | ForEach-Object {[pscustomobject][ordered]@{X=$_; Sinx="=Sin(Radians(x)) "} } | + Export-Excel -now -LineChart -AutoNameRange + + Creates a line chart showing the value of Sine(x) for values of X between 0 and 360 degrees. + + + + -------------------------- EXAMPLE 16 -------------------------- + PS\> Invoke-Sqlcmd -ServerInstance localhost\DEFAULT -Database AdventureWorks2014 -Query "select * from sys.tables" -OutputAs DataRows | + Export-Excel -Path .\SysTables_AdventureWorks2014.xlsx -WorksheetName Tables + + Runs a query against a SQL Server database and outputs the resulting rows as DataRows using the -OutputAs parameter. The results are then piped to the Export-Excel function. + NOTE: You need to install the SqlServer module from the PowerShell Gallery in order to get the -OutputAs parameter for the Invoke-Sqlcmd cmdlet. + + + + + + Online Version: + + + + https://github.com/dfinke/ImportExcel + https://github.com/dfinke/ImportExcel + + + + + + Get-ExcelSheetInfo + Get + ExcelSheetInfo + + Get worksheet names and their indices of an Excel workbook. + + + + The Get-ExcelSheetInfo cmdlet gets worksheet names and their indices of an Excel workbook. + + + + Get-ExcelSheetInfo + + Path + + Specifies the path to the Excel file. (This parameter is required.) + + Object + + Object + + + None + + + + + + Path + + Specifies the path to the Excel file. (This parameter is required.) + + Object + + Object + + + None + + + + + + + CHANGELOG 2016/01/07 Added Created by Johan Akerstrom ( https://github.com/CosmosKey (https://github.com/CosmosKey)\) + + + + + -------------------------- EXAMPLE 1 -------------------------- + Get-ExcelSheetInfo .\Test.xlsx + + + + + + + + Online Version: + + + + https://github.com/dfinke/ImportExcel + https://github.com/dfinke/ImportExcel + + + + + + Get-ExcelWorkbookInfo + Get + ExcelWorkbookInfo + + Retrieve information of an Excel workbook. + + + + The Get-ExcelWorkbookInfo cmdlet retrieves information (LastModifiedBy, LastPrinted, Created, Modified, ...) fron an Excel workbook. These are the same details that are visible in Windows Explorer when right clicking the Excel file, selecting Properties and check the Details tabpage. + + + + Get-ExcelWorkbookInfo + + Path + + Specifies the path to the Excel file. This parameter is required. + + String + + String + + + None + + + + + + Path + + Specifies the path to the Excel file. This parameter is required. + + String + + String + + + None + + + + + + + CHANGELOG 2016/01/07 Added Created by Johan Akerstrom ( https://github.com/CosmosKey (https://github.com/CosmosKey)\) + + + + + -------------------------- EXAMPLE 1 -------------------------- + Get-ExcelWorkbookInfo .\Test.xlsx + + CorePropertiesXml : \#document Title : Subject : Author : Konica Minolta User Comments : Keywords : LastModifiedBy : Bond, James (London) GBR LastPrinted : 2017-01-21T12:36:11Z Created : 17/01/2017 13:51:32 Category : Status : ExtendedPropertiesXml : \#document Application : Microsoft Excel HyperlinkBase : AppVersion : 14.0300 Company : Secret Service Manager : Modified : 10/02/2017 12:45:37 CustomPropertiesXml : \#document + + + + + + Online Version: + + + + https://github.com/dfinke/ImportExcel + https://github.com/dfinke/ImportExcel + + + + + + Import-Excel + Import + Excel + + Create custom objects from the rows in an Excel worksheet. + + + + The Import-Excel cmdlet creates custom objects from the rows in an Excel worksheet. Each row is represented as one object. + This is possible without installing Microsoft Excel by using the .NET library 'EPPLus.dll'. + By default, the property names of the objects are retrieved from the column headers. Because an object cannot have a blank property name, only columns with column headers will be imported. + If the default behavior is not desired and you want to import the complete worksheet 'as is', the parameter '-NoHeader' can be used. In case you want to provide your own property names, you can use the parameter '-HeaderName'. + + + + Import-Excel + + Path + + Specifies the path to the Excel file. + + String + + String + + + None + + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. + This switch is best used when you want to import the complete worksheet 'as is' and are not concerned with the property names. + + + SwitchParameter + + + False + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + Import-Excel + + Path + + Specifies the path to the Excel file. + + String + + String + + + None + + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + HeaderName + + Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. + If you provide fewer header names than there are columns of data in the worksheet, then data will only be imported from that number of columns - the others will be ignored. + If you provide more header names than there are columns of data in the worksheet, it will result in blank properties being added to the objects returned. + + String[] + + String[] + + + None + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + Import-Excel + + Path + + Specifies the path to the Excel file. + + String + + String + + + None + + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + Import-Excel + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + ExcelPackage + + Instead of specifying a path, provides an Excel Package object (from Open-ExcelPackage). Using this avoids re-reading the whole file when importing multiple parts of it. + To allow multiple read operations Import-Excel does NOT close the package, and you should use Close-ExcelPackage -noSave to close it. + + ExcelPackage + + ExcelPackage + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. + This switch is best used when you want to import the complete worksheet 'as is' and are not concerned with the property names. + + + SwitchParameter + + + False + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + Import-Excel + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + ExcelPackage + + Instead of specifying a path, provides an Excel Package object (from Open-ExcelPackage). Using this avoids re-reading the whole file when importing multiple parts of it. + To allow multiple read operations Import-Excel does NOT close the package, and you should use Close-ExcelPackage -noSave to close it. + + ExcelPackage + + ExcelPackage + + + None + + + HeaderName + + Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. + If you provide fewer header names than there are columns of data in the worksheet, then data will only be imported from that number of columns - the others will be ignored. + If you provide more header names than there are columns of data in the worksheet, it will result in blank properties being added to the objects returned. + + String[] + + String[] + + + None + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + Import-Excel + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + ExcelPackage + + Instead of specifying a path, provides an Excel Package object (from Open-ExcelPackage). Using this avoids re-reading the whole file when importing multiple parts of it. + To allow multiple read operations Import-Excel does NOT close the package, and you should use Close-ExcelPackage -noSave to close it. + + ExcelPackage + + ExcelPackage + + + None + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + + + Path + + Specifies the path to the Excel file. + + String + + String + + + None + + + ExcelPackage + + Instead of specifying a path, provides an Excel Package object (from Open-ExcelPackage). Using this avoids re-reading the whole file when importing multiple parts of it. + To allow multiple read operations Import-Excel does NOT close the package, and you should use Close-ExcelPackage -noSave to close it. + + ExcelPackage + + ExcelPackage + + + None + + + WorksheetName + + Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. + + String + + String + + + None + + + HeaderName + + Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. + If you provide fewer header names than there are columns of data in the worksheet, then data will only be imported from that number of columns - the others will be ignored. + If you provide more header names than there are columns of data in the worksheet, it will result in blank properties being added to the objects returned. + + String[] + + String[] + + + None + + + NoHeader + + Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow. + This switch is best used when you want to import the complete worksheet 'as is' and are not concerned with the property names. + + SwitchParameter + + SwitchParameter + + + False + + + StartRow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. + When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. If either is provided, the property names are automatically created and this row will be treated as a regular row containing data. + + Int32 + + Int32 + + + 1 + + + EndRow + + By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row. + + Int32 + + Int32 + + + 0 + + + StartColumn + + The number of the first column to read data from (1 by default). + + Int32 + + Int32 + + + 1 + + + EndColumn + + By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number. + + Int32 + + Int32 + + + 0 + + + DataOnly + + Import only rows and columns that contain data, empty rows and empty columns are not imported. + + SwitchParameter + + SwitchParameter + + + False + + + AsText + + Normally Import-Excel returns the Cell values. AsText allows selected columns to be returned as the text displayed in their cells. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + AsDate + + Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. (* is supported as a wildcard.) + + String[] + + String[] + + + None + + + Password + + Accepts a string that will be used to open a password protected Excel file. + + String + + String + + + None + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + ---------------------------------------------- +| File: Movies.xlsx - Sheet: Actors | +---------------------------------------------- +| A B C | +|1 First Name Address | +|2 Chuck Norris California | +|3 Jean-Claude Vandamme Brussels | +---------------------------------------------- + +PS C:> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors + +First Name: Chuck +Address : California + +First Name: Jean-Claude +Address : Brussels + + Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the column names defined in the first row. In case a column doesn't have a column header (usually in row 1 when '-StartRow' is not used), then the unnamed columns will be skipped and the data in those columns will not be imported. + Notice that column 'B' is not imported because there's no value in cell 'B1' that can be used as property name for the objects. + + + + -------------------------- EXAMPLE 2 -------------------------- + ---------------------------------------------- +| File: Movies.xlsx - Sheet: Actors | +---------------------------------------------- +| A B C | +|1 First Name Address | +|2 Chuck Norris California | +|3 Jean-Claude Vandamme Brussels | +---------------------------------------------- + +PS\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors -NoHeader + +P1: First Name +P2: +P3: Address + +P1: Chuck +P2: Norris +P3: California + +P1: Jean-Claude +P2: Vandamme +P3: Brussels + + Imports the complete Excel worksheet 'as is' by using the '-NoHeader' switch. One object is created for each row. The property names of the objects will be automatically generated (P1, P2, P3, ..). + Notice that the column header (row 1) is imported as an object too. + + + + -------------------------- EXAMPLE 3 -------------------------- + ---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Movies | +---------------------------------------------------------- +| A B C D | +|1 The Bodyguard 1992 9 | +|2 The Matrix 1999 8 | +|3 | +|4 Skyfall 2012 9 | +---------------------------------------------------------- + +PS\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Movies -HeaderName 'Movie name', 'Year', 'Rating', 'Genre' + +Movie name: The Bodyguard +Year : 1992 +Rating : 9 +Genre : + +Movie name: The Matrix +Year : 1999 +Rating : 8 +Genre : + +Movie name: +Year : +Rating : +Genre : + +Movie name: Skyfall +Year : 2012 +Rating : 9 +Genre : + + This imports data from an Excel worksheet, and as before one object is created for each row. The property names for the objects are defined in the parameter '-HeaderName'. The properties are named starting from the most left column (A) to the right. In case no value is present in one of the columns, that property will have an empty value. + Notice that empty rows are imported and that data for the property 'Genre' is not present in the worksheet. As such, the 'Genre' property will be blank for all objects. + + + + -------------------------- EXAMPLE 4 -------------------------- + ---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Movies | +---------------------------------------------------------- +| A B C D | +|1 The Bodyguard 1992 9 | +|2 The Matrix 1999 8 | +|3 | +|4 Skyfall 2012 9 | +---------------------------------------------------------- + +PS\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Movies -NoHeader -DataOnly + +P1: The Bodyguard +P2: 1992 +P3: 9 + +P1: The Matrix +P2: 1999 +P3: 8 + +P1: Skyfall +P2: 2012 +P3: 9 + + Import data from an Excel worksheet, and one object is created for each non-blank row. The property names of the objects (P1, P2, P3, ..) are automatically generated by using the switch '-NoHeader' . The switch '-DataOnly' will speed up the import because empty rows and empty columns are not imported. + Notice that empty rows and empty columns are not imported. + + + + -------------------------- EXAMPLE 5 -------------------------- + ---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Actors | +---------------------------------------------------------- +| A B C D | +|1 Chuck Norris California | +|2 | +|3 Jean-Claude Vandamme Brussels | +---------------------------------------------------------- + +PS\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors -DataOnly -HeaderName 'FirstName', 'SecondName', 'City' -StartRow 2 + +FirstName : Jean-Claude +SecondName: Vandamme +City : Brussels + + Import data from an Excel worksheet. One object is created for each row. The property names are provided with the '-HeaderName' parameter. The import will start from row 2 and empty columns and rows are not imported. + Notice that only 1 object is imported with only 3 properties. Column B and row 2 are empty and have been disregarded by using the switch '-DataOnly'. The property names have been named with the values provided with the parameter '-HeaderName'. Row number 1 with 'Chuck Norris' has not been imported, because we started the import from row 2 with the parameter '-StartRow 2'. + + + + -------------------------- EXAMPLE 6 -------------------------- + PS\> ,(Import-Excel -Path .\SysTables_AdventureWorks2014.xlsx) | + Write-SqlTableData -ServerInstance localhost\DEFAULT -Database BlankDB -SchemaName dbo -TableName MyNewTable_fromExcel -Force + + Imports data from an Excel file and pipes the result to the Write-SqlTableData command 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 -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. + + + + + + Online Version: + + + + https://github.com/dfinke/ImportExcel + https://github.com/dfinke/ImportExcel + + + + + + Join-Worksheet + Join + Worksheet + + Combines data on all the sheets in an Excel worksheet onto a single sheet. + + + + Join-Worksheet can work in two main ways, either Combining data which has the same layout from many pages into one, or Combining pages which have nothing in common. In the former case the header row is copied from the first sheet and, by default, each row of data is labelled with the name of the sheet it came from. + In the latter case -NoHeader is specified, and each copied block can have the sheet it came from placed above it as a title. + + + + Join-Worksheet + + Path + + Path to a new or existing .XLSX file. + + String + + String + + + None + + + WorkSheetName + + The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default. + + Object + + Object + + + Combined + + + Clearsheet + + If specified ,any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet. + + + SwitchParameter + + + False + + + NoHeader + + Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified. + + + SwitchParameter + + + False + + + FromLabel + + If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came from. FromLabel is the header for this column. If it is null or empty, the labels will be omitted. + + String + + String + + + From + + + LabelBlocks + + If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title. + + + SwitchParameter + + + False + + + AutoSize + + Sets the width of the Excel columns to display all the data in their cells. + + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the formRowNumber , ColumnNumber). + + Int32[] + + Int32[] + + + None + + + AutoFilter + + Enables the Excel filter on the headers of the combined sheet. + + + SwitchParameter + + + False + + + BoldTopRow + + Makes the top row boldface. + + + SwitchParameter + + + False + + + HideSource + + If specified, hides the sheets that the data is copied from. + + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in Cell A1. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + TitleBold + + Sets the title in boldface type. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + PivotTableDefinition + + Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or morePivotTable(s). + + Hashtable + + Hashtable + + + None + + + ExcelChartDefinition + + A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. + + Object[] + + Object[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. + + Object[] + + Object[] + + + None + + + AutoNameRange + + Makes each column a named range. + + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + ReturnRange + + If specified, returns the range of cells in the combined sheet, in the format "A1:Z100". + + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. + + + SwitchParameter + + + False + + + PassThru + + If specified, an object representing the unsaved Excel package will be returned, it then needs to be saved. + + + SwitchParameter + + + False + + + + Join-Worksheet + + Path + + Path to a new or existing .XLSX file. + + String + + String + + + None + + + WorkSheetName + + The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default. + + Object + + Object + + + Combined + + + Clearsheet + + If specified ,any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet. + + + SwitchParameter + + + False + + + NoHeader + + Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified. + + + SwitchParameter + + + False + + + FromLabel + + If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came from. FromLabel is the header for this column. If it is null or empty, the labels will be omitted. + + String + + String + + + From + + + LabelBlocks + + If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title. + + + SwitchParameter + + + False + + + AutoSize + + Sets the width of the Excel columns to display all the data in their cells. + + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the formRowNumber , ColumnNumber). + + Int32[] + + Int32[] + + + None + + + BoldTopRow + + Makes the top row boldface. + + + SwitchParameter + + + False + + + HideSource + + If specified, hides the sheets that the data is copied from. + + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in Cell A1. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + TitleBold + + Sets the title in boldface type. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + PivotTableDefinition + + Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or morePivotTable(s). + + Hashtable + + Hashtable + + + None + + + ExcelChartDefinition + + A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. + + Object[] + + Object[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. + + Object[] + + Object[] + + + None + + + AutoNameRange + + Makes each column a named range. + + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + TableName + + Makes the data in the worksheet a table with a name and applies a style to it. Name must not contain spaces. + + String + + String + + + None + + + TableStyle + + Selects the style for the named table - defaults to "Medium6". + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + Medium6 + + + ReturnRange + + If specified, returns the range of cells in the combined sheet, in the format "A1:Z100". + + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. + + + SwitchParameter + + + False + + + PassThru + + If specified, an object representing the unsaved Excel package will be returned, it then needs to be saved. + + + SwitchParameter + + + False + + + + Join-Worksheet + + ExcelPackage + + An object representing an Excel Package - either from Open-ExcelPackage or specifying -PassThru to Export-Excel. + + ExcelPackage + + ExcelPackage + + + None + + + WorkSheetName + + The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default. + + Object + + Object + + + Combined + + + Clearsheet + + If specified ,any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet. + + + SwitchParameter + + + False + + + NoHeader + + Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified. + + + SwitchParameter + + + False + + + FromLabel + + If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came from. FromLabel is the header for this column. If it is null or empty, the labels will be omitted. + + String + + String + + + From + + + LabelBlocks + + If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title. + + + SwitchParameter + + + False + + + AutoSize + + Sets the width of the Excel columns to display all the data in their cells. + + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the formRowNumber , ColumnNumber). + + Int32[] + + Int32[] + + + None + + + BoldTopRow + + Makes the top row boldface. + + + SwitchParameter + + + False + + + HideSource + + If specified, hides the sheets that the data is copied from. + + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in Cell A1. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + TitleBold + + Sets the title in boldface type. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + PivotTableDefinition + + Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or morePivotTable(s). + + Hashtable + + Hashtable + + + None + + + ExcelChartDefinition + + A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. + + Object[] + + Object[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. + + Object[] + + Object[] + + + None + + + AutoNameRange + + Makes each column a named range. + + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + TableName + + Makes the data in the worksheet a table with a name and applies a style to it. Name must not contain spaces. + + String + + String + + + None + + + TableStyle + + Selects the style for the named table - defaults to "Medium6". + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + Medium6 + + + ReturnRange + + If specified, returns the range of cells in the combined sheet, in the format "A1:Z100". + + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. + + + SwitchParameter + + + False + + + PassThru + + If specified, an object representing the unsaved Excel package will be returned, it then needs to be saved. + + + SwitchParameter + + + False + + + + Join-Worksheet + + ExcelPackage + + An object representing an Excel Package - either from Open-ExcelPackage or specifying -PassThru to Export-Excel. + + ExcelPackage + + ExcelPackage + + + None + + + WorkSheetName + + The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default. + + Object + + Object + + + Combined + + + Clearsheet + + If specified ,any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet. + + + SwitchParameter + + + False + + + NoHeader + + Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified. + + + SwitchParameter + + + False + + + FromLabel + + If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came from. FromLabel is the header for this column. If it is null or empty, the labels will be omitted. + + String + + String + + + From + + + LabelBlocks + + If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title. + + + SwitchParameter + + + False + + + AutoSize + + Sets the width of the Excel columns to display all the data in their cells. + + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the formRowNumber , ColumnNumber). + + Int32[] + + Int32[] + + + None + + + AutoFilter + + Enables the Excel filter on the headers of the combined sheet. + + + SwitchParameter + + + False + + + BoldTopRow + + Makes the top row boldface. + + + SwitchParameter + + + False + + + HideSource + + If specified, hides the sheets that the data is copied from. + + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in Cell A1. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + TitleBold + + Sets the title in boldface type. + + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + PivotTableDefinition + + Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or morePivotTable(s). + + Hashtable + + Hashtable + + + None + + + ExcelChartDefinition + + A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. + + Object[] + + Object[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. + + Object[] + + Object[] + + + None + + + AutoNameRange + + Makes each column a named range. + + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + ReturnRange + + If specified, returns the range of cells in the combined sheet, in the format "A1:Z100". + + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. + + + SwitchParameter + + + False + + + PassThru + + If specified, an object representing the unsaved Excel package will be returned, it then needs to be saved. + + + SwitchParameter + + + False + + + + + + Path + + Path to a new or existing .XLSX file. + + String + + String + + + None + + + ExcelPackage + + An object representing an Excel Package - either from Open-ExcelPackage or specifying -PassThru to Export-Excel. + + ExcelPackage + + ExcelPackage + + + None + + + WorkSheetName + + The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default. + + Object + + Object + + + Combined + + + Clearsheet + + If specified ,any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet. + + SwitchParameter + + SwitchParameter + + + False + + + NoHeader + + Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified. + + SwitchParameter + + SwitchParameter + + + False + + + FromLabel + + If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came from. FromLabel is the header for this column. If it is null or empty, the labels will be omitted. + + String + + String + + + From + + + LabelBlocks + + If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title. + + SwitchParameter + + SwitchParameter + + + False + + + AutoSize + + Sets the width of the Excel columns to display all the data in their cells. + + SwitchParameter + + SwitchParameter + + + False + + + FreezeTopRow + + Freezes headers etc. in the top row. + + SwitchParameter + + SwitchParameter + + + False + + + FreezeFirstColumn + + Freezes titles etc. in the left column. + + SwitchParameter + + SwitchParameter + + + False + + + FreezeTopRowFirstColumn + + Freezes top row and left column (equivalent to Freeze pane 2,2 ). + + SwitchParameter + + SwitchParameter + + + False + + + FreezePane + + Freezes panes at specified coordinates (in the formRowNumber , ColumnNumber). + + Int32[] + + Int32[] + + + None + + + AutoFilter + + Enables the Excel filter on the headers of the combined sheet. + + SwitchParameter + + SwitchParameter + + + False + + + BoldTopRow + + Makes the top row boldface. + + SwitchParameter + + SwitchParameter + + + False + + + HideSource + + If specified, hides the sheets that the data is copied from. + + SwitchParameter + + SwitchParameter + + + False + + + Title + + Text of a title to be placed in Cell A1. + + String + + String + + + None + + + TitleFillPattern + + Sets the fill pattern for the title cell. + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + TitleBackgroundColor + + Sets the cell background color for the title cell. + + Object + + Object + + + None + + + TitleBold + + Sets the title in boldface type. + + SwitchParameter + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 22 + + + PivotTableDefinition + + Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or morePivotTable(s). + + Hashtable + + Hashtable + + + None + + + ExcelChartDefinition + + A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. + + Object[] + + Object[] + + + None + + + ConditionalFormat + + One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. + + Object[] + + Object[] + + + None + + + ConditionalText + + Applies a Conditional formatting rule defined with New-ConditionalText. + + Object[] + + Object[] + + + None + + + AutoNameRange + + Makes each column a named range. + + SwitchParameter + + SwitchParameter + + + False + + + RangeName + + Makes the data in the worksheet a named range. + + String + + String + + + None + + + TableName + + Makes the data in the worksheet a table with a name and applies a style to it. Name must not contain spaces. + + String + + String + + + None + + + TableStyle + + Selects the style for the named table - defaults to "Medium6". + + TableStyles + + TableStyles + + + Medium6 + + + ReturnRange + + If specified, returns the range of cells in the combined sheet, in the format "A1:Z100". + + SwitchParameter + + SwitchParameter + + + False + + + Show + + Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. + + SwitchParameter + + SwitchParameter + + + False + + + PassThru + + If specified, an object representing the unsaved Excel package will be returned, it then needs to be saved. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> foreach ($computerName in @('Server1', 'Server2', 'Server3', 'Server4')) { + Get-Service -ComputerName $computerName | + Select-Object -Property Status, Name, DisplayName, StartType | + Export-Excel -Path .\test.xlsx -WorkSheetname $computerName -AutoSize +} +PS\> $ptDef = New-PivotTableDefinition -PivotTableName "Pivot1" -SourceWorkSheet "Combined" -PivotRows "Status" -PivotFilter "MachineName" -PivotData @{Status='Count'} -IncludePivotChart -ChartType BarClustered3D +PS\> Join-Worksheet -Path .\test.xlsx -WorkSheetName combined -FromLabel "MachineName" -HideSource-AutoSize -FreezeTopRow -BoldTopRow -PivotTableDefinition $pt -Show + + The foreach command gets a list of services running on four servers and exports each list to its own page in Test.xlsx. And $PtDef=... creates a definition for a PivotTable. + The Join-Worksheet command uses the same file and merges the results into a sheet named "Combined". It sets a column header of "Machinename", this column will contain the name of the sheet the data was copied from; after copying the data to the sheet "Combined", the other sheets will be hidden. Join-Worksheet finishes by calling Export-Excel to AutoSize cells, freeze the top row and make it bold and add thePivotTable. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Get-CimInstance -ClassName win32_logicaldisk | + Select-Object -Property DeviceId,VolumeName, Size,Freespace | + Export-Excel -Path "$env:computerName.xlsx" -WorkSheetname Volumes -NumberFormat "0,000" +PS\> Get-NetAdapter| Select-Object Name,InterfaceDescription,MacAddress,LinkSpeed | + Export-Excel -Path "$env:COMPUTERNAME.xlsx" -WorkSheetname NetAdapter +PS\> Join-Worksheet -Path "$env:COMPUTERNAME.xlsx"-WorkSheetName Summary -Title "Summary" -TitleBold -TitleSize 22 -NoHeader -LabelBlocks -AutoSize -HideSource -show + + The first two commands get logical-disk and network-card information; each type is exported to its own sheet in a workbook. + The Join-Worksheet command copies both onto a page named "Summary".Because the data is dissimilar, -NoHeader is specified, ensuring the whole of each page is copied. Specifying -LabelBlocks causes each sheet's name to become a title on the summary page above the copied data. The source data is hidden, a title is added in 22 point boldface and the columns are sized to fit the data. + + + + + + Online Version: + + + + + + + Merge-MultipleSheets + Merge + MultipleSheets + + Merges Worksheets into a single Worksheet with differences marked up. + + + + The Merge Worksheet command combines two sheets. Merge-MultipleSheets is designed to merge more than two. + If asked to merge sheets A,B,C which contain Services, with a Name, Displayname and Start mode, where "Name" is treated as the key, Merge-MultipleSheets: + * Calls Merge-Worksheet to merge "Name", "Displayname" and "Startmode" from sheets A and C; the result has column headings "_Row", "Name", "DisplayName", "Startmode", "C-DisplayName", "C-StartMode", "C-Is" and "C-Row". + * Calls Merge-Worksheet again passing it the intermediate result and sheet B, comparing "Name", "Displayname" and "Start mode" columns on each side, and gets a result with columns "_Row", "Name", "DisplayName", "Startmode", "B-DisplayName", "B-StartMode", "B-Is", "B-Row", "C-DisplayName", "C-StartMode", "C-Is" and "C-Row". + + Any columns on the "reference" side which are not used in the comparison are added on the right, which is why we compare the sheets in reverse order. + The "Is" columns hold "Same", "Added", "Removed" or "Changed" and is used for conditional formatting in the output sheet (these columns are hidden by default), and when the data is written to Excel the "reference" columns, in this case "DisplayName" and "Start" are renamed to reflect their source, so they become "A-DisplayName" and "A-Start". + Conditional formatting is also applied to the Key column ("Name" in this case) so the view can be filtered to rows with changes by filtering this column on color. + Note: the processing order can affect what is seen as a change.For example, if there is an extra item in sheet B in the example above, Sheet C will be processed first and that row and will not be seen to be missing. When sheet B is processed it is marked as an addition, and the conditional formatting marks the entries from sheet A to show that a values were added in at least one sheet. + However if Sheet B is the reference sheet, A and C will be seen to have an item removed; and if B is processed before C, the extra item is known when C is processed and so C is considered to be missing that item. + + + + Merge-MultipleSheets + + Path + + Paths to the files to be merged. Files are also accepted + + Object + + Object + + + None + + + KeyFontColor + + Sets the font color for the Key field; this means you can filter by color to get only changed rows. + + Object + + Object + + + [System.Drawing.Color]::Red + + + ChangeBackgroundColor + + Sets the background color for changed rows. + + Object + + Object + + + [System.Drawing.Color]::Orange + + + DeleteBackgroundColor + + Sets the background color for rows in the reference but deleted from the difference sheet. + + Object + + Object + + + [System.Drawing.Color]::LightPink + + + AddBackgroundColor + + Sets the background color for rows not in the reference but added to the difference sheet. + + Object + + Object + + + [System.Drawing.Color]::Orange + + + Startrow + + The row from where we start to import data, all rows above the Start row are disregarded. By default this is the first row. + + Int32 + + Int32 + + + 1 + + + Headername + + Specifies custom property names to use, instead of the values defined in the column headers of the Start row. + + String[] + + String[] + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. + + Object + + Object + + + Sheet1 + + + OutputFile + + File to write output to. + + Object + + Object + + + .\temp.xlsx + + + OutputSheetName + + Name of Worksheet to output - if none specified will use the reference Worksheet name. + + Object + + Object + + + Sheet1 + + + Property + + Properties to include in the comparison - supports wildcards, default is "*". + + Object + + Object + + + * + + + ExcludeProperty + + Properties to exclude from the the comparison - supports wildcards. + + Object + + Object + + + None + + + Key + + Name of a column which is unique used to pair up rows from the reference and difference sides, default is "Name". + + Object + + Object + + + Name + + + NoHeader + + If specified, property names will be automatically generated (P1, P2, P3, ..) instead of using the values from the start row. + + + SwitchParameter + + + False + + + HideRowNumbers + + If specified, hides the columns in the spreadsheet that contain the row numbers. + + + SwitchParameter + + + False + + + Passthru + + If specified, outputs the data to the pipeline (you can add -whatif so it the command only outputs to the pipeline). + + + SwitchParameter + + + False + + + Show + + If specified, opens the output workbook. + + + SwitchParameter + + + False + + + + + + Path + + Paths to the files to be merged. Files are also accepted + + Object + + Object + + + None + + + Startrow + + The row from where we start to import data, all rows above the Start row are disregarded. By default this is the first row. + + Int32 + + Int32 + + + 1 + + + Headername + + Specifies custom property names to use, instead of the values defined in the column headers of the Start row. + + String[] + + String[] + + + None + + + NoHeader + + If specified, property names will be automatically generated (P1, P2, P3, ..) instead of using the values from the start row. + + SwitchParameter + + SwitchParameter + + + False + + + WorksheetName + + Name(s) of Worksheets to compare. + + Object + + Object + + + Sheet1 + + + OutputFile + + File to write output to. + + Object + + Object + + + .\temp.xlsx + + + OutputSheetName + + Name of Worksheet to output - if none specified will use the reference Worksheet name. + + Object + + Object + + + Sheet1 + + + Property + + Properties to include in the comparison - supports wildcards, default is "*". + + Object + + Object + + + * + + + ExcludeProperty + + Properties to exclude from the the comparison - supports wildcards. + + Object + + Object + + + None + + + Key + + Name of a column which is unique used to pair up rows from the reference and difference sides, default is "Name". + + Object + + Object + + + Name + + + KeyFontColor + + Sets the font color for the Key field; this means you can filter by color to get only changed rows. + + Object + + Object + + + [System.Drawing.Color]::Red + + + ChangeBackgroundColor + + Sets the background color for changed rows. + + Object + + Object + + + [System.Drawing.Color]::Orange + + + DeleteBackgroundColor + + Sets the background color for rows in the reference but deleted from the difference sheet. + + Object + + Object + + + [System.Drawing.Color]::LightPink + + + AddBackgroundColor + + Sets the background color for rows not in the reference but added to the difference sheet. + + Object + + Object + + + [System.Drawing.Color]::Orange + + + HideRowNumbers + + If specified, hides the columns in the spreadsheet that contain the row numbers. + + SwitchParameter + + SwitchParameter + + + False + + + Passthru + + If specified, outputs the data to the pipeline (you can add -whatif so it the command only outputs to the pipeline). + + SwitchParameter + + SwitchParameter + + + False + + + Show + + If specified, opens the output workbook. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> dir Server*.xlsx | Merge-MulipleSheets -WorksheetName Services -OutputFile Test2.xlsx -OutputSheetName Services -Show + + Here we are auditing servers and each one has a workbook in the current directory which contains a "Services" Worksheet (the result of Get-WmiObject -Class win32_service \| Select-Object -Property Name, Displayname, Startmode). No key is specified so the key is assumed to be the "Name" column. The files are merged and the result is opened on completion. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> dir Serv*.xlsx | Merge-MulipleSheets -WorksheetName Software -Key "*" -ExcludeProperty Install* -OutputFile Test2.xlsx -OutputSheetName Software -Show + + The server audit files in the previous example also have "Software" worksheet, but no single field on that sheet works as a key. Specifying "*" for the key produces a compound key using all non-excluded fields (and the installation date and file location are excluded). + + + + -------------------------- EXAMPLE 3 -------------------------- + Merge-MulipleSheets -Path hotfixes.xlsx -WorksheetName Serv* -Key hotfixid -OutputFile test2.xlsx -OutputSheetName hotfixes -HideRowNumbers -Show + + This time all the servers have written their hotfix information to their own worksheets in a shared Excel workbook named "Hotfixes.xlsx" (the information was obtained by running Get-Hotfix \| Sort-Object -Property description,hotfixid \| Select-Object -Property Description,HotfixID) This ignores any sheets which are not named "Serv*", and uses the HotfixID as the key; in this version the row numbers are hidden. + + + + + + Online Version: + + + + + + + Merge-Worksheet + Merge + Worksheet + + Merges two Worksheets (or other objects) into a single Worksheet with differences marked up. + + + + The Compare-Worksheet command takes two Worksheets and marks differences in the source document, and optionally outputs a grid showing the changes. + By contrast the Merge-Worksheet command takes the Worksheets and combines them into a single sheet showing the old and new data side by side. Although it is designed to work with Excel data it can work with arrays of any kind of object; so it can be a merge of Worksheets, or a merge to a Worksheet. + + + + Merge-Worksheet + + Referencefile + + First Excel file to compare. You can compare two Excel files or two other objects or a reference obhct against a difference file, but not a reference file against an object. works with the following parameter sets + * A = Compare two files default headers + * B = Compare two files user supplied headers + * C = Compare two files headers P1, P2, P3 etc + + Object + + Object + + + None + + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + + Merge-Worksheet + + Referencefile + + First Excel file to compare. You can compare two Excel files or two other objects or a reference obhct against a difference file, but not a reference file against an object. works with the following parameter sets + * A = Compare two files default headers + * B = Compare two files user supplied headers + * C = Compare two files headers P1, P2, P3 etc + + Object + + Object + + + None + + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + + Merge-Worksheet + + Referencefile + + First Excel file to compare. You can compare two Excel files or two other objects or a reference obhct against a difference file, but not a reference file against an object. works with the following parameter sets + * A = Compare two files default headers + * B = Compare two files user supplied headers + * C = Compare two files headers P1, P2, P3 etc + + Object + + Object + + + None + + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + + Merge-Worksheet + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + + Merge-Worksheet + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + + Merge-Worksheet + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + + + + Referencefile + + First Excel file to compare. You can compare two Excel files or two other objects or a reference obhct against a difference file, but not a reference file against an object. works with the following parameter sets + * A = Compare two files default headers + * B = Compare two files user supplied headers + * C = Compare two files headers P1, P2, P3 etc + + Object + + Object + + + None + + + Differencefile + + Second Excel file to compare. Works with paramter sets A,B,C as well as the following + * D = Compare two objects; + * E = Compare one object one file that uses default headers + * F = Compare one object one file that uses user supplied headers + * G = Compare one object one file that uses headers P1, P2, P3 etc + + Object + + Object + + + None + + + WorksheetName + + Name(s) of Worksheets to compare. Applies to all parameter sets EXCEPT D which is two objects (no sheets) + + Object + + Object + + + Sheet1 + + + Startrow + + The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. Applies to all sets EXCEPT D which is two objects (no sheets, so no start row ) + + Int32 + + Int32 + + + 1 + + + Headername + + Specifies custom property names to use, instead of the values defined in the column headers of the Start Row. Works with the following parameter sets: + * B 2 sheets with user supplied headers + * F Compare object + sheet + + ```yaml + Type: String[] + Parameter Sets: B, F + Aliases: + Required: True Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False + + ### -NoHeader + Automatically generate property names (P1, P2, P3, ..) instead of using the values the top row of the sheet. Works with parameter sets + + * C 2 sheets with headers of P1, P2, P3 ... + * G Compare object + sheet + + yaml Type: SwitchParameter Parameter Sets: C, G Aliases: + Required: True Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False + + ### -ReferenceObject + + Reference object to compare if a Worksheet is NOT being used. Reference object can combine with a difference sheet or difference object + + yaml Type: Object Parameter Sets: G, F, E, D Aliases: RefObject + Required: True Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False + + ### -DifferenceObject + + Difference object to compare if a Worksheet is NOT being used for either half. Can't have a reference sheet and difference object. + + yaml Type: Object Parameter Sets: D Aliases: DiffObject + Required: True Position: 2 Default value: None Accept pipeline input: False Accept wildcard characters: False + + ### -DiffPrefix + + If there isn't a filename to use to label data from the "Difference" side, DiffPrefix is used, it defaults to "=&gt;" + + yaml Type: Object Parameter Sets: G, F, E, D Aliases: + Required: False Position: 3 Default value: => Accept pipeline input: False Accept wildcard characters: False + + ### -OutputFile + + File to hold merged data. + + yaml Type: Object Parameter Sets: (All) Aliases: OutFile + Required: False Position: 4 Default value: None Accept pipeline input: False Accept wildcard characters: False + + ### -OutputSheetName + + Name of Worksheet to output - if none specified will use the reference Worksheet name. + + yaml Type: Object Parameter Sets: (All) Aliases: OutSheet + Required: False Position: 5 Default value: Sheet1 Accept pipeline input: False Accept wildcard characters: False + + ### -Property + + Properties to include in the DIFF - supports wildcards, default is "\*". + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: * Accept pipeline input: False Accept wildcard characters: False + + ### -ExcludeProperty + + Properties to exclude from the the search - supports wildcards. + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False + + ### -Key + + Name of a column which is unique used to pair up rows from the refence and difference side, default is "Name". + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: Name Accept pipeline input: False Accept wildcard characters: False + + ### -KeyFontColor + + Sets the font color for the "key" field; this means you can filter by color to get only changed rows. + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: [System.Drawing.Color]::DarkRed Accept pipeline input: False Accept wildcard characters: False + + ### -ChangeBackgroundColor + + Sets the background color for changed rows. + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: [System.Drawing.Color]::Orange Accept pipeline input: False Accept wildcard characters: False + + ### -DeleteBackgroundColor + + Sets the background color for rows in the reference but deleted from the difference sheet. + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: [System.Drawing.Color]::LightPink Accept pipeline input: False Accept wildcard characters: False + + ### -AddBackgroundColor + + Sets the background color for rows not in the reference but added to the difference sheet. + + yaml Type: Object Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: [System.Drawing.Color]::PaleGreen Accept pipeline input: False Accept wildcard characters: False + + ### -HideEqual + + if specified, hides the rows in the spreadsheet that are equal and only shows changes, added or deleted rows. + + yaml Type: SwitchParameter Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False + + ### -Passthru + + If specified, outputs the data to the pipeline \(you can add -WhatIf so the command only outputs to the pipeline\). + + yaml Type: SwitchParameter Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False + + ### -Show + + If specified, opens the output workbook. + + yaml Type: SwitchParameter Parameter Sets: (All) Aliases: + Required: False Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False + + ### -WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + yaml Type: SwitchParameter Parameter Sets: (All) Aliases: wi + Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False + + ### -Confirm + + Prompts you for confirmation before running the cmdlet. + + yaml Type: SwitchParameter Parameter Sets: (All) Aliases: cf + Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False ``` + + + + + + + None + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Merge-Worksheet "Server54.xlsx" "Server55.xlsx" -WorksheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -show + + The workbooks contain audit information for two servers, one sheet contains a list of services. + This command creates a worksheet named "54-55" in a workbook named "services.xlsx" which shows all the services and their differences, and opens the new workbook in Excel. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Merge-Worksheet "Server54.xlsx" "Server55.xlsx" -WorksheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -HideEqual -AddBackgroundColor LightBlue -show + + This modifies the previous command to hide the equal rows in the output sheet and changes the color used to mark rows added to the second file. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> Merge-Worksheet -OutputFile .\j1.xlsx -OutputSheetName test11 -ReferenceObject (dir .\ImportExcel\4.0.7) -DifferenceObject (dir .\ImportExcel\4.0.8) -Property Length -Show + + This version compares two directories, and marks what has changed. Because no "Key" property is given, "Name" is assumed to be the key and the only other property examined is length. Files which are added or deleted or have changed size will be highlighed in the output sheet. Changes to dates or other attributes will be ignored. + + + + -------------------------- EXAMPLE 4 -------------------------- + PS\> Merge-Worksheet -RefO (dir .\ImportExcel\4.0.7) -DiffO (dir .\ImportExcel\4.0.8) -Pr Length | Out-GridView + + This time no file is written and the results - which include all properties, not just length, are output and sent to Out-Gridview. + This version uses aliases to shorten the parameters, (OutputFileName can be "outFile" and the Sheet can be"OutSheet"; DifferenceObject & ReferenceObject can be DiffObject & RefObject respectively). + + + + + + Online Version: + + + + + + + New-ConditionalFormattingIconSet + New + ConditionalFormattingIconSet + + Creates an object which describes a conditional formatting rule a for 3,4 or 5 icon set. + + + + Export-Excel takes a -ConditionalFormat parameter which can hold one or more descriptions for conditional formats; this command builds the defintion of a Conditional formatting rule for an icon set. + + + + New-ConditionalFormattingIconSet + + Range + + The range of cells that the conditional format applies to. + + Object + + Object + + + None + + + ConditionalFormat + + The type of rule: one of "ThreeIconSet","FourIconSet" or "FiveIconSet" + + Object + + Object + + + None + + + Reverse + + Use the icons in the reverse order. + + + SwitchParameter + + + False + + + + + + Range + + The range of cells that the conditional format applies to. + + Object + + Object + + + None + + + ConditionalFormat + + The type of rule: one of "ThreeIconSet","FourIconSet" or "FiveIconSet" + + Object + + Object + + + None + + + Reverse + + Use the icons in the reverse order. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $cfRange = [OfficeOpenXml.ExcelAddress]::new($topRow, $column, $lastDataRow, $column) +PS\> $cfdef = New-ConditionalFormattingIconSet -Range $cfrange -ConditionalFormat ThreeIconSet -IconType Arrows +PS\> Export-Excel -ExcelPackage $excel -ConditionalFormat $cfdef -show + + The first line creates a range - one column wide in the column $column, running from $topRow to $lastDataRow. The second line creates a definition object using this range and the third uses Export-Excel with an open package to apply the format and save and open the file. + + + + + + Online Version: + + + + Add-Add-ConditionalFormatting + + + + + + + New-ConditionalText + New + ConditionalText + + Creates an object which describes a conditional formatting rule for single valued rules. + + + + Some Conditional formatting rules don't apply styles to a cell (IconSets and Databars); some take two parameters (Between); some take none (ThisWeek, ContainsErrors, AboveAverage etc).The others take a single parameter (Top, BottomPercent, GreaterThan, Contains etc). + This command creates an object to describe the last two categories, which can then be passed to Export-Excel. + + + + New-ConditionalText + + Text + + The text (or other value) to use in the rule. Note that Equals, GreaterThan/LessThan rules require text to wrapped in double quotes. + + Object + + Object + + + None + + + ConditionalTextColor + + The font color for the cell - by default: "DarkRed". + + Object + + Object + + + [System.Drawing.Color]::DarkRed + + + BackgroundColor + + The fill color for the cell - by default: "LightPink". + + Object + + Object + + + [System.Drawing.Color]::LightPink + + + Range + + The range of cells that the conditional format applies to; if none is specified the range will be apply to all the data in the sheet. + + String + + String + + + None + + + PatternType + + The background pattern for the cell - by default: "Solid" + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + ConditionalType + + One of the supported rules; by default "ContainsText" is selected. + + Object + + Object + + + ContainsText + + + + + + Text + + The text (or other value) to use in the rule. Note that Equals, GreaterThan/LessThan rules require text to wrapped in double quotes. + + Object + + Object + + + None + + + ConditionalTextColor + + The font color for the cell - by default: "DarkRed". + + Object + + Object + + + [System.Drawing.Color]::DarkRed + + + BackgroundColor + + The fill color for the cell - by default: "LightPink". + + Object + + Object + + + [System.Drawing.Color]::LightPink + + + Range + + The range of cells that the conditional format applies to; if none is specified the range will be apply to all the data in the sheet. + + String + + String + + + None + + + PatternType + + The background pattern for the cell - by default: "Solid" + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + ConditionalType + + One of the supported rules; by default "ContainsText" is selected. + + Object + + Object + + + ContainsText + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $ct = New-ConditionalText -Text 'Ferrari' +PS\> Export-Excel -ExcelPackage $excel -ConditionalTest $ct -show + + The first line creates a definition object which will highlight the word "Ferrari" in any cell. and the second uses Export-Excel with an open package to apply the format and save and open the file. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $ct = New-ConditionalText -Text "Ferrari" +PS\> $ct2 = New-ConditionalText -Range $worksheet.Names\["FinishPosition"\].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalTextColor Red -BackgroundColor White +PS\> Export-Excel -ExcelPackage $excel -ConditionalText $ct,$ct2 -show + + This builds on the previous example, and specifies a condition of \&lt;=3 with a format of red text on a white background; this applies to a named range "Finish Position". + The range could be written -Range "C:C" to specify a named column, or -Range "C2:C102" to specify certain cells in the column. + + + + + + Online Version: + + + + Add-ConditionalFormatting + + + + + + + New-ExcelChartDefinition + New + ExcelChartDefinition + + Creates a Definition of a chart which can be added using Export-Excel, or Add-PivotTable + + + + All the parameters which are passed to Add-ExcelChart can be added to a chart-definition object and passed to Export-Excel with the -ExcelChartDefinition parameter, or to Add-PivotTable with the -PivotChartDefinition parameter. This command sets up those definition objects. + + + + New-ExcelChartDefinition + + Title + + The title for the chart. + + Object + + Object + + + Chart Title + + + RowOffSetPixels + + Offset to position the chart by a fraction of a row. + + Object + + Object + + + 10 + + + Column + + Column position of the top left corner of the chart. 0 places it at the edge of the sheet, 1 to the right of column A and so on. + + Object + + Object + + + 6 + + + ColumnOffSetPixels + + Offset to position the chart by a fraction of a column. + + Object + + Object + + + 5 + + + LegendPosition + + Location of the key, either "Left", "Right", "Top", "Bottom" or "TopRight". + + + Top + Left + Right + Bottom + TopRight + + eLegendPosition + + eLegendPosition + + + None + + + LegendSize + + Font size for the key. + + Object + + Object + + + None + + + SeriesHeader + + Specifies explicit name(s) for the data series, which will appear in the legend/key + + Object + + Object + + + None + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 0 + + + XAxisTitleText + + Specifies a title for the X-axis. + + String + + String + + + None + + + XAxisTitleSize + + Sets the font size for the axis title. + + Object + + Object + + + None + + + XAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers along the X-axis. + + String + + String + + + None + + + Header + + No longer used. This may be removed in future versions. + + Object + + Object + + + None + + + XMajorUnit + + Spacing for the major gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMinorUnit + + Spacing for the minor gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMaxValue + + Maximum value for the scale along the X-axis. + + Object + + Object + + + None + + + XMinValue + + Minimum value for the scale along the X-axis. + + Object + + Object + + + None + + + XAxisPosition + + Position for the X-axis ("Top" or" Bottom"). + + + Left + Bottom + Right + Top + + eAxisPosition + + eAxisPosition + + + None + + + YAxisTitleText + + Specifies a title for the Y-axis. + + String + + String + + + None + + + YAxisTitleSize + + Sets the font size for the Y-axis title. + + Object + + Object + + + None + + + YAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers on the Y-axis + + String + + String + + + None + + + YMajorUnit + + Spacing for the major gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMinorUnit + + Spacing for the minor gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + ChartType + + One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + ColumnStacked + + + YMaxValue + + Maximum value on the Y-axis. + + Object + + Object + + + None + + + YMinValue + + Minimum value on the Y-axis. + + Object + + Object + + + None + + + YAxisPosition + + Position for the Y-axis ("Left" or "Right"). + + + Left + Bottom + Right + Top + + eAxisPosition + + eAxisPosition + + + None + + + ChartTrendLine + + Superimposes one of Excel's trenline types on the chart. + + + Exponential + Linear + Logarithmic + MovingAvgerage + Polynomial + Power + + eTrendLine[] + + eTrendLine[] + + + None + + + XRange + + The range of cells containing values for the X-Axis - usually labels. + + Object + + Object + + + None + + + YRange + + The range(s) of cells holding values for the Y-Axis - usually "data". + + Object + + Object + + + None + + + Width + + Width of the chart in pixels. Defaults to 500. + + Object + + Object + + + 500 + + + Height + + Height of the chart in pixels. Defaults to 350. + + Object + + Object + + + 350 + + + Row + + Row position of the top left corner of the chart. 0 places it at the top of the sheet, 1 below row 1 and so on. + + Object + + Object + + + 0 + + + LegendBold + + Sets the key in bold type. + + + SwitchParameter + + + False + + + NoLegend + + If specified, turns off display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. + + + SwitchParameter + + + False + + + ShowCategory + + Attaches a category label in charts which support this. + + + SwitchParameter + + + False + + + ShowPercent + + Attaches a percentage label in charts which support this. + + + SwitchParameter + + + False + + + TitleBold + + Sets the title in bold face. + + + SwitchParameter + + + False + + + XAxisTitleBold + + Sets the X-axis title in bold face. + + + SwitchParameter + + + False + + + YAxisTitleBold + + Sets the Y-axis title in bold face. + + + SwitchParameter + + + False + + + + + + Title + + The title for the chart. + + Object + + Object + + + Chart Title + + + Header + + No longer used. This may be removed in future versions. + + Object + + Object + + + None + + + ChartType + + One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". + + eChartType + + eChartType + + + ColumnStacked + + + ChartTrendLine + + Superimposes one of Excel's trenline types on the chart. + + eTrendLine[] + + eTrendLine[] + + + None + + + XRange + + The range of cells containing values for the X-Axis - usually labels. + + Object + + Object + + + None + + + YRange + + The range(s) of cells holding values for the Y-Axis - usually "data". + + Object + + Object + + + None + + + Width + + Width of the chart in pixels. Defaults to 500. + + Object + + Object + + + 500 + + + Height + + Height of the chart in pixels. Defaults to 350. + + Object + + Object + + + 350 + + + Row + + Row position of the top left corner of the chart. 0 places it at the top of the sheet, 1 below row 1 and so on. + + Object + + Object + + + 0 + + + RowOffSetPixels + + Offset to position the chart by a fraction of a row. + + Object + + Object + + + 10 + + + Column + + Column position of the top left corner of the chart. 0 places it at the edge of the sheet, 1 to the right of column A and so on. + + Object + + Object + + + 6 + + + ColumnOffSetPixels + + Offset to position the chart by a fraction of a column. + + Object + + Object + + + 5 + + + LegendPosition + + Location of the key, either "Left", "Right", "Top", "Bottom" or "TopRight". + + eLegendPosition + + eLegendPosition + + + None + + + LegendSize + + Font size for the key. + + Object + + Object + + + None + + + LegendBold + + Sets the key in bold type. + + SwitchParameter + + SwitchParameter + + + False + + + NoLegend + + If specified, turns off display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. + + SwitchParameter + + SwitchParameter + + + False + + + ShowCategory + + Attaches a category label in charts which support this. + + SwitchParameter + + SwitchParameter + + + False + + + ShowPercent + + Attaches a percentage label in charts which support this. + + SwitchParameter + + SwitchParameter + + + False + + + SeriesHeader + + Specifies explicit name(s) for the data series, which will appear in the legend/key + + Object + + Object + + + None + + + TitleBold + + Sets the title in bold face. + + SwitchParameter + + SwitchParameter + + + False + + + TitleSize + + Sets the point size for the title. + + Int32 + + Int32 + + + 0 + + + XAxisTitleText + + Specifies a title for the X-axis. + + String + + String + + + None + + + XAxisTitleBold + + Sets the X-axis title in bold face. + + SwitchParameter + + SwitchParameter + + + False + + + XAxisTitleSize + + Sets the font size for the axis title. + + Object + + Object + + + None + + + XAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers along the X-axis. + + String + + String + + + None + + + XMajorUnit + + Spacing for the major gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMinorUnit + + Spacing for the minor gridlines / tick marks along the X-axis. + + Object + + Object + + + None + + + XMaxValue + + Maximum value for the scale along the X-axis. + + Object + + Object + + + None + + + XMinValue + + Minimum value for the scale along the X-axis. + + Object + + Object + + + None + + + XAxisPosition + + Position for the X-axis ("Top" or" Bottom"). + + eAxisPosition + + eAxisPosition + + + None + + + YAxisTitleText + + Specifies a title for the Y-axis. + + String + + String + + + None + + + YAxisTitleBold + + Sets the Y-axis title in bold face. + + SwitchParameter + + SwitchParameter + + + False + + + YAxisTitleSize + + Sets the font size for the Y-axis title. + + Object + + Object + + + None + + + YAxisNumberformat + + A number formatting string, like "\#,\#\#0.00", for numbers on the Y-axis + + String + + String + + + None + + + YMajorUnit + + Spacing for the major gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMinorUnit + + Spacing for the minor gridlines / tick marks on the Y-axis. + + Object + + Object + + + None + + + YMaxValue + + Maximum value on the Y-axis. + + Object + + Object + + + None + + + YMinValue + + Minimum value on the Y-axis. + + Object + + Object + + + None + + + YAxisPosition + + Position for the Y-axis ("Left" or "Right"). + + eAxisPosition + + eAxisPosition + + + None + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $cDef = New-ExcelChartDefinition -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 -SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPosition Bottom +PS\> 0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -now -WorkSheetname SinX -ExcelChartDefinition $cDef -Show + + This reworks an example from Add-Excel-Chart but here the chart is defined and the defintion stored in $cDef and then Export-Excel uses $cDef . + + + + + + Online Version: + + + + + + + New-PivotTableDefinition + New + PivotTableDefinition + + Creates PivotTable definitons for Export-Excel + + + + Export-Excel allows a single PivotTable to be defined using the parameters -IncludePivotTable, -PivotColumns, -PivotRows, -PivotData, -PivotFilter, -PivotTotals, -PivotDataToColumn, -IncludePivotChart and -ChartType. + Its -PivotTableDefintion paramater allows multiple PivotTables to be defined, with additional parameters. New-PivotTableDefinition is a convenient way to build these definitions. + + + + New-PivotTableDefinition + + PivotTableName + + Name for the new pivot table + This command previously had a typo - and has an alias to avoid breaking scripts This will be removed in a future release + + Object + + Object + + + None + + + SourceWorkSheet + + Worksheet where the data is found + + Object + + Object + + + None + + + SourceRange + + Address range in the worksheet e.g "A10:F20" - the first row must contain the column names to pivot by: if the range is not specified the whole source sheet will be used. + + Object + + Object + + + None + + + PivotRows + + Fields to set as rows in the PivotTable + + Object + + Object + + + None + + + PivotData + + A hash-table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP + + Hashtable + + Hashtable + + + None + + + PivotColumns + + Fields to set as columns in the PivotTable + + Object + + Object + + + None + + + PivotFilter + + Fields to use to filter in the PivotTable + + Object + + Object + + + None + + + PivotDataToColumn + + If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns. + + + SwitchParameter + + + False + + + PivotTotals + + By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + + String + + String + + + Both + + + NoTotalsInPivot + + Included for compatibility - equivalent to -PivotTotals "None" + + + SwitchParameter + + + False + + + GroupDateRow + + The name of a row field which should be grouped by parts of the date/time (ignored if GroupDatePart is not specified) + + String + + String + + + None + + + GroupDateColumn + + The name of a column field which should be grouped by parts of the date/time (ignored if GroupDatePart is not specified) + + String + + String + + + None + + + GroupDatePart + + The Part(s) of the date to use in the grouping (ignored if GroupDateRow is not specified) + + + Years + Quarters + Months + Days + Hours + Minutes + Seconds + + eDateGroupBy[] + + eDateGroupBy[] + + + None + + + GroupNumericRow + + The name of a row field which should be grouped by Number (e.g 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericColumn + + The name of a column field which should be grouped by Number (e.g 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericMin + + The starting point for grouping + + Double + + Double + + + 0 + + + GroupNumericMax + + The endpoint for grouping + + Double + + Double + + + 1.79769313486232E+308 + + + GroupNumericInterval + + The interval for grouping + + Double + + Double + + + 100 + + + PivotNumberFormat + + Number format to apply to the data cells in the PivotTable + + String + + String + + + None + + + PivotTableStyle + + Apply a table style to the PivotTable + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + None + + + PivotChartDefinition + + Use a chart definition instead of specifying chart settings one by one + + Object + + Object + + + None + + + Activate + + If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified + + + SwitchParameter + + + False + + + + New-PivotTableDefinition + + PivotTableName + + Name for the new pivot table + This command previously had a typo - and has an alias to avoid breaking scripts This will be removed in a future release + + Object + + Object + + + None + + + SourceWorkSheet + + Worksheet where the data is found + + Object + + Object + + + None + + + SourceRange + + Address range in the worksheet e.g "A10:F20" - the first row must contain the column names to pivot by: if the range is not specified the whole source sheet will be used. + + Object + + Object + + + None + + + PivotRows + + Fields to set as rows in the PivotTable + + Object + + Object + + + None + + + PivotData + + A hash-table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP + + Hashtable + + Hashtable + + + None + + + PivotColumns + + Fields to set as columns in the PivotTable + + Object + + Object + + + None + + + PivotFilter + + Fields to use to filter in the PivotTable + + Object + + Object + + + None + + + PivotDataToColumn + + If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns. + + + SwitchParameter + + + False + + + PivotTotals + + By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + + String + + String + + + Both + + + NoTotalsInPivot + + Included for compatibility - equivalent to -PivotTotals "None" + + + SwitchParameter + + + False + + + GroupDateRow + + The name of a row field which should be grouped by parts of the date/time (ignored if GroupDatePart is not specified) + + String + + String + + + None + + + GroupDateColumn + + The name of a column field which should be grouped by parts of the date/time (ignored if GroupDatePart is not specified) + + String + + String + + + None + + + GroupDatePart + + The Part(s) of the date to use in the grouping (ignored if GroupDateRow is not specified) + + + Years + Quarters + Months + Days + Hours + Minutes + Seconds + + eDateGroupBy[] + + eDateGroupBy[] + + + None + + + GroupNumericRow + + The name of a row field which should be grouped by Number (e.g 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericColumn + + The name of a column field which should be grouped by Number (e.g 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericMin + + The starting point for grouping + + Double + + Double + + + 0 + + + GroupNumericMax + + The endpoint for grouping + + Double + + Double + + + 1.79769313486232E+308 + + + GroupNumericInterval + + The interval for grouping + + Double + + Double + + + 100 + + + PivotNumberFormat + + Number format to apply to the data cells in the PivotTable + + String + + String + + + None + + + PivotTableStyle + + Apply a table style to the PivotTable + + + None + Custom + Light1 + Light2 + Light3 + Light4 + Light5 + Light6 + Light7 + Light8 + Light9 + Light10 + Light11 + Light12 + Light13 + Light14 + Light15 + Light16 + Light17 + Light18 + Light19 + Light20 + Light21 + Medium1 + Medium2 + Medium3 + Medium4 + Medium5 + Medium6 + Medium7 + Medium8 + Medium9 + Medium10 + Medium11 + Medium12 + Medium13 + Medium14 + Medium15 + Medium16 + Medium17 + Medium18 + Medium19 + Medium20 + Medium21 + Medium22 + Medium23 + Medium24 + Medium25 + Medium26 + Medium27 + Medium28 + Dark1 + Dark2 + Dark3 + Dark4 + Dark5 + Dark6 + Dark7 + Dark8 + Dark9 + Dark10 + Dark11 + + TableStyles + + TableStyles + + + None + + + IncludePivotChart + + If specified a chart Will be included. + + + SwitchParameter + + + False + + + ChartTitle + + Optional title for the pivot chart, by default the title omitted. + + String + + String + + + None + + + ChartHeight + + Height of the chart in Pixels (400 by default) + + Int32 + + Int32 + + + 400 + + + ChartWidth + + Width of the chart in Pixels (600 by default) + + Int32 + + Int32 + + + 600 + + + ChartRow + + Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart (default is 0, chart starts at top edge of row 1). + + Int32 + + Int32 + + + 0 + + + ChartColumn + + Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart (default is 4, chart starts at left edge of column E) + + Int32 + + Int32 + + + 4 + + + ChartRowOffSetPixels + + Vertical offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartColumnOffSetPixels + + Horizontal offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartType + + Type of chart + + + Area + Line + Pie + Bubble + ColumnClustered + ColumnStacked + ColumnStacked100 + ColumnClustered3D + ColumnStacked3D + ColumnStacked1003D + BarClustered + BarStacked + BarStacked100 + BarClustered3D + BarStacked3D + BarStacked1003D + LineStacked + LineStacked100 + LineMarkers + LineMarkersStacked + LineMarkersStacked100 + PieOfPie + PieExploded + PieExploded3D + BarOfPie + XYScatterSmooth + XYScatterSmoothNoMarkers + XYScatterLines + XYScatterLinesNoMarkers + AreaStacked + AreaStacked100 + AreaStacked3D + AreaStacked1003D + DoughnutExploded + RadarMarkers + RadarFilled + Surface + SurfaceWireframe + SurfaceTopView + SurfaceTopViewWireframe + Bubble3DEffect + StockHLC + StockOHLC + StockVHLC + StockVOHLC + CylinderColClustered + CylinderColStacked + CylinderColStacked100 + CylinderBarClustered + CylinderBarStacked + CylinderBarStacked100 + CylinderCol + ConeColClustered + ConeColStacked + ConeColStacked100 + ConeBarClustered + ConeBarStacked + ConeBarStacked100 + ConeCol + PyramidColClustered + PyramidColStacked + PyramidColStacked100 + PyramidBarClustered + PyramidBarStacked + PyramidBarStacked100 + PyramidCol + XYScatter + Radar + Doughnut + Pie3D + Line3D + Column3D + Area3D + + eChartType + + eChartType + + + Pie + + + NoLegend + + If specified hides the chart legend + + + SwitchParameter + + + False + + + ShowCategory + + if specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type. + + + SwitchParameter + + + False + + + ShowPercent + + If specified attaches percentages to slices in a pie chart. + + + SwitchParameter + + + False + + + Activate + + If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified + + + SwitchParameter + + + False + + + + + + PivotTableName + + Name for the new pivot table + This command previously had a typo - and has an alias to avoid breaking scripts This will be removed in a future release + + Object + + Object + + + None + + + SourceWorkSheet + + Worksheet where the data is found + + Object + + Object + + + None + + + SourceRange + + Address range in the worksheet e.g "A10:F20" - the first row must contain the column names to pivot by: if the range is not specified the whole source sheet will be used. + + Object + + Object + + + None + + + PivotRows + + Fields to set as rows in the PivotTable + + Object + + Object + + + None + + + PivotData + + A hash-table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP + + Hashtable + + Hashtable + + + None + + + PivotColumns + + Fields to set as columns in the PivotTable + + Object + + Object + + + None + + + PivotFilter + + Fields to use to filter in the PivotTable + + Object + + Object + + + None + + + PivotDataToColumn + + If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns. + + SwitchParameter + + SwitchParameter + + + False + + + PivotTotals + + By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected. + + String + + String + + + Both + + + NoTotalsInPivot + + Included for compatibility - equivalent to -PivotTotals "None" + + SwitchParameter + + SwitchParameter + + + False + + + GroupDateRow + + The name of a row field which should be grouped by parts of the date/time (ignored if GroupDatePart is not specified) + + String + + String + + + None + + + GroupDateColumn + + The name of a column field which should be grouped by parts of the date/time (ignored if GroupDatePart is not specified) + + String + + String + + + None + + + GroupDatePart + + The Part(s) of the date to use in the grouping (ignored if GroupDateRow is not specified) + + eDateGroupBy[] + + eDateGroupBy[] + + + None + + + GroupNumericRow + + The name of a row field which should be grouped by Number (e.g 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericColumn + + The name of a column field which should be grouped by Number (e.g 0-99, 100-199, 200-299 ) + + String + + String + + + None + + + GroupNumericMin + + The starting point for grouping + + Double + + Double + + + 0 + + + GroupNumericMax + + The endpoint for grouping + + Double + + Double + + + 1.79769313486232E+308 + + + GroupNumericInterval + + The interval for grouping + + Double + + Double + + + 100 + + + PivotNumberFormat + + Number format to apply to the data cells in the PivotTable + + String + + String + + + None + + + PivotTableStyle + + Apply a table style to the PivotTable + + TableStyles + + TableStyles + + + None + + + PivotChartDefinition + + Use a chart definition instead of specifying chart settings one by one + + Object + + Object + + + None + + + IncludePivotChart + + If specified a chart Will be included. + + SwitchParameter + + SwitchParameter + + + False + + + ChartTitle + + Optional title for the pivot chart, by default the title omitted. + + String + + String + + + None + + + ChartHeight + + Height of the chart in Pixels (400 by default) + + Int32 + + Int32 + + + 400 + + + ChartWidth + + Width of the chart in Pixels (600 by default) + + Int32 + + Int32 + + + 600 + + + ChartRow + + Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart (default is 0, chart starts at top edge of row 1). + + Int32 + + Int32 + + + 0 + + + ChartColumn + + Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart (default is 4, chart starts at left edge of column E) + + Int32 + + Int32 + + + 4 + + + ChartRowOffSetPixels + + Vertical offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartColumnOffSetPixels + + Horizontal offset of the chart from the cell corner. + + Int32 + + Int32 + + + 0 + + + ChartType + + Type of chart + + eChartType + + eChartType + + + Pie + + + NoLegend + + If specified hides the chart legend + + SwitchParameter + + SwitchParameter + + + False + + + ShowCategory + + if specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type. + + SwitchParameter + + SwitchParameter + + + False + + + ShowPercent + + If specified attaches percentages to slices in a pie chart. + + SwitchParameter + + SwitchParameter + + + False + + + Activate + + If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $pt = New-PivotTableDefinition -PivotTableName "PT1" -SourceWorkSheet "Sheet1" -PivotRows "Status" -PivotData @{Status='Count'} -PivotFilter 'StartType' -IncludePivotChart -ChartType BarClustered3D +PS\> $Pt += New-PivotTableDefinition -PivotTableName "PT2" -SourceWorkSheet "Sheet2" -PivotRows "Company" -PivotData @{Company='Count'} -IncludePivotChart -ChartType PieExploded3D -ShowPercent -ChartTitle "Breakdown of processes by company" +PS\> Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -AutoSize +PS\> Get-Process | Select-Object -Property Name,Company,Handles,CPU,VM | Export-Excel -Path .\test.xlsx -AutoSize -WorksheetName 'sheet2' +PS\> $excel = Export-Excel -Path .\test.xlsx -PivotTableDefinition $pt -Show + + This is a re-work of one of the examples in Export-Excel - instead of writing out the pivot definition hash-table, it is built by calling New-PivotTableDefinition. + + + + + + Online Version: + + + + + + + Open-ExcelPackage + Open + ExcelPackage + + Returns an ExcelPackage object for the specified XLSX file. + + + + Import-Excel and Export-Excel open an Excel file, carry out their tasks and close it again. + Sometimes it is necessary to open a file and do other work on it. Open-ExcelPackage allows the file to be opened for these tasks. + It takes a -KillExcel switch to make sure Excel is not holding the file open; a -Password parameter for existing protected files, and a -Create switch to set-up a new file if no file already exists. + + + + Open-ExcelPackage + + Path + + The path to the file to open. + + Object + + Object + + + None + + + Password + + The password for a protected worksheet, as a [normal] string (not a secure string). + + String + + String + + + None + + + KillExcel + + If specified, any running instances of Excel will be terminated before opening the file. This may result in lost work, so should be used with caution. + + + SwitchParameter + + + False + + + Create + + By default Open-ExcelPackage will only open an existing file; -Create instructs it to create a new file if required. + + + SwitchParameter + + + False + + + + + + Path + + The path to the file to open. + + Object + + Object + + + None + + + KillExcel + + If specified, any running instances of Excel will be terminated before opening the file. This may result in lost work, so should be used with caution. + + SwitchParameter + + SwitchParameter + + + False + + + Password + + The password for a protected worksheet, as a [normal] string (not a secure string). + + String + + String + + + None + + + Create + + By default Open-ExcelPackage will only open an existing file; -Create instructs it to create a new file if required. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.ExcelPackage + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $excel = Open-ExcelPackage -Path "$env:TEMP\test99.xlsx" -Create +PS\> $ws = Add-WorkSheet -ExcelPackage $excel + + This will create a new file in the temp folder if it doesn't already exist. It then adds a worksheet - because no name is specified it will use the default name of "Sheet1" + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $excel= Open-ExcelPackage -path "$xlPath" -Password $password +PS\> $sheet1 = $excel.Workbook.Worksheets["sheet1"] +PS\> Set-ExcelRange -Range $sheet1.Cells ["E1:S1048576" ], $sheet1.Cells ["V1:V1048576" ] -NFormat ( [cultureinfo ]::CurrentCulture.DateTimeFormat.ShortDatePattern) +PS\> Close-ExcelPackage $excel -Show + + This will open the password protected file at $xlPath using the password stored in $Password. Sheet1 is selected and formatting applied to two blocks of the sheet; then the file is saved and loaded into Excel. + + + + + + Online Version: + + + + + + + Remove-WorkSheet + Remove + WorkSheet + + Removes one or more worksheets from one or more workbooks + + + + + + Remove-WorkSheet + + FullName + + The fully qualified path to the XLSX file(s) + + Object + + Object + + + None + + + WorksheetName + + The worksheet to be removed (sheet1 by default) + + String[] + + String[] + + + Sheet1 + + + Show + + If specified the file will be opened in excel after the sheet is removed. + + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + + + + FullName + + The fully qualified path to the XLSX file(s) + + Object + + Object + + + None + + + WorksheetName + + The worksheet to be removed (sheet1 by default) + + String[] + + String[] + + + Sheet1 + + + Show + + If specified the file will be opened in excel after the sheet is removed. + + SwitchParameter + + SwitchParameter + + + False + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + SwitchParameter + + SwitchParameter + + + False + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Remove-WorkSheet -Path Test1.xlsx -WorksheetName Sheet1 + + Removes the worksheet named 'Sheet1' from 'Test1.xlsx' + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Remove-WorkSheet -Path Test1.xlsx -WorksheetName Sheet1,Target1 + + Removes the worksheet named 'Sheet1' and 'Target1' from 'Test1.xlsx' + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> Remove-WorkSheet -Path Test1.xlsx -WorksheetName Sheet1,Target1 -Show + + Removes the worksheets and then launches the xlsx in Excel + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> dir c:\reports\*.xlsx | Remove-WorkSheet + + Removes 'Sheet1' from all the xlsx files in the c:\reports directory + + + + + + Online Version: + + + + + + + Select-Worksheet + Select + Worksheet + + Sets the selected tab in an Excel workbook to be the chosen sheet and unselects all the others. + + + + Sometimes when a sheet is added we want it to be the active sheet, sometimes we want the active sheet to be left as it was. Select-Worksheet exists to change which sheet is the selected tab when Excel opens the file. + + + + Select-Worksheet + + ExcelPackage + + An object representing an ExcelPackage. + + ExcelPackage + + ExcelPackage + + + None + + + WorksheetName + + The name of the worksheet "Sheet1" by default. + + String + + String + + + None + + + + Select-Worksheet + + ExcelWorkbook + + An Excel workbook to which the Worksheet will be added - a package contains one Workbook so you can use workbook or package as it suits. + + ExcelWorkbook + + ExcelWorkbook + + + None + + + WorksheetName + + The name of the worksheet "Sheet1" by default. + + String + + String + + + None + + + + Select-Worksheet + + ExcelWorksheet + + An object representing an Excel worksheet. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + + + + ExcelPackage + + An object representing an ExcelPackage. + + ExcelPackage + + ExcelPackage + + + None + + + ExcelWorkbook + + An Excel workbook to which the Worksheet will be added - a package contains one Workbook so you can use workbook or package as it suits. + + ExcelWorkbook + + ExcelWorkbook + + + None + + + WorksheetName + + The name of the worksheet "Sheet1" by default. + + String + + String + + + None + + + ExcelWorksheet + + An object representing an Excel worksheet. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Select-Worksheet -ExcelWorkbook $ExcelWorkbook -WorksheetName "NewSheet" + + $ExcelWorkbook holds a workbook object containing a sheet named "NewSheet"; This sheet will become the [only] active sheet in the workbook + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Select-Worksheet -ExcelPackage $Pkg -WorksheetName "NewSheet2" + + $pkg holds an Excel Package, whose workbook contains a sheet named "NewSheet2" This sheet will become the [only] active sheet in the workbook. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> Select-Worksheet -ExcelWorksheet $ws + + $ws holds an Excel worksheet which will become the [only] active sheet in its workbook. + + + + + + Online Version: + + + + + + + Send-SQLDataToExcel + Send + SQLDataToExcel + + Inserts a DataTable - returned by a SQL query - into an ExcelSheet + + + + This command takes a SQL statement and run it against a database connection; for the connection it accepts either + * an object representing a session with a SQL server or ODBC database, or + * a connection string to make a session (if -MSSQLServer is specified it uses the SQL Native client, + + and -Connection can be a server name instead of a detailed connection string. Without this switch it uses ODBC) + The command takes all the parameters of Export-Excel, except for -InputObject (alias TargetData); after fetching the data it calls Export-Excel with the data as the value of InputParameter and whichever of Export-Excel's parameters it was passed; for details of these parameters see the help for Export-Excel. + + + + Send-SQLDataToExcel + + Connection + + A database connection string to be used to create a database session; either + * A Data source name written in the form DSN=ODBC_Data_Source_Name, or + * A full ODBC or SQL Native Client Connection string, or + * The name of a SQL server. + + Object + + Object + + + None + + + SQL + + The SQL query to run against the session which was passed in -Session or set up from -Connection. + + String + + String + + + None + + + QueryTimeout + + Override the default query time of 30 seconds. + + Int32 + + Int32 + + + 0 + + + Force + + If specified Export-Excel will be called with parameters specified, even if there is no data to send + + + SwitchParameter + + + False + + + + Send-SQLDataToExcel + + Connection + + A database connection string to be used to create a database session; either + * A Data source name written in the form DSN=ODBC_Data_Source_Name, or + * A full ODBC or SQL Native Client Connection string, or + * The name of a SQL server. + + Object + + Object + + + None + + + MsSQLserver + + Specifies the connection string is for SQL server, not ODBC. + + + SwitchParameter + + + False + + + DataBase + + Switches to a specific database on a SQL server. + + String + + String + + + None + + + SQL + + The SQL query to run against the session which was passed in -Session or set up from -Connection. + + String + + String + + + None + + + QueryTimeout + + Override the default query time of 30 seconds. + + Int32 + + Int32 + + + 0 + + + Force + + If specified Export-Excel will be called with parameters specified, even if there is no data to send + + + SwitchParameter + + + False + + + + Send-SQLDataToExcel + + Session + + An active ODBC Connection or SQL connection object representing a session with a database which will be queried to get the data . + + Object + + Object + + + None + + + SQL + + The SQL query to run against the session which was passed in -Session or set up from -Connection. + + String + + String + + + None + + + QueryTimeout + + Override the default query time of 30 seconds. + + Int32 + + Int32 + + + 0 + + + Force + + If specified Export-Excel will be called with parameters specified, even if there is no data to send + + + SwitchParameter + + + False + + + + Send-SQLDataToExcel + + QueryTimeout + + Override the default query time of 30 seconds. + + Int32 + + Int32 + + + 0 + + + DataTable + + A System.Data.DataTable object containing the data to be inserted into the spreadsheet without running a query. This remains supported to avoid breaking older scripts, but if you have a DataTable object you can pass the it into Export-Excel using -InputObject. + + DataTable + + DataTable + + + None + + + Force + + If specified Export-Excel will be called with parameters specified, even if there is no data to send + + + SwitchParameter + + + False + + + + + + Connection + + A database connection string to be used to create a database session; either + * A Data source name written in the form DSN=ODBC_Data_Source_Name, or + * A full ODBC or SQL Native Client Connection string, or + * The name of a SQL server. + + Object + + Object + + + None + + + Session + + An active ODBC Connection or SQL connection object representing a session with a database which will be queried to get the data . + + Object + + Object + + + None + + + MsSQLserver + + Specifies the connection string is for SQL server, not ODBC. + + SwitchParameter + + SwitchParameter + + + False + + + DataBase + + Switches to a specific database on a SQL server. + + String + + String + + + None + + + SQL + + The SQL query to run against the session which was passed in -Session or set up from -Connection. + + String + + String + + + None + + + QueryTimeout + + Override the default query time of 30 seconds. + + Int32 + + Int32 + + + 0 + + + DataTable + + A System.Data.DataTable object containing the data to be inserted into the spreadsheet without running a query. This remains supported to avoid breaking older scripts, but if you have a DataTable object you can pass the it into Export-Excel using -InputObject. + + DataTable + + DataTable + + + None + + + Force + + If specified Export-Excel will be called with parameters specified, even if there is no data to send + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Send-SQLDataToExcel -MsSQLserver -Connection localhost -SQL "select name,type,type_desc from [master].[sys].[all_objects]" -Path .\temp.xlsx -WorkSheetname master -AutoSize -FreezeTopRow -AutoFilter -BoldTopRow + + Connects to the local SQL server and selects 3 columns from [Sys].[all_objects] and exports then to a sheet named master with some basic header management + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> $dbPath = 'C:\Users\James\Documents\Database1.accdb' +PS\> $Connection = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=$dbPath;" +PS\> $SQL="SELECT top 25 Name,Length From TestData ORDER BY Length DESC" +PS\> Send-SQLDataToExcel -Connection $connection -SQL $sql -path .\demo1.xlsx -WorkSheetname "Sizes" -AutoSize + + This creates an ODBC connection string to read from an Access file and a SQL Statement to extracts data from it, and sends the resulting data to a new worksheet + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> $dbPath = 'C:\users\James\Documents\f1Results.xlsx' + +PS\> $Connection = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Dbq=$dbPath;" +PS\> $SQL="SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps " + + " FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" + +PS\>Send-SQLDataToExcel -Connection $connection -SQL $sql -path .\demo2.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange -ConditionalFormat @{DataBarColor="Blue"; Range="Wins"} + + Similar to the previous example, this creates a connection string, this time for an Excel file, and runs a SQL statement to get a list of motor-racing results, outputting the resulting data to a new spreadsheet. The spreadsheet is formatted and a data bar added to show make the drivers' wins clearer. (The F1 results database is available from https://1drv.ms/x/s!AhfYu7-CJv4ehNdZWxJE9LMAX\_N5sg (https://1drv.ms/x/s!AhfYu7-CJv4ehNdZWxJE9LMAX_N5sg) \) + + + + -------------------------- EXAMPLE 4 -------------------------- + PS\> $dbPath = 'C:\users\James\Documents\f1Results.xlsx' + +PS\> $SQL = "SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps " + + " FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" +PS\> $null = Get-SQL -Session F1 -excel -Connection $dbPath -sql $sql -OutputVariable Table + +PS\> Send-SQLDataToExcel -DataTable $Table -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -autosize -TableName winners -TableStyle Light6 -show + + This uses Get-SQL (at least V1.1 - download from the PowerShell gallery with Install-Module -Name GetSQL - (note the function is Get-SQL the module is GetSQL without the "-" ) + Get-SQL simplifies making database connections and building /submitting SQL statements. Here Get-SQL uses the same SQL statement as before; -OutputVariable leaves a System.Data.DataTable object in $table and Send-SQLDataToExcel puts $table into the worksheet and sets it as an Excel table. The command is equivalent to running + PS&gt; Export-Excel -inputObject $Table -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -autosize -TableName winners -TableStyle Light6 -show + This is quicker than using PS&gt; Get-SQL \ \| export-excel -ExcludeProperty rowerror,rowstate,table,itemarray,haserrors \ + (the F1 results database is available from https://1drv.ms/x/s!AhfYu7-CJv4ehNdZWxJE9LMAX\_N5sg (https://1drv.ms/x/s!AhfYu7-CJv4ehNdZWxJE9LMAX_N5sg) \) + + + + -------------------------- EXAMPLE 5 -------------------------- + PS\>$SQL = "SELECT top 25 DriverName, Count(Win) as Wins FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" +PS\> Send-SQLDataToExcel -Session $DbSessions\["f1"\] -SQL $sql -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -ClearSheet -autosize -ColumnChart + + Like the previous example, this uses Get-SQL (download from the gallery with Install-Module -Name GetSQL). It uses the database session which Get-SQL created, rather than an ODBC connection string. The Session parameter can either be a object (as shown here), or the name used by Get-SQL ("F1" in this case). + Here the data is presented as a quick chart. + + + + -------------------------- EXAMPLE 6 -------------------------- + Send-SQLDataToExcel -path .\demo4.xlsx -WorkSheetname "LR" -Connection "DSN=LR" -sql "SELECT name AS CollectionName FROM AgLibraryCollection Collection ORDER BY CollectionName" + + This example uses an Existing ODBC datasource name "LR" which maps to an adobe lightroom database and gets a list of collection names into a worksheet + + + + + + Online Version: + + + + Export-Excel + + + + + + + Set-ExcelColumn + Set + ExcelColumn + + Adds or modifies a column in an Excel worksheet, filling values, setting formatting and/or creating named ranges. + + + + Set-ExcelColumn can take a value which is either a string containing a value or formula or a scriptblock which evaluates to a string, and optionally a column number and fills that value down the column. + A column heading can be specified, and the column can be made a named range. + The column can be formatted in the same operation. + + + + Set-ExcelColumn + + ExcelPackage + + If specifying the worksheet by name, the ExcelPackage object which contains the worksheet also needs to be passed. + + ExcelPackage + + ExcelPackage + + + None + + + Worksheetname + + The sheet to update can be given as a name or an Excel Worksheet object - this sets it by name. + + String + + String + + + Sheet1 + + + Column + + Column to fill down - the first column is 1. 0 will be interpreted as first empty column. + + Object + + Object + + + 0 + + + StartRow + + First row to fill data in. + + Int32 + + Int32 + + + 0 + + + Value + + A value, formula or scriptblock to fill in. A script block can use $worksheet, $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn. + + Object + + Object + + + None + + + Heading + + Optional column heading. + + Object + + Object + + + None + + + NumberFormat + + Number format to apply to cells for example "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" or "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the row. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Colour for the text - if none specified it will be left as it it is. + + Object + + Object + + + None + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + + None + Single + Double + SingleAccounting + DoubleAccounting + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -StrikeThru:$false to remove strike through. + + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or None). + + + None + Baseline + Subscript + Superscript + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - "Solid" by default. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. Default is "General". + + + General + Left + Center + CenterContinuous + Right + Fill + Distributed + Justify + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + + Top + Center + Bottom + Distributed + Justify + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text; up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + AutoSize + + Attempt to auto-fit cells to the width their contents. + + + SwitchParameter + + + False + + + Width + + Set cells to a fixed width, ignored if -AutoSize is specified. + + Single + + Single + + + 0 + + + AutoNameRange + + Set the inserted data to be a named range. + + + SwitchParameter + + + False + + + Hide + + Hide the column. + + + SwitchParameter + + + False + + + Specified + + If specified, returns the range of cells which were affected. + + + SwitchParameter + + + False + + + PassThru + + If specified, return an object representing the Column, to allow further work to be done on it. + + + SwitchParameter + + + False + + + + Set-ExcelColumn + + Worksheet + + This passes the worksheet object instead of passing a sheet name and an Excelpackage object. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + Column + + Column to fill down - the first column is 1. 0 will be interpreted as first empty column. + + Object + + Object + + + 0 + + + StartRow + + First row to fill data in. + + Int32 + + Int32 + + + 0 + + + Value + + A value, formula or scriptblock to fill in. A script block can use $worksheet, $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn. + + Object + + Object + + + None + + + Heading + + Optional column heading. + + Object + + Object + + + None + + + NumberFormat + + Number format to apply to cells for example "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" or "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the row. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Colour for the text - if none specified it will be left as it it is. + + Object + + Object + + + None + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + + None + Single + Double + SingleAccounting + DoubleAccounting + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -StrikeThru:$false to remove strike through. + + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or None). + + + None + Baseline + Subscript + Superscript + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - "Solid" by default. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. Default is "General". + + + General + Left + Center + CenterContinuous + Right + Fill + Distributed + Justify + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + + Top + Center + Bottom + Distributed + Justify + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text; up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + AutoSize + + Attempt to auto-fit cells to the width their contents. + + + SwitchParameter + + + False + + + Width + + Set cells to a fixed width, ignored if -AutoSize is specified. + + Single + + Single + + + 0 + + + AutoNameRange + + Set the inserted data to be a named range. + + + SwitchParameter + + + False + + + Hide + + Hide the column. + + + SwitchParameter + + + False + + + Specified + + If specified, returns the range of cells which were affected. + + + SwitchParameter + + + False + + + PassThru + + If specified, return an object representing the Column, to allow further work to be done on it. + + + SwitchParameter + + + False + + + + + + ExcelPackage + + If specifying the worksheet by name, the ExcelPackage object which contains the worksheet also needs to be passed. + + ExcelPackage + + ExcelPackage + + + None + + + Worksheetname + + The sheet to update can be given as a name or an Excel Worksheet object - this sets it by name. + + String + + String + + + Sheet1 + + + Worksheet + + This passes the worksheet object instead of passing a sheet name and an Excelpackage object. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + Column + + Column to fill down - the first column is 1. 0 will be interpreted as first empty column. + + Object + + Object + + + 0 + + + StartRow + + First row to fill data in. + + Int32 + + Int32 + + + 0 + + + Value + + A value, formula or scriptblock to fill in. A script block can use $worksheet, $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn. + + Object + + Object + + + None + + + Heading + + Optional column heading. + + Object + + Object + + + None + + + NumberFormat + + Number format to apply to cells for example "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" or "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the row. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Colour for the text - if none specified it will be left as it it is. + + Object + + Object + + + None + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + SwitchParameter + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + SwitchParameter + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + SwitchParameter + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -StrikeThru:$false to remove strike through. + + SwitchParameter + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or None). + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - "Solid" by default. + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + SwitchParameter + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. Default is "General". + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text; up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + AutoSize + + Attempt to auto-fit cells to the width their contents. + + SwitchParameter + + SwitchParameter + + + False + + + Width + + Set cells to a fixed width, ignored if -AutoSize is specified. + + Single + + Single + + + 0 + + + AutoNameRange + + Set the inserted data to be a named range. + + SwitchParameter + + SwitchParameter + + + False + + + Hide + + Hide the column. + + SwitchParameter + + SwitchParameter + + + False + + + Specified + + If specified, returns the range of cells which were affected. + + SwitchParameter + + SwitchParameter + + + False + + + PassThru + + If specified, return an object representing the Column, to allow further work to be done on it. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.ExcelColumn + + + + + + + + System.String + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency' + + $ws contains a worksheet object - and column "E" is set to use the local currency format. + Intelisense will complete the names of predefined number formats. + You can see how currency is interpreted on the local computer with the command Expand-NumberFormat currency + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Set-ExcelColumn -Worksheet $ws -Heading "WinsToFastLaps" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange + + Here, $WS already contains a worksheet which holds counts of races won and fastest laps recorded by racing drivers (in columns C and E). Set-ExcelColumn specifies that Column 7 should have a heading of "WinsToFastLaps" and the data cells should contain =E2/C2 , =E3/C3 etc the new data cells should become a named range, which will also be named "WinsToFastLaps" and the column width will be set automatically. + When a value begins with "=", it is treated as a formula. + If value is a script block it will be evaluated, so here the string "=E$row/C$Row" will have the number of the current row inserted; see the value parameter for a list of variables which can be used. + Note than when evaluating an expression in a string, it is necessary to wrap it in $() so $row is valid but $($row+1) is needed. + To preventVariables merging into other parts of the string, use the back tick "$columnName`4" will be "G4" - without the backtick the string will look for a variable named "columnName4" + + + + -------------------------- EXAMPLE 3 -------------------------- + Set-ExcelColumn -Worksheet $ws -Heading "Link" -Value {"https://en.wikipedia.org" + $worksheet.cells["B$Row"].value } -AutoSize + + In this example, the worksheet in $ws has partial links to Wikipedia pages in column B. + The -Value parameter is a script block which outputs a string beginning "https..." and ending with the value of the cell at column B in the current row. + When given a valid URI, Set-ExcelColumn makes it a hyperlink. + The column will be autosized to fit the links. + + + + -------------------------- EXAMPLE 4 -------------------------- + 4..6 | Set-ExcelColumn -Worksheet $ws -AutoNameRange + + Again $ws contains a worksheet. Here columns 4 to 6 are made into named ranges, row 1 is used for the range name and the rest of the column becomes the range. + + + + + + Online Version: + + + + + + + Set-ExcelRange + Set + ExcelRange + + Applies number, font, alignment and/or color formatting, values or formulas to a range of Excel cells. + + + + Set-ExcelRange was created to set the style elements for a range of cells, this includes auto-sizing and hiding, setting font elements (Name, Size, Bold, Italic, Underline & UnderlineStyle and Subscript & SuperScript), font and background colors, borders, text wrapping, rotation, alignment within cells, and number format. + It was orignally named "Set-Format", but it has been extended to set Values, Formulas and ArrayFormulas (sometimes called Ctrl-shift-Enter [CSE] formulas); because of this, the name has become Set-ExcelRange but the old name of Set-Format is preserved as an alias. + + + + Set-ExcelRange + + Range + + One or more row(s), Column(s) and/or block(s) of cells to format. + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + NumberFormat + + Number format to apply to cells for example "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" or "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the range. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderColor + + Color of the border. + + Object + + Object + + + [System.Drawing.Color]::Black + + + BorderBottom + + Style for the bottom border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderTop + + Style for the top border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderLeft + + Style for the left border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderRight + + Style for the right border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Colour for the text - if none is specified it will be left as it is. + + Object + + Object + + + None + + + Value + + Value for the cell. + + Object + + Object + + + None + + + Formula + + Formula for the cell. + + Object + + Object + + + None + + + ArrayFormula + + Specifies formula should be an array formula (a.k.a CSE [ctrl-shift-enter] formula). + + + SwitchParameter + + + False + + + ResetFont + + Clear Bold, Italic, StrikeThrough and Underline and set color to Black. + + + SwitchParameter + + + False + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + + None + Single + Double + SingleAccounting + DoubleAccounting + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -Strikethru:$false to remove Strike through + + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or none). + + + None + Baseline + Subscript + Superscript + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - Solid by default. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. default is 'General'. + + + General + Left + Center + CenterContinuous + Right + Fill + Distributed + Justify + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + + Top + Center + Bottom + Distributed + Justify + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text; up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + AutoSize + + Autofit cells to width (columns or ranges only). + + + SwitchParameter + + + False + + + Width + + Set cells to a fixed width (columns or ranges only), ignored if Autosize is specified. + + Single + + Single + + + 0 + + + Height + + Set cells to a fixed height (rows or ranges only). + + Single + + Single + + + 0 + + + Hidden + + Hide a row or column (not a range); use -Hidden:$false to unhide. + + + SwitchParameter + + + False + + + Locked + + Locks cells. Cells are locked by default use -locked:$false on the whole sheet and then lock specific ones, and enable protection on the sheet. + + + SwitchParameter + + + False + + + Merge + + Merges cells - it is recommended that you explicitly set -HorizontalAlignment + + + SwitchParameter + + + False + + + + + + Range + + One or more row(s), Column(s) and/or block(s) of cells to format. + + Object + + Object + + + None + + + WorkSheet + + The worksheet where the format is to be applied. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + NumberFormat + + Number format to apply to cells for example "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" or "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the range. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderColor + + Color of the border. + + Object + + Object + + + [System.Drawing.Color]::Black + + + BorderBottom + + Style for the bottom border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderTop + + Style for the top border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderLeft + + Style for the left border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderRight + + Style for the right border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Colour for the text - if none is specified it will be left as it is. + + Object + + Object + + + None + + + Value + + Value for the cell. + + Object + + Object + + + None + + + Formula + + Formula for the cell. + + Object + + Object + + + None + + + ArrayFormula + + Specifies formula should be an array formula (a.k.a CSE [ctrl-shift-enter] formula). + + SwitchParameter + + SwitchParameter + + + False + + + ResetFont + + Clear Bold, Italic, StrikeThrough and Underline and set color to Black. + + SwitchParameter + + SwitchParameter + + + False + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + SwitchParameter + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + SwitchParameter + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + SwitchParameter + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -Strikethru:$false to remove Strike through + + SwitchParameter + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or none). + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - Solid by default. + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + SwitchParameter + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. default is 'General'. + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text; up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + AutoSize + + Autofit cells to width (columns or ranges only). + + SwitchParameter + + SwitchParameter + + + False + + + Width + + Set cells to a fixed width (columns or ranges only), ignored if Autosize is specified. + + Single + + Single + + + 0 + + + Height + + Set cells to a fixed height (rows or ranges only). + + Single + + Single + + + 0 + + + Hidden + + Hide a row or column (not a range); use -Hidden:$false to unhide. + + SwitchParameter + + SwitchParameter + + + False + + + Locked + + Locks cells. Cells are locked by default use -locked:$false on the whole sheet and then lock specific ones, and enable protection on the sheet. + + SwitchParameter + + SwitchParameter + + + False + + + Merge + + Merges cells - it is recommended that you explicitly set -HorizontalAlignment + + SwitchParameter + + SwitchParameter + + + False + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NumberFormat "#,###" -AutoFit + + Selects column 3 from a sheet object (within a workbook object, which is a child of the ExcelPackage object) and passes it to Set-ExcelRange which formats numbers as a integers with comma-separated groups, aligns it right, and auto-fits the column to the contents. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Set-ExcelRange -Range $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NumberFormat "#,###" + + Instead of piping the address, this version specifies a block of cells and applies similar formatting. + + + + -------------------------- EXAMPLE 3 -------------------------- + PS\> Set-ExcelRange $excel.Workbook.Worksheets[1].Tables["Processes"] -Italic + + This time instead of specifying a range of cells, a table is selected by name and formatted as italic. + + + + + + Online Version: + + + + + + + Set-ExcelRow + Set + ExcelRow + + Fills values into a [new] row in an Excel spreadsheet, and sets row formats. + + + + Set-ExcelRow accepts either a Worksheet object or an ExcelPackage object returned by Export-Excel and the name of a sheet, and inserts the chosen contents into a row of the sheet. + The contents can be a constant, like "42", a formula or a script block which is converted into a constant or a formula. + The first cell of the row can optionally be given a heading. + + + + Set-ExcelRow + + ExcelPackage + + An Excel package object - for example from Export-Excel -PassThru - if specified requires a sheet name to be passed a parameter. + + ExcelPackage + + ExcelPackage + + + None + + + Worksheetname + + The name of the sheet to update in the package. + + Object + + Object + + + Sheet1 + + + Row + + Row to fill right - first row is 1. 0 will be interpreted as first unused row. + + Object + + Object + + + 0 + + + StartColumn + + Position in the row to start from. + + Int32 + + Int32 + + + 0 + + + Value + + Value, Formula or ScriptBlock to fill in. A ScriptBlock can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn. + + Object + + Object + + + None + + + Heading + + Optional row-heading. + + Object + + Object + + + None + + + HeadingBold + + Set the heading in bold type. + + + SwitchParameter + + + False + + + HeadingSize + + Change the font-size of the heading. + + Int32 + + Int32 + + + 0 + + + NumberFormat + + Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" , "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the row. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderColor + + Color of the border. + + Object + + Object + + + [System.Drawing.Color]::Black + + + BorderBottom + + Style for the bottom border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderTop + + Style for the top border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderLeft + + Style for the left border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderRight + + Style for the right border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Color for the text - if not specified the font will be left as it it is. + + Object + + Object + + + None + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + + None + Single + Double + SingleAccounting + DoubleAccounting + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -StrikeThru:$false to remove strike through. + + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or none). + + + None + Baseline + Subscript + Superscript + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - solid by default. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. default is 'General'. + + + General + Left + Center + CenterContinuous + Right + Fill + Distributed + Justify + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + + Top + Center + Bottom + Distributed + Justify + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + Height + + Set cells to a fixed height. + + Single + + Single + + + 0 + + + Hide + + Hide the row. + + + SwitchParameter + + + False + + + ReturnRange + + If sepecified, returns the range of cells which were affected. + + + SwitchParameter + + + False + + + PassThru + + If Specified, return a row object to allow further work to be done. + + + SwitchParameter + + + False + + + + Set-ExcelRow + + Worksheet + + A worksheet object instead of passing a name and package. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + Row + + Row to fill right - first row is 1. 0 will be interpreted as first unused row. + + Object + + Object + + + 0 + + + StartColumn + + Position in the row to start from. + + Int32 + + Int32 + + + 0 + + + Value + + Value, Formula or ScriptBlock to fill in. A ScriptBlock can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn. + + Object + + Object + + + None + + + Heading + + Optional row-heading. + + Object + + Object + + + None + + + HeadingBold + + Set the heading in bold type. + + + SwitchParameter + + + False + + + HeadingSize + + Change the font-size of the heading. + + Int32 + + Int32 + + + 0 + + + NumberFormat + + Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" , "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the row. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderColor + + Color of the border. + + Object + + Object + + + [System.Drawing.Color]::Black + + + BorderBottom + + Style for the bottom border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderTop + + Style for the top border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderLeft + + Style for the left border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderRight + + Style for the right border. + + + None + Hair + Dotted + DashDot + Thin + DashDotDot + Dashed + MediumDashDotDot + MediumDashed + MediumDashDot + Thick + Medium + Double + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Color for the text - if not specified the font will be left as it it is. + + Object + + Object + + + None + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + + None + Single + Double + SingleAccounting + DoubleAccounting + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -StrikeThru:$false to remove strike through. + + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or none). + + + None + Baseline + Subscript + Superscript + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - solid by default. + + + None + Solid + DarkGray + MediumGray + LightGray + Gray125 + Gray0625 + DarkVertical + DarkHorizontal + DarkDown + DarkUp + DarkGrid + DarkTrellis + LightVertical + LightHorizontal + LightDown + LightUp + LightGrid + LightTrellis + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. default is 'General'. + + + General + Left + Center + CenterContinuous + Right + Fill + Distributed + Justify + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + + Top + Center + Bottom + Distributed + Justify + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + Height + + Set cells to a fixed height. + + Single + + Single + + + 0 + + + Hide + + Hide the row. + + + SwitchParameter + + + False + + + ReturnRange + + If sepecified, returns the range of cells which were affected. + + + SwitchParameter + + + False + + + PassThru + + If Specified, return a row object to allow further work to be done. + + + SwitchParameter + + + False + + + + + + ExcelPackage + + An Excel package object - for example from Export-Excel -PassThru - if specified requires a sheet name to be passed a parameter. + + ExcelPackage + + ExcelPackage + + + None + + + Worksheetname + + The name of the sheet to update in the package. + + Object + + Object + + + Sheet1 + + + Worksheet + + A worksheet object instead of passing a name and package. + + ExcelWorksheet + + ExcelWorksheet + + + None + + + Row + + Row to fill right - first row is 1. 0 will be interpreted as first unused row. + + Object + + Object + + + 0 + + + StartColumn + + Position in the row to start from. + + Int32 + + Int32 + + + 0 + + + Value + + Value, Formula or ScriptBlock to fill in. A ScriptBlock can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn. + + Object + + Object + + + None + + + Heading + + Optional row-heading. + + Object + + Object + + + None + + + HeadingBold + + Set the heading in bold type. + + SwitchParameter + + SwitchParameter + + + False + + + HeadingSize + + Change the font-size of the heading. + + Int32 + + Int32 + + + 0 + + + NumberFormat + + Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£\#,\#\#0.00;[Red]-£\#,\#\#0.00", "0.00%" , "\#\#/\#\#" , "0.0E+0" etc. + + Object + + Object + + + None + + + BorderAround + + Style of border to draw around the row. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderColor + + Color of the border. + + Object + + Object + + + [System.Drawing.Color]::Black + + + BorderBottom + + Style for the bottom border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderTop + + Style for the top border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderLeft + + Style for the left border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + BorderRight + + Style for the right border. + + ExcelBorderStyle + + ExcelBorderStyle + + + None + + + FontColor + + Color for the text - if not specified the font will be left as it it is. + + Object + + Object + + + None + + + Bold + + Make text bold; use -Bold:$false to remove bold. + + SwitchParameter + + SwitchParameter + + + False + + + Italic + + Make text italic; use -Italic:$false to remove italic. + + SwitchParameter + + SwitchParameter + + + False + + + Underline + + Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining. + + SwitchParameter + + SwitchParameter + + + False + + + UnderLineType + + Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single". + + ExcelUnderLineType + + ExcelUnderLineType + + + Single + + + StrikeThru + + Strike through text; use -StrikeThru:$false to remove strike through. + + SwitchParameter + + SwitchParameter + + + False + + + FontShift + + Subscript or Superscript (or none). + + ExcelVerticalAlignmentFont + + ExcelVerticalAlignmentFont + + + None + + + FontName + + Font to use - Excel defaults to Calibri. + + String + + String + + + None + + + FontSize + + Point size for the text. + + Single + + Single + + + 0 + + + BackgroundColor + + Change background color. + + Object + + Object + + + None + + + BackgroundPattern + + Background pattern - solid by default. + + ExcelFillStyle + + ExcelFillStyle + + + Solid + + + PatternColor + + Secondary color for background pattern. + + Object + + Object + + + None + + + WrapText + + Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping. + + SwitchParameter + + SwitchParameter + + + False + + + HorizontalAlignment + + Position cell contents to Left, Right, Center etc. default is 'General'. + + ExcelHorizontalAlignment + + ExcelHorizontalAlignment + + + None + + + VerticalAlignment + + Position cell contents to Top, Bottom or Center. + + ExcelVerticalAlignment + + ExcelVerticalAlignment + + + None + + + TextRotation + + Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. + + Int32 + + Int32 + + + 0 + + + Height + + Set cells to a fixed height. + + Single + + Single + + + 0 + + + Hide + + Hide the row. + + SwitchParameter + + SwitchParameter + + + False + + + ReturnRange + + If sepecified, returns the range of cells which were affected. + + SwitchParameter + + SwitchParameter + + + False + + + PassThru + + If Specified, return a row object to allow further work to be done. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + OfficeOpenXml.ExcelRow + + + + + + + + System.String + + + + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> Set-ExcelRow -Worksheet $ws -Heading Total -Value {"=sum($columnName`2:$columnName$endrow)" } + + $Ws contains a worksheet object, and no Row number is specified so Set-ExcelRow will select the next row after the end of the data in the sheet. + The first cell in the row will contain "Total", and each of the other cells will contain =Sum(xx2:xx99) where xx is the column name, and 99 is the last row of data. + Note the use of the backtick in the script block (`2) to Prevent 2 becoming part of the variable "ColumnName" + The script block can use $Worksheet, $Row, $Column (number), $ColumnName (letter), $StartRow/Column and $EndRow/Column. + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\> Set-ExcelRow -Worksheet $ws -Heading Total -HeadingBold -Value {"=sum($columnName`2:$columnName$endrow)" } -NumberFormat 'Currency' -StartColumn 2 -Bold -BorderTop Double -BorderBottom Thin + + This builds on the previous example, but this time the label "Total" appears in column 2 and the formula fills from column 3 onwards. + The formula and heading are set in bold face, and the formula is formatted for the local currency, and given a double line border above and single line border below. + + + + + + Online Version: + + + + + + + Update-FirstObjectProperties + Update + FirstObjectProperties + + Updates the first object to contain all the properties of the object with the most properties in the array. + + + + Updates the first object to contain all the properties found anywhere in the array. + This is usefull when not all objects have the same quantity of properties and CmdLets like Out-GridView or Export-Excel are not able to show all the properties because the first object doesn't have them all. + + + + Update-FirstObjectProperties + + + + + + + + CHANGELOG 2017/06/08 Function born + + + + + -------------------------- EXAMPLE 1 -------------------------- + PS\> $Array = @() +PS\> $Obj1 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' +} +PS\> $Obj2 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' +} +PS\> $Obj3 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' + Member4 = 'Fourth' +} +PS\> $Array = $Obj1, $Obj2, $Obj3 +PS\> $Array | Out-GridView -Title 'Not showing Member3 and Member4' +PS\> $Array | Update-FirstObjectProperties | Out-GridView -Title 'All properties are visible' + + Updates the first object of the array by adding Member3 and Member4 and shows before and after in gridviews + + + + -------------------------- EXAMPLE 2 -------------------------- + PS\>$ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> $Array = @() +PS\> $Obj1 = [PSCustomObjectable@{ + Member1 = 'First' + Member2 = 'Second' +} +PS\> $Obj2 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' +} +PS\> $Obj3 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' + Member4 = 'Fourth' +} +PS\> $Array = $Obj1, $Obj2, $Obj3 +PS\> $Array | Out-GridView -Title 'Not showing Member3 and Member4' +PS\> $Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorkSheetname Numbers + + Updates the first object of the array by adding property 'Member3' and 'Member4'. Afterwards, all objects are exported to an Excel file and all column headers are visible. + + + + + + Online Version: + + + + https://github.com/dfinke/ImportExcel + https://github.com/dfinke/ImportExcel + + + + \ No newline at end of file diff --git a/en/Strings.psd1 b/en/Strings.psd1 new file mode 100644 index 00000000..e6dc1991 --- /dev/null +++ b/en/Strings.psd1 @@ -0,0 +1,5 @@ +ConvertFrom-StringData @' +SystemDrawingAvailable=System.Drawing could not be loaded. Color and font look-ups may not be available. +PS5NeededForPlot=PowerShell 5 is required for plot.ps1 +ModuleReadyExceptPlot=The ImportExcel module is ready, except for that functionality +'@ \ No newline at end of file diff --git a/formatting.ps1 b/formatting.ps1 deleted file mode 100644 index 5d6d26a0..00000000 --- a/formatting.ps1 +++ /dev/null @@ -1,227 +0,0 @@ -Function Add-ConditionalFormatting { -<# -.Synopsis - Adds contitional formatting to worksheet -.Example - $excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru - - Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b":b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003" - Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled" - $excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern - $excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true - $excel.Save() ; $excel.Dispose() - - Here Export-Excel is called with the -passThru parameter so the Excel Package object is stored in $Excel - The desired worksheet is selected and the then columns B and i are conditially formatted (excluding the top row) to show - Fixed formats are then applied to dates in columns D..G and the top row is formatted - Finally the workbook is saved and the Excel closed. - -#> - Param ( - #The worksheet where the format is to be applied - [OfficeOpenXml.ExcelWorksheet]$WorkSheet , - #The area of the worksheet where the format is to be applied - [OfficeOpenXml.ExcelAddress]$Range , - #One of the standard named rules - Top / Bottom / Less than / Greater than / Contains etc - [Parameter(Mandatory=$true,ParameterSetName="NamedRule",Position=3)] - [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType]$RuleType , - #Text colour for matching objects - [Alias("ForeGroundColour")] - [System.Drawing.Color]$ForeGroundColor, - #colour for databar type charts - [Parameter(Mandatory=$true,ParameterSetName="DataBar")] - [Alias("DataBarColour")] - [System.Drawing.Color]$DataBarColor, - #One of the three-icon set types (e.g. Traffic Lights) - [Parameter(Mandatory=$true,ParameterSetName="ThreeIconSet")] - [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting3IconsSetType]$ThreeIconsSet, - #A four-icon set name - [Parameter(Mandatory=$true,ParameterSetName="FourIconSet")] - [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting4IconsSetType]$FourIconsSet, - #A five-icon set name - [Parameter(Mandatory=$true,ParameterSetName="FiveIconSet")] - [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting5IconsSetType]$FiveIconsSet, - #A value for the condition (e.g. "2000" if the test is 'lessthan 2000') - [string]$ConditionValue, - #A second value for the conditions like between x and Y - [string]$ConditionValue2, - #Background colour for matching items - [System.Drawing.Color]$BackgroundColor, - #Background pattern for matching items - [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid, - #Secondary colour when a background pattern requires it - [System.Drawing.Color]$PatternColor, - #Sets the numeric format for matching items - $NumberFormat, - #Put matching items in bold face - [switch]$Bold, - #Put matching items in italic - [switch]$Italic, - #Underline matching items - [switch]$Underline, - #Strikethrough text of matching items - [switch]$StrikeThru - ) - - If ($ThreeIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Range , $ThreeIconsSet)} - elseif ($FourIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFourIconSet( $Range , $FourIconsSet) } - elseif ($FiveIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFiveIconSet( $Range , $IconType) } - elseif ($DataBarColor) {$rule = $WorkSheet.ConditionalFormatting.AddDatabar( $Range , $DataBarColor) } - else { $rule = ($WorkSheet.ConditionalFormatting)."Add$RuleType"($Range)} - - if ($ConditionValue -and $RuleType -match "Top|Botom") {$rule.Rank = $ConditionValue } - if ($ConditionValue -and $RuleType -match "StdDev") {$rule.StdDev = $ConditionValue } - if ($ConditionValue -and $RuleType -match "Than|Equal|Expression") {$rule.Formula = $ConditionValue } - if ($ConditionValue -and $RuleType -match "Text|With") {$rule.Text = $ConditionValue } - if ($ConditionValue -and - $ConditionValue2 -and $RuleType -match "Between") {$rule.Formula = $ConditionValue - $rule.Formula2 = $ConditionValue2} - - if ($NumberFormat) {$rule.Style.NumberFormat.Format = $NumberFormat } - if ($Underline) {$rule.Style.Font.Underline = [OfficeOpenXml.Style.ExcelUnderLineType]::Single } - if ($Bold) {$rule.Style.Font.Bold = $true} - if ($Italic) {$rule.Style.Font.Italic = $true} - if ($StrikeThru) {$rule.Style.Font.Strike = $true} - if ($ForeGroundColor) {$rule.Style.Font.Color.color = $ForeGroundColor } - if ($BackgroundColor) {$rule.Style.Fill.BackgroundColor.color = $BackgroundColor } - if ($BackgroundPattern) {$rule.Style.Fill.PatternType = $BackgroundPattern } - if ($PatternColor) {$rule.Style.Fill.PatternColor.color = $PatternColor } -} - -Function Set-Format { -<# -.SYNOPSIS - Applies Number, font, alignment and colour formatting to a range of Excel Cells -.EXAMPLE - $sheet.Column(3) | Set-Format -HorizontalAlignment Right -NumberFormat "#,###" - Selects column 3 from a sheet object (within a workbook object, which is a child of the ExcelPackage object) and passes it to Set-Format which formats as an integer with comma seperated groups -.EXAMPLE - Set-Format -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NumberFormat "#,###" - Instead of piping the address in this version specifies a block of cells and applies similar formatting - -#> - Param ( - #One or more row(s), Column(s) and/or block(s) of cells to format - [Parameter(ValueFromPipeline=$true)] - [object[]]$Address , - #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc - [Alias("NFormat")] - $NumberFormat, - #Style of border to draw around the range - [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, - #Colour for the text - if none specified it will be left as it it is - [System.Drawing.Color]$FontColor, - #Clear Bold, Italic, StrikeThrough and Underline and set colour to black - [switch]$ResetFont, - #Make text bold - [switch]$Bold, - #Make text italic - [switch]$Italic, - #Underline the text using the underline style in -underline type - [switch]$Underline, - #Should Underline use single or double, normal or accounting mode : default is single normal - [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, - #StrikeThrough text - [switch]$StrikeThru, - #Subscript or superscript - [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, - #Font to use - Excel defaults to Calibri - [String]$FontName, - #Point size for the text - [float]$FontSize, - #Change background colour - [System.Drawing.Color]$BackgroundColor, - #Background pattern - solid by default - [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern =[OfficeOpenXml.Style.ExcelFillStyle]::Solid , - #Secondary colour for background pattern - [Alias("PatternColour")] - [System.Drawing.Color]$PatternColor, - #Turn on text wrapping - [switch]$WrapText, - #Position cell contents to left, right or centre ... - [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, - #Position cell contents to top bottom or centre - [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, - #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. - [ValidateRange(-90,90)] - [int]$TextRotation , - #Autofit cells to width (columns or ranges only) - [switch]$AutoFit, - #Set cells to a fixed width (columns or ranges only), ignored if Autofit is specified - [float]$Width, - #Set cells to a fixed hieght (rows or ranges only) - [float]$Height, - #Hide a row or column (not a range) - [switch]$Hidden - ) - process { - Foreach ($range in $Address) { - if ($ResetFont) {$Range.Style.Font.Color.SetColor("Black") - $Range.Style.Font.Bold = $false - $Range.Style.Font.Italic = $false - $Range.Style.Font.UnderLine = $false - $Range.Style.Font.Strike = $false - } - if ($Underline) {$Range.Style.Font.UnderLine = $true - $Range.Style.Font.UnderLineType =$UnderLineType - } - if ($Bold) {$Range.Style.Font.Bold = $true } - if ($Italic) {$Range.Style.Font.Italic = $true } - if ($StrikeThru) {$Range.Style.Font.Strike = $true } - if ($FontShift) {$Range.Style.Font.VerticalAlign = $FontShift } - if ($FontColor) {$Range.Style.Font.Color.SetColor( $FontColor ) } - if ($BorderAround) {$Range.Style.Border.BorderAround( $BorderAround ) } - if ($NumberFormat) {$Range.Style.Numberformat.Format= $NumberFormat } - if ($TextRotation) {$Range.Style.TextRotation = $TextRotation } - if ($WrapText) {$Range.Style.WrapText = $true } - if ($HorizontalAlignment) {$Range.Style.HorizontalAlignment= $HorizontalAlignment } - if ($VerticalAlignment) {$Range.Style.VerticalAlignment = $VerticalAlignment } - - if ($BackgroundColor) { - $Range.Style.Fill.PatternType = $BackgroundPattern - $Range.Style.Fill.BackgroundColor.SetColor($BackgroundColor) - if ($PatternColor) { - $range.Style.Fill.PatternColor.SetColor( $PatternColor) - } - } - - if ($Height) { - if ($Range -is [OfficeOpenXml.ExcelRow] ) {$Range.Height = $Height } - elseif ($Range -is [OfficeOpenXml.ExcelRange] ) { - ($range.Start.Row)..($range.Start.Row + $range.Rows) | - ForEach-Object {$ws.Row($_).Height = $Height } - } - else {Write-Warning -Message ("Can set the height of a row or a range but not a {0} object" -f ($Range.GetType().name)) } - } - if ($AutoFit) { - if ($Range -is [OfficeOpenXml.ExcelColumn]) {$Range.AutoFit() } - elseif ($Range -is [OfficeOpenXml.ExcelRange] ) {$Range.AutoFitColumns() } - else {Write-Warning -Message ("Can autofit a column or a range but not a {0} object" -f ($Range.GetType().name)) } - - } - elseif ($Width) { - if ($Range -is [OfficeOpenXml.ExcelColumn]) {$Range.Width = $Width} - elseif ($Range -is [OfficeOpenXml.ExcelRange] ) { - ($range.Start.Column)..($range.Start.Column+ $range.Columns) | - ForEach-Object {$ws.Column($_).Width = $Width} - } - else {Write-Warning -Message ("Can set the width of a column or a range but not a {0} object" -f ($Range.GetType().name)) } - } - if ($Hidden) { - if ($Range -is [OfficeOpenXml.ExcelRow] -or - $Range -is [OfficeOpenXml.ExcelColumn] ) {$Range.Hidden = $True} - else {Write-Warning -Message ("Can hide a row or a column but not a {0} object" -f ($Range.GetType().name)) } - } - } - } -} - -#Argument completer for colours. If we have PS 5 or Tab expansion++ then we'll register it. Otherwise it does nothing. -Function ColorCompletion{ - param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) - [System.Drawing.KnownColor].GetFields() | Where-Object {$_.IsStatic -and $_.name -like "$wordToComplete*" } | - Sort-Object name | ForEach-Object {New-CompletionResult $_.name $_.name - } -} - - \ No newline at end of file diff --git a/images/AutoCompleteSheetNames.png b/images/AutoCompleteSheetNames.png new file mode 100644 index 00000000..59b4cbd4 Binary files /dev/null and b/images/AutoCompleteSheetNames.png differ diff --git a/images/FAQ_Images/DataStructureExcelPkg.png b/images/FAQ_Images/DataStructureExcelPkg.png new file mode 100644 index 00000000..1709565e Binary files /dev/null and b/images/FAQ_Images/DataStructureExcelPkg.png differ diff --git a/images/FAQ_Images/ExcelFileContents.png b/images/FAQ_Images/ExcelFileContents.png new file mode 100644 index 00000000..d950cbe3 Binary files /dev/null and b/images/FAQ_Images/ExcelFileContents.png differ diff --git a/images/FAQ_Images/ExcelFileContentsPostAdd.png b/images/FAQ_Images/ExcelFileContentsPostAdd.png new file mode 100644 index 00000000..2e26d0cf Binary files /dev/null and b/images/FAQ_Images/ExcelFileContentsPostAdd.png differ diff --git a/images/FAQ_Images/ExcelFileDebugImg.jpg b/images/FAQ_Images/ExcelFileDebugImg.jpg new file mode 100644 index 00000000..31072634 Binary files /dev/null and b/images/FAQ_Images/ExcelFileDebugImg.jpg differ diff --git a/images/FAQ_Images/ValueAtIndexData.png b/images/FAQ_Images/ValueAtIndexData.png new file mode 100644 index 00000000..2e9f4ff0 Binary files /dev/null and b/images/FAQ_Images/ValueAtIndexData.png differ diff --git a/images/GroupDateColumn.png b/images/GroupDateColumn.png new file mode 100644 index 00000000..90dfcf83 Binary files /dev/null and b/images/GroupDateColumn.png differ diff --git a/images/GroupNumericColumn.png b/images/GroupNumericColumn.png new file mode 100644 index 00000000..6a526828 Binary files /dev/null and b/images/GroupNumericColumn.png differ diff --git a/images/GroupingNumeric.png b/images/GroupingNumeric.png new file mode 100644 index 00000000..6a392529 Binary files /dev/null and b/images/GroupingNumeric.png differ diff --git a/images/MonthlyTemperaturesWithDatabar.png b/images/MonthlyTemperaturesWithDatabar.png new file mode 100644 index 00000000..ef996911 Binary files /dev/null and b/images/MonthlyTemperaturesWithDatabar.png differ diff --git a/images/NewExcelStyle.png b/images/NewExcelStyle.png new file mode 100644 index 00000000..d409b392 Binary files /dev/null and b/images/NewExcelStyle.png differ diff --git a/images/SQL-Spreadsheet.png b/images/SQL-Spreadsheet.png new file mode 100644 index 00000000..fe493e60 Binary files /dev/null and b/images/SQL-Spreadsheet.png differ diff --git a/images/SalesData.png b/images/SalesData.png new file mode 100644 index 00000000..e85d1582 Binary files /dev/null and b/images/SalesData.png differ diff --git a/images/SalesDataChart.png b/images/SalesDataChart.png new file mode 100644 index 00000000..6c20bb8e Binary files /dev/null and b/images/SalesDataChart.png differ diff --git a/images/SalesDataChartPivotTable.png b/images/SalesDataChartPivotTable.png new file mode 100644 index 00000000..d720e3c9 Binary files /dev/null and b/images/SalesDataChartPivotTable.png differ diff --git a/images/SalesDataWithDatabar.png b/images/SalesDataWithDatabar.png new file mode 100644 index 00000000..724adadb Binary files /dev/null and b/images/SalesDataWithDatabar.png differ diff --git a/images/XLToPesterForRestAPI.gif b/images/XLToPesterForRestAPI.gif new file mode 100644 index 00000000..84f1079a Binary files /dev/null and b/images/XLToPesterForRestAPI.gif differ diff --git a/images/XLToPesterForRestAPIAndOutput.gif b/images/XLToPesterForRestAPIAndOutput.gif new file mode 100644 index 00000000..95b56d0b Binary files /dev/null and b/images/XLToPesterForRestAPIAndOutput.gif differ diff --git a/images/exportstockinfo.gif b/images/exportstockinfo.gif new file mode 100644 index 00000000..b273cff1 Binary files /dev/null and b/images/exportstockinfo.gif differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 00000000..ad6779c6 Binary files /dev/null and b/images/logo.png differ diff --git a/images/logoWithInstall.png b/images/logoWithInstall.png new file mode 100644 index 00000000..bb56ab75 Binary files /dev/null and b/images/logoWithInstall.png differ diff --git a/inferdata/README.md b/inferdata/README.md new file mode 100644 index 00000000..d9adfda9 --- /dev/null +++ b/inferdata/README.md @@ -0,0 +1,2 @@ +# InferData + diff --git a/inferdata/invoke-alltests.md b/inferdata/invoke-alltests.md new file mode 100644 index 00000000..37dd0ff6 --- /dev/null +++ b/inferdata/invoke-alltests.md @@ -0,0 +1,83 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: 'https://github.com/dfinke/ImportExcel' +schema: 2.0.0 +--- + +# Invoke-AllTests + +## SYNOPSIS + +## SYNTAX + +```text +Invoke-AllTests [[-target] ] [-OnlyPassing] [-FirstOne] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -FirstOne + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -OnlyPassing + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -target + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/inferdata/test-boolean.md b/inferdata/test-boolean.md new file mode 100644 index 00000000..d424faf9 --- /dev/null +++ b/inferdata/test-boolean.md @@ -0,0 +1,55 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Test-Boolean + +## SYNOPSIS + +## SYNTAX + +```text +Test-Boolean [[-p] ] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -p + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/inferdata/test-date.md b/inferdata/test-date.md new file mode 100644 index 00000000..3bc16883 --- /dev/null +++ b/inferdata/test-date.md @@ -0,0 +1,55 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Test-Date + +## SYNOPSIS + +## SYNTAX + +```text +Test-Date [[-p] ] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -p + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/inferdata/test-integer.md b/inferdata/test-integer.md new file mode 100644 index 00000000..9b963402 --- /dev/null +++ b/inferdata/test-integer.md @@ -0,0 +1,55 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Test-Integer + +## SYNOPSIS + +## SYNTAX + +```text +Test-Integer [[-p] ] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -p + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/inferdata/test-number.md b/inferdata/test-number.md new file mode 100644 index 00000000..0a427134 --- /dev/null +++ b/inferdata/test-number.md @@ -0,0 +1,55 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Test-Number + +## SYNOPSIS + +## SYNTAX + +```text +Test-Number [[-p] ] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -p + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/inferdata/test-string.md b/inferdata/test-string.md new file mode 100644 index 00000000..db6dc129 --- /dev/null +++ b/inferdata/test-string.md @@ -0,0 +1,55 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Test-String + +## SYNOPSIS + +## SYNTAX + +```text +Test-String [[-p] ] +``` + +## DESCRIPTION + +## EXAMPLES + +### Example 1 + +```text +PS C:\> {{ Add example code here }} +``` + +## PARAMETERS + +### -p + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/llms-examples.txt b/llms-examples.txt new file mode 100644 index 00000000..8ad05e26 --- /dev/null +++ b/llms-examples.txt @@ -0,0 +1,5592 @@ + + + + Examples/AddImage/Add-ExcelImage.ps1 + + function Add-ExcelImage { + <# + .SYNOPSIS + Adds an image to a worksheet in an Excel package. + .DESCRIPTION + Adds an image to a worksheet in an Excel package using the + `WorkSheet.Drawings.AddPicture(name, image)` method, and places the + image at the location specified by the Row and Column parameters. + + Additional position adjustment can be made by providing RowOffset and + ColumnOffset values in pixels. + .EXAMPLE + $image = [System.Drawing.Image]::FromFile($octocat) + $xlpkg = $data | Export-Excel -Path $path -PassThru + $xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell + + Where $octocat is a path to an image file, and $data is a collection of + data to be exported, and $path is the output path for the Excel document, + Add-Excel places the image at row 4 and column 6, resizing the column + and row as needed to fit the image. + .INPUTS + [OfficeOpenXml.ExcelWorksheet] + .OUTPUTS + None + #> + [CmdletBinding()] + param( + # Specifies the worksheet to add the image to. + [Parameter(Mandatory, ValueFromPipeline)] + [OfficeOpenXml.ExcelWorksheet] + $WorkSheet, + + # Specifies the Image to be added to the worksheet. + [Parameter(Mandatory)] + [System.Drawing.Image] + $Image, + + # Specifies the row where the image will be placed. Rows are counted from 1. + [Parameter(Mandatory)] + [ValidateRange(1, [int]::MaxValue)] + [int] + $Row, + + # Specifies the column where the image will be placed. Columns are counted from 1. + [Parameter(Mandatory)] + [ValidateRange(1, [int]::MaxValue)] + [int] + $Column, + + # Specifies the name to associate with the image. Names must be unique per sheet. + # Omit the name and a GUID will be used instead. + [Parameter()] + [string] + $Name, + + # Specifies the number of pixels to offset the image on the Y-axis. A + # positive number moves the image down by the specified number of pixels + # from the top border of the cell. + [Parameter()] + [int] + $RowOffset = 1, + + # Specifies the number of pixels to offset the image on the X-axis. A + # positive number moves the image to the right by the specified number + # of pixels from the left border of the cell. + [Parameter()] + [int] + $ColumnOffset = 1, + + # Increase the column width and row height to fit the image if the current + # dimensions are smaller than the image provided. + [Parameter()] + [switch] + $ResizeCell + ) + + begin { + if ($IsWindows -eq $false) { + throw "This only works on Windows and won't run on $([environment]::OSVersion)" + } + + <# + These ratios work on my machine but it feels fragile. Need to better + understand how row and column sizing works in Excel and what the + width and height units represent. + #> + $widthFactor = 1 / 7 + $heightFactor = 3 / 4 + } + + process { + if ([string]::IsNullOrWhiteSpace($Name)) { + $Name = (New-Guid).ToString() + } + if ($null -ne $WorkSheet.Drawings[$Name]) { + Write-Error "A picture with the name `"$Name`" already exists in worksheet $($WorkSheet.Name)." + return + } + + <# + The row and column offsets of 1 ensures that the image lands just + inside the gray cell borders at the top left. + #> + $picture = $WorkSheet.Drawings.AddPicture($Name, $Image) + $picture.SetPosition($Row - 1, $RowOffset, $Column - 1, $ColumnOffset) + + if ($ResizeCell) { + <# + Adding 1 to the image height and width ensures that when the + row and column are resized, the bottom right of the image lands + just inside the gray cell borders at the bottom right. + #> + $width = $widthFactor * ($Image.Width + 1) + $height = $heightFactor * ($Image.Height + 1) + $WorkSheet.Column($Column).Width = [Math]::Max($width, $WorkSheet.Column($Column).Width) + $WorkSheet.Row($Row).Height = [Math]::Max($height, $WorkSheet.Row($Row).Height) + } + } +} + + + + Examples/AddImage/AddImage.ps1 + + if ($IsWindows -eq $false) { + throw "This only works on Windows and won't run on $([environment]::OSVersion)" +} + +Add-Type -AssemblyName System.Drawing + +. $PSScriptRoot\Add-ExcelImage.ps1 + +$data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + +$path = "$PSScriptRoot/Add-Picture-test.xlsx" +Remove-Item $path -ErrorAction SilentlyContinue + + +try { + $octocat = "$PSScriptRoot/Octocat.jpg" + $image = [System.Drawing.Image]::FromFile($octocat) + $xlpkg = $data | Export-Excel -Path $path -PassThru + $xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell +} +finally { + if ($image) { + $image.Dispose() + } + if ($xlpkg) { + Close-ExcelPackage -ExcelPackage $xlpkg -Show + } +} + + + + + Examples/AddImage/README.md + + # Add-ExcelImage Example + +Adding pictures to an Excel worksheet is possible by calling the `AddPicture(name, image)` +method on the `Drawings` property of an `ExcelWorksheet` object. + +The `Add-ExcelImage` example here demonstrates how to add a picture at a given +cell location, and optionally resize the row and column to fit the image. + +## Running the example + +To try this example, run the script `AddImage.ps1`. The `Add-ExcelImage` +function will be dot-sourced, and an Excel document will be created in the same +folder with a sample data set. The Octocat image will then be embedded into +Sheet1. + +The creation of the Excel document and the `System.Drawing.Image` object +representing Octocat are properly disposed within a `finally` block to ensure +that the resources are released, even if an error occurs in the `try` block. + +## Note about column and row sizing + +Care has been taken in this example to get the image placement to be just inside +the cell border, and if the `-ResizeCell` switch is present, the height and width +of the row and column will be increased, if needed, so that the bottom right of +the image also lands just inside the cell border. + +The Excel row and column sizes are measured in "point" units rather than pixels, +and a fixed multiplication factor is used to convert the size of the image in +pixels, to the corresponding height and width values in Excel. + +It's possible that different DPI or text scaling options could result in +imperfect column and row sizing and if a better strategy is found for converting +the image dimensions to column and row sizes, this example will be updated. + + + + + Examples/AddWorkSheet/AddMultiWorkSheet.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Put some simple data in a worksheet and Get an excel package object to represent the file +1..5 | Export-Excel $xlSourcefile -WorksheetName 'Tab1' -AutoSize -AutoFilter + +#Add another tab. Replace the $TabData2 with your data +1..10 | Export-Excel $xlSourcefile -WorksheetName 'Tab 2' -AutoSize -AutoFilter + +#Add another tab. Replace the $TabData3 with your data +1..15 | Export-Excel $xlSourcefile -WorksheetName 'Tab 3' -AutoSize -AutoFilter -Show + + + + + Examples/AddWorkSheet/AddWorkSheet.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Put some simple data in a worksheet and Get an excel package object to represent the file +$excel = 1..10 | Export-Excel $xlSourcefile -PassThru +#Add a new worksheet named 'NewSheet' and copying the sheet that was just made (Sheet1) to the new sheet +Add-Worksheet -ExcelPackage $excel -WorkSheetname "NewSheet" -CopySource $excel.Workbook.Worksheets["Sheet1"] +#Save and open in Excel +Close-ExcelPackage -ExcelPackage $excel -Show + + + + + Examples/Charts/ChartAndTrendlines.ps1 + + # Creates a worksheet, addes a chart and then a Linear trendline +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screws,60 +South,lemon,48 +South,apple,71 +East,screwdriver,70 +East,kiwi,32 +West,screwdriver,1 +South,melon,21 +East,apple,79 +South,apple,68 +South,avocado,73 +"@ + +$cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine Linear +$data | Export-Excel $xlSourcefile -ExcelChartDefinition $cd -AutoNameRange -Show + + + + + Examples/Charts/ChartDataSeparatePage.ps1 + + $data = ConvertFrom-Csv @" +Region,State,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + +$xlfile = "$PSScriptRoot\spike.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$xlpkg = $data | Export-Excel $xlfile -WorksheetName Data -AutoNameRange -PassThru + +$null = Add-Worksheet -ExcelPackage $xlpkg -WorksheetName Summary -Activate + +$params = @{ + Worksheet = $xlpkg.Summary + Title = "Sales by Region" + ChartType = 'ColumnClustered' + + # XRange = "Data!A2:A10" + # YRange = "Data!C2:C10" + + XRange = 'Data!Region' + YRange = 'Data!Units' +} + +Add-ExcelChart @params + +Close-ExcelPackage $xlpkg -Show + + + + + Examples/Charts/MultiSeries.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = Invoke-Sum -data (Get-Process) -dimension Company -measure Handles, PM, VirtualMemorySize + +$c = New-ExcelChartDefinition -Title "ProcessStats" ` + -ChartType LineMarkersStacked ` + -XRange "Processes[Name]" ` + -YRange "Processes[PM]","Processes[VirtualMemorySize]" ` + -SeriesHeader "PM","VM" + +$data | + Export-Excel -Path $xlSourcefile -AutoSize -TableName Processes -ExcelChartDefinition $c -Show + + + + + Examples/Charts/MultiSeries1.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = @" +A,B,C,Date +2,1,1,2016-03-29 +5,10,1,2016-03-29 +"@ + +$c = New-ExcelChartDefinition -Title Impressions ` + -ChartType Line ` + -XRange "Impressions[Date]" ` + -YRange @("Impressions[B]","Impressions[A]") ` + -SeriesHeader 'B data','A data' ` + -Row 0 -Column 0 + +$data | ConvertFrom-Csv | Export-Excel -path $xlSourcefile -AutoSize -TableName Impressions +Export-Excel -path $xlSourcefile -worksheetName chartPage -ExcelChartDefinition $c -show + + + + + Examples/Charts/MultipleCharts.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = @" +ID,Product,Quantity,Price,Total +12001,Nails,37,3.99,147.63 +12002,Hammer,5,12.10,60.5 +12003,Saw,12,15.37,184.44 +12010,Drill,20,8,160 +12011,Crowbar,7,23.48,164.36 +"@ + +$c1 = New-ExcelChartDefinition -YRange "Price" -XRange "Product" -Title "Item price" -NoLegend -Height 225 +$c2 = New-ExcelChartDefinition -YRange "Total "-XRange "Product" -Title "Total sales" -NoLegend -Height 225 -Row 9 -Column 15 +$c3 = New-ExcelChartDefinition -YRange "Quantity"-XRange "Product" -Title "Sales volume" -NoLegend -Height 225 -Row 15 + +$data | ConvertFrom-Csv | + Export-Excel -Path $xlSourcefile -AutoFilter -AutoNameRange -AutoSize -ExcelChartDefinition $c1,$c2,$c3 -Show + + + + Examples/Charts/NumberOfVisitors.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Week, TotalVisitors +1,11916 +2,11665 +3,13901 +4,15444 +5,21592 +6,15057 +7,26187 +8,20662 +9,28935 +10,32443 +"@ + +$cd = New-ExcelChartDefinition ` + -XRange Week ` + -YRange TotalVisitors ` + -Title "No. Of Visitors" ` + -ChartType ColumnClustered ` + -NoLegend ` + -ChartTrendLine Linear + +$data | Export-Excel $xlSourcefile -Show -AutoNameRange -AutoSize -TableName Visitors -ExcelChartDefinition $cd + + + + + + Examples/Charts/plot.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +function plot { + param( + $f, + $minx, + $maxx + ) + + $minx=[math]::Round($minx,1) + $maxx=[math]::Round($maxx,1) + + #Get rid of pre-exisiting sheet + $xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" + Write-Verbose -Verbose -Message "Save location: $xlSourcefile" + Remove-Item $xlSourcefile -ErrorAction Ignore + + # $c = New-ExcelChart -XRange X -YRange Y -ChartType Line -NoLegend -Title Plot -Column 2 -ColumnOffSetPixels 35 + + $(for ($i = $minx; $i -lt $maxx-.1; $i+=.1) { + [pscustomobject]@{ + X=$i.ToString("N1") + Y=(&$f $i) + } + }) | Export-Excel $xlSourcefile -Show -AutoNameRange -LineChart -NoLegend #-ExcelChartDefinition $c +} + +function pi {[math]::pi} + +plot -f {[math]::Tan($args[0])} -minx (pi) -maxx (3*(pi)/2-.01) + + + + Examples/CommunityContributions/MultipleWorksheets.ps1 + + <# + To see this written up with example screenshots, head over to the IT Splat blog + URL: http://bit.ly/2SxieeM +#> + +## Create an Excel file with multiple worksheets +# Get a list of processes on the system +$processes = Get-Process | Sort-Object -Property ProcessName | Group-Object -Property ProcessName | Where-Object {$_.Count -gt 2} + +# Export the processes to Excel, each process on its own sheet +$processes | ForEach-Object { $_.Group | Export-Excel -Path MultiSheetExample.xlsx -WorksheetName $_.Name -AutoSize -AutoFilter } + +# Show the completed file +Invoke-Item .\MultiSheetExample.xlsx + +## Add an additional sheet to the new workbook +# Use Open-ExcelPackage to open the workbook +$excelPackage = Open-ExcelPackage -Path .\MultiSheetExample.xlsx + +# Create a new worksheet and give it a name, set MoveToStart to make it the first sheet +$ws = Add-Worksheet -ExcelPackage $excelPackage -WorksheetName 'All Services' -MoveToStart + +# Get all the running services on the system +Get-Service | Export-Excel -ExcelPackage $excelPackage -WorksheetName $ws -AutoSize -AutoFilter + +# Close the package and show the final result +Close-ExcelPackage -ExcelPackage $excelPackage -Show + + + + + Examples/ConditionalFormatting/CodeGenExamples.ps1 + + "Last7Days", "LastMonth", "LastWeek", "NextMonth", "NextWeek", "ThisMonth", "ThisWeek", "Today", "Tomorrow", "Yesterday" | + Foreach-Object { + $text = @" +`$f = ".\testExport.xlsx" + +remove-item `$f -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel `$f -Show -AutoSize -ConditionalText `$( + New-ConditionalText -ConditionalType $_ + ) +"@ + $text | Set-Content -Encoding Ascii "Highlight-$($_).ps1" + } + + + + + Examples/ConditionalFormatting/ConditionalFormattingIcontSetOnlyIcon.ps1 + + try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$data = ConvertFrom-Csv @" +Region,State,Other,Units,Price,InStock +West,Texas,1,927,923.71,1 +North,Tennessee,3,466,770.67,0 +East,Florida,0,1520,458.68,1 +East,Maine,1,1828,661.24,0 +West,Virginia,1,465,053.58,1 +North,Missouri,1,436,235.67,1 +South,Kansas,0,214,992.47,1 +North,North Dakota,1,789,640.72,0 +South,Delaware,-1,712,508.55,1 +"@ + +$xlfile = "$PSScriptRoot\test.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly +$cfi2 = New-ConditionalFormattingIconSet -Range F:F -ConditionalFormat ThreeIconSet -IconType Symbols2 -ShowIconOnly + +$data | Export-Excel $xlfile -AutoSize -ConditionalFormat $cfi1, $cfi2 -Show + + + + Examples/ConditionalFormatting/ConditionalText.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +Get-Service | + Select-Object Status, Name, DisplayName, ServiceName | + Export-Excel $xlSourcefile -Show -AutoSize -AutoFilter -ConditionalText $( + New-ConditionalText stop #Stop is the condition value, the rule is defaults to 'Contains text' and the default Colors are used + New-ConditionalText runn darkblue cyan #runn is the condition value, the rule is defaults to 'Contains text'; the foregroundColur is darkblue and the background is cyan + New-ConditionalText -ConditionalType EndsWith svc wheat green #the rule here is 'Ends with' and the value is 'svc' the forground is wheat and the background dark green + New-ConditionalText -ConditionalType BeginsWith windows darkgreen wheat #this is 'Begins with "Windows"' the forground is dark green and the background wheat + ) + + + + Examples/ConditionalFormatting/ContainsBlanks.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Define a "Contains blanks" rule. No format is specified so it default to dark-red text on light-pink background. +$ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks + +$data = $( + New-PSItem a b c @('p1', 'p2', 'p3') + New-PSItem + New-PSItem d e f + New-PSItem + New-PSItem + New-PSItem g h i +) + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#use the conditional format definition created above +$data | Export-Excel $xlSourcefile -show -ConditionalText $ContainsBlanks + + + + Examples/ConditionalFormatting/Databar.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Export processes, and get an ExcelPackage object representing the file. +$excel = Get-Process | + Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | + Export-Excel -Path $xlSourcefile -ClearSheet -WorkSheetname "Processes" -PassThru + +$sheet = $excel.Workbook.Worksheets["Processes"] + +#Apply fixed formatting to columns. -NFormat is an alias for numberformat +$sheet.Column(1) | Set-ExcelRange -Bold -AutoFit +$sheet.Column(2) | Set-ExcelRange -Width 29 -WrapText +$sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NFormat "#,###" + +Set-ExcelRange -Range $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" + +Set-ExcelRange -Range $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold +#In Set-ExcelRange "-Address" is an alias for "-Range" +Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center + +#Create a Red Data-bar for the values in Column D +Add-ConditionalFormatting -Worksheet $sheet -Address "D2:D1048576" -DataBarColor Red +# Conditional formatting applies to "Addreses" aliases allow either "Range" or "Address" to be used in Set-ExcelRange or Add-Conditional formatting. +Add-ConditionalFormatting -Worksheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red + +foreach ($c in 5..9) {Set-ExcelRange -Address $sheet.Column($c) -AutoFit } + +#Create a pivot and save the file. +Export-Excel -ExcelPackage $excel -WorkSheetname "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show + + + + Examples/ConditionalFormatting/FormatCalculations.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = $( + + New-PSItem North 111 @( 'Region', 'Amount' ) + New-PSItem East 111 + New-PSItem West 122 + New-PSItem South 200 + + New-PSItem NorthEast 103 + New-PSItem SouthEast 145 + New-PSItem SouthWest 136 + New-PSItem South 127 + + New-PSItem NorthByNory 100 + New-PSItem NothEast 110 + New-PSItem Westerly 120 + New-PSItem SouthWest 118 +) +# in this example instead of doing $variable = New-Conditional text .... ; Export-excel -ConditionalText $variable +# the syntax is used is Export-excel -ConditionalText (New-Conditional text ) + + +#$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType AboveAverage) +$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType BelowAverage) +#$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType TopPercent) + + + + + Examples/ConditionalFormatting/GenDates.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +function Get-DateOffset { + param($days=0) + + (Get-Date).AddDays($days).ToShortDateString() +} + +function Get-Number { + Get-Random -Minimum 10 -Maximum 100 +} + +New-PSItem (Get-DateOffset -7) (Get-Number) 'LastWeek,Last7Days,ThisMonth' @('Date', 'Amount', 'Label') +New-PSItem (Get-DateOffset) (Get-Number) 'Today,ThisMonth,ThisWeek' +New-PSItem (Get-DateOffset -30) (Get-Number) LastMonth +New-PSItem (Get-DateOffset -1) (Get-Number) 'Yesterday,ThisMonth,ThisWeek' +New-PSItem (Get-DateOffset) (Get-Number) 'Today,ThisMonth,ThisWeek' +New-PSItem (Get-DateOffset -5) (Get-Number) 'LastWeek,Last7Days,ThisMonth' +New-PSItem (Get-DateOffset 7) (Get-Number) 'NextWeek,ThisMonth' +New-PSItem (Get-DateOffset 28) (Get-Number) NextMonth +New-PSItem (Get-DateOffset) (Get-Number) 'Today,ThisMonth,ThisWeek' +New-PSItem (Get-DateOffset -6) (Get-Number) 'LastWeek,Last7Days,ThisMonth' +New-PSItem (Get-DateOffset -2) (Get-Number) 'Last7Days,ThisMonth,ThisWeek' +New-PSItem (Get-DateOffset 1) (Get-Number) 'Tomorrow,ThisMonth,ThisWeek' + + + + + Examples/ConditionalFormatting/GetConditionalFormatting.ps1 + + try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return} + +# This example is using Excel generated by Highlight-DiffCells.ps1 +# The displayed rule should be the same as in the PS script + +function Get-ConditionalFormatting { + param ( + [string] $xlSourcefile + ) + $excel = Open-ExcelPackage -Path $xlSourcefile + + $excel.Workbook.Worksheets | ForEach-Object { + $wsNme = $_.Name + $_.ConditionalFormatting | ForEach-Object { + "Add-ConditionalFormatting -Worksheet `$excel[""$wsNme""] -Range '$($_.Address)' -ConditionValue '=$($_.Formula)' -RuleType $($_.Type) " + } + } +} + +$xlSourcefile = "$PSScriptRoot\GetConditionalFormatting.xlsx" +Get-ConditionalFormatting -xlSourcefile $xlSourcefile + + + + Examples/ConditionalFormatting/GetProcess.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +Get-Process | Where-Object Company | Select-Object Company, Name, PM, Handles, *mem* | + +#This example creates a 3 Icon set for the values in the "PM column, and Highlights company names (anywhere in the data) with different colors + + Export-Excel -Path $xlSourcefile -Show -AutoSize -AutoNameRange ` + -ConditionalFormat $( + New-ConditionalFormattingIconSet -Range "C:C" ` + -ConditionalFormat ThreeIconSet -IconType Arrows + + ) -ConditionalText $( + New-ConditionalText Microsoft -ConditionalTextColor Black + New-ConditionalText Google -BackgroundColor Cyan -ConditionalTextColor Black + New-ConditionalText authors -BackgroundColor LightBlue -ConditionalTextColor Black + New-ConditionalText nvidia -BackgroundColor LightGreen -ConditionalTextColor Black + ) + + + + + Examples/ConditionalFormatting/Highlight-DiffCells.ps1 + + try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" + +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Region,State,Units2021,Units2022 +West,Texas,927,925 +North,Tennessee,466,466 +East,Florida,520,458 +East,Maine,828,661 +West,Virginia,465,465 +North,Missouri,436,235 +South,Kansas,214,214 +North,North Dakota,789,640 +South,Delaware,712,508 +"@ + +$excel = $data | Export-Excel $xlSourcefile -AutoSize -PassThru + +Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "C2:D10" -ConditionValue '=$C2=$D2' -RuleType Expression -BackgroundColor ([System.Drawing.Color]::Thistle) -Bold +Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "A2:D10" -ConditionValue '=$C2=$D2' -RuleType Expression -BackgroundColor ([System.Drawing.Color]::LavenderBlush) + +Close-ExcelPackage $excel -Show + + + + Examples/ConditionalFormatting/Highlight-Last7Days.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType Last7Days + ) + + + + + Examples/ConditionalFormatting/Highlight-LastMonth.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType LastMonth + ) + + + + + Examples/ConditionalFormatting/Highlight-LastWeek.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType LastWeek + ) + + + + + Examples/ConditionalFormatting/Highlight-NextMonth.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType NextMonth + ) + + + + + Examples/ConditionalFormatting/Highlight-NextWeek.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType NextWeek + ) + + + + + Examples/ConditionalFormatting/Highlight-ThisMonth.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType ThisMonth + ) + + + + + Examples/ConditionalFormatting/Highlight-ThisWeek.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType ThisWeek + ) + + + + + Examples/ConditionalFormatting/Highlight-Today.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType Today + ) + + + + + Examples/ConditionalFormatting/Highlight-Tomorrow.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType Tomorrow + ) + + + + + Examples/ConditionalFormatting/Highlight-Yesterday.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +.\GenDates.ps1 | + Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText $( + New-ConditionalText -ConditionalType Yesterday + ) + + + + + Examples/ConditionalFormatting/HighlightDuplicates.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = $( + + New-PSItem North 111 @('Region', 'Amount' ) + New-PSItem East 11 + New-PSItem West 12 + New-PSItem South 1000 + + New-PSItem NorthEast 10 + New-PSItem SouthEast 14 + New-PSItem SouthWest 13 + New-PSItem South 12 + + New-PSItem NorthByNory 100 + New-PSItem NothEast 110 + New-PSItem Westerly 120 + New-PSItem SouthWest 11 +) + +$data | Export-Excel $xlSourcefile -Show -AutoSize -ConditionalText (New-ConditionalText -ConditionalType DuplicateValues) + + + + Examples/ConditionalFormatting/MonthlyTemperatuesDatabar.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$excel = @" +Month,New York City,Austin Texas,Portland Oregon +Jan,39,61,46 +Feb,42,65,51 +Mar,50,73,56 +Apr,62,80,61 +May,72,86,67 +Jun,80,92,73 +Jul,85,95,80 +Aug,84,96,80 +Sep,76,90,75 +Oct,65,82,63 +Nov,54,71,52 +Dec,44,63,46 +"@ | ConvertFrom-csv | + Export-Excel -Path $xlSourcefile -WorkSheetname Sheet1 -AutoNameRange -AutoSize -Title "Monthly Temperatures" -PassThru + +$sheet = $excel.Workbook.Worksheets["Sheet1"] +Add-ConditionalFormatting -Worksheet $sheet -Range "B1:D14" -DataBarColor CornflowerBlue + +Close-ExcelPackage $excel -Show + + + + Examples/ConditionalFormatting/RangeFormatting.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +function Get-DateOffset ($days=0) { + (Get-Date).AddDays($days).ToShortDateString() +} + +$( + New-PSItem (Get-DateOffset -1) (Get-DateOffset 1) @("Start", "End") + New-PSItem (Get-DateOffset) (Get-DateOffset 7) + New-PSItem (Get-DateOffset -10) (Get-DateOffset -1) +) | + + Export-Excel $xlSourcefile -Show -AutoSize -AutoNameRange -ConditionalText $( + New-ConditionalText -Range Start -ConditionalType Yesterday -ConditionalTextColor Red + New-ConditionalText -Range End -ConditionalType Yesterday -BackgroundColor Blue -ConditionalTextColor Red + ) + + + + Examples/ConditionalFormatting/SalesReportWithDatabar.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$excel = @" +Month,Sales +Jan,1277 +Feb,1003 +Mar,1105 +Apr,952 +May,770 +Jun,621 +"@ | ConvertFrom-csv | + Export-Excel -Path $xlSourcefile -WorkSheetname Sheet1 -AutoNameRange -PassThru + +$sheet = $excel.Workbook.Worksheets["Sheet1"] +Add-ConditionalFormatting -Worksheet $sheet -Range "B1:B7" -DataBarColor LawnGreen + +Set-ExcelRange -Address $sheet.Cells["A8"] -Value "Total" +Set-ExcelRange -Address $sheet.Cells["B8"] -Formula "=Sum(Sales)" + +Close-ExcelPackage $excel -Show + + + + Examples/ConditionalFormatting/TextComparisons.ps1 + + try {Import-Module ..\..\ImportExcel.psd1 -Force} catch {throw ; return} + + $data = $( + New-PSItem 100 @('test', 'testx') + New-PSItem 200 + New-PSItem 300 + New-PSItem 400 + New-PSItem 500 + ) + + #Get rid of pre-exisiting sheet + $xlSourcefile1 = "$env:TEMP\ImportExcelExample1.xlsx" + $xlSourcefile2 = "$env:TEMP\ImportExcelExample2.xlsx" + + Write-Verbose -Verbose -Message "Save location: $xlSourcefile1" + Write-Verbose -Verbose -Message "Save location: $xlSourcefile2" + + Remove-Item $xlSourcefile1 -ErrorAction Ignore + Remove-Item $xlSourcefile2 -ErrorAction Ignore + + $data | Export-Excel $xlSourcefile1 -Show -ConditionalText $( + New-ConditionalText -ConditionalType GreaterThan 300 + New-ConditionalText -ConditionalType LessThan 300 -BackgroundColor cyan + ) + + $data | Export-Excel $xlSourcefile2 -Show -ConditionalText $( + New-ConditionalText -ConditionalType GreaterThanOrEqual 275 + New-ConditionalText -ConditionalType LessThanOrEqual 250 -BackgroundColor cyan + ) + + + + + Examples/ConditionalFormatting/Top10-DataBar-TwoColorScale.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-csv @" +Store,January,February,March,April,May,June +store27,99511,64582,45216,48690,64921,54066 +store82,22275,23708,28223,26699,41388,31648 +store41,24683,22583,97947,31999,39092,41201 +store16,16568,48040,68589,20394,63202,26197 +store21,99353,23470,28398,21788,94101,88608 +store86,66662,83321,27489,92627,54084,24278 +store07,92692,53300,29284,39643,33556,53885 +store58,68875,83705,66635,81025,30207,75570 +store01,21292,82341,81339,12505,29516,41634 +store82,74047,93325,25002,40113,76278,45707 +"@ + +Export-Excel -InputObject $data -Path $xlSourcefile -TableName RawData -WorksheetName RawData +Export-Excel -InputObject $data -Path $xlSourcefile -TableName TopData -WorksheetName StoresTop10Sales +Export-Excel -InputObject $data -Path $xlSourcefile -TableName Databar -WorksheetName StoresSalesDataBar +Export-Excel -InputObject $data -Path $xlSourcefile -TableName TwoColorScale -WorksheetName StoresSalesTwoColorScale + +$xl = Open-ExcelPackage -Path $xlSourcefile + +Set-ExcelRange -Worksheet $xl.StoresTop10Sales -Range $xl.StoresTop10Sales.dimension.address -NumberFormat 'Currency' -AutoSize +Set-ExcelRange -Worksheet $xl.StoresSalesDataBar -Range $xl.StoresSalesDataBar.dimension.address -NumberFormat 'Currency' -AutoSize +Set-ExcelRange -Worksheet $xl.StoresSalesTwoColorScale -Range $xl.StoresSalesDataBar.dimension.address -NumberFormat 'Currency' -AutoSize + +Add-ConditionalFormatting -Worksheet $xl.StoresTop10Sales -Address $xl.StoresTop10Sales.dimension.address -RuleType Top -ForegroundColor white -BackgroundColor green -ConditionValue 10 +Add-ConditionalFormatting -Worksheet $xl.StoresSalesDataBar -Address $xl.StoresSalesDataBar.dimension.address -DataBarColor Red +Add-ConditionalFormatting -Worksheet $xl.StoresSalesTwoColorScale -Address $xl.StoresSalesDataBar.dimension.address -RuleType TwoColorScale + +Close-ExcelPackage $xl -Show + + + + Examples/ConvertFrom/ConvertFrom.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +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" +} + + + + Examples/CustomNumbers/ShortenNumbers.ps1 + + # How to convert abbreviate or shorten long numbers in Excel + +Remove-Item .\custom.xlsx -ErrorAction SilentlyContinue + +$data = $( + 12000 + 1000 + 2000 + 3000 + 2400 + 3600 + 6000 + 13000 + 40000 + 400000 + 1000000 +) + +$excel = $data | Export-Excel .\custom.xlsx -PassThru + +Set-ExcelRange -Worksheet $excel.Sheet1 -Range "A:A" -NumberFormat '[>999999]#,,"M";#,"K"' + +Close-ExcelPackage $excel -Show + + + + Examples/CustomReporting/CustomReport.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = @" +From,To,RDollars,RPercent,MDollars,MPercent,Revenue,Margin +Atlanta,New York,3602000,.0809,955000,.09,245,65 +New York,Washington,4674000,.105,336000,.03,222,16 +Chicago,New York,4674000,.0804,1536000,.14,550,43 +New York,Philadelphia,12180000,.1427,-716000,-.07,321,-25 +New York,San Francisco,3221000,.0629,1088000,.04,436,21 +New York,Phoneix,2782000,.0723,467000,.10,674,33 +"@ | ConvertFrom-Csv + +$data | Export-Excel $xlSourcefile -AutoSize + +$excel = Open-ExcelPackage $xlSourcefile + +$sheet1 = $excel.Workbook.Worksheets["sheet1"] + +$sheet1.View.ShowGridLines = $false +$sheet1.View.ShowHeaders = $false + +Set-ExcelRange -Address $sheet1.Cells["C:C"] -NumberFormat "$#,##0" -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["D:D"] -NumberFormat "#.#0%" -WrapText -HorizontalAlignment Center + +Set-ExcelRange -Address $sheet1.Cells["E:E"] -NumberFormat "$#,##0" -WrapText -HorizontalAlignment Center +Set-ExcelRange -Address $sheet1.Cells["F:F"] -NumberFormat "#.#0%" -WrapText -HorizontalAlignment Center + +Set-ExcelRange -Address $sheet1.Cells["G:H"] -WrapText -HorizontalAlignment Center + +## Insert Rows/Columns +$sheet1.InsertRow(1, 1) + +foreach ($col in @(2, 4, 6, 8, 10, 12, 14)) { + $sheet1.InsertColumn($col, 1) + $sheet1.Column($col).width = .75 +} + +Set-ExcelRange -Address $sheet1.Cells["E:E"] -Width 12 +Set-ExcelRange -Address $sheet1.Cells["I:I"] -Width 12 + +$BorderBottom = "Thick" +$BorderColor = "Black" + +Set-ExcelRange -Address $sheet1.Cells["A2"] -BorderBottom $BorderBottom -BorderColor $BorderColor + +Set-ExcelRange -Address $sheet1.Cells["C2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["E2:G2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["I2:K2"] -BorderBottom $BorderBottom -BorderColor $BorderColor +Set-ExcelRange -Address $sheet1.Cells["M2:O2"] -BorderBottom $BorderBottom -BorderColor $BorderColor + +Set-ExcelRange -Address $sheet1.Cells["A2:C8"] -FontColor Gray + +$HorizontalAlignment = "Center" +Set-ExcelRange -Address $sheet1.Cells["F1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Revenue +Set-ExcelRange -Address $sheet1.Cells["J1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Margin +Set-ExcelRange -Address $sheet1.Cells["N1"] -HorizontalAlignment $HorizontalAlignment -Bold -Value Passenger + +Set-ExcelRange -Address $sheet1.Cells["E2"] -Value '($)' +Set-ExcelRange -Address $sheet1.Cells["G2"] -Value '%' +Set-ExcelRange -Address $sheet1.Cells["I2"] -Value '($)' +Set-ExcelRange -Address $sheet1.Cells["K2"] -Value '%' + +Set-ExcelRange -Address $sheet1.Cells["C10"] -HorizontalAlignment Right -Bold -Value "Grand Total Calculation" +Set-ExcelRange -Address $sheet1.Cells["E10"] -Formula "=Sum(E3:E8)" -Bold +Set-ExcelRange -Address $sheet1.Cells["I10"] -Formula "=Sum(I3:I8)" -Bold +Set-ExcelRange -Address $sheet1.Cells["M10"] -Formula "=Sum(M3:M8)" -Bold +Set-ExcelRange -Address $sheet1.Cells["O10"] -Formula "=Sum(O3:O8)" -Bold + +Close-ExcelPackage $excel -Show + + + + + Examples/CustomizeExportExcel/Out-Excel.ps1 + + <# + This is an example on how to customize Export-Excel to your liking. + First select a name for your function, in ths example its "Out-Excel" you can even set the name to "Export-Excel". + You can customize the following things: + 1. To add parameters to the function define them in "param()", here I added "Preset1" and "Preset2". + The parameters need to be removed after use (see comments and code below). + 2. To remove parameters from the function add them to the list under "$_.Name -notmatch", I removed "Now". + 3. Add your custom code, here I defined what the Presets do: + Preset1 configure the TableStyle, name the table depending on WorksheetName and FreezeTopRow. + Preset2 will set AutoFilter and add the Title "Daily Report". + (see comments and code below). +#> +function Out-Excel { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param( + [switch] + ${Preset1}, + [switch] + ${Preset2} + ) + DynamicParam { + $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() + foreach ($P in (Get-Command -Name Export-Excel).Parameters.values.where( { $_.Name -notmatch 'Verbose|Debug|Action$|Variable$|Buffer$|Now' })) { + $paramDictionary.Add($P.Name, [System.Management.Automation.RuntimeDefinedParameter]::new( $P.Name, $P.ParameterType, $P.Attributes ) ) + } + return $paramDictionary + } + + begin { + try { + # Run you custom code here if it need to run before calling Export-Excel. + $PSBoundParameters['Now'] = $true + if ($Preset1) { + $PSBoundParameters['TableStyle'] = 'Medium7' + $PSBoundParameters['FreezeTopRow'] = $true + if ($PSBoundParameters['WorksheetName'] -and -not $PSBoundParameters['TableName']) { + $PSBoundParameters['TableName'] = $PSBoundParameters['WorksheetName'] + '_Table' + } + } + elseif ($Preset2) { + $PSBoundParameters['Title'] = 'Daily Report' + $PSBoundParameters['AutoFilter'] = $true + } + # Remove the extra params we added as Export-Excel will not know what to do with them: + $null = $PSBoundParameters.Remove('Preset1') + $null = $PSBoundParameters.Remove('Preset2') + + # The rest of the code was auto generated. + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Export-Excel', [System.Management.Automation.CommandTypes]::Function) + # You can add a pipe after @PSBoundParameters to manipulate the output. + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline() + $steppablePipeline.Begin($PSCmdlet) + } + catch { + throw + } + } + + process { + try { + $steppablePipeline.Process($_) + } + catch { + throw + } + } + + end { + try { + $steppablePipeline.End() + } + catch { + throw + } + } + <# + + .ForwardHelpTargetName Export-Excel + .ForwardHelpCategory Function + + #> +} + + + + Examples/ExcelBuiltIns/DSUM.ps1 + + # DSUM +# Adds the numbers in a field (column) of records in a list or database that match conditions that you specify. +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Color,Date,Sales +Red,1/15/2018,250 +Blue,1/15/2018,200 +Red,1/16/2018,175 +Blue,1/16/2018,325 +Red,1/17/2018,150 +Blue,1/17/2018,300 +"@ + +$xl = Export-Excel -InputObject $data -Path $xlSourcefile -AutoSize -AutoFilter -TableName SalesInfo -AutoNameRange -PassThru + +$databaseAddress = $xl.Sheet1.Dimension.Address +Set-Format -Worksheet $xl.Sheet1 -Range C:C -NumberFormat '$##0' + +Set-Format -Worksheet $xl.Sheet1 -Range E1 -Value Color +Set-Format -Worksheet $xl.Sheet1 -Range F1 -Value Date +Set-Format -Worksheet $xl.Sheet1 -Range G1 -Value Sales + +Set-Format -Worksheet $xl.Sheet1 -Range E2 -Value Red + +Set-Format -Worksheet $xl.Sheet1 -Range E4 -Value Sales +Set-Format -Worksheet $xl.Sheet1 -Range F4 -Formula ('=DSUM({0},"Sales",E1:G2)' -f $databaseAddress) -NumberFormat '$##0' + +Close-ExcelPackage $xl -Show + + + + Examples/ExcelBuiltIns/VLOOKUP.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv @" +Fruit,Amount +Apples,50 +Oranges,20 +Bananas,60 +Lemons,40 +"@ + +$xl = Export-Excel -InputObject $data -Path $xlSourcefile -PassThru -AutoSize + +Set-ExcelRange -Worksheet $xl.Sheet1 -Range D2 -BackgroundColor LightBlue -Value Apples + +$rows = $xl.Sheet1.Dimension.Rows +Set-ExcelRange -Worksheet $xl.Sheet1 -Range E2 -Formula "=VLookup(D2,A2:B$($rows),2,FALSE)" + +Close-ExcelPackage $xl -Show + + + + Examples/ExcelDataValidation/MutipleValidations.ps1 + + #region Setup +<# + This examples demos three types of validation: + * Creating a list using a PowerShell array + * Creating a list data from another Excel Worksheet + * Creating a rule for numbers to be between 0 an 10000 + + Run the script then try" + * Add random data in Column B + * Then choose from the drop down list + * Add random data in Column C + * Then choose from the drop down list + * Add .01 in column F +#> + +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$data = ConvertFrom-Csv -InputObject @" +ID,Region,Product,Quantity,Price +12001,North,Nails,37,3.99 +12002,South,Hammer,5,12.10 +12003,East,Saw,12,15.37 +12010,West,Drill,20,8 +12011,North,Crowbar,7,23.48 +"@ + +# Export the raw data +$excelPackage = $Data | + Export-Excel -WorksheetName "Sales" -Path $xlSourcefile -PassThru + +# Creates a sheet with data that will be used in a validation rule +$excelPackage = @('Chisel', 'Crowbar', 'Drill', 'Hammer', 'Nails', 'Saw', 'Screwdriver', 'Wrench') | + Export-excel -ExcelPackage $excelPackage -WorksheetName Values -PassThru + +#endregion + +#region Creating a list using a PowerShell array +$ValidationParams = @{ + Worksheet = $excelPackage.sales + ShowErrorMessage = $true + ErrorStyle = 'stop' + ErrorTitle = 'Invalid Data' +} + + +$MoreValidationParams = @{ + Range = 'B2:B1001' + ValidationType = 'List' + ValueSet = @('North', 'South', 'East', 'West') + ErrorBody = "You must select an item from the list." +} + +Add-ExcelDataValidationRule @ValidationParams @MoreValidationParams +#endregion + +#region Creating a list data from another Excel Worksheet +$MoreValidationParams = @{ + Range = 'C2:C1001' + ValidationType = 'List' + Formula = 'values!$a$1:$a$10' + ErrorBody = "You must select an item from the list.`r`nYou can add to the list on the values page" #Bucket +} + +Add-ExcelDataValidationRule @ValidationParams @MoreValidationParams +#endregion + +#region Creating a rule for numbers to be between 0 an 10000 +$MoreValidationParams = @{ + Range = 'F2:F1001' + ValidationType = 'Integer' + Operator = 'between' + Value = 0 + Value2 = 10000 + ErrorBody = 'Quantity must be a whole number between 0 and 10000' +} + +Add-ExcelDataValidationRule @ValidationParams @MoreValidationParams +#endregion + +#region Close Package +Close-ExcelPackage -ExcelPackage $excelPackage -Show +#endregion + + + + Examples/ExcelToSQLInsert/DemoSQLInsert.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path ".\Movies.xlsx" -ConvertEmptyStringsToNull +'' +'# UseMSSQLSyntax' +ConvertFrom-ExcelToSQLInsert -UseMSSQLSyntax -TableName "Movies" -Path ".\Movies.xlsx" -ConvertEmptyStringsToNull + + + + Examples/Experimental/Export-MultipleExcelSheets.ps1 + + function Export-MultipleExcelSheets { + <# + .Synopsis + Takes a hash table of scriptblocks and exports each as a sheet in an Excel file + + .Example +$p = Get-Process + +$InfoMap = @{ + PM = { $p | Select-Object company, pm } + Handles = { $p | Select-Object company, handles } + Services = { Get-Service } +} + +Export-MultipleExcelSheets -Path $xlfile -InfoMap $InfoMap -Show -AutoSize + #> + param( + [Parameter(Mandatory = $true)] + $Path, + [Parameter(Mandatory = $true)] + [hashtable]$InfoMap, + [string]$Password, + [Switch]$Show, + [Switch]$AutoSize + ) + + $parameters = @{ } + $PSBoundParameters + $parameters.Remove("InfoMap") + $parameters.Remove("Show") + + $parameters.Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) + + foreach ($entry in $InfoMap.GetEnumerator()) { + if ($entry.Value -is [scriptblock]) { + Write-Progress -Activity "Exporting" -Status "$($entry.Key)" + $parameters.WorkSheetname = $entry.Key + + & $entry.Value | Export-Excel @parameters + } + else { + Write-Warning "$($entry.Key) not exported, needs to be a scriptblock" + } + } + + if ($Show) { Invoke-Item $Path } +} + + + + + Examples/Experimental/tryExportMultipleExcelSheets.ps1 + + . "$PSScriptRoot\Export-MultipleExcelSheets.ps1" + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$p = Get-Process + +$InfoMap = @{ + PM = { $p | Select-Object company, pm } + Handles = { $p | Select-Object company, handles } + Services = { Get-Service } + Files = { Get-ChildItem -File } + Albums = { ConvertFrom-Csv (Invoke-RestMethod https://raw.githubusercontent.com/dfinke/powershell-for-developers/master/chapter05/BeaverMusic/BeaverMusic.UI.Shell/albums.csv) } + WillNotGetExported = "Hello World" +} + +Export-MultipleExcelSheets -Path $xlSourcefile -InfoMap $InfoMap -Show -AutoSize + + + + Examples/Extra/Get-ModuleStats.ps1 + + <# + .Synopsis + Chart download stats for modules/scripts published on the PowerShell Gallery + .Example + .\Get-ModuleStats.ps1 ImportExcel +#> + +param( + $moduleName = "ImportExcel", + [ValidateSet('Column','Bar','Line','Pie')] + $chartType="Line" +) + +$download = Get-HtmlTable "https://www.powershellgallery.com/packages/$moduleName" -FirstDataRow 1 | + Select-Object @{n="Version";e={$v = $Null ; if ($_.version -is [valuetype]) {[string][version]($_.version.tostring("0.0")) } + elseif ($_.version -is [string] -and [version]::TryParse($_.version.trim(),[ref]$v)) {$v} + else {$_.Version.trim() -replace "\s+"," " } }}, + Downloads, @{n="LastUpdated";e={[datetime]$_.last_updated}} | + Sort-Object lastupdated -Descending + +& "$($chartType)Chart" $download "Download stats for $moduleName" -nolegend:($chartype -ne 'pie') + + + + + Examples/Fibonacci/ShowFibonacci.ps1 + + param ($fibonacciDigits=10) + +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$( + New-PSItem 0 + New-PSItem 1 + + ( + 2..$fibonacciDigits | + ForEach-Object { + New-PSItem ('=a{0}+a{1}' -f ($_+1),$_) + } + ) +) | Export-Excel $xlSourcefile -Show + + + + + Examples/FormatCellStyles/ApplyFormatInScriptBlock.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +Get-Process | + Select-Object Company,Handles,PM, NPM| + Export-Excel $xlSourcefile -Show -AutoSize -CellStyleSB { + param( + $workSheet, + $totalRows, + $lastColumn + ) + + Set-CellStyle $workSheet 1 $LastColumn Solid Cyan + + foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 0})) { + Set-CellStyle $workSheet $row $LastColumn Solid Gray + } + + foreach($row in (2..$totalRows | Where-Object {$_ % 2 -eq 1})) { + Set-CellStyle $workSheet $row $LastColumn Solid LightGray + } + } + + + + Examples/FormatCellStyles/ApplyStyle.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$data = ConvertFrom-Csv @' +Item,Quantity,Price,Total Cost +Footballs,9,21.95,197.55 +Cones,36,7.99,287.64 +Shin Guards,14,10.95,153.3 +Turf Shoes,22,79.95,1758.9 +Baseballs,68,7.99,543.32 +Baseball Gloves,31,65.00,2015.00 +Baseball Bats,38,159.00,6042.00 +'@ + +$f = "$env:TEMP\styles.xlsx" +Remove-Item $f -ErrorAction SilentlyContinue + +$pkg = $data | Export-Excel -Path $f -AutoSize -PassThru + +$ws = $pkg.Workbook.Worksheets["Sheet1"] + +Set-ExcelRange -Worksheet $ws -Range "A2:C6" -BackgroundColor PeachPuff -FontColor Purple -FontSize 12 -Width 12 +Set-ExcelRange -Worksheet $ws -Range "D2:D6" -BackgroundColor WhiteSmoke -FontColor Orange -Bold -FontSize 12 -Width 12 +Set-ExcelRange -Worksheet $ws -Range "A1:D1" -BackgroundColor BlueViolet -FontColor Wheat -FontSize 12 -Width 12 +Set-ExcelRange -Worksheet $ws -Range "A:A" -Width 15 + +Close-ExcelPackage -ExcelPackage $pkg -Show + + + + Examples/FormatCellStyles/PassInScriptBlock.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$RandomStyle = { + param( + $workSheet, + $totalRows, + $lastColumn + ) + + 2..$totalRows | ForEach-Object{ + Set-CellStyle $workSheet $_ $LastColumn Solid (Get-Random @("LightGreen", "Gray", "Red")) + } +} + +Get-Process | + Select-Object Company,Handles,PM, NPM| + Export-Excel $xlSourcefile -Show -AutoSize -CellStyleSB $RandomStyle + + + + + Examples/FormatResults/GetAsMarkdownTable.ps1 + + param( + [Alias('FullName')] + [String[]]$Path +) + +if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command Format-Markdown -ErrorAction SilentlyContinue)) { + throw "This requires EZOut. Install-Module EZOut -AllowClobber -Scope CurrentUser" +} + +Import-Excel $Path | Format-Markdown + + + + Examples/FormatResults/GetAsYaml.ps1 + + param( + [Alias('FullName')] + [String[]]$Path +) + +if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command Format-YAML -ErrorAction SilentlyContinue)) { + throw "This requires EZOut. Install-Module EZOut -AllowClobber -Scope CurrentUser" +} + +Import-Excel $Path | Format-YAML + + + + Examples/FormatResults/Sample.csv + + "OrderId","Category","Sales","Quantity","Discount" +"1","Cosmetics","744.01","7","0.7" +"2","Grocery","349.13","25","0.3" +"3","Apparels","535.11","88","0.2" +"4","Electronics","524.69","60","0.1" +"5","Electronics","439.1","41","0" +"6","Apparels","56.84","54","0.8" +"7","Electronics","326.66","97","0.7" +"8","Cosmetics","17.25","74","0.6" +"9","Grocery","199.96","39","0.4" +"10","Grocery","731.77","20","0.3" + + + + + Examples/Freeze/FreezePane.ps1 + + # Freeze the columns/rows to left and above the cell + +$data = ConvertFrom-Csv @" +Region,State,Units,Price,Name,NA,EU,JP,Other +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46 +"@ + +$xlfilename = "test.xlsx" +Remove-Item $xlfilename -ErrorAction SilentlyContinue + +<# + Freezes the top two rows and the two leftmost column +#> + +$data | Export-Excel $xlfilename -Show -Title 'Sales Data' -FreezePane 3, 3 + + + + Examples/GenerateData/GenDataForCustomReport.ps1 + + if(!(Get-Command ig -ErrorAction SilentlyContinue)) { + + "Use ``Install-Module NameIT`` to get the needed module from the gallery to support running this script" + + return +} + +$sign=@{sign=@( "+", "-" )} +$location=@{location=@("Atlanta", "Newark", "Washington", "Chicago", "Philadelphia", "Houston", "Phoneix")} + +$(1..6 | Foreach-Object { + + $from=$to="" + while($from -eq $to) { + $from=ig "[location]" -CustomData $location + $to=ig "[location]" -CustomData $location + } + + [double]$a=ig "########" + [double]$b=ig ".####" + [double]$c=ig "#######" + [double]$d=ig "[sign].##" -CustomData $sign + [double]$e=ig "###" + [double]$f=ig "[sign]##" -CustomData $sign + + #"{0},{1},{2},{3},{4},{5},{6},{7}" -f $from, $to, $a, $b, $c, $d, $e, $f + + [PSCustomObject][Ordered]@{ + From=$from + To=$to + RDollars=$a + RPercent=$b + MDollars=$c + MPercent=$d + Revenue=$e + Margin=$f + } +} | ConvertTo-Csv -NoTypeInformation) -replace '"','' # | Export-Excel + + + + + Examples/Grouping/First10Races.csv + + Race,Date,FinishPosition,Driver,GridPosition,Team,Points +Australian,25/03/2018,1,Sebastian Vettel,3,Ferrari,25 +Australian,25/03/2018,2,Lewis Hamilton,1,Mercedes,18 +Australian,25/03/2018,3,Kimi Räikkönen,2,Ferrari,15 +Australian,25/03/2018,4,Daniel Ricciardo,8,Red Bull Racing-TAG Heuer,12 +Australian,25/03/2018,5,Fernando Alonso,10,McLaren-Renault,10 +Australian,25/03/2018,6,Max Verstappen,4,Red Bull Racing-TAG Heuer,8 +Australian,25/03/2018,7,Nico Hülkenberg,7,Renault,6 +Australian,25/03/2018,8,Valtteri Bottas,15,Mercedes,4 +Australian,25/03/2018,9,Stoffel Vandoorne,11,McLaren-Renault,2 +Australian,25/03/2018,10,Carlos Sainz,9,Renault,1 +Bahrain,08/04/2018,1,Sebastian Vettel,1,Ferrari,25 +Bahrain,08/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Bahrain,08/04/2018,3,Lewis Hamilton,9,Mercedes,15 +Bahrain,08/04/2018,4,Pierre Gasly,5,STR-Honda,12 +Bahrain,08/04/2018,5,Kevin Magnussen,6,Haas-Ferrari,10 +Bahrain,08/04/2018,6,Nico Hülkenberg,7,Renault,8 +Bahrain,08/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Bahrain,08/04/2018,8,Stoffel Vandoorne,14,McLaren-Renault,4 +Bahrain,08/04/2018,9,Marcus Ericsson,17,Sauber-Ferrari,2 +Bahrain,08/04/2018,10,Esteban Ocon,8,Force India-Mercedes,1 +Chinese,15/04/2018,1,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,25 +Chinese,15/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Chinese,15/04/2018,3,Kimi Räikkönen,2,Ferrari,15 +Chinese,15/04/2018,4,Lewis Hamilton,4,Mercedes,12 +Chinese,15/04/2018,5,Max Verstappen,5,Red Bull Racing-TAG Heuer,10 +Chinese,15/04/2018,6,Nico Hülkenberg,7,Renault,8 +Chinese,15/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Chinese,15/04/2018,8,Sebastian Vettel,1,Ferrari,4 +Chinese,15/04/2018,9,Carlos Sainz,9,Renault,2 +Chinese,15/04/2018,10,Kevin Magnussen,11,Haas-Ferrari,1 +Azerbaijan,29/04/2018,1,Lewis Hamilton,2,Mercedes,25 +Azerbaijan,29/04/2018,2,Kimi Räikkönen,6,Ferrari,18 +Azerbaijan,29/04/2018,3,Sergio Pérez,8,Force India-Mercedes,15 +Azerbaijan,29/04/2018,4,Sebastian Vettel,1,Ferrari,12 +Azerbaijan,29/04/2018,5,Carlos Sainz,9,Renault,10 +Azerbaijan,29/04/2018,6,Charles Leclerc,13,Sauber-Ferrari,8 +Azerbaijan,29/04/2018,7,Fernando Alonso,12,McLaren-Renault,6 +Azerbaijan,29/04/2018,8,Lance Stroll,10,Williams-Mercedes,4 +Azerbaijan,29/04/2018,9,Stoffel Vandoorne,16,McLaren-Renault,2 +Azerbaijan,29/04/2018,10,Brendon Hartley,19,STR-Honda,1 +Spanish,13/05/2018,1,Lewis Hamilton,1,Mercedes,25 +Spanish,13/05/2018,2,Valtteri Bottas,2,Mercedes,18 +Spanish,13/05/2018,3,Max Verstappen,5,Red Bull Racing-TAG Heuer,15 +Spanish,13/05/2018,4,Sebastian Vettel,3,Ferrari,12 +Spanish,13/05/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +Spanish,13/05/2018,6,Kevin Magnussen,7,Haas-Ferrari,8 +Spanish,13/05/2018,7,Carlos Sainz,9,Renault,6 +Spanish,13/05/2018,8,Fernando Alonso,8,McLaren-Renault,4 +Spanish,13/05/2018,9,Sergio Pérez,15,Force India-Mercedes,2 +Spanish,13/05/2018,10,Charles Leclerc,14,Sauber-Ferrari,1 +Monaco,27/05/2018,1,Daniel Ricciardo,1,Red Bull Racing-TAG Heuer,25 +Monaco,27/05/2018,2,Sebastian Vettel,2,Ferrari,18 +Monaco,27/05/2018,3,Lewis Hamilton,3,Mercedes,15 +Monaco,27/05/2018,4,Kimi Räikkönen,4,Ferrari,12 +Monaco,27/05/2018,5,Valtteri Bottas,5,Mercedes,10 +Monaco,27/05/2018,6,Esteban Ocon,6,Force India-Mercedes,8 +Monaco,27/05/2018,7,Pierre Gasly,10,STR-Honda,6 +Monaco,27/05/2018,8,Nico Hülkenberg,11,Renault,4 +Monaco,27/05/2018,9,Max Verstappen,20,Red Bull Racing-TAG Heuer,2 +Monaco,27/05/2018,10,Carlos Sainz,8,Renault,1 +Canadian,10/06/2018,1,Sebastian Vettel,1,Ferrari,25 +Canadian,10/06/2018,2,Valtteri Bottas,2,Mercedes,18 +Canadian,10/06/2018,3,Max Verstappen,3,Red Bull Racing-TAG Heuer,15 +Canadian,10/06/2018,4,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,12 +Canadian,10/06/2018,5,Lewis Hamilton,4,Mercedes,10 +Canadian,10/06/2018,6,Kimi Räikkönen,5,Ferrari,8 +Canadian,10/06/2018,7,Nico Hülkenberg,7,Renault,6 +Canadian,10/06/2018,8,Carlos Sainz,9,Renault,4 +Canadian,10/06/2018,9,Esteban Ocon,8,Force India-Mercedes,2 +Canadian,10/06/2018,10,Charles Leclerc,13,Sauber-Ferrari,1 +French,24/06/2018,1,Lewis Hamilton,1,Mercedes,25 +French,24/06/2018,2,Max Verstappen,4,Red Bull Racing-TAG Heuer,18 +French,24/06/2018,3,Kimi Räikkönen,6,Ferrari,15 +French,24/06/2018,4,Daniel Ricciardo,5,Red Bull Racing-TAG Heuer,12 +French,24/06/2018,5,Sebastian Vettel,3,Ferrari,10 +French,24/06/2018,6,Kevin Magnussen,9,Haas-Ferrari,8 +French,24/06/2018,7,Valtteri Bottas,2,Mercedes,6 +French,24/06/2018,8,Carlos Sainz,7,Renault,4 +French,24/06/2018,9,Nico Hülkenberg,12,Renault,2 +French,24/06/2018,10,Charles Leclerc,8,Sauber-Ferrari,1 +Austrian,01/07/2018,1,Max Verstappen,4,Red Bull Racing-TAG Heuer,25 +Austrian,01/07/2018,2,Kimi Räikkönen,3,Ferrari,18 +Austrian,01/07/2018,3,Sebastian Vettel,6,Ferrari,15 +Austrian,01/07/2018,4,Romain Grosjean,5,Haas-Ferrari,12 +Austrian,01/07/2018,5,Kevin Magnussen,8,Haas-Ferrari,10 +Austrian,01/07/2018,6,Esteban Ocon,11,Force India-Mercedes,8 +Austrian,01/07/2018,7,Sergio Pérez,15,Force India-Mercedes,6 +Austrian,01/07/2018,8,Fernando Alonso,20,McLaren-Renault,4 +Austrian,01/07/2018,9,Charles Leclerc,17,Sauber-Ferrari,2 +Austrian,01/07/2018,10,Marcus Ericsson,18,Sauber-Ferrari,1 +British,08/07/2018,1,Sebastian Vettel,2,Ferrari,25 +British,08/07/2018,2,Lewis Hamilton,1,Mercedes,18 +British,08/07/2018,3,Kimi Räikkönen,3,Ferrari,15 +British,08/07/2018,4,Valtteri Bottas,4,Mercedes,12 +British,08/07/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +British,08/07/2018,6,Nico Hülkenberg,11,Renault,8 +British,08/07/2018,7,Esteban Ocon,10,Force India-Mercedes,6 +British,08/07/2018,8,Fernando Alonso,13,McLaren-Renault,4 +British,08/07/2018,9,Kevin Magnussen,7,Haas-Ferrari,2 +British,08/07/2018,10,Sergio Pérez,12,Force India-Mercedes,1 + + + + Examples/Grouping/GroupDateColumn.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points ` + -PivotRows Driver -PivotColumns Date -PivotData @{Points = "SUM"} -GroupDateColumn Date -GroupDatePart Years, Months + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition + + + + Examples/Grouping/GroupDateRow.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points ` + -PivotRows Driver, Date -PivotData @{Points = "SUM"} -GroupDateRow Date -GroupDatePart Years, Months + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition + + + + Examples/Grouping/GroupNumericColumn.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places ` + -PivotRows Driver -PivotColumns FinishPosition -PivotData @{Date = "Count"} -GroupNumericColumn FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3 + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition + + + + Examples/Grouping/GroupNumericRow.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places ` + -PivotRows Driver, FinishPosition -PivotData @{Date = "Count"} -GroupNumericRow FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3 + +Import-Csv "$PSScriptRoot\First10Races.csv" | + Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points | + Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition + + + + Examples/Grouping/TimestampBucket.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} +$data = ConvertFrom-Csv @" +Timestamp,Tenant +10/29/2018 3:00:00.123,1 +10/29/2018 3:00:10.456,1 +10/29/2018 3:01:20.389,1 +10/29/2018 3:00:30.222,1 +10/29/2018 3:00:40.143,1 +10/29/2018 3:00:50.809,1 +10/29/2018 3:01:00.193,1 +10/29/2018 3:01:10.555,1 +10/29/2018 3:01:20.739,1 +10/29/2018 3:01:30.912,1 +10/29/2018 3:01:40.989,1 +10/29/2018 3:01:50.545,1 +10/29/2018 3:02:00.999,1 +"@ | Select-Object @{n = 'Timestamp'; e = {Get-date $_.timestamp}}, tenant, @{n = 'Bucket'; e = { - (Get-date $_.timestamp).Second % 30}} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$pivotDefParams = @{ + PivotTableName = 'Timestamp Buckets' + PivotRows = @('Timestamp', 'Tenant') + PivotData = @{'Bucket' = 'count'} + GroupDateRow = 'TimeStamp' + GroupDatePart = @('Hours', 'Minutes') + Activate = $true +} + +$excelParams = @{ + PivotTableDefinition = New-PivotTableDefinition @pivotDefParams + Path = $xlSourcefile + WorkSheetname = "Log Data" + AutoSize = $true + AutoFilter = $true + Show = $true +} + +$data | Export-Excel @excelParams + + + + Examples/HyperLinks/First10Races.csv + + Race,Date,FinishPosition,Driver,GridPosition,Team,Points +Australian,25/03/2018,1,Sebastian Vettel,3,Ferrari,25 +Australian,25/03/2018,2,Lewis Hamilton,1,Mercedes,18 +Australian,25/03/2018,3,Kimi Räikkönen,2,Ferrari,15 +Australian,25/03/2018,4,Daniel Ricciardo,8,Red Bull Racing-TAG Heuer,12 +Australian,25/03/2018,5,Fernando Alonso,10,McLaren-Renault,10 +Australian,25/03/2018,6,Max Verstappen,4,Red Bull Racing-TAG Heuer,8 +Australian,25/03/2018,7,Nico Hülkenberg,7,Renault,6 +Australian,25/03/2018,8,Valtteri Bottas,15,Mercedes,4 +Australian,25/03/2018,9,Stoffel Vandoorne,11,McLaren-Renault,2 +Australian,25/03/2018,10,Carlos Sainz,9,Renault,1 +Bahrain,08/04/2018,1,Sebastian Vettel,1,Ferrari,25 +Bahrain,08/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Bahrain,08/04/2018,3,Lewis Hamilton,9,Mercedes,15 +Bahrain,08/04/2018,4,Pierre Gasly,5,STR-Honda,12 +Bahrain,08/04/2018,5,Kevin Magnussen,6,Haas-Ferrari,10 +Bahrain,08/04/2018,6,Nico Hülkenberg,7,Renault,8 +Bahrain,08/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Bahrain,08/04/2018,8,Stoffel Vandoorne,14,McLaren-Renault,4 +Bahrain,08/04/2018,9,Marcus Ericsson,17,Sauber-Ferrari,2 +Bahrain,08/04/2018,10,Esteban Ocon,8,Force India-Mercedes,1 +Chinese,15/04/2018,1,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,25 +Chinese,15/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Chinese,15/04/2018,3,Kimi Räikkönen,2,Ferrari,15 +Chinese,15/04/2018,4,Lewis Hamilton,4,Mercedes,12 +Chinese,15/04/2018,5,Max Verstappen,5,Red Bull Racing-TAG Heuer,10 +Chinese,15/04/2018,6,Nico Hülkenberg,7,Renault,8 +Chinese,15/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Chinese,15/04/2018,8,Sebastian Vettel,1,Ferrari,4 +Chinese,15/04/2018,9,Carlos Sainz,9,Renault,2 +Chinese,15/04/2018,10,Kevin Magnussen,11,Haas-Ferrari,1 +Azerbaijan,29/04/2018,1,Lewis Hamilton,2,Mercedes,25 +Azerbaijan,29/04/2018,2,Kimi Räikkönen,6,Ferrari,18 +Azerbaijan,29/04/2018,3,Sergio Pérez,8,Force India-Mercedes,15 +Azerbaijan,29/04/2018,4,Sebastian Vettel,1,Ferrari,12 +Azerbaijan,29/04/2018,5,Carlos Sainz,9,Renault,10 +Azerbaijan,29/04/2018,6,Charles Leclerc,13,Sauber-Ferrari,8 +Azerbaijan,29/04/2018,7,Fernando Alonso,12,McLaren-Renault,6 +Azerbaijan,29/04/2018,8,Lance Stroll,10,Williams-Mercedes,4 +Azerbaijan,29/04/2018,9,Stoffel Vandoorne,16,McLaren-Renault,2 +Azerbaijan,29/04/2018,10,Brendon Hartley,19,STR-Honda,1 +Spanish,13/05/2018,1,Lewis Hamilton,1,Mercedes,25 +Spanish,13/05/2018,2,Valtteri Bottas,2,Mercedes,18 +Spanish,13/05/2018,3,Max Verstappen,5,Red Bull Racing-TAG Heuer,15 +Spanish,13/05/2018,4,Sebastian Vettel,3,Ferrari,12 +Spanish,13/05/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +Spanish,13/05/2018,6,Kevin Magnussen,7,Haas-Ferrari,8 +Spanish,13/05/2018,7,Carlos Sainz,9,Renault,6 +Spanish,13/05/2018,8,Fernando Alonso,8,McLaren-Renault,4 +Spanish,13/05/2018,9,Sergio Pérez,15,Force India-Mercedes,2 +Spanish,13/05/2018,10,Charles Leclerc,14,Sauber-Ferrari,1 +Monaco,27/05/2018,1,Daniel Ricciardo,1,Red Bull Racing-TAG Heuer,25 +Monaco,27/05/2018,2,Sebastian Vettel,2,Ferrari,18 +Monaco,27/05/2018,3,Lewis Hamilton,3,Mercedes,15 +Monaco,27/05/2018,4,Kimi Räikkönen,4,Ferrari,12 +Monaco,27/05/2018,5,Valtteri Bottas,5,Mercedes,10 +Monaco,27/05/2018,6,Esteban Ocon,6,Force India-Mercedes,8 +Monaco,27/05/2018,7,Pierre Gasly,10,STR-Honda,6 +Monaco,27/05/2018,8,Nico Hülkenberg,11,Renault,4 +Monaco,27/05/2018,9,Max Verstappen,20,Red Bull Racing-TAG Heuer,2 +Monaco,27/05/2018,10,Carlos Sainz,8,Renault,1 +Canadian,10/06/2018,1,Sebastian Vettel,1,Ferrari,25 +Canadian,10/06/2018,2,Valtteri Bottas,2,Mercedes,18 +Canadian,10/06/2018,3,Max Verstappen,3,Red Bull Racing-TAG Heuer,15 +Canadian,10/06/2018,4,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,12 +Canadian,10/06/2018,5,Lewis Hamilton,4,Mercedes,10 +Canadian,10/06/2018,6,Kimi Räikkönen,5,Ferrari,8 +Canadian,10/06/2018,7,Nico Hülkenberg,7,Renault,6 +Canadian,10/06/2018,8,Carlos Sainz,9,Renault,4 +Canadian,10/06/2018,9,Esteban Ocon,8,Force India-Mercedes,2 +Canadian,10/06/2018,10,Charles Leclerc,13,Sauber-Ferrari,1 +French,24/06/2018,1,Lewis Hamilton,1,Mercedes,25 +French,24/06/2018,2,Max Verstappen,4,Red Bull Racing-TAG Heuer,18 +French,24/06/2018,3,Kimi Räikkönen,6,Ferrari,15 +French,24/06/2018,4,Daniel Ricciardo,5,Red Bull Racing-TAG Heuer,12 +French,24/06/2018,5,Sebastian Vettel,3,Ferrari,10 +French,24/06/2018,6,Kevin Magnussen,9,Haas-Ferrari,8 +French,24/06/2018,7,Valtteri Bottas,2,Mercedes,6 +French,24/06/2018,8,Carlos Sainz,7,Renault,4 +French,24/06/2018,9,Nico Hülkenberg,12,Renault,2 +French,24/06/2018,10,Charles Leclerc,8,Sauber-Ferrari,1 +Austrian,01/07/2018,1,Max Verstappen,4,Red Bull Racing-TAG Heuer,25 +Austrian,01/07/2018,2,Kimi Räikkönen,3,Ferrari,18 +Austrian,01/07/2018,3,Sebastian Vettel,6,Ferrari,15 +Austrian,01/07/2018,4,Romain Grosjean,5,Haas-Ferrari,12 +Austrian,01/07/2018,5,Kevin Magnussen,8,Haas-Ferrari,10 +Austrian,01/07/2018,6,Esteban Ocon,11,Force India-Mercedes,8 +Austrian,01/07/2018,7,Sergio Pérez,15,Force India-Mercedes,6 +Austrian,01/07/2018,8,Fernando Alonso,20,McLaren-Renault,4 +Austrian,01/07/2018,9,Charles Leclerc,17,Sauber-Ferrari,2 +Austrian,01/07/2018,10,Marcus Ericsson,18,Sauber-Ferrari,1 +British,08/07/2018,1,Sebastian Vettel,2,Ferrari,25 +British,08/07/2018,2,Lewis Hamilton,1,Mercedes,18 +British,08/07/2018,3,Kimi Räikkönen,3,Ferrari,15 +British,08/07/2018,4,Valtteri Bottas,4,Mercedes,12 +British,08/07/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +British,08/07/2018,6,Nico Hülkenberg,11,Renault,8 +British,08/07/2018,7,Esteban Ocon,10,Force India-Mercedes,6 +British,08/07/2018,8,Fernando Alonso,13,McLaren-Renault,4 +British,08/07/2018,9,Kevin Magnussen,7,Haas-Ferrari,2 +British,08/07/2018,10,Sergio Pérez,12,Force India-Mercedes,1 + + + + Examples/HyperLinks/Hyperlinks.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +@" +site,link +google,http://www.google.com +stackoverflow,http://stackoverflow.com +microsoft,http://microsoft.com +"@ | ConvertFrom-Csv | Export-Excel + + + + + Examples/HyperLinks/Races.ps1 + + +#First 10 races is a CSV file containing the top 10 finishers for the first 10 Formula one races of 2018. Read this file and group the results by race +#We will create links to each race in the first 10 rows of the spreadSheet +#The next row will be column labels +#After that will come a block for each race. +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Read the data, and decide how much space to leave for the hyperlinks +$scriptPath = Split-Path -Path $MyInvocation.MyCommand.path -Parent +$dataPath = Join-Path -Path $scriptPath -ChildPath "First10Races.csv" +$results = Import-Csv -Path $dataPath | Group-Object -Property RACE +$topRow = $lastDataRow = 1 + $results.Count + +#Export the first row of the first group (race) with headers. +$path = "$env:TEMP\Results.xlsx" +Remove-Item -Path $path -ErrorAction SilentlyContinue +$excel = $results[0].Group[0] | Export-Excel -Path $path -StartRow $TopRow -BoldTopRow -PassThru + +#export each group (race) below the last one, without headers, and create a range for each using the group (Race) name +foreach ($r in $results) { + $excel = $R.Group | Export-Excel -ExcelPackage $excel -NoHeader -StartRow ($lastDataRow +1) -RangeName $R.Name -PassThru -AutoSize + $lastDataRow += $R.Group.Count +} + +#Create a hyperlink for each property with display text of "RaceNameGP" which links to the range created when the rows were exported a +$results | ForEach-Object {(New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP")} | + Export-Excel -ExcelPackage $excel -AutoSize -Show + + + + + + Examples/Import-Excel/ImportMultipleSheetsAsArray.ps1 + + Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +$xlfile = "$PSScriptRoot\yearlySales.xlsx" + +$result = Import-Excel -Path $xlfile -WorksheetName * -Raw + +$result | Measure-Object + + + + Examples/Import-Excel/ImportMultipleSheetsAsHashtable.ps1 + + Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force + +$xlfile = "$PSScriptRoot\yearlySales.xlsx" + +$result = Import-Excel -Path $xlfile -WorksheetName * + +foreach ($sheet in $result.Values) { + $sheet +} + + + + Examples/ImportByColumns/import-by-columns.ps1 + + function Import-ByColumns { +<# + .synopsis + Works like Import-Excel but with data in columns instead of the conventional rows. + .Description. + Import-excel will read the sample file in this folder like this + > Import-excel FruitCity.xlsx | ft * + GroupAs Apple Orange Banana + ------- ----- ------ ------ + London 1 4 9 + Paris 2 4 10 + NewYork 6 5 11 + Munich 7 8 12 + Import-ByColumns transposes it + > Import-Bycolumns FruitCity.xlsx | ft * + GroupAs London Paris NewYork Munich + ------- ------ ----- ------- ------ + Apple 1 2 6 7 + Orange 4 4 5 8 + Banana 9 10 11 12 + .Example + C:\> Import-Bycolumns -path .\VM_Build_Example.xlsx -StartRow 7 -EndRow 21 -EndColumn 7 -HeaderName Desc,size,type, + cpu,ram,NetAcc,OS,OSDiskSize,DataDiskSize,LogDiskSize,TempDbDiskSize,BackupDiskSize,ImageDiskDize,AzureBackup,AzureReplication | ft -a * + + This reads a spreadsheet which has a block from row 7 to 21 containing 14 properties of virtual machines. + The properties names are in column A and the 6 VMS are in columns B-G + Because the property names are written for easy reading by the person completing the spreadsheet, they are replaced with new names. + All the parameters work as they would for Import-Excel +#> + + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + param( + [Alias('FullName')] + [Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] + [String]$Path, + + [Parameter(ParameterSetName = "PackageA", Mandatory)] + [Parameter(ParameterSetName = "PackageB", Mandatory)] + [Parameter(ParameterSetName = "PackageC", Mandatory)] + [OfficeOpenXml.ExcelPackage]$ExcelPackage, + + [Alias('Sheet')] + [Parameter(Position = 1)] + [ValidateNotNullOrEmpty()] + [String]$WorksheetName, + + [Parameter(ParameterSetName = 'PathB' , Mandatory)] + [Parameter(ParameterSetName = 'PackageB', Mandatory)] + [String[]]$HeaderName , + [Parameter(ParameterSetName = 'PathC' , Mandatory)] + [Parameter(ParameterSetName = 'PackageC', Mandatory)] + [Switch]$NoHeader, + + [Alias('TopRow')] + [ValidateRange(1, 9999)] + [Int]$StartRow = 1, + + [Alias('StopRow', 'BottomRow')] + [Int]$EndRow , + + [Alias('LeftColumn','LabelColumn')] + [Int]$StartColumn = 1, + + [Int]$EndColumn, + [switch]$DataOnly, + [switch]$AsHash, + + [ValidateNotNullOrEmpty()] + [String]$Password + ) + function Get-PropertyNames { + <# + .SYNOPSIS + Create objects containing the row number and the row name for each of the different header types. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")] + param( + [Parameter(Mandatory)] + [Int[]]$Rows, + [Parameter(Mandatory)] + [Int]$StartColumn + ) + if ($HeaderName) { + $i = 0 + foreach ($h in $HeaderName) { + $h | Select-Object @{n='Row'; e={$rows[$i]}}, @{n='Value'; e={$h} } + $i++ + } + } + elseif ($NoHeader) { + $i = 0 + foreach ($r in $rows) { + $i++ + $r | Select-Object @{n='Row'; e={$_}}, @{n='Value'; e={"P$i"} } + } + } + else { + foreach ($r in $Rows) { + #allow "False" or "0" to be headings + $Worksheet.Cells[$r, $StartColumn] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{n='Row'; e={$r} }, Value + } + } + } + +#region open file if necessary, find worksheet and ensure we have start/end row/columns + if ($Path -and -not $ExcelPackage -and $Password) { + $ExcelPackage = Open-ExcelPackage -Path $Path -Password $Password + } + elseif ($Path -and -not $ExcelPackage ) { + $ExcelPackage = Open-ExcelPackage -Path $Path + } + if (-not $ExcelPackage) { + throw 'Could not get an Excel workbook to work on' ; return + } + + if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] } + elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) { + throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return + } + + if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row } + if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column } +#endregion + + $Rows = $Startrow .. $EndRow ; + $Columns = (1 + $StartColumn)..$EndColumn + + if ((-not $rows) -or (-not ($PropertyNames = Get-PropertyNames -Rows $Rows -StartColumn $StartColumn))) { + throw "No headers found in left coulmn '$Startcolumn'. "; return + } + if (-not $Columns) { + Write-Warning "Worksheet '$WorksheetName' in workbook contains no data in the rows after left column '$StartColumn'" + } + else { + foreach ($c in $Columns) { + $NewColumn = [Ordered]@{ } + foreach ($p in $PropertyNames) { + $NewColumn[$p.Value] = $Worksheet.Cells[$p.row,$c].text + } + if ($AsHash) {$NewColumn} + elseif (($NewColumn.Values -ne "") -or -not $dataonly) {[PSCustomObject]$NewColumn} + } + } +} + + + + + Examples/ImportColumns/ImportColumns.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +# Create example file +$xlFile = "$PSScriptRoot\ImportColumns.xlsx" +Get-Process | Export-Excel -Path $xlFile +# -ImportColumns will also arrange columns +Import-Excel -Path $xlFile -ImportColumns @(1,3,2) -NoHeader -StartRow 1 +# Get only pm, npm, cpu, id, processname +Import-Excel -Path $xlFile -ImportColumns @(6,7,12,25,46) | Format-Table -AutoSize + + + + Examples/ImportHtml/DemoGraphics.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + + +Import-Html "http://en.wikipedia.org/wiki/Demographics_of_India" 4 + + + + Examples/ImportHtml/PeriodicElements.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Import-Html "http://www.science.co.il/PTelements.asp" 1 + + + + Examples/ImportHtml/StarTrek.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Import-Html "https://en.wikipedia.org/wiki/List_of_Star_Trek:_The_Original_Series_episodes" 2 + + + + Examples/Index - Music.ps1 + + #requires -modules "Get-IndexedItem" +[CmdletBinding()] +Param() +Remove-Item ~\documents\music.xlsx -ErrorAction SilentlyContinue +[System.Diagnostics.Stopwatch]$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() + +#Query system index for .MP3 files in C:\Users, where album artist is non-blank. Leave sorted table with columns of interest in $Music. + +Get-IndexedItem "itemtype='.mp3'","AlbumArtist like '%'" -Recurse C:\Users -OutputVariable Music ` + -OrderBy AlbumArtist, AlbumTitle, TrackNumber, Title -NoFiles ` + -Property AlbumArtist, AlbumTitle, TrackNumber, Title, Duration, Size, SampleRate +Write-Verbose -Message ("Fetched " + $music.Rows.Count + " rows from index: " + $stopwatch.Elapsed.TotalSeconds) +#Send Table in $Music to Excel, format as a table, point $ws to the Worksheet +$excel = Send-SQLDataToExcel -Path ~\documents\music.xlsx -DataTable $music -WorkSheetname Music -TableName Music -Passthru +Write-Verbose -Message ("Inserted into Excel: " + $stopwatch.Elapsed.TotalSeconds) +$ws = $excel.Music + +#Strip "SYSTEM.", "SYSTEM.AUDIO", "SYSTEM.MEDIA", "SYSTEM.MUSIC" from the column headings +#Convert Duration (column 5) from 100ns ticks to days and format as minutes, seconds, decimal +#Format filesize and sample rate nicely +#Autofit the columns. +Set-ExcelRow -Worksheet $ws -Row 1 -Value {($worksheet.cells[$row,$column].value -replace '^SYSTEM\.','') -replace '^MEDIA\.|^AUDIO\.|^MUSIC\.','' } +Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'mm:ss.0' -StartRow 2 -Value {$worksheet.cells[$row,$column].value / 864000000000 } +Write-Verbose -Message ("Cells Reset: " + $stopwatch.Elapsed.TotalSeconds) +Set-ExcelColumn -Worksheet $ws -Column 6 -NumberFormat '#.#,,"MB"' +Set-ExcelColumn -Worksheet $ws -Column 7 -NumberFormat '0.0,"KHz"' +$ws.Cells[$ws.Dimension].AutoFitColumns() + +#Make a Pivot table for sum of space and count of tracks by artist. Sort by artist, apply formatting to space, give it nice titles. +$pt = Add-PivotTable -PassThru -PivotTableName SpaceUsedByMusic -ExcelPackage $excel -SourceWorkSheet $ws ` + -PivotRows ALBUMARTIST -PivotData ([ordered]@{"Size"="Sum"; "Duration"="Count"}) -PivotDataToColumn + +$pt.RowFields[0].Sort = [OfficeOpenXml.Table.PivotTable.eSortType]::Ascending +$pt.DataFields[0].Format = '#.0,,"MB"' +$pt.DataFields[0].Name = 'Space Used' +$pt.DataFields[1].Name = 'Tracks' + +#Save the file, and load it into Excel +$stopwatch.Stop() +Write-Verbose -Message ("Pivot Done: " + $stopwatch.Elapsed.TotalSeconds) +Close-ExcelPackage -show $excel + + + + + Examples/InteractWithOtherModules/Pester/Analyze_that.ps1 + + param( + $PesterTestsPath = "$PSScriptRoot\..\..\..\__tests__\" +) + +$xlfile = "$env:Temp\testResults.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$xlparams = @{ + Path = $xlfile + InputObject = (Invoke-Pester -Script $PesterTestsPath -PassThru).TestResult | Sort-Object describe + WorksheetName = 'FullResults' + + IncludePivotTable = $true + PivotRows = 'Describe' + PivotColumns = 'Passed' + PivotData = @{'Passed' = 'Count' } + + IncludePivotChart = $true + ChartType = 'BarClustered' + + AutoSize = $true + AutoFilter = $true + Activate = $true +} + +Export-Excel -Show @xlparams + + + + Examples/InteractWithOtherModules/ScriptAnalyzer/Analyze_this.ps1 + + <# + .Synopsis + Runs PsScriptAnalyzer against one or more folders and pivots the results to form a report. + + .Example + Analyze_this.ps1 + Invokes script analyzer on the current directory; creates a file in $env:temp and opens it in Excel + .Example + Analyze_this.ps1 -xlfile ..\mymodule.xlsx -quiet + Invokes script analyzer on the current directory; creates a file in the parent directory but does not open it + .Example + "." , (dir 'C:\Program Files\WindowsPowerShell\Modules\ImportExcel\') | .\examples\ScriptAnalyzer\Analyze_this.ps1 + run from a developemnt directory for importExcel it will produce a report for that directory compared against installed versions + this creates the file in the default location and opens it +#> +[CmdletBinding()] +param ( + [parameter(ValueFromPipeline = $true)] + $Path = $PWD, + $xlfile = "$env:TEMP\ScriptAnalyzer.xlsx", + $ChartType = 'BarClustered' , + $PivotColumns = 'Location', + [switch]$Quiet +) + +begin { + Remove-Item -Path $xlfile -ErrorAction SilentlyContinue + $xlparams = @{ + Path = $xlfile + WorksheetName = 'FullResults' + AutoSize = $true + AutoFilter = $true + Activate = $true + Show = (-not $Quiet) + } + $pivotParams = @{ + PivotTableName = 'BreakDown' + PivotData = @{RuleName = 'Count' } + PivotRows = 'Severity', 'RuleName' + PivotColumns = 'Location' + PivotTotals = 'Rows' + } + $dirsToProcess = @() +} +process { + if ($path.fullName) {$dirsToProcess += $path.fullName} + elseif ($path.path) {$dirsToProcess += $path.Path} + else {$dirsToProcess += $path} +} + +end { + $pivotParams['-PivotChartDefinition'] = New-ExcelChartDefinition -ChartType $chartType -Column (1 + $dirsToProcess.Count) -Title "Script analysis" -LegendBold + $xlparams['PivotTableDefinition'] = New-PivotTableDefinition @pivotParams + + $dirsToProcess | ForEach-Object { + $dirName = (Resolve-Path -Path $_) -replace "^.*\\(.*?)\\(.*?)$", '$1-$2' + Write-Progress -Activity "Running Script Analyzer" -CurrentOperation $dirName + Invoke-ScriptAnalyzer -Path $_ -ErrorAction SilentlyContinue | + Add-Member -MemberType NoteProperty -Name Location -Value $dirName -PassThru + } | Export-Excel @xlparams + Write-Progress -Activity "Running Script Analyzer" -Completed +} + + + + + Examples/InvokeExcelQuery/Examples.ps1 + + try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$queries = +'select * from [sheet1$A:A]', +'select * from [sheet1$]', +'select * from [sheet1$A2:E11]', +'select F2,F5 from [sheet1$A2:E11]', +'select * from [sheet1$A2:E11] where F2 = "Grocery"', +'select F2 as [Category], F5 as [Discount], F5*2 as [DiscountPlus] from [sheet1$A2:E11]' + +foreach ($query in $queries) { + "query: $($query)" + Invoke-ExcelQuery .\testOleDb.xlsx $query | Format-Table +} + + + + + Examples/JoinWorksheet/EastSales.csv + + "Region","Item","UnitSold","UnitCost" +"East","Banana","38","0.26" +"East","Kale","71","0.69" +"East","Apple","35","0.55" +"East","Potato","48","0.48" +"East","Kale","41","0.74" + + + + Examples/JoinWorksheet/Join-Worksheet.sample.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Create simple pages for 3 stores with product ID, Product Name, quanity price and total + +@" +ID,Product,Quantity,Price,Total +12001,Nails,37,3.99,147.63 +12002,Hammer,5,12.10,60.5 +12003,Saw,12,15.37,184.44 +12010,Drill,20,8,160 +12011,Crowbar,7,23.48,164.36 +"@ | ConvertFrom-Csv| Export-Excel -Path $xlSourcefile -WorkSheetname Oxford + +@" +ID,Product,Quantity,Price,Total +12001,Nails,53,3.99,211.47 +12002,Hammer,6,12.10,72.60 +12003,Saw,10,15.37,153.70 +12010,Drill,10,8,80 +12012,Pliers,2,14.99,29.98 +"@ | ConvertFrom-Csv| Export-Excel -Path $xlSourcefile -WorkSheetname Abingdon + + +@" +ID,Product,Quantity,Price,Total +12001,Nails,20,3.99,79.80 +12002,Hammer,2,12.10,24.20 +12010,Drill,11,8,88 +12012,Pliers,3,14.99,44.97 +"@ | ConvertFrom-Csv| Export-Excel -Path $xlSourcefile -WorkSheetname Banbury + +#define a pivot table with a chart to show a sales by store, broken down by product +$ptdef = New-PivotTableDefinition -PivotTableName "Summary" -PivotRows "Store" -PivotColumns "Product" -PivotData @{"Total"="SUM"} -IncludePivotChart -ChartTitle "Sales Breakdown" -ChartType ColumnStacked -ChartColumn 10 + +#Join the 3 worksheets. +#Name the combined page "Total" and Name the column with the sheet names "store" (as the sheets 'Oxford','Abingdon' and 'Banbury' are the names of the stores +#Format the data as a table named "Summary", using the style "Light1", put the column headers in bold +#Put in a title and freeze to top of the sheet including title and colmun headings +#Add the Pivot table. +#Show the result +Join-Worksheet -Path $xlSourcefile -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "Combined" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2,1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -PivotTableDefinition $ptdef -show + + + + + Examples/JoinWorksheet/Join-worksheet-blocks.sample.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Export disk volume, and Network adapter to their own sheets. +Get-CimInstance -ClassName Win32_LogicalDisk | + Select-Object -Property DeviceId,VolumeName, Size,Freespace | + Export-Excel -Path $xlSourcefile -WorkSheetname Volumes -NumberFormat "0,000" +Get-NetAdapter | + Select-Object -Property Name,InterfaceDescription,MacAddress,LinkSpeed | + Export-Excel -Path $xlSourcefile -WorkSheetname NetAdapters + +#Create a summary page with a title of Summary, label the blocks with the name of the sheet they came from and hide the source sheets +Join-Worksheet -Path $xlSourcefile -HideSource -WorkSheetName Summary -NoHeader -LabelBlocks -AutoSize -Title "Summary" -TitleBold -TitleSize 22 -show + + + + + Examples/JoinWorksheet/JoinSalesData.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$params = @{ + AutoSize = $true + AutoFilter = $true + AutoNameRange = $true + ExcelChartDefinition = New-ExcelChartDefinition -XRange Item -YRange UnitSold -Title 'Units Sold' + Path = $xlSourcefile +} +#Import 4 sets of sales data from 4 CSV files, using the parameters above. +Import-Csv $PSScriptRoot\NorthSales.csv | Export-Excel -WorkSheetname North @params +Import-Csv $PSScriptRoot\EastSales.csv | Export-Excel -WorkSheetname East @params +Import-Csv $PSScriptRoot\SouthSales.csv | Export-Excel -WorkSheetname South @params +Import-Csv $PSScriptRoot\WestSales.csv | Export-Excel -WorkSheetname West @params + +#Join the 4 worksheets together on a sheet named Allsales, use the same parameters, except for AutoNameRange and ExcelChartDefinition. +$params.Remove("AutoNameRange") +$params.Remove("ExcelChartDefinition") +Join-Worksheet -WorkSheetName AllSales -Show @params + + + + Examples/JoinWorksheet/NorthSales.csv + + "Region","Item","UnitSold","UnitCost" +"North","Apple","40","0.68" +"North","Kale","55","0.35" +"North","Banana","33","0.31" +"North","Pear","29","0.74" + + + + Examples/JoinWorksheet/SouthSales.csv + + "Region","Item","UnitSold","UnitCost" +"South","Banana","54","0.46" +"South","Pear","39","0.44" +"South","Potato","33","0.46" +"South","Banana","49","0.31" +"South","Apple","38","0.59" + + + + Examples/JoinWorksheet/WestSales.csv + + "Region","Item","UnitSold","UnitCost" +"West","Banana","74","0.56" +"West","Apple","26","0.7" +"West","Banana","59","0.49" +"West","Potato","56","0.62" +"West","Banana","60","0.64" +"West","Pear","32","0.29" +"West","Apple","73","0.26" +"West","Banana","49","0.59" +"West","Pear","65","0.35" +"West","Apple","60","0.34" +"West","Kale","67","0.38" + + + + Examples/JustCharts/CentralLimitTheorem.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +ColumnChart -Title "Central Limit Theorem" -NoLegend ($( + for ($i = 1; $i -le 500; $i++) { + $s = 0 + for ($j = 1; $j -le 100; $j++) { + $s += Get-Random -Minimum 0 -Maximum 2 + } + $s + } + ) | Sort-Object | Group-Object | Select-Object Count, Name) + + + + Examples/JustCharts/PieChartHandles.ps1 + + # Get only processes hat have a company name +# Sum up handles by company +# Show the Pie Chart + +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +PieChart -Title "Total Handles by Company" ` + (Invoke-Sum (Get-Process | Where-Object company) company handles) + + + + + Examples/JustCharts/PieChartPM.ps1 + + # Get only processes hat have a company name +# Sum up PM by company +# Show the Pie Chart + +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +PieChart -Title "Total PM by Company" ` + (Invoke-Sum (Get-Process|Where-Object company) company pm) + + + + + + Examples/JustCharts/TargetData.csv + + Cost,Date,Name +1.1,1/1/2015,John +2.1,1/2/2015,Tom +5.1,1/2/2015,Dick +11.1,1/2/2015,Harry +7.1,1/2/2015,Jane +22.1,1/2/2015,Mary +32.1,1/2/2015,Liz + + + + + Examples/JustCharts/TargetData.ps1 + + $PropertyNames = @("Cost", "Date", "Name") + +New-PSItem 1.1 1/1/2015 John $PropertyNames +New-PSItem 2.1 1/2/2015 Tom +New-PSItem 5.1 1/2/2015 Dick +New-PSItem 11.1 1/2/2015 Harry +New-PSItem 7.1 1/2/2015 Jane +New-PSItem 22.1 1/2/2015 Mary +New-PSItem 32.1 1/2/2015 Liz + + + + + Examples/JustCharts/TryBarChart.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +BarChart (.\TargetData.ps1) "A BarChart" + + + + Examples/JustCharts/TryColumnChart.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +ColumnChart (.\TargetData.ps1) "A ColumnChart" + + + + + Examples/JustCharts/TryPieChart.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +PieChart (.\TargetData.ps1) "A PieChart" + + + + Examples/MergeWorkSheet/MergeCSV.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +$leftCsv = @" +MyProp1,MyProp2,Length +a,b,10 +c,d,20 +"@ | ConvertFrom-Csv + +$rightCsv = @" +MyProp1,MyProp2,Length +a,b,10 +c,d,21 +"@ | ConvertFrom-Csv + +Merge-Worksheet -OutputFile $xlSourcefile -ReferenceObject $leftCsv -DifferenceObject $rightCsv -Key Length -Show + + + + Examples/MergeWorkSheet/Merge_2_Servers_Services.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item -Path "$env:temp\server*.xlsx" , "$env:temp\Combined*.xlsx" -ErrorAction SilentlyContinue + +#Get a subset of services into $s and export them +[System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property * +$s | Export-Excel -Path $env:temp\server1.xlsx + +#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s. +#Change a row. Add a row. Delete a row. And export the changed $s to a second file. +$s[2].DisplayName = "Changed from the orginal" #This will be row 4 in Excel - this should be highlighted as a change + +$d = $s[-1] | Select-Object -Property * +$d.DisplayName = "Dummy Service" +$d.Name = "Dummy" +$s.Insert(3,$d) #This will be row 5 in Excel - this should be highlighted as a new item + +$s.RemoveAt(5) #This will be row 7 in Excel - this should be highlighted as deleted item + +$s | Export-Excel -Path $env:temp\server2.xlsx + +#This use of Merge-worksheet Assumes a default worksheet name, (sheet1) We will check and output Name (the key), DisplayName and StartType and ignore other properties. +Merge-Worksheet -Referencefile "$env:temp\server1.xlsx" -Differencefile "$env:temp\Server2.xlsx" -OutputFile "$env:temp\combined1.xlsx" -Property name,displayname,startType -Key name -Show + + + + Examples/MergeWorkSheet/Merge_3_Servers_Services.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item -Path "$env:temp\server*.xlsx" , "$env:temp\Combined*.xlsx" -ErrorAction SilentlyContinue + +#Get a subset of services into $s and export them +[System.Collections.ArrayList]$s = Get-service | Select-Object -first 25 -Property Name,DisplayName,StartType +$s | Export-Excel -Path $env:temp\server1.xlsx + +#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s. +#Change a row. Add a row. Delete a row. And export the changed $s to a second file. +$row4Displayname = $s[2].DisplayName +$s[2].DisplayName = "Changed from the orginal" #This will be excel row 4 and Server 2 will show as changed. + +$d = $s[-1] | Select-Object -Property * +$d.DisplayName = "Dummy Service" +$d.Name = "Dummy" +$s.Insert(3,$d) #This will be Excel row 5 and server 2 will show as changed - so will Server 3 + +$s.RemoveAt(5) #This will be Excel row 7 and Server 2 will show as missing. + +$s | Export-Excel -Path $env:temp\server2.xlsx + +#Make some more changes to $s and export it to a third file +$s[2].displayname = $row4Displayname #Server 3 row 4 will match server 1 so won't be highlighted + +$d = $s[-1] | Select-Object -Property * +$d.DisplayName = "Second Service" +$d.Name = "Service2" +$s.Insert(6,$d) #This will be an extra row in Server 3 at row 8. It will show as missing in Server 2. +$s.RemoveAt(8) #This will show as missing in Server 3 at row 11 () + +$s | Export-Excel -Path $env:temp\server3.xlsx + +#Now bring the three files together. + +Merge-MultipleSheets -Path "$env:temp\server1.xlsx", "$env:temp\Server2.xlsx","$env:temp\Server3.xlsx" -OutputFile "$env:temp\combined3.xlsx" -Property name,displayname,startType -Key name -Show + + + + Examples/MortgageCalculator/MortgageCalculator.ps1 + + <# + Fixed Rate Loan/Mortgage Calculator in Excel +#> + +param( + $Amount = 400000, + $InterestRate = .065, + $Term = 30 +) +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} +function New-CellData { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification='Does not change system state')] + param( + $Range, + $Value, + $Format + ) + + $setFormatParams = @{ + Worksheet = $ws + Range = $Range + NumberFormat = $Format + } + + if ($Value -is [string] -and $Value.StartsWith('=')) { + $setFormatParams.Formula = $Value + } + else { + $setFormatParams.Value = $Value + } + + Set-ExcelRange @setFormatParams +} + +$f = "$PSScriptRoot\mortgage.xlsx" +Remove-Item $f -ErrorAction SilentlyContinue + +$pkg = "" | Export-Excel $f -Title 'Fixed Rate Loan Payments' -PassThru -AutoSize +$ws = $pkg.Workbook.Worksheets["Sheet1"] + +New-CellData -Range A3 -Value 'Amount' +New-CellData -Range B3 -Value $Amount -Format '$#,##0' + +New-CellData -Range A4 -Value "Interest Rate" +New-CellData -Range B4 -Value $InterestRate -Format 'Percentage' + +New-CellData -Range A5 -Value "Term (Years)" +New-CellData -Range B5 -Value $Term + +New-CellData -Range D3 -Value "Monthly Payment" +New-CellData -Range F3 -Value "=-PMT(F4, B5*12, B3)" -Format '$#,##0.#0' + +New-CellData -Range D4 -Value "Monthly Rate" +New-CellData -Range F4 -Value "=((1+B4)^(1/12))-1" -Format 'Percentage' + +Close-ExcelPackage $pkg -Show + + + + Examples/MoveSheets/MoveSheets.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\testThis.xlsx" +Remove-Item $xlfile -ErrorAction Ignore + +1..10 | Export-Excel $xlfile -WorkSheetname First #'First' will be the only sheet +11..20 | Export-Excel $xlfile -WorkSheetname Second -MoveToStart #'Second' is moved before first so the order is 'Second', 'First' +21..30 | Export-Excel $xlfile -WorkSheetname Third -MoveBefore First #'Second' is moved before first so the order is 'Second', 'Third', 'First' +31..40 | Export-Excel $xlfile -WorkSheetname Fourth -MoveAfter Third -Show #'Fourth' is moved after third so the order is ' 'Second', 'Third', 'Fourth' First' + + + + Examples/Nasa/FireBalls.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$header = @( + 'Date/Time - Peak Brightness (UT)' , + 'Latitude (Deg)' , + 'Longitude (Deg)' , + 'Altitude (km)' , + 'Velocity (km/s)' , + 'Velocity Components (km/s) vx' , + 'Velocity Components (km/s) vy' , + 'Velocity Components (km/s) vz' , + 'Total Radiated Energy (J)' , + 'Calculated Total Impact Energy (kt)' +) + +$splat=@{ + url='http://neo.jpl.nasa.gov/fireballs/' + index=5 + Header=$header + FirstDataRow=1 +} + +Import-Html @splat + + + + Examples/New-PSItem.ps1 + + function New-PSItem { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification='Does not change system state')] + param() + $totalArgs = $args.Count + + if($args[-1] -is [array]) { + $script:PSItemHeader=$args[-1] + $totalArgs-=1 + } + + $h=[ordered]@{} + + for ($idx = 0; $idx -lt $totalArgs; $idx+=1) { + if($PSItemHeader) { + $key = $PSItemHeader[$idx] + } else { + $key = "P$($idx+1)" + } + + $h.$key=$args[$idx] + } + + [PSCustomObject]$h +} + + + + Examples/NumberFormat/ColorizeNumbers.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "$env:TEMP\disks.xlsx" + +Remove-Item $file -ErrorAction Ignore + +$data = $( + New-PSItem 100 -100 + New-PSItem 1 -1 + New-PSItem 1.2 -1.1 + New-PSItem -3.2 -4.1 + New-PSItem -5.2 6.1 +) +#Set the numbers throughout the sheet to format as positive in blue with a + sign, negative in Red with a - sign. +$data | Export-Excel -Path $file -Show -AutoSize -NumberFormat "[Blue]+0.#0;[Red]-0.#0" + + + + + Examples/NumberFormat/CurrencyFormat.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "$env:temp\disks.xlsx" + +Remove-Item $file -ErrorAction Ignore + +$data = $( + New-PSItem 100 -100 + New-PSItem 1 -1 + New-PSItem 1.2 -1.1 + New-PSItem -3.2 -4.1 + New-PSItem -5.2 6.1 + New-PSItem 1000 -2000 +) +#Number format can expand terms like Currency, to the local currency format +$data | Export-Excel -Path $file -Show -AutoSize -NumberFormat 'Currency' + + + + + Examples/NumberFormat/PercentagFormat.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "disks.xlsx" + +Remove-Item $file -ErrorAction Ignore + +$data = $( + New-PSItem 1 + New-PSItem .5 + New-PSItem .3 + New-PSItem .41 + New-PSItem .2 + New-PSItem -.12 +) + +$data | Export-Excel -Path $file -Show -AutoSize -NumberFormat "0.0%;[Red]-0.0%" + + + + + Examples/NumberFormat/PosNegNumbers.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "disks.xlsx" + +Remove-Item $file -ErrorAction Ignore + +$data = $( + New-PSItem 100 -100 + New-PSItem 1 -1 + New-PSItem 1.2 -1.1 +) + +$data | Export-Excel -Path $file -Show -AutoSize -NumberFormat "0.#0;-0.#0" + + + + Examples/NumberFormat/Win32LogicalDisk.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "disks.xlsx" + +Remove-Item $file -ErrorAction Ignore + +Get-CimInstance win32_logicaldisk -filter "drivetype=3" | + Select-Object DeviceID,Volumename,Size,Freespace | + Export-Excel -Path $file -Show -AutoSize -NumberFormat "0" + + + + Examples/NumberFormat/Win32LogicalDiskFormatted.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "disks.xlsx" + +Remove-Item $file -ErrorAction Ignore + +Get-CimInstance win32_logicaldisk -filter "drivetype=3" | + Select-Object DeviceID,Volumename,Size,Freespace | + Export-Excel -Path $file -Show -AutoSize + + + + Examples/OpenExcelPackage/EnableFeatures.ps1 + + # How to use Enable-ExcelAutoFilter and Enable-ExcelAutofit + +try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$data = ConvertFrom-Csv @" +RegionInfo,StateInfo,Units,Price +West,Texas,927,923.71 +North,Tennessee,466,770.67 +East,Florida,520,458.68 +East,Maine,828,661.24 +West,Virginia,465,053.58 +North,Missouri,436,235.67 +South,Kansas,214,992.47 +North,North Dakota,789,640.72 +South,Delaware,712,508.55 +"@ + +$xlfile = "$PSScriptRoot\enableFeatures.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data | Export-Excel $xlfile + +$excel = Open-ExcelPackage $xlfile + +Enable-ExcelAutoFilter -Worksheet $excel.Sheet1 +Enable-ExcelAutofit -Worksheet $excel.Sheet1 + +Close-ExcelPackage $excel -Show + + + + Examples/OutTabulator/demo.txt + + # ConvertFrom-Excel +'' + +.\test.xlsx + +Import-Excel .\test.xlsx | ft + +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html + +# Create a column definition +$columnOptions = @() + +$columnOptions += New-ColumnOption -ColumnName Progress -formatter progress +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions + +$columnOptions += New-ColumnOption Activity -formatter lineFormatter +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions + +$columnOptions += New-ColumnOption -ColumnName Rating -formatter star +$columnOptions += New-ColumnOption Driver -formatter tickCross +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions + +ConvertFrom-Excel -ExcelFile .\test.xlsx -outFile .\targetout.html -columnOptions $columnOptions -groupBy Gender + + + + Examples/OutTabulator/start-demo.ps1 + + ## Start-Demo.ps1 +################################################################################################## +## This is an overhaul of Jeffrey Snover's original Start-Demo script by Joel "Jaykul" Bennett +## +## I've switched it to using ReadKey instead of ReadLine (you don't have to hit Enter each time) +## As a result, I've changed the names and keys for a lot of the operations, so that they make +## sense with only a single letter to tell them apart (sorry if you had them memorized). +## +## I've also been adding features as I come across needs for them, and you'll contribute your +## improvements back to the PowerShell Script repository as well. +################################################################################################## +## Revision History (version 3.3) +## 3.3.3 Fixed: Script no longer says "unrecognized key" when you hit shift or ctrl, etc. +## Fixed: Blank lines in script were showing as errors (now printed like comments) +## 3.3.2 Fixed: Changed the "x" to match the "a" in the help text +## 3.3.1 Fixed: Added a missing bracket in the script +## 3.3 - Added: Added a "Clear Screen" option +## - Added: Added a "Rewind" function (which I'm not using much) +## 3.2 - Fixed: Put back the trap { continue; } +## 3.1 - Fixed: No Output when invoking Get-Member (and other cmdlets like it???) +## 3.0 - Fixed: Commands which set a variable, like: $files = ls +## - Fixed: Default action doesn't continue +## - Changed: Use ReadKey instead of ReadLine +## - Changed: Modified the option prompts (sorry if you had them memorized) +## - Changed: Various time and duration strings have better formatting +## - Enhance: Colors are settable: prompt, command, comment +## - Added: NoPauseAfterExecute switch removes the extra pause +## If you set this, the next command will be displayed immediately +## - Added: Auto Execute mode (FullAuto switch) runs the rest of the script +## at an automatic speed set by the AutoSpeed parameter (or manually) +## - Added: Automatically append an empty line to the end of the demo script +## so you have a chance to "go back" after the last line of you demo +################################################################################################## +## +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Correct and desirable usage')] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '', Justification='Correct and desirable usage')] +param( + $file=".\demo.txt", + [int]$command=0, + [System.ConsoleColor]$promptColor="Yellow", + [System.ConsoleColor]$commandColor="White", + [System.ConsoleColor]$commentColor="Green", + [switch]$FullAuto, + [int]$AutoSpeed = 3, + [switch]$NoPauseAfterExecute +) + +$RawUI = $Host.UI.RawUI +$hostWidth = $RawUI.BufferSize.Width + +# A function for reading in a character +function Read-Char() { + $_OldColor = $RawUI.ForeGroundColor + $RawUI.ForeGroundColor = "Red" + $inChar=$RawUI.ReadKey("IncludeKeyUp") + # loop until they press a character, so Shift or Ctrl, etc don't terminate us + while($inChar.Character -eq 0){ + $inChar=$RawUI.ReadKey("IncludeKeyUp") + } + $RawUI.ForeGroundColor = $_OldColor + return $inChar.Character +} + +function Rewind($lines, $index, $steps = 1) { + $started = $index; + $index -= $steps; + while(($index -ge 0) -and ($lines[$index].Trim(" `t").StartsWith("#"))){ + $index-- + } + if( $index -lt 0 ) { $index = $started } + return $index +} + +$file = Resolve-Path $file +while(-not(Test-Path $file)) { + $file = Read-Host "Please enter the path of your demo script (Crtl+C to cancel)" + $file = Resolve-Path $file +} + +Clear-Host + +$_lines = Get-Content $file +# Append an extra (do nothing) line on the end so we can still go back after the last line. +$_lines += "Write-Host 'The End'" +$_starttime = [DateTime]::now +$FullAuto = $false + +Write-Host -nonew -back black -fore $promptColor $(" " * $hostWidth) +Write-Host -nonew -back black -fore $promptColor @" +$(' ' * ($hostWidth -(18 + $(split-path $file -leaf).Length))) +"@ +Write-Host -nonew -back black -fore $promptColor "Press" +Write-Host -nonew -back black -fore Red " ? " +Write-Host -nonew -back black -fore $promptColor "for help.$(' ' * ($hostWidth -17))" +Write-Host -nonew -back black -fore $promptColor $(" " * $hostWidth) + +# We use a FOR and an INDEX ($_i) instead of a FOREACH because +# it is possible to start at a different location and/or jump +# around in the order. +for ($_i = $Command; $_i -lt $_lines.count; $_i++) +{ + # Put the current command in the Window Title along with the demo duration + $Dur = [DateTime]::Now - $_StartTime + $RawUI.WindowTitle = "$(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s {3}" -f + $dur.Hours, $dur.Minutes, $dur.Seconds, $($_Lines[$_i]) + + # Echo out the commmand to the console with a prompt as though it were real + Write-Host -nonew -fore $promptColor "[$_i]$([char]0x2265) " + if ($_lines[$_i].Trim(" ").StartsWith("#") -or $_lines[$_i].Trim(" ").Length -le 0) { + Write-Host -fore $commentColor "$($_Lines[$_i]) " + continue + } else { + Write-Host -nonew -fore $commandColor "$($_Lines[$_i]) " + } + + if( $FullAuto ) { Start-Sleep $autoSpeed; $ch = [char]13 } else { $ch = Read-Char } + switch($ch) + { + "?" { + Write-Host -Fore $promptColor @" + +Running demo: $file +(n) Next (p) Previous +(q) Quit (s) Suspend +(t) Timecheck (v) View $(split-path $file -leaf) +(g) Go to line by number +(f) Find lines by string +(a) Auto Execute mode +(c) Clear Screen +"@ + $_i-- # back a line, we're gonna step forward when we loop + } + "n" { # Next (do nothing) + Write-Host -Fore $promptColor "" + } + "p" { # Previous + Write-Host -Fore $promptColor "" + while ($_lines[--$_i].Trim(" ").StartsWith("#")){} + $_i-- # back a line, we're gonna step forward when we loop + } + "a" { # EXECUTE (Go Faster) + $AutoSpeed = [int](Read-Host "Pause (seconds)") + $FullAuto = $true; + Write-Host -Fore $promptColor "" + $_i-- # Repeat this line, and then just blow through the rest + } + "q" { # Quit + Write-Host -Fore $promptColor "" + $_i = $_lines.count; + break; + } + "v" { # View Source + $lines[0..($_i-1)] | Write-Host -Fore Yellow + $lines[$_i] | Write-Host -Fore Green + $lines[($_i+1)..$lines.Count] | Write-Host -Fore Yellow + $_i-- # back a line, we're gonna step forward when we loop + } + "t" { # Time Check + $dur = [DateTime]::Now - $_StartTime + Write-Host -Fore $promptColor $( + "{3} -- $(if($dur.Hours -gt 0){'{0}h '})$(if($dur.Minutes -gt 0){'{1}m '}){2}s" -f + $dur.Hours, $dur.Minutes, $dur.Seconds, ([DateTime]::Now.ToShortTimeString())) + $_i-- # back a line, we're gonna step forward when we loop + } + "s" { # Suspend (Enter Nested Prompt) + Write-Host -Fore $promptColor "" + $Host.EnterNestedPrompt() + $_i-- # back a line, we're gonna step forward when we loop + } + "g" { # GoTo Line Number + $i = [int](Read-Host "line number") + if($i -le $_lines.Count) { + if($i -gt 0) { + # extra line back because we're gonna step forward when we loop + $_i = Rewind -lines $_lines -index $_i -steps (($_i-$i)+1) + } else { + $_i = -1 # Start negative, because we step forward when we loop + } + } + } + "f" { # Find by pattern + $match = $_lines | Select-String (Read-Host "search string") + if($null -eq $match) { + Write-Host -Fore Red "Can't find a matching line" + } else { + $match | ForEach-Object { Write-Host -Fore $promptColor $("[{0,2}] {1}" -f ($_.LineNumber - 1), $_.Line) } + if($match.Count -lt 1) { + $_i = $match.lineNumber - 2 # back a line, we're gonna step forward when we loop + } else { + $_i-- # back a line, we're gonna step forward when we loop + } + } + } + "c" { + Clear-Host + $_i-- # back a line, we're gonna step forward when we loop + } + "$([char]13)" { # on enter + Write-Host + trap [System.Exception] {Write-Error $_; continue;} + Invoke-Expression ($_lines[$_i]) | out-default + if(-not $NoPauseAfterExecute -and -not $FullAuto) { + $null = $RawUI.ReadKey("NoEcho,IncludeKeyUp") # Pause after output for no apparent reason... ;) + } + } + default + { + Write-Host -Fore Green "`nKey not recognized. Press ? for help, or ENTER to execute the command." + $_i-- # back a line, we're gonna step forward when we loop + } + } +} +$dur = [DateTime]::Now - $_StartTime +Write-Host -Fore $promptColor $( + "" -f + $dur.Hours, $dur.Minutes, $dur.Seconds, [DateTime]::Now.ToLongTimeString()) +Write-Host -Fore $promptColor $([DateTime]::now) +Write-Host + + + + Examples/OutTabulator/targetout.html + +  + + + + + + + Out-TabulatorView + + + + + + + + + + + +
    + + + + + +
    +
    + + Examples/OutTabulator/tryConvertFromExcel.ps1 + + [CmdletBinding()] +param($outFile = "$PSScriptRoot\targetout.html") + +$columnOptions = @() + +$columnOptions += New-ColumnOption -ColumnName Progress -formatter progress +$columnOptions += New-ColumnOption -ColumnName Activity -formatter lineFormatter + +ConvertFrom-Excel -ExcelFile $PSScriptRoot\test.xlsx -outFile $PSScriptRoot\targetout.html -columnOptions $columnOptions + + + + Examples/PassThru/TryPassThru.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "$env:Temp\sales.xlsx" + +Remove-Item $file -ErrorAction Ignore + +#Using -Passthru with Export-Excel returns an Excel Package object. +$xlPkg = Import-Csv .\sales.csv | Export-Excel $file -PassThru + +#We add script properties to the package so $xlPkg.Sheet1 is equivalent to $xlPkg.Workbook.WorkSheets["Sheet1"] +$ws = $xlPkg.Sheet1 + +#We can manipulate the cells ... +$ws.Cells["E1"].Value = "TotalSold" +$ws.Cells["F1"].Value = "Add 10%" + +#This is for illustration - there are more efficient ways to do this. +2..($ws.Dimension.Rows) | + ForEach-Object { + $ws.Cells["E$_"].Formula = "=C$_+D$_" + $ws.Cells["F$_"].Formula = "=E$_+(10%*(C$_+D$_))" + } + +$ws.Cells.AutoFitColumns() + +#You can call close-ExcelPackage $xlPkg -show, but here we will do the ssteps explicitly +$xlPkg.Save() +$xlPkg.Dispose() +Invoke-Item $file + + + + Examples/PassThru/sales.csv + + "Region","Item","UnitSold","UnitCost" +"South","Banana","54","0.46" +"West","Banana","74","0.56" +"West","Apple","26","0.7" +"East","Banana","38","0.26" +"East","Kale","71","0.69" +"East","Apple","35","0.55" +"East","Potato","48","0.48" +"West","Banana","59","0.49" +"West","Potato","56","0.62" +"North","Apple","40","0.68" +"South","Pear","39","0.44" +"West","Banana","60","0.64" +"West","Pear","32","0.29" +"North","Kale","55","0.35" +"West","Apple","73","0.26" +"South","Potato","33","0.46" +"West","Banana","49","0.59" +"West","Pear","65","0.35" +"North","Banana","33","0.31" +"East","Kale","41","0.74" +"South","Banana","49","0.31" +"West","Apple","60","0.34" +"South","Apple","38","0.59" +"North","Pear","29","0.74" +"West","Kale","67","0.38" + + + + Examples/Pester-To-XLSx.ps1 + + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectComparisonWithNull', '', Justification = 'Intentional use to select non null array items')] +[CmdletBinding(DefaultParameterSetName = 'Default')] +param( + [Parameter(Position = 0)] + [string]$XLFile, + + [Parameter(ParameterSetName = 'Default', Position = 1)] + [Alias('Path', 'relative_path')] + [object[]]$Script = '.', + + [Parameter(ParameterSetName = 'Existing', Mandatory = $true)] + [switch] + $UseExisting, + + [Parameter(ParameterSetName = 'Default', Position = 2)] + [Parameter(ParameterSetName = 'Existing', Position = 2, Mandatory = $true)] + [string]$OutputFile, + + [Parameter(ParameterSetName = 'Default')] + [Alias("Name")] + [string[]]$TestName, + + [Parameter(ParameterSetName = 'Default')] + [switch]$EnableExit, + + [Parameter(ParameterSetName = 'Default')] + [Alias('Tags')] + [string[]]$Tag, + [string[]]$ExcludeTag, + + [Parameter(ParameterSetName = 'Default')] + [switch]$Strict, + + [string]$WorkSheetName = 'PesterResults', + [switch]$append, + [switch]$Show +) + +$InvokePesterParams = @{OutputFormat = 'NUnitXml' } + $PSBoundParameters +if (-not $InvokePesterParams['OutputFile']) { + $InvokePesterParams['OutputFile'] = Join-Path -ChildPath 'Pester.xml'-Path ([environment]::GetFolderPath([System.Environment+SpecialFolder]::MyDocuments)) +} +if ($InvokePesterParams['Show'] ) { } +if ($InvokePesterParams['XLFile']) { $InvokePesterParams.Remove('XLFile') } +else { $XLFile = $InvokePesterParams['OutputFile'] -replace '.xml$', '.xlsx' } +if (-not $UseExisting) { + $InvokePesterParams.Remove('Append') + $InvokePesterParams.Remove('UseExisting') + $InvokePesterParams.Remove('Show') + $InvokePesterParams.Remove('WorkSheetName') + Invoke-Pester @InvokePesterParams +} + +if (-not (Test-Path -Path $InvokePesterParams['OutputFile'])) { + throw "Could not output file $($InvokePesterParams['OutputFile'])"; return +} + +$resultXML = ([xml](Get-Content $InvokePesterParams['OutputFile'])).'test-results' +$startDate = [datetime]$resultXML.date +$startTime = $resultXML.time +$machine = $resultXML.environment.'machine-name' +#$user = $resultXML.environment.'user-domain' + '\' + $resultXML.environment.user +$os = $resultXML.environment.platform -replace '\|.*$', " $($resultXML.environment.'os-version')" +<#hierarchy goes + root, [date], start [time], [Name] (always "Pester"), test results broken down as [total],[errors],[failures],[not-run] etc. + Environment (user & machine info) + Culture-Info (current, and currentUi culture) + Test-Suite [name] = "Pester" [result], [time] to execute, etc. + Results + Test-Suite [name] = filename,[result], [Time] to Execute etc + Results + Test-Suite [Name] = Describe block Name, [result], [Time] to execute etc.. + Results + Test-Suite [Name] = Context block name [result], [Time] to execute etc. + Results + Test-Case [name] = Describe.Context.It block names [description]= it block name, result], [Time] to execute etc + or if the tests are parameterized + Test suite [description] - name in the the it block with not filled in + Results + Test-case [description] - name as rendered for display with filled in +#> +$testResults = foreach ($test in $resultXML.'test-suite'.results.'test-suite') { + $testPs1File = $test.name + #Test if there are context blocks in the hierarchy OR if we go straight from Describe to test-case + if ($test.results.'test-suite'.results.'test-suite' -ne $null) { + foreach ($suite in $test.results.'test-suite') { + $Describe = $suite.description + foreach ($subsuite in $suite.results.'test-suite') { + $Context = $subsuite.description + if ($subsuite.results.'test-suite'.results.'test-case') { + $testCases = $subsuite.results.'test-suite'.results.'test-case' + } + else { $testCases = $subsuite.results.'test-case' } + $testCases | ForEach-Object { + New-Object -TypeName psobject -Property ([ordered]@{ + Machine = $machine ; OS = $os + Date = $startDate ; Time = $startTime + Executed = $(if ($_.executed -eq 'True') { 1 }) + Success = $(if ($_.success -eq 'True') { 1 }) + Duration = $_.time + File = $testPs1File; Group = $Describe + SubGroup = $Context ; Name = ($_.Description -replace '\s{2,}', ' ') + Result = $_.result ; FullDesc = '=Group&" "&SubGroup&" "&Name' + }) + } + } + } + } + else { + $test.results.'test-suite' | ForEach-Object { + $Describe = $_.description + $_.results.'test-case' | ForEach-Object { + New-Object -TypeName psobject -Property ([ordered]@{ + Machine = $machine ; OS = $os + Date = $startDate ; Time = $startTime + Executed = $(if ($_.executed -eq 'True') { 1 }) + Success = $(if ($_.success -eq 'True') { 1 }) + Duration = $_.time + File = $testPs1File; Group = $Describe + SubGroup = $null ; Name = ($_.Description -replace '\s{2,}', ' ') + Result = $_.result ; FullDesc = '=Group&" "&Test' + }) + } + } + } +} +if (-not $testResults) { Write-Warning 'No Results found' ; return } +$clearSheet = -not $Append +$excel = $testResults | Export-Excel -Path $xlFile -WorkSheetname $WorkSheetName -ClearSheet:$clearSheet -Append:$append -PassThru -BoldTopRow -FreezeTopRow -AutoSize -AutoFilter -AutoNameRange +$ws = $excel.Workbook.Worksheets[$WorkSheetName] +<# Worksheet should look like .. + |A |B |C D |E |F |G |H |I |J |K |L |M + 1|Machine |OS |Date Time |Executed |Success |Duration |File |Group |SubGroup |Name |Result |FullDescription + 2|Flatfish |Name_Version |[run started] |Boolean |Boolean |In seconds |xx.ps1 |Describe |Context |It |Success |Desc_Context_It +#> + +#Display Date as a date, not a date time +Set-Column -Worksheet $ws -Column 3 -NumberFormat 'Short Date' # -AutoSize + +#Hide columns E to J (Executed, Success, Duration, File, Group and Subgroup) +(5..10) | ForEach-Object { Set-ExcelColumn -Worksheet $ws -Column $_ -Hide } + +#Use conditional formatting to make Failures red, and Successes green (skipped remains black ) ... and save +$endRow = $ws.Dimension.End.Row +Add-ConditionalFormatting -WorkSheet $ws -range "L2:L$endrow" -RuleType ContainsText -ConditionValue "Failure" -BackgroundPattern None -ForegroundColor Red -Bold +Add-ConditionalFormatting -WorkSheet $ws -range "L2:L$endRow" -RuleType ContainsText -ConditionValue "Success" -BackgroundPattern None -ForeGroundColor Green +Close-ExcelPackage -ExcelPackage $excel -Show:$show + + + + + Examples/PesterTestReport/Pester test report.ps1 + + #Requires -Modules @{ ModuleName='Pester'; ModuleVersion='5.1' } + +<# +.SYNOPSIS + Run Pester tests and export the results to an Excel file. + +.DESCRIPTION + Use the `PesterConfigurationFile` to configure Pester to your requirements. + (Set the Path to the folder containing the tests, ...). Pester will be + invoked with the configuration you defined. + + Each Pester 'it' clause will be exported to a row in an Excel file + containing the details of the test (Path, Duration, Result, ...). + +.EXAMPLE + $params = @{ + PesterConfigurationFile = 'C:\TestResults\PesterConfiguration.json' + ExcelFilePath = 'C:\TestResults\Tests.xlsx' + WorkSheetName = 'Tests' + } + & 'Pester test report.ps1' @params + + # Content 'C:\TestResults\PesterConfiguration.json': + { + "Run": { + "Path": "C:\Scripts" + } + + Executing the script with this configuration file will generate 1 file: + - 'C:\TestResults\Tests.xlsx' created by this script with Export-Excel + +.EXAMPLE + $params = @{ + PesterConfigurationFile = 'C:\TestResults\PesterConfiguration.json' + ExcelFilePath = 'C:\TestResults\Tests.xlsx' + WorkSheetName = 'Tests' + } + & 'Pester test report.ps1' @params + + # Content 'C:\TestResults\PesterConfiguration.json': + { + "Run": { + "Path": "C:\Scripts" + }, + "TestResult": { + "Enabled": true, + "OutputFormat": "NUnitXml", + "OutputPath": "C:/TestResults/PesterTestResults.xml", + "OutputEncoding": "UTF8" + } + } + + Executing the script with this configuration file will generate 2 files: + - 'C:\TestResults\PesterTestResults.xml' created by Pester + - 'C:\TestResults\Tests.xlsx' created by this script with Export-Excel + +.LINK + https://pester-docs.netlify.app/docs/commands/Invoke-Pester#-configuration +#> + +[CmdletBinding()] +Param ( + [String]$PesterConfigurationFile = 'PesterConfiguration.json', + [String]$WorkSheetName = 'PesterTestResults', + [String]$ExcelFilePath = 'PesterTestResults.xlsx' +) + +Begin { + Function Get-PesterTests { + [CmdLetBinding()] + Param ( + $Container + ) + + if ($testCaseResults = $Container.Tests) { + foreach ($result in $testCaseResults) { + Write-Verbose "Result '$($result.result)' duration '$($result.time)' name '$($result.name)'" + $result + } + } + + if ($containerResults = $Container.Blocks) { + foreach ($result in $containerResults) { + Get-PesterTests -Container $result + } + } + } + + #region Import Pester configuration file + Try { + Write-Verbose 'Import Pester configuration file' + $getParams = @{ + Path = $PesterConfigurationFile + Raw = $true + } + [PesterConfiguration]$pesterConfiguration = Get-Content @getParams | + ConvertFrom-Json + } + Catch { + throw "Failed importing the Pester configuration file '$PesterConfigurationFile': $_" + } + #endregion +} + +Process { + #region Execute Pester tests + Try { + Write-Verbose 'Execute Pester tests' + $pesterConfiguration.Run.PassThru = $true + $invokePesterParams = @{ + Configuration = $pesterConfiguration + ErrorAction = 'Stop' + } + $invokePesterResult = Invoke-Pester @invokePesterParams + } + Catch { + throw "Failed to execute the Pester tests: $_ " + } + #endregion + + #region Get Pester test results for the it clauses + $pesterTestResults = foreach ( + $container in $invokePesterResult.Containers + ) { + Get-PesterTests -Container $container | + Select-Object -Property *, + @{name = 'Container'; expression = { $container } } + } + #endregion +} + +End { + if ($pesterTestResults) { + #region Export Pester test results to an Excel file + $exportExcelParams = @{ + Path = $ExcelFilePath + WorksheetName = $WorkSheetName + ClearSheet = $true + PassThru = $true + BoldTopRow = $true + FreezeTopRow = $true + AutoSize = $true + AutoFilter = $true + AutoNameRange = $true + } + + Write-Verbose "Export Pester test results to Excel file '$($exportExcelParams.Path)'" + + $excel = $pesterTestResults | Select-Object -Property @{ + name = 'FilePath'; expression = { $_.container.Item.FullName } + }, + @{name = 'FileName'; expression = { $_.container.Item.Name } }, + @{name = 'Path'; expression = { $_.ExpandedPath } }, + @{name = 'Name'; expression = { $_.ExpandedName } }, + @{name = 'Date'; expression = { $_.ExecutedAt } }, + @{name = 'Time'; expression = { $_.ExecutedAt } }, + Result, + Passed, + Skipped, + @{name = 'Duration'; expression = { $_.Duration.TotalSeconds } }, + @{name = 'TotalDuration'; expression = { $_.container.Duration } }, + @{name = 'Tag'; expression = { $_.Tag -join ', ' } }, + @{name = 'Error'; expression = { $_.ErrorRecord -join ', ' } } | + Export-Excel @exportExcelParams + #endregion + + #region Format the Excel worksheet + $ws = $excel.Workbook.Worksheets[$WorkSheetName] + + # Display ExecutedAt in Date and Time format + Set-Column -Worksheet $ws -Column 5 -NumberFormat 'Short Date' + Set-Column -Worksheet $ws -Column 6 -NumberFormat 'hh:mm:ss' + + # Display Duration in seconds with 3 decimals + Set-Column -Worksheet $ws -Column 10 -NumberFormat '0.000' + + # Add comment to Duration column title + $comment = $ws.Cells['J1:J1'].AddComment('Total seconds', $env:USERNAME) + $comment.AutoFit = $true + + # Set the width for column Path + $ws.Column(3) | Set-ExcelRange -Width 29 + + # Center the column titles + Set-ExcelRange -Address $ws.Row(1) -Bold -HorizontalAlignment Center + + # Hide columns FilePath, Name, Passed and Skipped + (1, 4, 8, 9) | ForEach-Object { + Set-ExcelColumn -Worksheet $ws -Column $_ -Hide + } + + # Set the color to red when 'Result' is 'Failed' + $endRow = $ws.Dimension.End.Row + $formattingParams = @{ + Worksheet = $ws + range = "G2:L$endRow" + RuleType = 'ContainsText' + ConditionValue = "Failed" + BackgroundPattern = 'None' + ForegroundColor = 'Red' + Bold = $true + } + Add-ConditionalFormatting @formattingParams + + # Set the color to green when 'Result' is 'Passed' + $endRow = $ws.Dimension.End.Row + $formattingParams = @{ + Worksheet = $ws + range = "G2:L$endRow" + RuleType = 'ContainsText' + ConditionValue = "Passed" + BackgroundPattern = 'None' + ForegroundColor = 'Green' + } + Add-ConditionalFormatting @formattingParams + #endregion + + #region Save the formatted Excel file + Close-ExcelPackage -ExcelPackage $excel + #endregion + } + else { + Write-Warning 'No Pester test results to export' + } +} + + + + Examples/PivotTable/MultiplePivotTables.ps1 + + $data = ConvertFrom-Csv @" +Region,Date,Fruit,Sold +North,1/1/2017,Pears,50 +South,1/1/2017,Pears,150 +East,4/1/2017,Grapes,100 +West,7/1/2017,Bananas,150 +South,10/1/2017,Apples,200 +North,1/1/2018,Pears,100 +East,4/1/2018,Grapes,200 +West,7/1/2018,Bananas,300 +South,10/1/2018,Apples,400 +"@ | Select-Object -Property Region, @{n = "Date"; e = {[datetime]::ParseExact($_.Date, "M/d/yyyy", (Get-Culture))}}, Fruit, Sold + +$xlfile = "$env:temp\multiplePivotTables.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$excel = $data | Export-Excel $xlfile -PassThru -AutoSize -TableName FruitData + +$pivotTableParams = @{ + PivotTableName = "ByRegion" + Address = $excel.Sheet1.cells["F1"] + SourceWorkSheet = $excel.Sheet1 + PivotRows = @("Region", "Fruit", "Date") + PivotData = @{'sold' = 'sum'} + PivotTableStyle = 'Light21' + GroupDateRow = "Date" + GroupDatePart = @("Years", "Quarters") +} + +$pt = Add-PivotTable @pivotTableParams -PassThru +#$pt.RowHeaderCaption ="By Region,Fruit,Date" +$pt.RowHeaderCaption = "By " + ($pivotTableParams.PivotRows -join ",") + +$pivotTableParams.PivotTableName = "ByFruit" +$pivotTableParams.Address = $excel.Sheet1.cells["J1"] +$pivotTableParams.PivotRows = @("Fruit", "Region", "Date") + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Fruit,Region" + +$pivotTableParams.PivotTableName = "ByDate" +$pivotTableParams.Address = $excel.Sheet1.cells["N1"] +$pivotTableParams.PivotRows = @("Date", "Region", "Fruit") + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Date,Region,Fruit" + +$pivotTableParams.PivotTableName = "ByYears" +$pivotTableParams.Address = $excel.Sheet1.cells["S1"] +$pivotTableParams.GroupDatePart = "Years" + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Years,Region" + +Close-ExcelPackage $excel -Show + + + + Examples/PivotTable/PivotTableWithName.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$ExcelParams = @{ + Path = "$env:TEMP\test1.xlsx" + IncludePivotTable = $true + PivotRows = 'Company' + PivotTableName = 'MyTable' + PivotData = @{'Handles' = 'sum'} + Show = $true + Activate = $true +} +Remove-Item $ExcelParams.Path -ErrorAction Ignore +Get-Process | Select-Object Company, Handles | Export-Excel @ExcelParams + +<# Builds a pivot table that looks like this: + + Sum of Handles + Row Labels Total + Adobe Systems Incorporated 3100 + (blank) 214374 + Apple Inc. 215 + etc + etc + Grand Total 365625 +#> + + + + Examples/PivotTable/TableAndPivotTable.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +#Get rid of pre-exisiting sheet +$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx" +Write-Verbose -Verbose -Message "Save location: $xlSourcefile" +Remove-Item $xlSourcefile -ErrorAction Ignore + +#Export some sales data to Excel, format it as a table and put a data-bar in. For this example we won't create the pivot table during the export +$excel = ConvertFrom-Csv @" +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 +"@ | Export-Excel -PassThru -Path $xlSourcefile -TableStyle Medium13 -tablename "RawData" -ConditionalFormat @{Range="C2:C7"; DataBarColor="Green"} + +#Add a pivot table, specify its address to put it on the same sheet, use the data that was just exported set the table style and number format. +#Use the "City" for the row names, and "Product" for the columnnames, and sum both the gross and net values for each City/Product combination; add grand totals to rows and columns. +# activate the sheet and add a pivot chart (defined in a hash table) +Add-PivotTable -Address $excel.Sheet1.Cells["F1"] -SourceWorkSheet $Excel.Sheet1 -SourceRange $Excel.Sheet1.Dimension.Address -PivotTableName "Sales" -PivotTableStyle "Medium12" -PivotNumberFormat "$#,##0.00" ` + -PivotRows "City" -PivotColumns "Product" -PivotData @{Gross="Sum";Net="Sum"}-PivotTotals "Both" -Activate -PivotChartDefinition @{ + Title="Gross and net by city and product"; + ChartType="ColumnClustered"; + Column=11; Width=500; Height=360; + YMajorUnit=500; YMinorUnit=100; YAxisNumberformat="$#,##0" + LegendPosition="Bottom"} +#Save and open in excel +Close-ExcelPackage $excel -Show + + + + Examples/PivotTableFilters/testPivotFilter.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlFile="$env:TEMP\testPivot.xlsx" +Remove-Item $xlFile -ErrorAction Ignore + +$data =@" +Region,Area,Product,Units,Cost +North,A1,Apple,100,.5 +South,A2,Pear,120,1.5 +East,A3,Grape,140,2.5 +West,A4,Banana,160,3.5 +North,A1,Pear,120,1.5 +North,A1,Grape,140,2.5 +"@ | ConvertFrom-Csv + +$data | + Export-Excel $xlFile -Show ` + -AutoSize -AutoFilter ` + -IncludePivotTable ` + -PivotRows Product ` + -PivotData @{"Units"="sum"} -PivotFilter Region, Area -Activate + +<# +Creates a Pivot table that looks like +Region All^ +Area All^ + +Sum of Units +Row Labels Total +Apple 100 +Pear 240 +Grape 280 +Banana 160 +Grand Total 780 +#> + + + + Examples/Plot/PlotCos.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$plt = New-Plot +$plt.Plot((Get-Range 0 5 .02|Foreach-Object {[math]::Cos(2*[math]::pi*$_)})) +$plt.SetChartSize(800,300) +$plt.Show() + + + + Examples/PsGallery.ps1 + + +$top1000 = foreach ($p in 1..50) { + $c = Invoke-WebRequest -Uri "https://www.powershellgallery.com/packages" -method Post -Body "q=&sortOrder=package-download-count&page=$p" + [regex]::Matches($c.Content,'.*?
    ', [System.Text.RegularExpressions.RegexOptions]::Singleline) | foreach { + $name = [regex]::Match($_, "(?<=

    ).*(?=

    )").value + $n = [regex]::replace($_,'^.*By:\s*
  • ','', [System.Text.RegularExpressions.RegexOptions]::Singleline) + $n = [regex]::replace($n,'.*$','', [System.Text.RegularExpressions.RegexOptions]::Singleline) + $by = [regex]::match($n,'(?<=">).*(?=)').value + $qty = [regex]::match($n,'\S*(?= downloads)').value + [PSCustomObject]@{ + Name = $name + by = $by + Downloads = $qty + } + } +} + +del "~\Documents\gallery.xlsx" +$pivotdef = New-PivotTableDefinition -PivotTableName 'Summary' -PivotRows by -PivotData @{name="Count" + Downloads="Sum"} -PivotDataToColumn -Activate -ChartType ColumnClustered -PivotNumberFormat '#,###' +$top1000 | export-excel -path '~\Documents\gallery.xlsx' -Numberformat '#,###' -PivotTableDefinition $pivotdef -TableName 'TopDownloads' -Show + + + + Examples/ReadAllSheets/GenerateXlsx.ps1 + + param( + [Parameter(Mandatory)] + $path +) + +$sheet1 = ConvertFrom-Csv @" +Region,Item,TotalSold +West,melon,27 +North,avocado,21 +West,kiwi,84 +East,melon,23 +North,kiwi,8 +North,nail,29 +North,kiwi,46 +South,nail,83 +East,pear,10 +South,avocado,40 +"@ + +$sheet2 = ConvertFrom-Csv @" +Region,Item,TotalSold +West,lemon,24 +North,hammer,41 +East,nail,87 +West,lemon,68 +North,screwdriver,9 +North,drill,76 +West,lime,28 +West,pear,78 +North,apple,95 +South,melon,40 +"@ + +$sheet3 = ConvertFrom-Csv @" +Region,Item,TotalSold +South,drill,100 +East,saw,22 +North,saw,5 +West,orange,78 +East,saw,27 +North,screwdriver,57 +South,hammer,66 +East,saw,62 +West,nail,98 +West,nail,98 +"@ + +Remove-Item $path -ErrorAction SilentlyContinue + +$sheet1 | Export-Excel $path -WorksheetName Sheet1 +$sheet2 | Export-Excel $path -WorksheetName Sheet2 +$sheet3 | Export-Excel $xlfile -WorksheetName Sheet3 + +$path + + + + Examples/ReadAllSheets/Get-ExcelSheets.ps1 + + # Get-ExcelSheets + +param( + [Parameter(Mandatory)] + $path +) + + +$hash = @{ } + +$e = Open-ExcelPackage $path + +foreach ($sheet in $e.workbook.worksheets) { + $hash[$sheet.name] = Import-Excel -ExcelPackage $e -WorksheetName $sheet.name +} + +Close-ExcelPackage $e -NoSave + +$hash + + + + Examples/ReadAllSheets/ReadAllSheets.ps1 + + $xlfile = "$env:TEMP\MultipleSheets.xlsx" + +.\GenerateXlsx.ps1 $xlfile +.\Get-ExcelSheets.ps1 $xlfile + + + + Examples/SQL+FillColumns+Pivot/Example.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$sql = @" + SELECT rootfile.baseName , rootfile.extension , Image.fileWidth AS width , image.fileHeight AS height , + metadata.dateDay , metadata.dateMonth , metadata.dateYear , Image.captureTime AS dateTaken, + metadata.hasGPS , metadata.GPSLatitude , metadata.GPSLongitude , + metadata.focalLength , metadata.flashFired , metadata.ISOSpeedRating AS ISOSpeed, + metadata.Aperture AS apertureValue , metadata.ShutterSpeed AS shutterSpeedValue, + Image.bitdepth , image.colorLabels , + Camera.Value AS cameraModel , LensRef.value AS lensModel + FROM Adobe_images image + JOIN AgLibraryFile rootFile ON rootfile.id_local = image.rootFile + JOIN AgharvestedExifMetadata metadata ON image.id_local = metadata.image + LEFT JOIN AgInternedExifLens LensRef ON LensRef.id_Local = metadata.lensRef + LEFT JOIN AgInternedExifCameraModel Camera ON Camera.id_local = metadata.cameraModelRef +"@ + +#Sql Statement gets 20 columns of data from Adobe lightroom database +#Define a pivot table and chart for total pictures with each lens. + +$pt = @{"LensPivot" = @{ "PivotTableName" = "LensPivot"; + "SourceWorkSheet" = "Sheet1" ; + "PivotRows" = "LensModel" ; + "PivotData" = @{"basename" = "Count"} ; + "IncludePivotChart" = $true ; + "NoLegend" = $true ; + "ShowPercent" = $true ; + "ChartType" = "Pie" ; + "ChartTitle" = "Split by Lens" } +} + +#we want to add 3 columns, translate Apperture value and Shutter speed value into familar f/ and seconds notation, and use these and ISO to calculate EV level +$Avalue = {"=IF(P$ROW>6.63,TEXT(ROUND(Sqrt(Power(2,O$ROW)),1),`"`"`"f/`"`"0.0`")," + + "TEXT(ROUND(Sqrt(Power(2,O$ROW)),1),`"`"`"f/`"`"0.0`"))"} +$Svalue = {"=IF(P$ROW>2,TEXT(ROUND(POWER(2,P$ROW),0),`"`"`"1/`"`"0`"`"sec`"`"`"),"+ + "IF(P$ROW>3.32,TEXT(ROUND(1/POWER(2,P$ROW),2),`"0.0`"`"Sec`"`"`"),"+ + "TEXT(ROUND(1/POWER(2,P$ROW),2),`"0`"`"Sec`"`"`")))"} +$evValue = {"=ROUND(P$Row+O$Row-(LOG(N$Row/100,2)),0)" } + +#remove and recreate the file +Remove-Item -Path "~\Documents\temp.xlsx" -ErrorAction SilentlyContinue + +#Open a connection to the ODBC source "LR" (which points to the SQLLite DB for Lightroom), run the SQL query, and drop into Excel - in sheet1, autosizing columns. +$e = Send-SQLDataToExcel -Path "~\Documents\temp.xlsx" -WorkSheetname "Sheet1" -Connection "DSN=LR" -SQL $sql -AutoSize -Passthru + +#Add columns, then format them and hide the ones which aren't of interest. +Set-ExcelColumn -Worksheet $e.workbook.Worksheets["sheet1"] -Column 21 -Value $Avalue -Heading "Apperture" +Set-ExcelColumn -Worksheet $e.workbook.Worksheets["sheet1"] -Column 22 -Value $Svalue -Heading "Shutter" +Set-ExcelColumn -Worksheet $e.workbook.Worksheets["sheet1"] -Column 23 -Value $Evvalue -Heading "Ev" +Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Column(21) -HorizontalAlignment Left -AutoFit +Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Column(22) -HorizontalAlignment Right -AutoFit +@(5,6,7,13,15,16,17,18) | ForEach-Object { + Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Column($_) -Hidden +} + +#Center the column labels. +Set-ExcelRange -Address $e.workbook.Worksheets["sheet1" ].Row(1) -HorizontalAlignment Center + +#Format the data as a nice Table, Create the pivot table & chart defined above, show the file in Excel in excel after saving. +Export-Excel -ExcelPackage $e -WorkSheetname "sheet1" -TableName "Table" -PivotTableDefinition $pt -Show + +############################################################ + +Remove-Item .\demo3.xlsx +#Database query to get race wins, Poles and fastest lapes for the 25 best drivers; we already have a connection to the DB in $dbSessions +$session = $DbSessions["f1"] +$SQL = @" + SELECT TOP 25 DriverName, + Count(RaceDate) AS Races, + Count(Win) AS Wins, + Count(Pole) AS Poles, + Count(FastestLap) AS Fastlaps + FROM Results + GROUP BY DriverName + ORDER BY (Count(win)) DESC +"@ + +#Run the query and put the results in workshet "Winners", autosize the columns and hold on to the ExcelPackage object +$Excel = Send-SQLDataToExcel -SQL $sql -Session $session -path .\demo3.xlsx -WorkSheetname "Winners" -AutoSize -Passthru +#Create and format columns for the ratio of Wins to poles and fast laps. +Set-ExcelColumn -ExcelPackage $Excel -WorkSheetname "Winners" -column 6 -Heading "WinsToPoles" -Value {"=D$row/C$row"} +Set-ExcelColumn -ExcelPackage $Excel -WorkSheetname "Winners" -column 7 -Heading "WinsToFast" -Value {"=E$row/C$row"} +6..7 | ForEach-Object { + Set-ExcelRange -Address $Excel.Workbook.Worksheets["Winners"].column($_) -NumberFormat "0.0%" -AutoFit } +#Define a chart to show the relationship of lest on an XY Grid, create the ranges required in the, add the chart and show the file in Excel in excel after saving. +$chart = New-ExcelChartDefinition -NoLegend -ChartType XYScatter -XRange WinsToFast -YRange WinsToPoles -ShowCategory -Column 7 -Width 2000 -Height 700 +Export-Excel -ExcelPackage $Excel -WorkSheetname "Winners" -AutoNameRange -ExcelChartDefinition $chart -Show + + + + + + Examples/SQL+FillColumns+Pivot/Example2.ps1 + + #requires -modules "getSql" + +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} +#download f1Results from https://1drv.ms/f/s!AhfYu7-CJv4egbt5FD7Cdxi8jSz3aQ and update the path below +Get-SQL -Session f1 -Excel -Connection C:\Users\mcp\OneDrive\Public\F1\f1Results.xlsx -showtables -Verbose + +Remove-Item .\demo3.xlsx +$session = $DbSessions["f1"] + +$SQL = "SELECT top 25 DriverName, Count(RaceDate) as Races , + Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps + FROM Results GROUP BY DriverName + order by (count(win)) desc" +$Excel = Send-SQLDataToExcel -SQL $sql -Session $session -path .\demo3.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange -BoldTopRow -FreezeTopRow -Passthru + +$ws = $Excel.Workbook.Worksheets["Winners"] + +Set-ExcelRow -Worksheet $ws -Heading "Average" -Value {"=Average($columnName`2:$columnName$endrow)"} -NumberFormat "0.0" -Bold +Set-ExcelColumn -Worksheet $ws -Heading "WinsToPoles" -Value {"=D$row/C$row"} -Column 6 -AutoSize -AutoNameRange +Set-ExcelColumn -Worksheet $ws -Heading "WinsToFast" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange + +Set-ExcelRange -Worksheet $ws -Range "F2:G50" -NumberFormat "0.0%" +$chart = New-ExcelChartDefinition -NoLegend -ChartType XYScatter -XRange WinsToFast -YRange WinsToPoles -Column 7 -Width 2000 -Height 700 -Title "Poles vs fastlaps" +Export-Excel -ExcelPackage $Excel -WorkSheetname "Winners" -ExcelChartDefinition $chart -Show + + + + Examples/SetColumnBackgroundColor/SetColumnBackgroundColor.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$path = "$env:TEMP\testBackgroundColor.xlsx" + +$p = Get-Process | Select-Object Company, Handles | Export-Excel $path -ClearSheet -PassThru + +$ws = $p.Workbook.WorkSheets[1] +$totalRows = $ws.Dimension.Rows + +#Set the range from B2 to the last active row. s +Set-ExcelRange -Range $ws.Cells["B2:B$($totalRows)"] -BackgroundColor LightBlue + +Export-Excel -ExcelPackage $p -show -AutoSize + + + + Examples/Sparklines/SalesByQuarter.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\SalesByQuarter.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data = ConvertFrom-Csv @" +Region,Q1,Q2,Q3,Q4,YTDPerformance +Asia,1400,7200,5700,6900 +Europe,3400,2300,9400,7300 +Midwest,4700,9300,3700,8600 +Northeast,2300,4300,4600,5600 +"@ + +$excel = $data | Export-Excel $xlfile -Passthru -AutoSize -TableName SalesByQuarter + +$ws = $excel.Sheet1 + +Set-ExcelRange -Worksheet $ws -Range "B2:E5" -NumberFormat "$#,##0" -AutoSize +$sparkLineType = "line" +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F2"], $ws.Cells["B2:E2"] ) +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F3"], $ws.Cells["B3:E3"] ) +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F4"], $ws.Cells["B4:E4"] ) +$null = $ws.SparklineGroups.Add( $sparkLineType, $ws.Cells["F5"], $ws.Cells["B5:E5"] ) + +Close-ExcelPackage $excel -Show + + + + Examples/Sparklines/Sparklines.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +class data { + [datetime]$Date + [Double]$AUD + [Double]$CAD + [Double]$CHF + [Double]$DKK + [Double]$EUR + [Double]$GBP + [Double]$HKD + [Double]$JPY + [Double]$MYR + [Double]$NOK + [Double]$NZD + [Double]$RUB + [Double]$SEK + [Double]$THB + [Double]$TRY + [Double]$USD +} + +[data[]]$data = ConvertFrom-Csv @" +Date,AUD,CAD,CHF,DKK,EUR,GBP,HKD,JPY,MYR,NOK,NZD,RUB,SEK,THB,TRY,USD +2016-03-01,6.17350,6.42084,8.64785,1.25668,9.37376,12.01683,1.11067,0.07599,2.06900,0.99522,5.69227,0.11665,1.00000,0.24233,2.93017,8.63185 +2016-03-02,6.27223,6.42345,8.63480,1.25404,9.35350,12.14970,1.11099,0.07582,2.07401,0.99311,5.73277,0.11757,1.00000,0.24306,2.94083,8.63825 +2016-03-07,6.33778,6.38403,8.50245,1.24980,9.32373,12.05756,1.09314,0.07478,2.07171,0.99751,5.77539,0.11842,1.00000,0.23973,2.91088,8.48885 +2016-03-08,6.30268,6.31774,8.54066,1.25471,9.36254,12.03361,1.09046,0.07531,2.05625,0.99225,5.72501,0.11619,1.00000,0.23948,2.91067,8.47020 +2016-03-09,6.32630,6.33698,8.46118,1.24399,9.28125,11.98879,1.08544,0.07467,2.04128,0.98960,5.71601,0.11863,1.00000,0.23893,2.91349,8.42945 +2016-03-10,6.24241,6.28817,8.48684,1.25260,9.34350,11.99193,1.07956,0.07392,2.04500,0.98267,5.58145,0.11769,1.00000,0.23780,2.89150,8.38245 +2016-03-11,6.30180,6.30152,8.48295,1.24848,9.31230,12.01194,1.07545,0.07352,2.04112,0.98934,5.62335,0.11914,1.00000,0.23809,2.90310,8.34510 +2016-03-15,6.19790,6.21615,8.42931,1.23754,9.22896,11.76418,1.07026,0.07359,2.00929,0.97129,5.49278,0.11694,1.00000,0.23642,2.86487,8.30540 +2016-03-16,6.18508,6.22493,8.41792,1.23543,9.21149,11.72470,1.07152,0.07318,2.01179,0.96907,5.49138,0.11836,1.00000,0.23724,2.84767,8.31775 +2016-03-17,6.25214,6.30642,8.45981,1.24327,9.26623,11.86396,1.05571,0.07356,2.01706,0.98159,5.59544,0.12024,1.00000,0.23543,2.87595,8.18825 +2016-03-18,6.25359,6.32400,8.47826,1.24381,9.26976,11.91322,1.05881,0.07370,2.02554,0.98439,5.59067,0.12063,1.00000,0.23538,2.86880,8.20950 +"@ + +$xlfile = "$env:TEMP\sparklines.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$excel = $data | Export-Excel $xlfile -WorksheetName SEKRates -AutoSize -PassThru + +# Add a column sparkline for all currencies +Set-ExcelRange -Worksheet $excel.SEKRates -Range "A2:A12" -NumberFormat "yyyy-mm-dd" -AutoSize +Set-ExcelRange -Worksheet $excel.SEKRates -Range A15 -Value Column -AutoSize + +$sparklineCol = $excel.SEKRates.SparklineGroups.Add( + "Column", + $excel.SEKRates.Cells["B15:Q15"], + $excel.SEKRates.Cells["B2:Q12"] +) + +$sparklineCol.High = $true +$sparklineCol.ColorHigh.SetColor("Red") + +# Add a line sparkline for all currencies +Set-ExcelRange -Worksheet $excel.SEKRates -Range A16 -Value Line -AutoSize +$sparklineLine = $excel.SEKRates.SparklineGroups.Add( + "Line", + $excel.SEKRates.Cells["B16:Q16"], + $excel.SEKRates.Cells["B2:Q12"] +) + +$sparklineLine.DateAxisRange = $excel.SEKRates.Cells["A2:A12"] + +# Add some more random values and add a stacked sparkline. +Set-ExcelRange -Worksheet $excel.SEKRates -Range A17 -Value Stacked -AutoSize + +$numbers = 2, -1, 3, -4, 8, 5, -12, 18, 99, 1, -4, 12, -8, 9, 0, -8 + +$col = 2 # Column B +foreach ($n in $numbers) { + $excel.SEKRates.Cells[17, $col++].Value = $n +} + +$sparklineStacked = $excel.SEKRates.SparklineGroups.Add( + "Stacked", + $excel.SEKRates.Cells["R17"], + $excel.SEKRates.Cells["B17:Q17"] +) + +$sparklineStacked.High = $true +$sparklineStacked.ColorHigh.SetColor("Red") +$sparklineStacked.Low = $true +$sparklineStacked.ColorLow.SetColor("Green") +$sparklineStacked.Negative = $true +$sparklineStacked.ColorNegative.SetColor("Blue") + +Set-ExcelRange -Worksheet $excel.SEKRates -Range "A15:A17" -Bold -Height 50 -AutoSize + +$v = @" +High - Red +Low - Green +Negative - Blue +"@ + +Set-ExcelRange -Worksheet $excel.SEKRates -Range S17 -Value $v -WrapText -Width 20 -HorizontalAlignment Center -VerticalAlignment Center + +Close-ExcelPackage $excel -Show + + + + Examples/SpreadsheetCells/CalculatedFields.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + + +#. ..\New-PSItem.ps1 + +Remove-Item "$env:temp\functions.xlsx" -ErrorAction SilentlyContinue + +$( + New-PSItem 12001 Nails 37 3.99 =C2*D2 @("ID", "Product", "Quantity", "Price", "Total") + New-PSItem 12002 Hammer 5 12.10 =C3*D3 + New-PSItem 12003 Saw 12 15.37 =C4*D4 + New-PSItem 12010 Drill 20 8 =C5*D5 + New-PSItem 12011 Crowbar 7 23.48 =C6*D6 +) | Export-Excel "$env:temp\functions.xlsx"-AutoSize -Show + + + + + Examples/SpreadsheetCells/ExcelFormulasUsingAddMember.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item .\testFormula.xlsx -ErrorAction Ignore + +@" +id,item,units,cost +12001,Nails,37,3.99 +12002,Hammer,5,12.10 +12003,Saw,12,15.37 +12010,Drill,20,8 +12011,Crowbar,7,23.48 +"@ | ConvertFrom-Csv | + Add-Member -PassThru -MemberType NoteProperty -Name Total -Value "=units*cost" | + Export-Excel -Path .\testFormula.xlsx -Show -AutoSize -AutoNameRange + + + + Examples/SpreadsheetCells/ExcelFunctions.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item "$env:temp\functions.xlsx" -ErrorAction SilentlyContinue + +$( + New-PSItem =2%/12 60 500000 "=pmt(rate,nper,pv)" @("rate", "nper", "pv", "pmt") + New-PSItem =3%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =4%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =5%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =6%/12 60 500000 "=pmt(rate,nper,pv)" + New-PSItem =7%/12 60 500000 "=pmt(rate,nper,pv)" +) | Export-Excel "$env:temp\functions.xlsx" -AutoNameRange -AutoSize -Show + + + + Examples/SpreadsheetCells/HyperLink.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +Remove-Item "$env:temp\hyperlink.xlsx" -ErrorAction SilentlyContinue + +$( + New-PSItem '=Hyperlink("http://dougfinke.com/blog","Doug Finke")' @("Link") + New-PSItem '=Hyperlink("http://blogs.msdn.com/b/powershell/","PowerShell Blog")' + New-PSItem '=Hyperlink("http://blogs.technet.com/b/heyscriptingguy/","Hey, Scripting Guy")' + +) | Export-Excel "$env:temp\hyperlink.xlsx" -AutoSize -Show + + + + + Examples/Stocks/Get-StockInfo.ps1 + + function Get-StockInfo { + param( + [Parameter(Mandatory)] + $symbols, + [ValidateSet('open', 'close', 'high', 'low', 'avgTotalVolume')] + $dataPlot = "close" + ) + + $xlfile = "$env:TEMP\stocks.xlsx" + Remove-Item -Path $xlfile -ErrorAction Ignore + + $result = Invoke-RestMethod "https://api.iextrading.com/1.0/stock/market/batch?symbols=$($symbols)&types=quote&last=1" + + $ecd = New-ExcelChartDefinition -Row 1 -Column 1 -SeriesHeader $dataPlot ` + -XRange symbol -YRange $dataPlot ` + -Title "$($dataPlot)`r`n As Of $((Get-Date).ToShortDateString())" + + $(foreach ($name in $result.psobject.Properties.name) { + $result.$name.quote + }) | Export-Excel $xlfile -AutoNameRange -AutoSize -Show -ExcelChartDefinition $ecd -StartRow 21 -StartColumn 2 +} + + + + + Examples/Stocks/GetStocksAvgTotVol.ps1 + + . $PSScriptRoot\Get-StockInfo.ps1 + +Get-StockInfo -symbols "msft,ibm,ge,xom,aapl" -dataPlot avgTotalVolume + + + + Examples/Styles/MultipleStyles.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\test.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data = ConvertFrom-Csv @" +Region,Item,TotalSold +North,melon,38 +South,screwdriver,21 +South,peach,33 +South,saw,81 +South,kiwi,70 +North,orange,59 +North,avocado,25 +South,lime,48 +South,nail,83 +North,apple,2 +"@ + +$styleParams = @{ + FontSize = 13 + Bold = $true +} + +$styles = $( + New-ExcelStyle -BackgroundColor LightBlue -FontSize 14 -Bold -Range "A1:H1" -HorizontalAlignment Center -Merge + + New-ExcelStyle -BackgroundColor LimeGreen -Range "B10" @styleParams + New-ExcelStyle -BackgroundColor PeachPuff -Range "B5" @styleParams + New-ExcelStyle -BackgroundColor Orange -Range "B8" @styleParams + New-ExcelStyle -BackgroundColor Red -Range "B12" @styleParams +) + +$reportTitle = "This is a report Title" +$data | Export-Excel $xlfile -Show -AutoSize -AutoFilter -Title $reportTitle -Style $styles + + + + Examples/Styles/NewExcelStyle.ps1 + + # https://raw.githubusercontent.com/dfinke/ImportExcel/master/images/NewExcelStyle.png +try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:TEMP\test.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$data = ConvertFrom-Csv @" +Region,Item,TotalSold +North,melon,38 +South,screwdriver,21 +South,peach,33 +South,saw,81 +South,kiwi,70 +North,orange,59 +North,avocado,25 +South,lime,48 +South,nail,83 +North,apple,2 +"@ + +$reportTitle = "This is a report Title" +$style = New-ExcelStyle -BackgroundColor LightBlue -FontSize 14 -Bold -Range "A1:H1" -HorizontalAlignment Center -Merge +$data | Export-Excel $xlfile -Show -AutoSize -AutoFilter -Title $reportTitle -Style $style + + + + Examples/Subtotals.ps1 + + $Data = ConvertFrom-Csv @' +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Grape, Munich, 100, 100 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 +'@ +$ExcelPath = "$env:temp\subtotal.xlsx" +$SheetName = 'Sheet1' +Remove-Item -Path $ExcelPath -ErrorAction SilentlyContinue + + +$GroupByFieldName = 'City' +$TotalSingleRows = $false +$GrandTotal = $false +$SubtotalRowHeight = 0 #If non zero will set subtotals to this height +$Subtotals =@{ 'Net' = {"=SUBTOTAL(3,D{0}:D{1})" -f $from, $to} + + +} +$SubtotalFieldName = 'Net' + +$SubtotalFormula = '=SUBTOTAL(3,D{0}:D{1})' # {0} and {1} are placeholders for the first and last row. D is the column to total in + # 1=AVERAGE; 2=COUNT; 3=COUNTA; 4=MAX; 5=MIN; 6=PRODUCT; 7=STDEV; 8=STDEVP; 9=SUM; 10=VAR; 11=VARP add 100 to ignore hidden values + +#at each change in the Group by field, insert a subtotal (count) formula in the title column & send to excel - list those rows and make them half height after export +$currentRow = 2 +$lastChangeRow = 2 +$insertedRows = @() +#$hideRows = @() +$lastValue = $Data[0].$GroupByFieldName +$excel = $Data | ForEach-Object -Process { + if ($_.$GroupByFieldName -ne $lastvalue) { + if ($lastChangeRow -lt ($currentrow - 1) -or $totalSingleRows) { + $formula = $SubtotalFormula -f $lastChangeRow, ($currentrow - 1) + $insertedRows += $currentRow + [pscustomobject]@{$SubtotalFieldName = $formula} + $currentRow += 1 + } + $lastChangeRow = $currentRow + $lastValue = $_.$GroupByFieldName + } + $_ + $currentRow += 1 +} -end { + $formula = $SubtotalFormula -f $lastChangeRow, ($currentrow - 1) + [pscustomobject]@{$SubtotalFieldName=$formula} + if ($GrandTotal) { + $formula = $SubtotalFormula -f $lastChangeRow, ($currentrow - 1) + [pscustomobject]@{$SubtotalFieldName=$formula} + } +} | Export-Excel -Path $ExcelPath -PassThru -AutoSize -AutoFilter -BoldTopRow -WorksheetName $sheetName + +#We kept a lists of the total rows. Since single rows won't get expanded/collapsed hide them. +if ($subtotalrowHeight) { + foreach ($r in $insertedrows) { $excel.WorkItems.Row($r).Height = $SubtotalRowHeight} +} +#foreach ($r in $hideRows) { $excel.$SheetName.Row($r).hidden = $true} +$range = $excel.$SheetName.Dimension.Address +$sheetIndex = $excel.Sheet1.Index +Close-ExcelPackage -ExcelPackage $excel + +try { $excelApp = New-Object -ComObject "Excel.Application" } +catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return } + +try { $excelWorkBook = $excelApp.Workbooks.Open($ExcelPath) } +catch { Write-Warning -Message "Could not Open $ExcelPath." ; return } +$ws = $excelWorkBook.Worksheets.Item($sheetIndex) +$null = $ws.Range($range).Select() +$null = $excelapp.Selection.AutoOutline() +$excelWorkBook.Save() +$excelWorkBook.Close() +$excelApp.Quit() + +Start-Process $ExcelPath + + + + Examples/Tables/MultipleTables.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfile = "$env:Temp\testData.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$r = Get-ChildItem C:\WINDOWS\system32 + +$BySize=@{} +$r | ForEach-Object{ $BySize.($_.extension)+=$_.length } + +$top10BySize = $BySize.GetEnumerator() | + ForEach-Object{ [PSCustomObject]@{Name=$_.key;Size=[double]$_.value} } | + Sort-Object size -Descending | + Select-Object -First 10 + +$top10ByCount = $r.extension | + Group-Object | + Sort-Object count -Descending | + Select-Object -First 10 Name, count + +$top10ByFileSize = $r | + Sort-Object length -Descending | + Select-Object -First 10 Name, @{n="Size";e={$_.Length}} #,Extension,Path + + +$xlPkg = $top10BySize | Export-Excel -path $xlfile -WorkSheetname FileInfo -TableName ExtSize -PassThru +$xlPkg = $top10ByCount | Export-Excel -ExcelPackage $xlPkg -WorkSheetname FileInfo -StartRow 13 -TableName ExtCount -PassThru +$xlPkg = $top10ByFileSize | Export-Excel -ExcelPackage $xlPkg -WorkSheetname FileInfo -StartRow 25 -TableName FileSize -PassThru -AutoSize + +#worksheets.tables["Name1","Name2"] returns 2 tables. Set-ExcelRange can process those and will set the number format over both +Set-ExcelRange -Range $xlpkg.Workbook.Worksheets[1].Tables["ExtSize","FileSize"] -NumberFormat '0,,"MB"' + +$ps = Get-Process | Where-Object Company + +$ps | + Sort-Object handles -Descending | + Select-Object -First 10 company, handles | + Export-Excel -ExcelPackage $xlPkg -WorkSheetname Handles -AutoSize -TableName Handles + +$ps | + Sort-Object PM -Descending | + Select-Object -First 10 company, PM | + Export-Excel $xlfile -WorkSheetname Handles -AutoSize -TableName PM -StartRow 13 -Show + + + + + Examples/Tables/SalesData-WithTotalRow.ps1 + + try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return } + +$data = ConvertFrom-Csv @" +OrderId,Category,Sales,Quantity,Discount +1,Cosmetics,744.01,07,0.7 +2,Grocery,349.13,25,0.3 +3,Apparels,535.11,88,0.2 +4,Electronics,524.69,60,0.1 +5,Electronics,439.10,41,0.0 +6,Apparels,56.84,54,0.8 +7,Electronics,326.66,97,0.7 +8,Cosmetics,17.25,74,0.6 +9,Grocery,199.96,39,0.4 +10,Grocery,731.77,20,0.3 +"@ + +$xlfile = "$PSScriptRoot\TotalsRow.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$TableTotalSettings = @{ + Quantity = 'Sum' + Category = '=COUNTIF([Category],"<>Electronics")' # Count the number of categories not equal to Electronics + Sales = @{ + Function = '=SUMIF([Category],"<>Electronics",[Sales])' + Comment = "Sum of sales for everything that is NOT Electronics" + } +} + +$data | Export-Excel -Path $xlfile -TableName Sales -TableStyle Medium10 -TableTotalSettings $TableTotalSettings -AutoSize -Show + + + + Examples/Tables/TotalsRow.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$r = Get-ChildItem C:\WINDOWS\system32 -File + +$TotalSettings = @{ + Name = "Count" + # You can create the formula in an Excel workbook first and copy-paste it here + # This syntax can only be used for the Custom type + Extension = "=COUNTIF([Extension];`".exe`")" + Length = @{ + Function = "=SUMIF([Extension];`".exe`";[Length])" + Comment = "Sum of all exe sizes" + } +} + +$r | Export-Excel -TableName system32files -TableStyle Medium10 -TableTotalSettings $TotalSettings -Show + + + + Examples/TestRestAPI/PSExcelPester.psm1 + + function ConvertTo-PesterTest { + param( + [parameter(Mandatory)] + $XlFilename, + $WorksheetName = 'Sheet1' + ) + + $testFileName = "{0}.tests.ps1" -f (Get-date).ToString("yyyyMMddHHmmss") + + $records = Import-Excel $XlFilename + + $params = @{} + + $blocks = $(foreach ($record in $records) { + foreach ($propertyName in $record.psobject.properties.name) { + if ($propertyName -notmatch 'ExpectedResult|QueryString') { + $params.$propertyName = $record.$propertyName + } + } + + if ($record.QueryString) { + $params.Uri += "?{0}" -f $record.QueryString + } + + @" + + it "Should have the expected result '$($record.ExpectedResult)'" { + `$target = '$($params | ConvertTo-Json -compress)' | ConvertFrom-Json + + `$target.psobject.Properties.name | ForEach-Object {`$p=@{}} {`$p.`$_=`$(`$target.`$_)} + + Invoke-RestMethod @p | Should -Be '$($record.ExpectedResult)' + } + +"@ + }) + + @" +Describe "Tests from $($XlFilename) in $($WorksheetName)" { +$($blocks) +} +"@ | Set-Content -Encoding Ascii $testFileName + + [PSCustomObject]@{ + TestFileName = (Get-ChildItem $testFileName).FullName + } +} + +function Show-PesterResult { + param( + [Parameter(ValueFromPipelineByPropertyName, Mandatory)] + $TestFileName + ) + + Begin { + $xlfilename = ".\test.xlsx" + Remove-Item $xlfilename -ErrorAction SilentlyContinue + + $ConditionalText = @() + $ConditionalText += New-ConditionalText -Range "Result" -Text failed -BackgroundColor red -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text passed -BackgroundColor green -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text pending -BackgroundColor gray -ConditionalTextColor black + + $xlParams = @{ + Path = $xlfilename + WorkSheetname = 'PesterTests' + ConditionalText = $ConditionalText + PivotRows = 'Result', 'Name' + PivotData = @{'Result' = 'Count'} + IncludePivotTable = $true + AutoSize = $true + AutoNameRange = $true + AutoFilter = $true + Show = $true + } + } + + End { + + $(foreach ($result in (Invoke-Pester -Script $TestFileName -PassThru -Show None).TestResult) { + [PSCustomObject][Ordered]@{ + Description = $result.Describe + Name = $result.Name + Result = $result.Result + Messge = $result.FailureMessage + StackTrace = $result.StackTrace + } + }) | Export-Excel @xlParams + } +} + + + + Examples/TestRestAPI/RunAndShowUnitTests.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$xlfilename=".\test.xlsx" +Remove-Item $xlfilename -ErrorAction Ignore + +$ConditionalText = @() +$ConditionalText += New-ConditionalText -Range "C:C" -Text failed -BackgroundColor red -ConditionalTextColor black +$ConditionalText += New-ConditionalText -Range "C:C" -Text passed -BackgroundColor green -ConditionalTextColor black + +$r = .\TryIt.ps1 + +$xlPkg = $(foreach($result in $r.TestResult) { + + [PSCustomObject]@{ + Name = $result.Name + #Time = $result.Time + Result = $result.Result + Messge = $result.FailureMessage + StackTrace = $result.StackTrace + } + +}) | Export-Excel -Path $xlfilename -AutoSize -ConditionalText $ConditionalText -PassThru + +$sheet1 = $xlPkg.Workbook.Worksheets["sheet1"] + +$sheet1.View.ShowGridLines = $false +$sheet1.View.ShowHeaders = $false + +Set-ExcelRange -Address $sheet1.Cells["A:A"] -AutoSize +Set-ExcelRange -Address $sheet1.Cells["B:D"] -WrapText + +$sheet1.InsertColumn(1, 1) +Set-ExcelRange -Address $sheet1.Cells["A:A"] -Width 5 + +Set-ExcelRange -Address $sheet1.Cells["B1:E1"] -HorizontalAlignment Center -BorderBottom Thick -BorderColor Cyan + +Close-ExcelPackage $xlPkg -Show + + + + Examples/TestRestAPI/ShowPesterResults.ps1 + + function Show-PesterResults { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="No suitable singular")] + Param() + $xlfilename = ".\test.xlsx" + Remove-Item $xlfilename -ErrorAction Ignore + + $ConditionalText = @() + $ConditionalText += New-ConditionalText -Range "Result" -Text failed -BackgroundColor red -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text passed -BackgroundColor green -ConditionalTextColor black + $ConditionalText += New-ConditionalText -Range "Result" -Text pending -BackgroundColor gray -ConditionalTextColor black + + $xlParams = @{ + Path = $xlfilename + WorkSheetname = 'PesterTests' + ConditionalText = $ConditionalText + PivotRows = 'Result', 'Name' + PivotData = @{'Result' = 'Count'} + IncludePivotTable = $true + AutoSize = $true + AutoNameRange = $true + AutoFilter = $true + Show = $true + } + + $(foreach ($result in (Invoke-Pester -PassThru -Show None).TestResult) { + [PSCustomObject]@{ + Description = $result.Describe + Name = $result.Name + Result = $result.Result + Messge = $result.FailureMessage + StackTrace = $result.StackTrace + } + }) | Sort-Object Description | Export-Excel @xlParams +} + + + + Examples/TestRestAPI/TestAPIReadXls.ps1 + + function Test-APIReadXls { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="False Positive")] + param( + [parameter(Mandatory)] + $XlFilename, + $WorksheetName = 'Sheet1' + ) + + $testFileName = "{0}.tests.ps1" -f (Get-date).ToString("yyyyMMddHHmmss") + + $records = Import-Excel $XlFilename + + $params = @{} + + $blocks = $(foreach ($record in $records) { + foreach ($propertyName in $record.psobject.properties.name) { + if ($propertyName -notmatch 'ExpectedResult|QueryString') { + $params.$propertyName = $record.$propertyName + } + } + + if ($record.QueryString) { + $params.Uri += "?{0}" -f $record.QueryString + } + + @" + + it "Should have the expected result '$($record.ExpectedResult)'" { + `$target = '$($params | ConvertTo-Json -compress)' | ConvertFrom-Json + + `$target.psobject.Properties.name | ForEach-Object {`$p=@{}} {`$p.`$_=`$(`$target.`$_)} + + Invoke-RestMethod @p | Should -Be '$($record.ExpectedResult)' + } + +"@ + }) + + @" +Describe "Tests from $($XlFilename) in $($WorksheetName)" { +$($blocks) +} +"@ | Set-Content -Encoding Ascii $testFileName + + (Get-ChildItem $testFileName).FullName +} + + + + Examples/TestRestAPI/TryIt.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +. $PSScriptRoot\TestAPIReadXls.ps1 + +Test-APIReadXls $PSScriptRoot\testlist.xlsx | Foreach-Object { + Invoke-Pester -Script $_.fullname -PassThru -Show None +} + + + + Examples/TryMultiplePivotTables.ps1 + + # To ship, is to choose + +#ipmo .\ImportExcel.psd1 -Force + +$pt=[ordered]@{} + +$pt.ServiceInfo=@{ + SourceWorkSheet='Services' + PivotRows = "Status" + PivotData= @{'Status'='count'} + IncludePivotChart=$true + ChartType='BarClustered3D' +} + +$pt.ProcessInfo=@{ + SourceWorkSheet='Processes' + PivotRows = "Company" + PivotData= @{'Company'='count'} + IncludePivotChart=$true + ChartType='PieExploded3D' +} + +$gsv=Get-Service | Select-Object status, Name, displayName, starttype +$ps=Get-Process | Select-Object Name,Company, Handles + +$file = "c:\temp\testPT.xlsx" +Remove-Item $file -ErrorAction Ignore + +$gsv| Export-Excel -Path $file -AutoSize -WorkSheetname Services +$ps | Export-Excel -Path $file -AutoSize -WorkSheetname Processes -PivotTableDefinition $pt -Show + + + + + Examples/TryMultiplePivotTablesFromOneSheet.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + +$file = "C:\Temp\test.xlsx" + +Remove-Item $file -ErrorAction Ignore -Force + +$base = @{ + SourceWorkSheet = 'gsv' + PivotData = @{'Status' = 'count'} + IncludePivotChart = $true + # ChartType = 'BarClustered3D' +} + +$ptd = [ordered]@{} + +# $ptd.gpt1 = $base + @{ PivotRows = "ServiceType" } +# $ptd.gpt2 = $base + @{ PivotRows = "Status" } +# $ptd.gpt3 = $base + @{ PivotRows = "StartType" } +# $ptd.gpt4 = $base + @{ PivotRows = "CanStop" } + +$ptd += New-PivotTableDefinition @base servicetype -PivotRows servicetype -ChartType Area3D +$ptd += New-PivotTableDefinition @base status -PivotRows status -ChartType PieExploded3D +$ptd += New-PivotTableDefinition @base starttype -PivotRows starttype -ChartType BarClustered3D +$ptd += New-PivotTableDefinition @base canstop -PivotRows canstop -ChartType ConeColStacked + +Get-Service | Export-Excel -path $file -WorkSheetname gsv -Show -PivotTableDefinition $ptd + + + + Examples/VBA/AddModuleMultipleWorksheetVBA.ps1 + + $xlfile = "$env:temp\test.xlsm" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +ConvertFrom-Csv @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize + +$Excel = ConvertFrom-Csv @" +Supplier,Item,TotalBought +Hardware,screwdriver,98 +Groceries,kiwi,19 +Hardware,screws,48 +Groceries,avocado,52 +Hardware,drill,61 +Groceries,orange,92 +Hardware,drill,29 +HArdware,saw,36 +"@ | Export-Excel $xlfile -TableName 'Purchases' -WorksheetName 'Purchases' -PassThru -AutoSize + +$wb = $Excel.Workbook +$wb.CreateVBAProject() + +# Create a module with a sub to highlight the selected row & column of the active table. +# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column +$codeModule = @" +Public Sub HighlightSelection(ByVal Target As Range) + ' Clear the color of all the cells + Cells.Interior.ColorIndex = 0 + If Target.Cells.Count > 1 Then Exit Sub + Application.ScreenUpdating = False + With ActiveCell + ' Highlight the row and column that contain the active cell, within the current region + Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38 + Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24 + End With + Application.ScreenUpdating = True +End Sub +"@ + +$module = $wb.VbaProject.Modules.AddModule("PSExcelModule") +$module.Code = $codeModule + +# Add a call to the row & column highlight sub on each worksheet. +$codeSheet = @" +Private Sub Worksheet_SelectionChange(ByVal Target As Range) + HighlightSelection Target +End Sub +"@ + +foreach ($sheet in $wb.Worksheets) { + $sheet.CodeModule.Code = $codeSheet +} + +Close-ExcelPackage $Excel -Show + + + + Examples/VBA/AddWorksheetVBA.ps1 + + $xlfile = "$env:temp\test.xlsm" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$Excel = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize -PassThru + +$wb = $Excel.Workbook +$sheet = $wb.Worksheets["Sales"] +$wb.CreateVBAProject() + +# Add a sub to the 'Worksheet_SelectionChange' event of the worksheet to highlight the selected row & column of the active table. +# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column +$code = @" +Private Sub Worksheet_SelectionChange(ByVal Target As Range) + ' Clear the color of all the cells + Cells.Interior.ColorIndex = 0 + If Target.Cells.Count > 1 Then Exit Sub + Application.ScreenUpdating = False + With ActiveCell + ' Highlight the row and column that contain the active cell, within the current region + Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38 + Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24 + End With + Application.ScreenUpdating = True +End Sub +"@ + +$sheet.CodeModule.Code = $code + +Close-ExcelPackage $Excel -Show + + + + Examples/VBA/ChangePivotTablesVBA.ps1 + + <# +Excel VBA macro which changes all PivotTables in the workbook to Tabular form, disables subtotals and repeats item labels. +https://github.com/dfinke/ImportExcel/issues/1196#issuecomment-1156320581 +#> +$ExcelFile = "$ENV:TEMP\test.xlsm" +Remove-Item -Path $ExcelFile -ErrorAction SilentlyContinue + +$Macro = @" +Private Sub Workbook_Open() +' +' ChangePivotTables Macro +' Runs when the Excel workbook is opened. +' +' Changes all PivotTables in the workbook to Tabular form, repeats labels +' and disables Subtotals. +' + ' Declare variables + Dim Ws As Worksheet + Dim Pt As PivotTable + Dim Pf As PivotField + ' Disable screen updates + Application.ScreenUpdating = False + ' Continue even if an error occurs + On Error Resume Next + For Each Ws In ActiveWorkbook.Worksheets + For Each Pt In Ws.PivotTables + Pt.RowAxisLayout xlTabularRow + Pt.RepeatAllLabels xlRepeatLabels + For Each Pf In Pt.PivotFields + Pf.Subtotals(1) = False + Next + Next + Next + Application.ScreenUpdating = True +End Sub +"@ + +$Data = ConvertFrom-Csv -InputObject @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ + +$ExcelPackage = $Data | Export-Excel -Path $ExcelFile -TableName "Sales" -WorksheetName "Sales" -AutoSize -PassThru +# Add Macro to the ThisWorkbook module +$ExcelPackage.Workbook.CreateVBAProject() +$VBAThisWorkbookModule = $ExcelPackage.Workbook.VbaProject.Modules | Where-Object -FilterScript { $_.Name -eq "ThisWorkbook" } +$VBAThisWorkbookModule.Code = $Macro + +# Create PivotTable example +Add-PivotTable -PivotTableName "SalesPivot" -Address $ExcelPackage.Sales.Cells["E1"] -SourceWorksheet $ExcelPackage.Sales ` + -SourceRange $ExcelPackage.Sales.Tables[0].Address -PivotRows "Region", "Item" -PivotData @{ "TotalSold" = "Sum" } + +Close-ExcelPackage -ExcelPackage $ExcelPackage -Show + + + + Examples/VBA/HelloWorldVBA.ps1 + + $xlfile = "$env:temp\test.xlsm" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$Excel = ConvertFrom-Csv @" +Region,Item,TotalSold +West,screwdriver,98 +West,kiwi,19 +North,kiwi,47 +West,screws,48 +West,avocado,52 +East,avocado,40 +South,drill,61 +North,orange,92 +South,drill,29 +South,saw,36 +"@ | Export-Excel $xlfile -PassThru -AutoSize + +$wb = $Excel.Workbook +$sheet = $wb.Worksheets["Sheet1"] +$wb.CreateVBAProject() + +$code = @" +Public Function HelloWorld() As String + HelloWorld = "Hello World" +End Function + +Public Function DoSum() As Integer + DoSum = Application.Sum(Range("C:C")) +End Function +"@ + +$module = $wb.VbaProject.Modules.AddModule("PSExcelModule") +$module.Code = $code + +Set-ExcelRange -Worksheet $sheet -Range "h7" -Formula "HelloWorld()" -AutoSize +Set-ExcelRange -Worksheet $sheet -Range "h8" -Formula "DoSum()" -AutoSize + +Close-ExcelPackage $Excel -Show + + + + Examples/XlRangeToImage/XlRangeToImage.ps1 + + try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return} + + +. .\ConvertExcelToImageFile.ps1 + +$xlFileName = "C:\Temp\testPNG.xlsx" + +Remove-Item C:\Temp\testPNG.xlsx -ErrorAction Ignore + +$range = @" +Region,Item,Cost +North,Pear,1 +South,Apple,2 +East,Grapes,3 +West,Berry,4 +North,Pear,1 +South,Apple,2 +East,Grapes,3 +West,Berry,4 +"@ | ConvertFrom-Csv | + Export-Excel $xlFileName -ReturnRange ` + -ConditionalText (New-ConditionalText Apple), (New-ConditionalText Berry -ConditionalTextColor White -BackgroundColor Purple) + +Convert-ExcelXlRangeToImage -Path $xlFileName -workSheetname sheet1 -range $range -Show + + + + + diff --git a/mdHelp/README.md b/mdHelp/README.md new file mode 100644 index 00000000..11aab70a --- /dev/null +++ b/mdHelp/README.md @@ -0,0 +1,2 @@ +# mdHelp + diff --git a/mdHelp/buildHelp.ps1 b/mdHelp/buildHelp.ps1 new file mode 100644 index 00000000..55abfbbd --- /dev/null +++ b/mdHelp/buildHelp.ps1 @@ -0,0 +1,4 @@ +Import-Module platyPS +Get-ChildItem $PSScriptRoot -Directory | ForEach-Object { + New-ExternalHelp -Path $_.FullName -OutputPath (Join-Path $PSScriptRoot "..\$($_.Name)") -Force -Verbose +} \ No newline at end of file diff --git a/mdHelp/en/README.md b/mdHelp/en/README.md new file mode 100644 index 00000000..bee0a741 --- /dev/null +++ b/mdHelp/en/README.md @@ -0,0 +1,2 @@ +# en + diff --git a/mdHelp/en/add-conditionalformatting.md b/mdHelp/en/add-conditionalformatting.md new file mode 100644 index 00000000..f3d60c61 --- /dev/null +++ b/mdHelp/en/add-conditionalformatting.md @@ -0,0 +1,516 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Add-ConditionalFormatting + +## SYNOPSIS + +Adds conditional formatting to all or part of a worksheet. + +## SYNTAX + +### NamedRule + +```text +Add-ConditionalFormatting [-Address] [-WorkSheet ] [-RuleType] [-ForegroundColor ] [-Reverse] [[-ConditionValue] ] [[-ConditionValue2] ] [-BackgroundColor ] [-BackgroundPattern ] [-PatternColor ] [-NumberFormat ] [-Bold] [-Italic] [-Underline] [-StrikeThru] [-StopIfTrue] [-Priority ] [-PassThru] [] +``` + +### DataBar + +```text +Add-ConditionalFormatting [-Address] [-WorkSheet ] -DataBarColor [-Priority ] [-PassThru] [] +``` + +### ThreeIconSet + +```text +Add-ConditionalFormatting [-Address] [-WorkSheet ] -ThreeIconsSet [-Reverse] [-Priority ] [-PassThru] [] +``` + +### FourIconSet + +```text +Add-ConditionalFormatting [-Address] [-WorkSheet ] -FourIconsSet [-Reverse] [-Priority ] [-PassThru] [] +``` + +### FiveIconSet + +```text +Add-ConditionalFormatting [-Address] [-WorkSheet ] -FiveIconsSet [-Reverse] [-Priority ] [-PassThru] [] +``` + +## DESCRIPTION + +Conditional formatting allows Excel to: + +* Mark cells with icons depending on their value +* Show a databar whose length indicates the value or a two or three color scale where the color indicates the relative value +* Change the color, font, or number format of cells which meet given criteria + + Add-ConditionalFormatting allows these parameters to be set; for fine tuning of the rules, the -PassThru switch will return the rule so that you can modify things which are specific to that type of rule, example, the values which correspond to each icon in an Icon-Set. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> $excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru + Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b2:b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003" + Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled" + $excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern + $excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true + $excel.Save() ; $excel.Dispose() +``` + +Here Export-Excel is called with the -PassThru parameter, so the ExcelPackage object representing Machines.XLSX is stored in $Excel. The desired worksheet is selected, and then columns" B" and "I" are conditionally formatted \(excluding the top row\) to show red text if they contain "2003" or "Disabled" respectively. + +A fixed date format is then applied to columns D to G, and the top row is formatted. + +Finally the workbook is saved and the Excel package object is closed. + +### EXAMPLE 2 + +```text +PS\> $r = Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Range "B1:B100" -ThreeIconsSet Flags -Passthru + $r.Reverse = $true ; $r.Icon1.Type = "Num"; $r.Icon2.Type = "Num" ; $r.Icon2.value = 100 ; $r.Icon3.type = "Num" ;$r.Icon3.value = 1000 +``` + +Again Export-Excel has been called with -PassThru leaving a package object in $Excel. + +This time B1:B100 has been conditionally formatted with 3 icons, using the "Flags" Icon-Set. + +Add-ConditionalFormatting does not provide access to every option in the formatting rule, so -PassThru has been used and the rule is modified to apply the flags in reverse order, and transitions between flags are set to 100 and 1000. + +### EXAMPLE 3 + +```text +PS\> Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red +``` + +This time $sheet holds an ExcelWorkshseet object and databars are added to column D, excluding the top row. + +### EXAMPLE 4 + +```text +PS\> Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue +``` + +In this example a named range is used to select the cells where the condition should apply, and instead of specifying a sheet and range within the sheet as separate parameters, the cells where the format should apply are specified directly. + +If a cell in the "FinishPosition" range is 1, then the text is turned to Bold & Purple. + +This rule is moved to first in the priority list, and where cells have a value of 1, no other rules will be processed. + +### EXAMPLE 5 + +```text +PS\> $excel = Get-ChildItem | Select-Object -Property Name,Length,LastWriteTime,CreationTime | Export-Excel "$env:temp\test43.xlsx" -PassThru -AutoSize + $ws = $excel.Workbook.Worksheets["Sheet1"] + $ws.Cells["E1"].Value = "SavedAt" + $ws.Cells["F1"].Value = [datetime]::Now + $ws.Cells["F1"].Style.Numberformat.Format = (Expand-NumberFormat -NumberFormat 'Date-Time') + $lastRow = $ws.Dimension.End.Row + Add-ConditionalFormatting -WorkSheet $ws -address "A2:A$Lastrow" -RuleType LessThan -ConditionValue "A" -ForeGroundColor Gray + Add-ConditionalFormatting -WorkSheet $ws -address "B2:B$Lastrow" -RuleType GreaterThan -ConditionValue 1000000 -NumberFormat '#,###,,.00"M"' + Add-ConditionalFormatting -WorkSheet $ws -address "C2:C$Lastrow" -RuleType GreaterThan -ConditionValue "=INT($F$1-7)" -ForeGroundColor Green -StopIfTrue + Add-ConditionalFormatting -WorkSheet $ws -address "D2:D$Lastrow" -RuleType Equal -ConditionValue "=C2" -ForeGroundColor Blue -StopIfTrue + Close-ExcelPackage -Show $excel +``` + +The first few lines of code export a list of file and directory names, sizes and dates to a spreadsheet. + +It puts the date of the export in cell F1. + +The first Conditional format changes the color of files and folders that begin with a ".", "\_" or anything else which sorts before "A". + +The second Conditional format changes the Number format of numbers bigger than 1 million, for example 1,234,567,890 will dispay as "1,234.57M" + +The third highlights datestamps of files less than a week old when the export was run; the = is necessary in the condition value otherwise the rule will look for the the text INT\($F$1-7\), and the cell address for the date is fixed using the standard Excel $ notation. + +The final Conditional format looks for files which have not changed since they were created. Here the condition value is "=C2". The = sign means C2 is treated as a formula, not literal text. Unlike the file age, we want the cell used to change for each cell where the conditional format applies. + +The first cell in the conditional format range is D2, which is compared against C2, then D3 is compared against C3 and so on. A common mistake is to include the title row in the range and accidentally apply conditional formatting to it, or to begin the range at row 2 but use row 1 as the starting point for comparisons. + +### EXAMPLE 6 + +```text +PS\> Add-ConditionalFormatting $ws.Cells["B:B"] GreaterThan 10000000 -Fore Red -Stop -Pri 1 +``` + +This version shows the shortest syntax - the Address, Ruletype, and Conditionvalue can be identified from their position, and ForegroundColor, StopIfTrue and Priority can all be shortend. + +## PARAMETERS + +### -Address + +A block of cells to format - you can use a named range with -Address $ws.names\[1\] or $ws.cells\["RangeName"\] + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: Range + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WorkSheet + +The worksheet where the format is to be applied + +```yaml +Type: ExcelWorksheet +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RuleType + +A standard named-rule - Top / Bottom / Less than / Greater than / Contains etc. + +```yaml +Type: eExcelConditionalFormattingRuleType +Parameter Sets: NamedRule +Aliases: +Accepted values: AboveAverage, AboveOrEqualAverage, BelowAverage, BelowOrEqualAverage, AboveStdDev, BelowStdDev, Bottom, BottomPercent, Top, TopPercent, Last7Days, LastMonth, LastWeek, NextMonth, NextWeek, ThisMonth, ThisWeek, Today, Tomorrow, Yesterday, BeginsWith, Between, ContainsBlanks, ContainsErrors, ContainsText, DuplicateValues, EndsWith, Equal, Expression, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual, NotBetween, NotContains, NotContainsBlanks, NotContainsErrors, NotContainsText, NotEqual, UniqueValues, ThreeColorScale, TwoColorScale, ThreeIconSet, FourIconSet, FiveIconSet, DataBar + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ForegroundColor + +Text color for matching objects + +```yaml +Type: Object +Parameter Sets: NamedRule +Aliases: ForegroundColour, FontColor + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DataBarColor + +Color for databar type charts + +```yaml +Type: Object +Parameter Sets: DataBar +Aliases: DataBarColour + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ThreeIconsSet + +One of the three-icon set types \(e.g. Traffic Lights\) + +```yaml +Type: eExcelconditionalFormatting3IconsSetType +Parameter Sets: ThreeIconSet +Aliases: +Accepted values: Arrows, ArrowsGray, Flags, Signs, Symbols, Symbols2, TrafficLights1, TrafficLights2 + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FourIconsSet + +A four-icon set name + +```yaml +Type: eExcelconditionalFormatting4IconsSetType +Parameter Sets: FourIconSet +Aliases: +Accepted values: Arrows, ArrowsGray, Rating, RedToBlack, TrafficLights + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FiveIconsSet + +A five-icon set name + +```yaml +Type: eExcelconditionalFormatting5IconsSetType +Parameter Sets: FiveIconSet +Aliases: +Accepted values: Arrows, ArrowsGray, Quarters, Rating + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Reverse + +Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales + +```yaml +Type: SwitchParameter +Parameter Sets: NamedRule, ThreeIconSet, FourIconSet, FiveIconSet +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ConditionValue + +A value for the condition \(for example 2000 if the test is 'lessthan 2000'; Formulas should begin with "=" \) + +```yaml +Type: Object +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ConditionValue2 + +A second value for the conditions like "Between X and Y" + +```yaml +Type: Object +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -BackgroundColor + +Background color for matching items + +```yaml +Type: Object +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -BackgroundPattern + +Background pattern for matching items + +```yaml +Type: ExcelFillStyle +Parameter Sets: NamedRule +Aliases: +Accepted values: None, Solid, DarkGray, MediumGray, LightGray, Gray125, Gray0625, DarkVertical, DarkHorizontal, DarkDown, DarkUp, DarkGrid, DarkTrellis, LightVertical, LightHorizontal, LightDown, LightUp, LightGrid, LightTrellis + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PatternColor + +Secondary color when a background pattern requires it + +```yaml +Type: Object +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NumberFormat + +Sets the numeric format for matching items + +```yaml +Type: Object +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Bold + +Put matching items in bold face + +```yaml +Type: SwitchParameter +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Italic + +Put matching items in italic + +```yaml +Type: SwitchParameter +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Underline + +Underline matching items + +```yaml +Type: SwitchParameter +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StrikeThru + +Strikethrough text of matching items + +```yaml +Type: SwitchParameter +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StopIfTrue + +Prevent the processing of subsequent rules + +```yaml +Type: SwitchParameter +Parameter Sets: NamedRule +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Priority + +Set the sequence for rule processing + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PassThru + +If specified pass the rule back to the caller to allow additional customization. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/add-excelchart.md b/mdHelp/en/add-excelchart.md new file mode 100644 index 00000000..3831a9e5 --- /dev/null +++ b/mdHelp/en/add-excelchart.md @@ -0,0 +1,781 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Add-ExcelChart + +## SYNOPSIS + +Creates a chart in an existing Excel worksheet. + +## SYNTAX + +### Worksheet \(Default\) + +```text +Add-ExcelChart [-Title ] [-ChartType ] [-ChartTrendLine ] [-XRange ] [-YRange ] [-Width ] [-Height ] [-Row ] [-RowOffSetPixels ] [-Column ] [-ColumnOffSetPixels ] [-LegendPosition ] [-LegendSize ] [-LegendBold] [-NoLegend] [-ShowCategory] [-ShowPercent] [-SeriesHeader ] [-TitleBold] [-TitleSize ] [-XAxisTitleText ] [-XAxisTitleBold] [-XAxisTitleSize ] [-XAxisNumberformat ] [-XMajorUnit ] [-XMinorUnit ] [-XMaxValue ] [-XMinValue ] [-XAxisPosition ] [-YAxisTitleText ] [-YAxisTitleBold] [-YAxisTitleSize ] [-YAxisNumberformat ] [-YMajorUnit ] [-YMinorUnit ] [-YMaxValue ] [-YMinValue ] [-YAxisPosition ] [-PassThru] [] +``` + +### PivotTable + +```text +Add-ExcelChart -PivotTable [-Title ] [-ChartType ] [-ChartTrendLine ] [-XRange ] [-YRange ] [-Width ] [-Height ] [-Row ] [-RowOffSetPixels ] [-Column ] [-ColumnOffSetPixels ] [-LegendPosition ] [-LegendSize ] [-LegendBold] [-NoLegend] [-ShowCategory] [-ShowPercent] [-SeriesHeader ] [-TitleBold] [-TitleSize ] [-XAxisTitleText ] [-XAxisTitleBold] [-XAxisTitleSize ] [-XAxisNumberformat ] [-XMajorUnit ] [-XMinorUnit ] [-XMaxValue ] [-XMinValue ] [-XAxisPosition ] [-YAxisTitleText ] [-YAxisTitleBold] [-YAxisTitleSize ] [-YAxisNumberformat ] [-YMajorUnit ] [-YMinorUnit ] [-YMaxValue ] [-YMinValue ] [-YAxisPosition ] [-PassThru] [] +``` + +## DESCRIPTION + +Creates a chart. + +It is possible to configure the type of chart, the range of X values \(labels\) and Y values, the title, the legend, the ranges for both axes, the format and position of the axes. + +Normally the command does not return anything, but if -passthru is specified the chart is returned so that it can be customized. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> $Excel = ConvertFrom-Csv @" + Product, City, Sales + Apple, London, 300 + Orange, London, 400 + Banana, London, 300 + Orange, Paris, 600 + Banana, Paris, 300 + Apple, New York, 1200 +"@ | Export-Excel -Path test.xlsx -PassThru + Add-ExcelChart -Worksheet $Excel.Workbook.Worksheets[1] -ChartType "Doughnut" -XRange "A2:B7" -YRange "C2:C7" -width 500 + Close-ExcelPackage -Show $Excel +``` + +The first command expands a multi-line string into 6 rows of data which is exported to new Excel file; leaving an ExcelPackage object in $excel The second command adds a chart - the cell ranges are explicitly specified. + +Note that the XRange \(labels\) is TWO columns wide and the chart will combine the name of the product and the name of the City to create the label. + +The width of the chart is set explictly, the default legend is used and there is no Chart title. + +### EXAMPLE 2 + +```text +PS\> $Excel = Invoke-Sum (Get-Process) Company Handles, PM, VirtualMemorySize | Export-Excel $path -AutoSize -ExcelChartDefinition $c -AutoNameRange -PassThru + Add-ExcelChart -Worksheet $Excel.Workbook.Worksheets[1] -Title "VM use" -ChartType PieExploded3D -XRange "Name" -YRange "VirtualMemorySize" -NoLegend -ShowCategory + Close-ExcelPackage $Excel -Show +``` + +The first line exports information and creates named ranges for each column. + +The Second line uses the ranges to specify a chart - the labels come from the range "Name" and the data from the range "VirtualMemorySize" + +The chart is specified as a 3D exploded PIE chart, with a title of "VM Use" and instead of a legend the the pie slices are identified with a label. + +### EXAMPLE 3 + +```text +PS\> $Excel = Invoke-Sum (Get-Process) Company Handles, PM, VirtualMemorySize | Export-Excel test.xlsx -TableName Processes -PassThru + Add-ExcelChart -Worksheet $Excel.Workbook.Worksheets[1] -Title Stats -ChartType LineMarkersStacked -XRange "Processes[Name]" -YRange "Processes[PM]", "Processes[VirtualMemorySize]" -SeriesHeader 'PM', 'VMSize' + Close-ExcelPackage $Excel -Show +``` + +The first line exports information to a table in new file; and captures the excel Package object in $Excel + +The second line creates a chart on the first page of the work sheet, using the notation "TableName\[ColumnName\]" to refer to the data, the labels come Name column in the table, and the data series from its PM and VirtualMemorySize columns. The display names for these in the header are set to 'PM' and 'VMSize'. + +### EXAMPLE 4 + +```text +PS\> $excel = 0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -Path Text.xlsx -WorkSheetname SinX -PassThru +Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 \` + -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" \` + -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 \` + -SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPosition Bottom +Close-ExcelPackage $Excel -Show +``` + +The first line puts numbers from 0 to 360 into a sheet, as the first column, and a formula to calculate the Sine of that number of number of degrees in the second column. It creates named-ranges for the two columns - "X" and "SinX" respectively + +The Add-ExcelChart command adds a chart to that worksheet, specifying a line chart with the X values coming from named-range "X" and the Y values coming from named-range "SinX". The chart has a title, and is positioned to the right of column 2 and sized 800 pixels wide + +The X-axis is labelled "Degrees", in bold 12 point type and runs from 0 to 361 with labels every 30, and minor tick marks every 10. Degrees are shown padded to 3 digits. + +The Y-axis is labelled "Sine" and to allow some room above and below its scale runs from -1.25 to 1.25, and is marked off in units of 0.25 shown to two decimal places. + +The key will for the chart will be at the bottom in 8 point bold type and the line will be named "Sin\(x\)". + +## PARAMETERS + +### -Worksheet + +An existing Sheet where the chart will be created. + +```yaml +Type: ExcelWorksheet +Parameter Sets: Worksheet +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotTable + +Instead of specify X and Y ranges, get data from a PivotTable by passing a PivotTable Object. + +```yaml +Type: ExcelPivotTable +Parameter Sets: PivotTable +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Title + +The title for the chart. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartType + +One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: Named +Default value: ColumnStacked +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartTrendLine + +```yaml +Type: eTrendLine[] +Parameter Sets: (All) +Aliases: +Accepted values: Exponential, Linear, Logarithmic, MovingAvgerage, Polynomial, Power + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XRange + +The range of cells containing values for the X-Axis - usually labels. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YRange + +The range\(s\) of cells holding values for the Y-Axis - usually "data". + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Width + +Width of the chart in Pixels; defaults to 500. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 500 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Height + +Height of the chart in Pixels; defaults to 350. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 350 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Row + +Row position of the top left corner of the chart. \) places at the top of the sheet, 1 below row 1 and so on. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RowOffSetPixels + +Offset to position the chart by a fraction of a row. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 10 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Column + +Column position of the top left corner of the chart; 0 places at the edge of the sheet 1 to the right of column A and so on. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 6 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ColumnOffSetPixels + +Offset to position the chart by a fraction of a column. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 5 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LegendPosition + +Location of the key, either left, right, top, bottom or TopRight. + +```yaml +Type: eLegendPosition +Parameter Sets: (All) +Aliases: +Accepted values: Top, Left, Right, Bottom, TopRight + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LegendSize + +Font size for the key. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LegendBold + +Sets the key in bold type. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +Attaches a category label, in charts which support this. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +Attaches a percentage label, in charts which support this. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SeriesHeader + +Specify explicit name\(s\) for the data series, which will appear in the legend/key. The contents of a cell can be specified in the from =Sheet9!Z10 . + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TitleBold + +Sets the title in bold face. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TitleSize + +Sets the point size for the title. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XAxisTitleText + +Specifies a title for the X-axis. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XAxisTitleBold + +Sets the X-axis title in bold face. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XAxisTitleSize + +Sets the font size for the axis title. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XAxisNumberformat + +A number formatting string, like "\#,\#\#0.00", for numbers along the X-axis. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XMajorUnit + +Spacing for the major gridlines / tick marks along the X-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XMinorUnit + +Spacing for the minor gridlines / tick marks along the X-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XMaxValue + +Maximum value for the scale along the X-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XMinValue + +Minimum value for the scale along the X-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -XAxisPosition + +Position for the X-axis \(Top or Bottom\). + +```yaml +Type: eAxisPosition +Parameter Sets: (All) +Aliases: +Accepted values: Left, Bottom, Right, Top + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YAxisTitleText + +Specifies a title for the Y-axis. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YAxisTitleBold + +Sets the Y-axis title in bold face. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YAxisTitleSize + +Sets the font size for the Y-axis title + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YAxisNumberformat + +A number formatting string, like "\#,\#\#0.00", for numbers on the Y-axis. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YMajorUnit + +Spacing for the major gridlines / tick marks on the Y-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YMinorUnit + +Spacing for the minor gridlines / tick marks on the Y-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YMaxValue + +Maximum value on the Y-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YMinValue + +Minimum value on the Y-axis. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -YAxisPosition + +Position for the Y-axis \(Left or Right\). + +```yaml +Type: eAxisPosition +Parameter Sets: (All) +Aliases: +Accepted values: Left, Bottom, Right, Top + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PassThru + +Add-Excel chart doesn't normally return anything, but if -PassThru is specified it returns the newly created chart to allow it to be fine tuned. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### OfficeOpenXml.Drawing.Chart.ExcelChart + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/add-exceldatavalidationrule.md b/mdHelp/en/add-exceldatavalidationrule.md new file mode 100644 index 00000000..9e668658 --- /dev/null +++ b/mdHelp/en/add-exceldatavalidationrule.md @@ -0,0 +1,342 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Add-ExcelDataValidationRule + +## SYNOPSIS + +Adds data validation to a range of cells + +## SYNTAX + +```text +Add-ExcelDataValidationRule [[-Range] ] [-WorkSheet ] [-ValidationType ] [-Operator ] [-Value ] [-Value2 ] [-Formula ] [-Formula2 ] [-ValueSet ] [-ShowErrorMessage] [-ErrorStyle ] [-ErrorTitle ] [-ErrorBody ] [-ShowPromptMessage] [-PromptBody ] [-PromptTitle ] [-NoBlank ] [] +``` + +## DESCRIPTION + +Excel supports the validation of user input, and ranges of cells can be marked to only contain numbers, or date, or Text up to a particular length, or selections from a list. This command adds validation rules to a worksheet. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\>Add-ExcelDataValidationRule -WorkSheet $PlanSheet -Range 'E2:E1001' -ValidationType Integer -Operator between -Value 0 -Value2 100 \` + -ShowErrorMessage -ErrorStyle stop -ErrorTitle 'Invalid Data' -ErrorBody 'Percentage must be a whole number between 0 and 100' +``` + +This defines a validation rule on cells E2-E1001; it is an integer rule and requires a number between 0 and 100. If a value is input with a fraction, negative number, or positive number > 100 a stop dialog box appears. + +### EXAMPLE 2 + +```text +PS\>Add-ExcelDataValidationRule -WorkSheet $PlanSheet -Range 'B2:B1001' -ValidationType List -Formula 'values!$a$2:$a$1000' + -ShowErrorMessage -ErrorStyle stop -ErrorTitle 'Invalid Data' -ErrorBody 'You must select an item from the list' +``` + +This defines a list rule on Cells B2:1001, and the posible values are in a sheet named "values" at cells A2 to A1000 Blank cells in this range are ignored. + +If $ signs were left out of the fomrmula B2 would be checked against A2-A1000, B3, against A3-A1001, B4 against A4-A1002 up to B1001 beng checked against A1001-A1999 + +### EXAMPLE 3 + +```text +PS\>Add-ExcelDataValidationRule -WorkSheet $PlanSheet -Range 'I2:N1001' -ValidationType List -ValueSet @('yes','YES','Yes') + -ShowErrorMessage -ErrorStyle stop -ErrorTitle 'Invalid Data' -ErrorBody "Select Yes or leave blank for no" +``` + +Similar to the previous example but this time provides a value set; Excel comparisons are case sesnsitive, hence 3 versions of Yes. + +## PARAMETERS + +### -Range + +The range of cells to be validate, for example, "B2:C100" + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: Address + +Required: False +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -WorkSheet + +The worksheet where the cells should be validated + +```yaml +Type: ExcelWorksheet +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ValidationType + +An option corresponding to a choice from the 'Allow' pull down on the settings page in the Excel dialog. "Any" means "any allowed" - in other words, no Validation + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Operator + +The operator to apply to Decimal, Integer, TextLength, DateTime and time fields, for example "equal" or "between" + +```yaml +Type: ExcelDataValidationOperator +Parameter Sets: (All) +Aliases: +Accepted values: between, notBetween, equal, notEqual, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual + +Required: False +Position: Named +Default value: Equal +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value + +For Decimal, Integer, TextLength, DateTime the \[first\] data value + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value2 + +When using the between operator, the second data value + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Formula + +The \[first\] data value as a formula. Use absolute formulas $A$1 if \(e.g.\) you want all cells to check against the same list + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Formula2 + +When using the between operator, the second data value as a formula + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ValueSet + +When using the list validation type, a set of values \(rather than refering to Sheet!B$2:B$100 \) + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowErrorMessage + +Corresponds to the the 'Show Error alert ...' check box on error alert page in the Excel dialog + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ErrorStyle + +Stop, Warning, or Infomation, corresponding to to the style setting in the Excel dialog + +```yaml +Type: ExcelDataValidationWarningStyle +Parameter Sets: (All) +Aliases: +Accepted values: undefined, stop, warning, information + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ErrorTitle + +The title for the message box corresponding to to the title setting in the Excel dialog + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ErrorBody + +The error message corresponding to to the Error message setting in the Excel dialog + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPromptMessage + +Corresponds to the the 'Show Input message ...' check box on input message page in the Excel dialog + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PromptBody + +The prompt message corresponding to to the Input message setting in the Excel dialog + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PromptTitle + +The title for the message box corresponding to to the title setting in the Excel dialog + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoBlank + +By default the 'Ignore blank' option will be selected, unless NoBlank is sepcified. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/add-excelname.md b/mdHelp/en/add-excelname.md new file mode 100644 index 00000000..4cfb1918 --- /dev/null +++ b/mdHelp/en/add-excelname.md @@ -0,0 +1,79 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Add-ExcelName + +## SYNOPSIS + +Adds a named-range to an existing Excel worksheet. + +## SYNTAX + +```text +Add-ExcelName [-Range] [[-RangeName] ] [] +``` + +## DESCRIPTION + +It is often helpful to be able to refer to sets of cells with a name rather than using their co-ordinates; Add-ExcelName sets up these names. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $rangeName +``` + +$WS is a worksheet, and $dataRange is a string describing a range of cells - for example "A1:Z10" - which will become a named range, using the name in $rangeName. + +## PARAMETERS + +### -Range + +The range of cells to assign as a name. + +```yaml +Type: ExcelRange +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RangeName + +The name to assign to the range. If the name exists it will be updated to the new range. If no name is specified, the first cell in the range will be used as the name. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/add-exceltable.md b/mdHelp/en/add-exceltable.md new file mode 100644 index 00000000..43793ae5 --- /dev/null +++ b/mdHelp/en/add-exceltable.md @@ -0,0 +1,264 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Add-ExcelTable + +## SYNOPSIS + +Adds Tables to Excel workbooks. + +## SYNTAX + +```text +Add-ExcelTable [-Range] [[-TableName] ] [[-TableStyle] ] [-ShowHeader] [-ShowFilter] [-ShowTotal] [[-TableTotalSettings] ] [-ShowFirstColumn] [-ShowLastColumn] [-ShowRowStripes] [-ShowColumnStripes] [-PassThru] [] +``` + +## DESCRIPTION + +Unlike named ranges, where the name only needs to be unique within a sheet, Table names must be unique in the workbook. + +Tables carry formatting and by default have a filter. + +The filter, header, totals, first and last column highlights can all be configured. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName +``` + +$WS is a worksheet, and $dataRange is a string describing a range of cells - for example "A1:Z10". This range which will become a table, named $TableName + +### EXAMPLE 2 + +```text +PS\> Add-ExcelTable -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName Musictable -ShowFilter:$false -ShowTotal -ShowFirstColumn +``` + +Again $ws is a worksheet, range here is the whole of the active part of the worksheet. The table style and name are set, the filter is turned off, and a "Totals" row added, and first column is set in bold. + +## PARAMETERS + +### -Range + +The range of cells to assign to a table. + +```yaml +Type: ExcelRange +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TableName + +The name for the Table - this should be unqiue in the Workbook - auto generated names will be used if this is left empty. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TableStyle + +The Style for the table, by default "Medium6" is used + +```yaml +Type: TableStyles +Parameter Sets: (All) +Aliases: +Accepted values: None, Custom, Light1, Light2, Light3, Light4, Light5, Light6, Light7, Light8, Light9, Light10, Light11, Light12, Light13, Light14, Light15, Light16, Light17, Light18, Light19, Light20, Light21, Medium1, Medium2, Medium3, Medium4, Medium5, Medium6, Medium7, Medium8, Medium9, Medium10, Medium11, Medium12, Medium13, Medium14, Medium15, Medium16, Medium17, Medium18, Medium19, Medium20, Medium21, Medium22, Medium23, Medium24, Medium25, Medium26, Medium27, Medium28, Dark1, Dark2, Dark3, Dark4, Dark5, Dark6, Dark7, Dark8, Dark9, Dark10, Dark11 + +Required: False +Position: 3 +Default value: Medium6 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowHeader + +By default the header row is shown - it can be turned off with -ShowHeader:$false. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowFilter + +By default the filter is enabled - it can be turned off with -ShowFilter:$false. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowTotal + +Show total adds a totals row. This does not automatically sum the columns but provides a drop-down in each to select sum, average etc + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TableTotalSettings + +A HashTable in the form of either + +- ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|\ $chartdef = New-ExcelChartDefinition -Title "Gross and net by city and product" -ChartType ColumnClustered ` + -Column 11 -Width 500 -Height 360 -YMajorUnit 500 -YMinorUnit 100 -YAxisNumberformat "$#,##0" -LegendPosition Bottom + $excel = ConvertFrom-Csv @" +Product, City, Gross, Net +Apple, London , 300, 250 +Orange, London , 400, 350 +Banana, London , 300, 200 +Orange, Paris, 600, 500 +Banana, Paris, 300, 200 +Apple, New York, 1200,700 +"@ | Export-Excel -Path "test.xlsx" -TableStyle Medium13 -tablename "RawData" -PassThru + Add-PivotTable -PivotTableName Sales -Address $excel.Workbook.Worksheets[1].Cells["F1"] ` + -SourceWorkSheet $excel.Workbook.Worksheets[1] -PivotRows City -PivotColumns Product -PivotData @{Gross="Sum";Net="Sum"} ` + -PivotNumberFormat "$#,##0.00" -PivotTotals Both -PivotTableStyle Medium12 -PivotChartDefinition $chartdef + Close-ExcelPackage -show $excel +``` + +This script starts by defining a chart. + +Then it exports some data to an XLSX file and keeps the file open. + +The next step is to add the pivot table, normally this would be on its own sheet in the workbook, but here -Address is specified to place it beside the data. + +The Add-Pivot table is given the chart definition and told to create a tale using the City field to create rows, the Product field to create columns and the data should be the sum of the gross field and the sum of the net field; grand totals for both gross and net are included for rows \(Cities\) and columns \(Products\) and the data is explicitly formatted as a currency. + +Note that in the chart definition the number format for the axis does not include any fraction part. + +### EXAMPLE 3 + +```text +PS> $excel = Convertfrom-csv @" +Location,OrderDate,quantity +Boston,1/1/2017,100 +New York,1/21/2017,200 +Boston,1/11/2017,300 +New York,1/9/2017,400 +Boston,1/18/2017,500 +Boston,2/1/2017,600 +New York,2/21/2017,700 +New York,2/11/2017,800 +Boston,2/9/2017,900 +Boston,2/18/2017,1000 +New York,1/1/2018,100 +Boston,1/21/2018,200 +New York,1/11/2018,300 +Boston,1/9/2018,400 +New York,1/18/2018,500 +Boston,2/1/2018,600 +Boston,2/21/2018,700 +New York,2/11/2018,800 +New York,2/9/2018,900 +Boston,2/18/2018,1000 +"@ | Select-Object -Property @{n="OrderDate";e={[datetime]::ParseExact($_.OrderDate,"M/d/yyyy",(Get-Culture))}}, + Location, Quantity | Export-Excel "test2.xlsx" -PassThru -AutoSize + Set-ExcelColumn -Worksheet $excel.sheet1 -Column 1 -NumberFormat 'Short Date' + $pt = Add-PivotTable -PassThru -PivotTableName "ByDate" -Address $excel.Sheet1.cells["F1"] -SourceWorkSheet $excel.Sheet1 -PivotRows location,orderdate -PivotData @{'quantity'='sum'} -GroupDateRow orderdate -GroupDatePart 'Months,Years' -PivotTotals None + $pt.RowFields[0].SubtotalTop=$false + $pt.RowFields[0].Compact=$false + Close-ExcelPackage $excel -Show +``` + +Here the data contains dates formatted as strings using US format. + +These are converted to DateTime objects before being exported to Excel; the "OrderDate" column is formatted with the local short-date style. + +Then the PivotTable is added; it groups information by date and location, the date is split into years and then months. + +No grand totals are displayed. + +The Pivot table object is caught in a variable, and the "Location" column has its subtotal moved from the top to the bottom of each location section, and the "Compact" option is disabled to prevent "Year" moving into the same column as location. + +Finally the workbook is saved and shown in Excel. + +## PARAMETERS + +### -PivotTableName + +Name for the new PivotTable - this will be the name of a sheet in the Workbook. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Address + +By default, a PivotTable will be created on its own sheet, but it can be created on an existing sheet by giving the address where the top left corner of the table should go. \(Allow two rows for the filter if one is used.\) + +```yaml +Type: ExcelAddressBase +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExcelPackage + +An Excel-package object for the workbook. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SourceWorkSheet + +Worksheet where the data is found. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SourceRange + +Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotRows + +Fields to set as rows in the PivotTable. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotData + +A hash table in form "FieldName"="Function", where function is one of Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotColumns + +Fields to set as columns in the PivotTable. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotFilter + +Fields to use to filter in the PivotTable. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotDataToColumn + +If there are multiple data items in a PivotTable, by default they are shown on separate rows; this switch makes them separate columns. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotTotals + +Define whether totals should be added to rows, columns neither, or both \(the default is both\). + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Both +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoTotalsInPivot + +Included for compatibility - equivalent to -PivotTotals "None". + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupDateRow + +The name of a row field which should be grouped by parts of the date/time \(ignored if GroupDateRow is not specified\) + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupDateColumn + +The name of a Column field which should be grouped by parts of the date/time \(ignored if GroupDateRow is not specified\) + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupDatePart + +The Part\(s\) of the date to use in the grouping \(ignored if GroupDateRow is not specified\) + +```yaml +Type: eDateGroupBy[] +Parameter Sets: (All) +Aliases: +Accepted values: Years, Quarters, Months, Days, Hours, Minutes, Seconds + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupNumericRow + +The name of a row field which should be grouped by Number \(e.g. 0-99, 100-199, 200-299 \) + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupNumericColumn + +The name of a Column field which should be grouped by Number \(e.g. 0-99, 100-199, 200-299 \) + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupNumericMin + +The starting point for grouping + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupNumericMax + +The endpoint for grouping + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 1.79769313486232E+308 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GroupNumericInterval + +The interval for grouping + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 100 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotNumberFormat + +Number format to apply to the data cells in the PivotTable. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotTableStyle + +Apply a table style to the PivotTable. + +```yaml +Type: TableStyles +Parameter Sets: (All) +Aliases: +Accepted values: None, Custom, Light1, Light2, Light3, Light4, Light5, Light6, Light7, Light8, Light9, Light10, Light11, Light12, Light13, Light14, Light15, Light16, Light17, Light18, Light19, Light20, Light21, Medium1, Medium2, Medium3, Medium4, Medium5, Medium6, Medium7, Medium8, Medium9, Medium10, Medium11, Medium12, Medium13, Medium14, Medium15, Medium16, Medium17, Medium18, Medium19, Medium20, Medium21, Medium22, Medium23, Medium24, Medium25, Medium26, Medium27, Medium28, Dark1, Dark2, Dark3, Dark4, Dark5, Dark6, Dark7, Dark8, Dark9, Dark10, Dark11 + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotChartDefinition + +Use a chart definition instead of specifying chart settings one by one. + +```yaml +Type: Object +Parameter Sets: ChartbyDef +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -IncludePivotChart + +If specified, a chart will be included. + +```yaml +Type: SwitchParameter +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartTitle + +Optional title for the pivot chart, by default the title omitted. + +```yaml +Type: String +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartHeight + +Height of the chart in Pixels \(400 by default\). + +```yaml +Type: Int32 +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: 400 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartWidth + +Width of the chart in Pixels \(600 by default\). + +```yaml +Type: Int32 +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: 600 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartRow + +Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart \(default is 0, chart starts at top edge of row 1\). + +```yaml +Type: Int32 +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartColumn + +Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart \(default is 4, chart starts at left edge of column E\). + +```yaml +Type: Int32 +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: 4 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartRowOffSetPixels + +Vertical offset of the chart from the cell corner. + +```yaml +Type: Int32 +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartColumnOffSetPixels + +Horizontal offset of the chart from the cell corner. + +```yaml +Type: Int32 +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartType + +Type of chart; defaults to "Pie". + +```yaml +Type: eChartType +Parameter Sets: ChartbyParams +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: Named +Default value: Pie +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +If specified hides the chart legend. + +```yaml +Type: SwitchParameter +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +If specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type. + +```yaml +Type: SwitchParameter +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +If specified attaches percentages to slices in a pie chart. + +```yaml +Type: SwitchParameter +Parameter Sets: ChartbyParams +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Activate + +If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PassThru + +Return the PivotTable so it can be customized. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### OfficeOpenXml.Table.PivotTable.ExcelPivotTable + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/add-worksheet.md b/mdHelp/en/add-worksheet.md new file mode 100644 index 00000000..33bfa548 --- /dev/null +++ b/mdHelp/en/add-worksheet.md @@ -0,0 +1,267 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Add-WorkSheet + +## SYNOPSIS + +Adds a worksheet to an existing workbook. + +## SYNTAX + +### Package + +```text +Add-WorkSheet [-ExcelPackage] [-WorksheetName ] [-ClearSheet] [-MoveToStart] [-MoveToEnd] [-MoveBefore ] [-MoveAfter ] [-Activate] [-CopySource ] [-NoClobber] [] +``` + +### WorkBook + +```text +Add-WorkSheet -ExcelWorkbook [-WorksheetName ] [-ClearSheet] [-MoveToStart] [-MoveToEnd] [-MoveBefore ] [-MoveAfter ] [-Activate] [-CopySource ] [-NoClobber] [] +``` + +## DESCRIPTION + +If the named worksheet already exists, the -Clearsheet parameter decides whether it should be deleted and a new one returned, or if not specified the existing sheet will be returned. + +By default the sheet is created at the end of the work book, the -MoveXXXX switches allow the sheet to be \[re\]positioned at the start or before or after another sheet. + +A new sheet will only be made the default sheet when excel opens if -Activate is specified. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> $WorksheetActors = $ExcelPackage | Add-WorkSheet -WorkSheetname Actors +``` + +$ExcelPackage holds an Excel package object \(returned by Open-ExcelPackage, or Export-Excel -passthru\). This command will add a sheet named 'Actors', or return the sheet if it exists, and the result is stored in $WorkSheetActors. + +### EXAMPLE 2 + +```text +PS\> $WorksheetActors = Add-WorkSheet -ExcelPackage $ExcelPackage -WorkSheetname "Actors" -ClearSheet -MoveToStart +``` + +This time the Excel package object is passed as a parameter instead of piped. + +If the 'Actors' sheet already exists it is deleted and re-created. + +The new sheet will be created last in the workbook, and -MoveToStart Moves it to the start. + +### EXAMPLE 3 + +```text +PS\> $null = Add-WorkSheet -ExcelWorkbook $wb -WorkSheetname $DestinationName -CopySource $sourceWs -Activate +``` + +This time a workbook is used instead of a package, and a worksheet is copied - $SourceWs is a worksheet object, which can come from the same workbook or a different one. + +Here the new copy of the data is made the active sheet when the workbook is opened. + +## PARAMETERS + +### -ExcelPackage + +An object representing an Excel Package. + +```yaml +Type: ExcelPackage +Parameter Sets: Package +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -ExcelWorkbook + +An Excel Workbook to which the Worksheet will be added - a Package contains one Workbook, so you can use whichever fits at the time. + +```yaml +Type: ExcelWorkbook +Parameter Sets: WorkBook +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WorksheetName + +The name of the worksheet, 'Sheet1' by default. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ClearSheet + +If the worksheet already exists, by default it will returned, unless -ClearSheet is specified in which case it will be deleted and re-created. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MoveToStart + +If specified, the worksheet will be moved to the start of the workbook. + +MoveToStart takes precedence over MoveToEnd, Movebefore and MoveAfter if more than one is specified. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MoveToEnd + +If specified, the worksheet will be moved to the end of the workbook. + +\(This is the default position for newly created sheets, but it can be used to move existing sheets.\) + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MoveBefore + +If specified, the worksheet will be moved before the nominated one \(which can be an index starting from 1, or a name\). + +MoveBefore takes precedence over MoveAfter if both are specified. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MoveAfter + +If specified, the worksheet will be moved after the nominated one \(which can be an index starting from 1, or a name or \*\). + +If \* is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Activate + +If there is already content in the workbook the new sheet will not be active UNLESS Activate is specified. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CopySource + +If worksheet is provided as a copy source the new worksheet will be a copy of it. The source can be in the same workbook, or in a different file. + +```yaml +Type: ExcelWorksheet +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoClobber + +Ignored but retained for backwards compatibility. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### OfficeOpenXml.ExcelWorksheet + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/close-excelpackage.md b/mdHelp/en/close-excelpackage.md new file mode 100644 index 00000000..d7a8305e --- /dev/null +++ b/mdHelp/en/close-excelpackage.md @@ -0,0 +1,155 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Close-ExcelPackage + +## SYNOPSIS + +Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file in Excel as required. + +## SYNTAX + +```text +Close-ExcelPackage [-ExcelPackage] [-Show] [-NoSave] [[-SaveAs] ] [[-Password] ] [-Calculate] [] +``` + +## DESCRIPTION + +When working with an ExcelPackage object, the Workbook is held in memory and not saved until the .Save\(\) method of the package is called. + +Close-ExcelPackage saves and disposes of the Package object. + +It can be called with -NoSave to abandon the file without saving, with a new "SaveAs" filename, and/or with a password to protect the file. And -Show will open the file in Excel; -Calculate will try to update the workbook, although not everything can be recalculated + +## EXAMPLES + +### EXAMPLE 1 + +```text +Close-ExcelPackage -show $excel +``` + +$excel holds a package object, this saves the workbook and loads it into Excel. + +### EXAMPLE 2 + +```text +Close-ExcelPackage -NoSave $excel +``` + +$excel holds a package object, this disposes of it without writing it to disk. + +## PARAMETERS + +### -ExcelPackage + +Package to close. + +```yaml +Type: ExcelPackage +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Show + +Open the file in Excel. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoSave + +Abandon the file without saving. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SaveAs + +Save file with a new name \(ignored if -NoSave Specified\). + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Password + +Password to protect the file. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Calculate + +Attempt to recalculation the workbook before saving + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/compare-worksheet.md b/mdHelp/en/compare-worksheet.md new file mode 100644 index 00000000..430f8d29 --- /dev/null +++ b/mdHelp/en/compare-worksheet.md @@ -0,0 +1,427 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Compare-WorkSheet + +## SYNOPSIS + +Compares two worksheets and shows the differences. + +## SYNTAX + +### True \(Default\) + +```text +Compare-WorkSheet [-Referencefile] [-Differencefile] [-WorkSheetName ] [-Property ] [-ExcludeProperty ] [-Startrow ] [-AllDataBackgroundColor ] [-BackgroundColor ] [-TabColor ] [-Key ] [-FontColor ] [-Show] [-GridView] [-PassThru] [-IncludeEqual] [-ExcludeDifferent] [] +``` + +### B + +```text +Compare-WorkSheet [-Referencefile] [-Differencefile] [-WorkSheetName ] [-Property ] [-ExcludeProperty ] -Headername [-Startrow ] [-AllDataBackgroundColor ] [-BackgroundColor ] [-TabColor ] [-Key ] [-FontColor ] [-Show] [-GridView] [-PassThru] [-IncludeEqual] [-ExcludeDifferent] [] +``` + +### C + +```text +Compare-WorkSheet [-Referencefile] [-Differencefile] [-WorkSheetName ] [-Property ] [-ExcludeProperty ] [-NoHeader] [-Startrow ] [-AllDataBackgroundColor ] [-BackgroundColor ] [-TabColor ] [-Key ] [-FontColor ] [-Show] [-GridView] [-PassThru] [-IncludeEqual] [-ExcludeDifferent] [] +``` + +## DESCRIPTION + +This command takes two file names, one or two worksheet names and a name for a "key" column. + +It reads the worksheet from each file and decides the column names and builds a hashtable of the key-column values and the rows in which they appear. + +It then uses PowerShell's Compare-Object command to compare the sheets \(explicitly checking all the column names which have not been excluded\). + +For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison, otherwise identical rows at different positions in the file will not be considered a match. + +We also add the name of the file and sheet in which the difference occurs. + +If -BackgroundColor is specified the difference rows will be changed to that background in the orginal file. + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | Format-Table +``` + +The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32\_product to Export-Excel. + +The command compares the "Products" pages in the two workbooks, but we don't want to register a difference if the software was installed on a different date or from a different place, and excluding Install\* removes InstallDate and InstallSource. + +This data doesn't have a "Name" column, so we specify the "IdentifyingNumber" column as the key. + +The results will be presented as a table. + +### EXAMPLE 2 + +```text +PS\> Compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName Services -GridView +``` + +This time two workbooks contain the result of redirecting the command Get-WmiObject -Class win32\_service to Export-Excel. + +Here the -Differencefile and -Referencefile parameter switches are assumed and the default setting for -Key \("Name"\) works for services. + +This will display the differences between the "Services" sheets using a grid view + +### EXAMPLE 3 + +```text +PS\> Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen +``` + +This version of the command outputs the differences between the "services" pages and highlights any different rows in the spreadsheet files. + +### EXAMPLE 4 + +```text +PS\> Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show +``` + +This example builds on the previous one: this time where two changed rows have the value in the "Name" column \(the default value for -Key\), this version adds highlighting of the changed cells in red; and then opens the Excel file. + +### EXAMPLE 5 + +```text +PS\> Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description" +``` + +This time the reference file and the difference file are the same file and two different sheets are used. + +Because the tests include the machine name and time the test was run, the command specifies that a limited set of columns should be used. + +### EXAMPLE 6 + +```text +PS\> Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent +``` + +The "General" page in the two workbooks has a title and two unlabelled columns with a row each for CPU, Memory, Domain, Disk and so on. + +So the command is told to start at row 2 in order to skip the title and given names for the columns: the first is "label" and the second "Value"; the label acts as the key. + +This time we are interested in those rows which are the same in both sheets, and the result is displayed using grid view. + +Note that grid view works best when the number of columns is small. + +### EXAMPLE 7 + +```text +PS\>Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray +``` + +This version of the previous command highlights all the cells in LightGray and then sets the changed rows back to white. + +Only the unchanged rows are highlighted. + +## PARAMETERS + +### -Referencefile + +First file to compare. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Differencefile + +Second file to compare. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WorkSheetName + +Name\(s\) of worksheets to compare. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Sheet1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Property + +Properties to include in the comparison - supports wildcards, default is "\*". + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: * +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExcludeProperty + +Properties to exclude from the comparison - supports wildcards. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Headername + +Specifies custom property names to use, instead of the values defined in the starting row of the sheet. + +```yaml +Type: String[] +Parameter Sets: B +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoHeader + +Automatically generate property names \(P1, P2, P3 ...\) instead of the using the values the starting row of the sheet. + +```yaml +Type: SwitchParameter +Parameter Sets: C +Aliases: + +Required: True +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Startrow + +The row from where we start to import data: all rows above the start row are disregarded. By default, this is the first row. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AllDataBackgroundColor + +If specified, highlights all the cells - so you can make Equal cells one color, and Different cells another. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -BackgroundColor + +If specified, highlights the rows with differences. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TabColor + +If specified identifies the tabs which contain difference rows \(ignored if -BackgroundColor is omitted\). + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Key + +Name of a column which is unique and will be used to add a row to the DIFF object, defaults to "Name". + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Name +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FontColor + +If specified, highlights the DIFF columns in rows which have the same key. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Show + +If specified, opens the Excel workbooks instead of outputting the diff to the console \(unless -PassThru is also specified\). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -GridView + +If specified, the command tries to the show the DIFF in a Grid-View and not on the console \(unless-PassThru is also specified\). This works best with few columns selected, and requires a key. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PassThru + +If specified a full set of DIFF data is returned without filtering to the specified properties. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IncludeEqual + +If specified the result will include equal rows as well. By default only different rows are returned. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExcludeDifferent + +If specified, the result includes only the rows where both are equal. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/convert-excelrangetoimage.md b/mdHelp/en/convert-excelrangetoimage.md new file mode 100644 index 00000000..543d7ea9 --- /dev/null +++ b/mdHelp/en/convert-excelrangetoimage.md @@ -0,0 +1,128 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Convert-ExcelRangeToImage + +## SYNOPSIS + +Gets the specified part of an Excel file and exports it as an image + +## SYNTAX + +```text +Convert-ExcelRangeToImage [-Path] [[-workSheetname] ] [-range] [[-destination] ] [-show] [] +``` + +## DESCRIPTION + +Excel allows charts to be exported directly to a file, but it can't do this with the rest of a sheet. To work round this, this function + +* Opens a copy of Excel and loads a file +* Selects a worksheet and then a range of cells in that worksheet +* Copies the select to the clipboard +* Saves the clipboard contents as an image file \(it will save as .JPG unless the file name ends .BMP or .PNG\) +* Copies a single cell to the clipboard \(to prevent the "you have put a lot in the clipboard" message appearing\) +* Closes Excel + + Unlike most functions in the module it needs a local copy of Excel to be installed. + + **EXAMPLES** + +## PARAMETERS + +### -Path + +Path to the Excel file + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WorkSheetname + +Worksheet name - if none is specified "Sheet1" will be assumed + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: Sheet1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Range + +Range of cells within the sheet, e.g "A1:Z99" + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Destination + +A bmp, png or jpg file where the result will be saved + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: "$pwd\temp.png" +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Show + +If specified opens the image in the default viewer. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/convertfrom-excelsheet.md b/mdHelp/en/convertfrom-excelsheet.md new file mode 100644 index 00000000..688d0d2f --- /dev/null +++ b/mdHelp/en/convertfrom-excelsheet.md @@ -0,0 +1,239 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: 'https://github.com/dfinke/ImportExcel' +schema: 2.0.0 +--- + +# ConvertFrom-ExcelSheet + +## SYNOPSIS + +Exports Sheets from Excel Workbooks to CSV files. + +## SYNTAX + +```text +ConvertFrom-ExcelSheet [-Path] [[-OutputPath] ] [[-SheetName] ] [[-Encoding] ] + [[-Extension] ] [[-Delimiter] ] [[-Property] ] [[-ExcludeProperty] ] [-Append] + [[-AsText] ] [] +``` + +## DESCRIPTION + +This command provides a convenient way to run Import-Excel @ImportParameters \| Select-Object @selectParameters \| export-Csv @ ExportParameters It can take the parameters -AsText , as used in Import-Excel, \)Properties & -ExcludeProperties as used in Select-Object and -Append, -Delimiter and -Encoding as used in Export-CSV + +## EXAMPLES + +### Example 1 + +```text +PS C:\> ConvertFrom-ExcelSheet Path .\__tests__\First10Races.xlsx -OutputPath .. -AsText GridPosition,date +``` + +First10Races.xlsx contains information about Motor races. The race date and grid \(starting\) position are stored with custom formats. The command specifies the path to the file, and the directory to create the output file, and specifies that the columns "GridPosition" and "Date" should be treated as text to preserve their formatting + +### Example 2 + +```text +PS C:\> ConvertFrom-ExcelSheet Path .\__tests__\First10Races.xlsx -OutputPath .. -AsText "GridPosition" -Property driver, @{n="date"; e={[datetime]::FromOADate($_.Date).tostring("#MM/dd/yyyy#")}} , FinishPosition, GridPosition +``` + +This uses the same file as example 1. Because the race date has a custom format, it imports as a number, The requirement is to create a CSV file with the Driver, a specially formatted Date, FinishPostion and GridPostion \(keeping its custom formatting\). The command specifies the path to the file, and the directory to create the output file, specifies that the column "GridPosition" should be treated as text instead of a number, and the output properties should be Driver, a calculated "date" field, FinishPosition and GridPsition. FromOADate converts the dates used by Excel \(Days since Jan 1 1900\) to a datetime object. + +## PARAMETERS + +### -Append + +Use this parameter to have the export add output to the end of the file. Without this parameter, the command replaces the file contents without warning. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AsText + +AsText allows selected columns to be returned as the text displayed in their cells, instead of their value. \(\* is supported as a wildcard.\) + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 8 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AsDate + +Not all date formats are recognized as indicating the number in the cell represents a date AsDate forces the number which would be returned to be converted to a date. \(\* is supported as a wildcard.\) + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 8 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Delimiter + +Selects , or ; as the delimeter for the exported data - if not specified , is used by default. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: +Accepted values: ;, , + +Required: False +Position: 5 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Encoding + +Sets the text encoding for the output data file; UTF8 bu default + +```yaml +Type: Encoding +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExcludeProperty + +Specifies the properties that to exclude from the export. Wildcards are permitted. This parameter is effective only when the command also includes the Property parameter. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 7 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Extension + +Sets the file extension for the exported data, defaults to CSV + +```yaml +Type: String +Parameter Sets: (All) +Aliases: +Accepted values: .txt, .log, .csv + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -OutputPath + +The directory where the output file\(s\) will be created. The file name\(s\) will match the name of the workbook page which contained the data. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path + +The path to the .XLSX file which will be exported. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Property + +Specifies the properties to select. Wildcards are permitted - the default is "\*". The value of the Property parameter can be a new calculated property, and follows the same pattern as Select-Item + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 6 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SheetName + +The name of a sheet to export, or a regular expression which is used to identify sheets + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/convertfrom-exceltosqlinsert.md b/mdHelp/en/convertfrom-exceltosqlinsert.md new file mode 100644 index 00000000..6d9329d0 --- /dev/null +++ b/mdHelp/en/convertfrom-exceltosqlinsert.md @@ -0,0 +1,227 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# ConvertFrom-ExcelToSQLInsert + +## SYNOPSIS + +Generate SQL insert statements from Excel spreadsheet. + +## SYNTAX + +```text +ConvertFrom-ExcelToSQLInsert [-TableName] [-Path] [[-WorkSheetname] ] [[-StartRow] ] [[-Header] ] [-NoHeader] [-DataOnly] [-ConvertEmptyStringsToNull] [-UseMSSQLSyntax] [] +``` + +## DESCRIPTION + +Generate SQL insert statements from Excel spreadsheet. + +## EXAMPLES + +### EXAMPLE 1 + +```text +Generate SQL insert statements from Movies.xlsx file, leaving blank cells as empty strings: + +---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Sheet1 | +---------------------------------------------------------- +| A B C | +|1 Movie Name Year Rating | +|2 The Bodyguard 1992 9 | +|3 The Matrix 1999 8 | +|4 Skyfall 2012 9 | +|5 The Avengers 2012 | +---------------------------------------------------------- + +PS C:\> ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path 'C:\Movies.xlsx' +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Bodyguard', '1992', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Matrix', '1999', '8'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('Skyfall', '2012', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Avengers', '2012', ''); +``` + +### EXAMPLE 2 + +```text +Generate SQL insert statements from Movies.xlsx file, specify NULL instead of an empty string. + +---------------------------------------------------------- +| File: Movies.xlsx - Sheet: Sheet1 | +---------------------------------------------------------- +| A B C | +|1 Movie Name Year Rating | +|2 The Bodyguard 1992 9 | +|3 The Matrix 1999 8 | +|4 Skyfall 2012 9 | +|5 The Avengers 2012 | +---------------------------------------------------------- + +PS C:\> ConvertFrom-ExcelToSQLInsert -TableName "Movies" -Path "C:\Movies.xlsx" -ConvertEmptyStringsToNull +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Bodyguard', '1992', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Matrix', '1999', '8'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('Skyfall', '2012', '9'); +INSERT INTO Movies ('Movie Name', 'Year', 'Rating') Values('The Avengers', '2012', NULL); +``` + +## PARAMETERS + +### -TableName + +Name of the target database table. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path + +Path to an existing .XLSX file This parameter is passed to Import-Excel as is. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: FullName + +Required: True +Position: 2 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -WorkSheetname + +Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported. This parameter is passed to Import-Excel as is. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: Sheet + +Required: False +Position: 3 +Default value: 1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StartRow + +The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. When the parameters '-NoHeader' and '-HeaderName' are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: HeaderRow, TopRow + +Required: False +Position: 4 +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Header + +Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. If you provide fewer header names than there is data in the worksheet, then only the data with a corresponding header name will be imported and the data without header name will be disregarded. If you provide more header names than there is data in the worksheet, then all data will be imported and all objects will have all the property names you defined in the header names. As such, the last properties will be blank as there is no data for them. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 5 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoHeader + +Automatically generate property names \(P1, P2, P3, ..\) instead of the ones defined in the column headers of the TopRow. This switch is best used when you want to import the complete worksheet 'as is' and are not concerned with the property names. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DataOnly + +Import only rows and columns that contain data, empty rows and empty columns are not imported. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ConvertEmptyStringsToNull + +If specified, cells without any data are replaced with NULL, instead of an empty string. This is to address behviors in certain DBMS where an empty string is insert as 0 for INT column, instead of a NULL value. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UseMSSQLSyntax + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/copy-excelworksheet.md b/mdHelp/en/copy-excelworksheet.md new file mode 100644 index 00000000..db9bbb29 --- /dev/null +++ b/mdHelp/en/copy-excelworksheet.md @@ -0,0 +1,152 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Copy-ExcelWorkSheet + +## SYNOPSIS + +Copies a worksheet between workbooks or within the same workbook. + +## SYNTAX + +```text +Copy-ExcelWorkSheet [-SourceObject] [[-SourceWorkSheet] ] [-DestinationWorkbook] + [[-DestinationWorksheet] ] [-Show] [] +``` + +## DESCRIPTION + +Copy-ExcelWorkSheet takes a Source object which is either a worksheet, or a package, Workbook or path, in which case the source worksheet can be specified by name or number \(starting from 1\). The destination worksheet can be explicitly named, or will follow the name of the source if no name is specified. The Destination workbook can be given as the path to an XLSx file, an ExcelPackage object or an ExcelWorkbook object. + +## EXAMPLES + +### EXAMPLE 1 + +```text +Copy-ExcelWorkSheet -SourceWorkbook Test1.xlsx -DestinationWorkbook Test2.xlsx +``` + +This is the simplest version of the command: no source worksheet is specified so Copy-ExcelWorksheet uses the first sheet in the workbook No Destination sheet is specified so the new worksheet will be the same as the one which is being copied. + +### EXAMPLE 2 + +```text +Copy-ExcelWorkSheet -SourceWorkbook Server1.xlsx -sourceWorksheet "Settings" -DestinationWorkbook Settings.xlsx -DestinationWorksheet "Server1" +``` + +Here the Settings page from Server1's workbook is copied to the 'Server1" page of a "Settings" workbook. + +### EXAMPLE 3 + +```text +$excel = Open-ExcelPackage .\test.xlsx +``` + +C:\> Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet "first" -DestinationWorkbook $excel -Show -DestinationWorksheet Duplicate This opens the workbook test.xlsx and copies the worksheet named "first" to a new worksheet named "Duplicate", because -Show is specified the file is saved and opened in Excel + +### EXAMPLE 4 + +```text +$excel = Open-ExcelPackage .\test.xlsx +``` + +C:\> Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet 1 -DestinationWorkbook $excel -DestinationWorksheet Duplicate C:\> Close-ExcelPackage $excel This is almost the same as the previous example, except source sheet is specified by position rather than name and because -Show is not specified, so other steps can be carried using the package object, at the end the file is saved by Close-ExcelPackage + +## PARAMETERS + +### -SourceObject + +An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data is found. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: SourceWorkbook + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -SourceWorkSheet + +Name or number \(starting from 1\) of the worksheet in the source workbook \(defaults to 1\). + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: 1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DestinationWorkbook + +An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data should be copied. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DestinationWorksheet + +Name of the worksheet in the destination workbook; by default the same as the source worksheet's name. If the sheet exists it will be deleted and re-copied. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Show + +if the destination is an excel package or a path, launch excel and open the file on completion. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/expand-numberformat.md b/mdHelp/en/expand-numberformat.md new file mode 100644 index 00000000..9b9e70c2 --- /dev/null +++ b/mdHelp/en/expand-numberformat.md @@ -0,0 +1,79 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: null +schema: 2.0.0 +--- + +# Expand-NumberFormat + +## SYNOPSIS + +Converts short names for number formats to the formatting strings used in Excel + +## SYNTAX + +```text +Expand-NumberFormat [[-NumberFormat] ] [] +``` + +## DESCRIPTION + +Where you can type a number format you can write, for example, 'Short-Date' and the module will translate it into the format string used by Excel. Some formats, like Short-Date, change when Excel loads \(so date will use the local ordering of year, month and Day\). Excel also changes how markers in the are presented different cultures "," is used in the format string to mean "local thousand seperator" but depending on the country "," or "." or " " may used as the thousand seperator. + +## EXAMPLES + +### EXAMPLE 1 + +```text +Expand-NumberFormat percentage +``` + +Returns "0.00%" + +### EXAMPLE 2 + +```text +Expand-NumberFormat Currency +``` + +Returns the currency format specified in the local regional settings, which may not be the same as Excel uses. + +The regional settings set the currency symbol and then whether it is before or after the number and separated with a space or not; for negative numbers the number may be wrapped in parentheses or a - sign might appear before or after the number and symbol. + +So this returns $\#,\#\#0.00;\($\#,\#\#0.00\) for English US, \#,\#\#0.00 €;€\#,\#\#0.00- for French. + +Note some Eurozone countries write €1,23 and others 1,23€. In French the decimal point will be rendered as a "," and the thousand separator as a space. + +## PARAMETERS + +### -NumberFormat + +The format string to Expand + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about\_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.String + +## NOTES + +## RELATED LINKS + diff --git a/mdHelp/en/export-excel.md b/mdHelp/en/export-excel.md new file mode 100644 index 00000000..3198c178 --- /dev/null +++ b/mdHelp/en/export-excel.md @@ -0,0 +1,1553 @@ +--- +external help file: ImportExcel-help.xml +Module Name: ImportExcel +online version: 'https://github.com/dfinke/ImportExcel' +schema: 2.0.0 +--- + +# Export-Excel + +## SYNOPSIS + +Exports data to an Excel worksheet. + +## SYNTAX + +### Default \(Default\) + +```text +Export-Excel [[-Path] ] [-InputObject ] [-Calculate] [-Show] [-WorksheetName ] [-Password ] [-ClearSheet] [-Append] [-Title ] [-TitleFillPattern ] [-TitleBold] [-TitleSize ] [-TitleBackgroundColor ][-IncludePivotTable] [-PivotTableName ] [-PivotRows [-PivotColumns ] [-PivotData ] [-PivotFilter ] [-PivotDataToColumn] [-PivotTableDefinition ] [-IncludePivotChart] [-ChartType ] [-NoLegend] [-ShowCategory] [-ShowPercent] [-AutoSize] [-MaxAutoSizeRows ] [-NoClobber] [-FreezeTopRow] [-FreezeFirstColumn] [-FreezeTopRowFirstColumn] [-FreezePane ] [-AutoFilter] [-BoldTopRow] [-NoHeader] [-RangeName ] [-TableName ] [-TableStyle ] [-TableTotalSettings ] [-Barchart] [-PieChart] [-LineChart] [-ColumnChart] [-ExcelChartDefinition ] [-HideSheet ] [-UnHideSheet ] [-MoveToStart] [-MoveToEnd] [-MoveBefore ] [-MoveAfter ] [-KillExcel] [-AutoNameRange] [-StartRow ] [-StartColumn ] [-PassThru] [-Numberformat ] [-ExcludeProperty ] [-NoAliasOrScriptPropeties] [-DisplayPropertySet] [-NoNumberConversion ] [-NoHyperLinkConversion ] [-ConditionalFormat ] [-ConditionalText ] [-Style ] [-CellStyleSB ] [-Activate] [-Now] [-ReturnRange] [-PivotTotals ] [-NoTotalsInPivot] [-ReZip] [] +``` + +### Package + +```text +Export-Excel -ExcelPackage [-InputObject ] [-Calculate] [-Show] [-WorksheetName ] [-Password ] [-ClearSheet] [-Append] [-Title ] [-TitleFillPattern ] [-TitleBold] [-TitleSize ] [-TitleBackgroundColor ] [-IncludePivotTable] [-PivotTableName ] [-PivotRows ] [-PivotColumns ] [-PivotData ] [-PivotFilter ] [-PivotDataToColumn] [-PivotTableDefinition ] [-IncludePivotChart] [-ChartType ] [-NoLegend] [-ShowCategory] [-ShowPercent] [-AutoSize] [-MaxAutoSizeRows ] [-NoClobber] [-FreezeTopRow] [-FreezeFirstColumn] [-FreezeTopRowFirstColumn] [-FreezePane ] [-AutoFilter] [-BoldTopRow] [-NoHeader] [-RangeName ] [-TableName ] [-TableStyle ] [-TableTotalSettings ] [-Barchart] [-PieChart] [-LineChart] [-ColumnChart] [-ExcelChartDefinition ] [-HideSheet ] [-UnHideSheet ] [-MoveToStart] [-MoveToEnd] [-MoveBefore ] [-MoveAfter ] [-KillExcel] [-AutoNameRange] [-StartRow ] [-StartColumn ] [-PassThru] [-Numberformat ] [-ExcludeProperty ] + [-NoAliasOrScriptPropeties] [-DisplayPropertySet] [-NoNumberConversion ] [-NoHyperLinkConversion ] [-ConditionalFormat ] [-ConditionalText ] [-Style ] [-CellStyleSB ] [-Activate] [-ReturnRange] [-PivotTotals ] [-NoTotalsInPivot] [-ReZip] [] +``` + +## DESCRIPTION + +Exports data to an Excel file and where possible tries to convert numbers in text fields so Excel recognizes them as numbers instead of text. After all: Excel is a spreadsheet program used for number manipulation and calculations. The parameter -NoNumberConversion \* can be used if number conversion is not desired. In the same way the parameter NoHyperLinkConversion \* can be used if hyperlink conversion is not desired + +## EXAMPLES + +### EXAMPLE 1 + +```text +PS\> Get-Process | Export-Excel .\Test.xlsx -show +``` + +Export all the processes to the Excel file 'Test.xlsx' and open the file immediately. + +### EXAMPLE 2 + +```text +PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> 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 numbers which use a thousand seperator and display to two decimal places. + +### EXAMPLE 3 + +```text +PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> [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.xlsx" and tries to convert all values to numbers where possible except for "IPAddress" and "Number1", which are stored in the sheet 'as is', without being converted to a number. + +### EXAMPLE 4 + +```text +PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> [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 * -NoHyperLinkConversion * +``` + +Exports all data to the Excel file 'Excel.xslx' as is, no number or hyperlink conversion will take place. This means that Excel will show the exact same data that you handed over to the 'Export-Excel' function. + +### EXAMPLE 5 + +```text +PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> 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 that will show cells with a value is greater than 525, with a background fill color of "LightPink" and the text in "DarkRed". + +Where the condition is not met the color will be the default, black text on a white background. + +### EXAMPLE 6 + +```text +PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true +} +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> Get-Service | Select-Object -Property Name, Status, DisplayName, ServiceName | + Export-Excel @ExcelParams -ConditionalText $( + New-ConditionalText Stop DarkRed LightPink + New-ConditionalText Running Blue Cyan + ) +``` + +Exports all services to an Excel sheet, setting a Conditional formatting rule that will set the background fill color to "LightPink" and the text color to "DarkRed" when the value contains the word "Stop". + +If the value contains the word "Running" it will have a background fill color of "Cyan" and text colored 'Blue'. + +If neither condition is met, the color will be the default, black text on a white background. + +### EXAMPLE 7 + +```text +PS\> $r = Get-ChildItem C:\WINDOWS\system32 -File + +PS\> $TotalSettings = @{ + Name = "Count" + Extension = "=COUNTIF([Extension];`".exe`")" + Length = @{ + Function = "=SUMIF([Extension];`".exe`";[Length])" + Comment = "Sum of all exe sizes" + } + } + +PS\> $r | Export-Excel -TableName system32files -TableStyle Medium10 -TableTotalSettings $TotalSettings -Show +``` + +Exports a list of files with a totals row with three calculated totals: + +- Total count of names +- Count of files with the extension ".exe" +- Total size of all file with extension ".exe" and add a comment as to not be mistaken that is is the total size of all files + +### EXAMPLE 8 + +```text +PS\> $ExcelParams = @{ + Path = $env:TEMP + '\Excel.xlsx' + Show = $true + Verbose = $true + } +PS\> Remove-Item -Path $ExcelParams.Path -Force -EA Ignore +PS\> $Array = @() +PS\> $Obj1 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' +} + +PS\> $Obj2 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' +} + + PS\> $Obj3 = [PSCustomObject]@{ + Member1 = 'First' + Member2 = 'Second' + Member3 = 'Third' + Member4 = 'Fourth' +} + +PS\> $Array = $Obj1, $Obj2, $Obj3 +PS\> $Array | Out-GridView -Title 'Not showing Member3 and Member4' +PS\> $Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorksheetName Numbers +``` + +Updates the first object of the array by adding property 'Member3' and 'Member4'. Afterwards, all objects are exported to an Excel file and all column headers are visible. + +### EXAMPLE 9 + +```text +PS\> Get-Process | Export-Excel .\test.xlsx -WorksheetName Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM +``` + +### EXAMPLE 10 + +```text +PS\> Get-Process | Export-Excel .\test.xlsx -WorksheetName Processes -ChartType PieExploded3D -IncludePivotChart -IncludePivotTable -Show -PivotRows Company -PivotData PM +``` + +### EXAMPLE 11 + +```text +PS\> Get-Service | Export-Excel 'c:\temp\test.xlsx' -Show -IncludePivotTable -PivotRows status -PivotData @{status='count'} +``` + +### EXAMPLE 12 + +```text +PS\> $pt = [ordered]@{} +PS\> $pt.pt1=@{ + SourceWorkSheet = 'Sheet1'; + PivotRows = 'Status' + PivotData = @{'Status'='count'} + IncludePivotChart = $true + ChartType = 'BarClustered3D' +} +PS\> $pt.pt2=@ + SourceWorkSheet = 'Sheet2'; + PivotRows = 'Company' + PivotData = @{'Company'='count'} + IncludePivotChart = $true + ChartType = 'PieExploded3D' +} +PS\> Remove-Item -Path .\test.xlsx +PS\> Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -AutoSize +PS\> Get-Process | Select-Object -Property Name,Company,Handles,CPU,VM | Export-Excel -Path .\test.xlsx -AutoSize -WorksheetName 'sheet2' +PS\> Export-Excel -Path .\test.xlsx -PivotTableDefinition $pt -Show +``` + +This example defines two PivotTables. + +Then it puts Service data on Sheet1 with one call to Export-Excel and Process Data on sheet2 with a second call to Export-Excel. + +The third and final call adds the two PivotTables and opens the spreadsheet in Excel. + +### EXAMPLE 13 + +```text +PS\> Remove-Item -Path .\test.xlsx +PS\> $excel = Get-Service | Select-Object -Property Status,Name,DisplayName,StartType | Export-Excel -Path .\test.xlsx -PassThru +PS\> $excel.Workbook.Worksheets ["Sheet1"].Row(1).style.font.bold = $true +PS\> $excel.Workbook.Worksheets ["Sheet1"].Column(3 ).width = 29 +PS\> $excel.Workbook.Worksheets ["Sheet1"].Column(3 ).Style.wraptext = $true +PS\> $excel.Save() +PS\> $excel.Dispose() +PS\> Start-Process .\test.xlsx +``` + +This example uses -PassThru. + +It puts service information into sheet1 of the workbook and saves the ExcelPackage object in $Excel. + +It then uses the package object to apply formatting, and then saves the workbook and disposes of the object, before loading the document in Excel. + +Note: Other commands in the module remove the need to work directly with the package object in this way. + +### EXAMPLE 14 + +```text +PS\> Remove-Item -Path .\test.xlsx -ErrorAction Ignore +PS\> $excel = Get-Process | Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | + Export-Excel -Path .\test.xlsx -ClearSheet -WorksheetName "Processes" -PassThru +PS\> $sheet = $excel.Workbook.Worksheets ["Processes"] +PS\> $sheet.Column(1) | Set-ExcelRange -Bold -AutoFit +PS\> $sheet.Column(2) | Set-ExcelRange -Width 29 -WrapText +PS\> $sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NFormat "#,###" +PS\> Set-ExcelRange -Address $sheet.Cells ["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" +PS\> Set-ExcelRange -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold +PS\> Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center +PS\> Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red +PS\> Add-ConditionalFormatting -WorkSheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red +PS\> foreach ($c in 5..9) {Set-ExcelRange -Address $sheet.Column($c) -AutoFit } +PS\> Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show +``` + +This a more sophisticated version of the previous example showing different ways of using Set-ExcelRange, and also adding conditional formatting. + +In the final command a PivotChart is added and the workbook is opened in Excel. + +### EXAMPLE 15 + +```text +PS\> 0..360 | ForEach-Object {[pscustomobject][ordered]@{X=$_; Sinx="=Sin(Radians(x)) "} } | + Export-Excel -now -LineChart -AutoNameRange +``` + +Creates a line chart showing the value of Sine\(x\) for values of X between 0 and 360 degrees. + +### EXAMPLE 16 + +```text +PS\> Invoke-Sqlcmd -ServerInstance localhost\DEFAULT -Database AdventureWorks2014 -Query "select * from sys.tables" -OutputAs DataRows | + Export-Excel -Path .\SysTables_AdventureWorks2014.xlsx -WorksheetName Tables +``` + +Runs a query against a SQL Server database and outputs the resulting rows as DataRows using the -OutputAs parameter. The results are then piped to the Export-Excel function. + +NOTE: You need to install the SqlServer module from the PowerShell Gallery in order to get the -OutputAs parameter for the Invoke-Sqlcmd cmdlet. + +## PARAMETERS + +### -Path + +Path to a new or existing .XLSX file. + +```yaml +Type: String +Parameter Sets: Default +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExcelPackage + +An object representing an Excel Package - usually this is returned by specifying -PassThru allowing multiple commands to work on the same workbook without saving and reloading each time. + +```yaml +Type: ExcelPackage +Parameter Sets: Package +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InputObject + +Data is usually piped into Export-Excel, but it also accepts data through the InputObject parameter + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: TargetData + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Calculate + +If specified, a recalculation of the worksheet will be requested before saving. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Show + +Opens the Excel file immediately after creation; convenient for viewing the results instantly without having to search for the file first. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WorksheetName + +The name of a sheet within the workbook - "Sheet1" by default. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Sheet1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Password + +Sets password protection on the workbook. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ClearSheet + +If specified Export-Excel will remove any existing worksheet with the selected name. + +The default behaviour is to overwrite cells in this sheet as needed \(but leaving non-overwritten ones in place\). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Append + +If specified data will be added to the end of an existing sheet, using the same column headings. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Title + +Text of a title to be placed in the top left cell. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TitleFillPattern + +Sets the fill pattern for the title cell. + +```yaml +Type: ExcelFillStyle +Parameter Sets: (All) +Aliases: +Accepted values: None, Solid, DarkGray, MediumGray, LightGray, Gray125, Gray0625, DarkVertical, DarkHorizontal, DarkDown, DarkUp, DarkGrid, DarkTrellis, LightVertical, LightHorizontal, LightDown, LightUp, LightGrid, LightTrellis + +Required: False +Position: Named +Default value: Solid +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TitleBold + +Sets the title in boldface type. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TitleSize + +Sets the point size for the title. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 22 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TitleBackgroundColor + +Sets the cell background color for the title cell. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IncludePivotTable + +Adds a PivotTable using the data in the worksheet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotTableName + +If a PivotTable is created from command line parameters, specifies the name of the new sheet holding the pivot. Defaults to "WorksheetName-PivotTable". + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotRows + +Name\(s\) of column\(s\) from the spreadsheet which will provide the Row name\(s\) in a PivotTable created from command line parameters. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotColumns + +Name\(s\) of columns from the spreadsheet which will provide the Column name\(s\) in a PivotTable created from command line parameters. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotData + +In a PivotTable created from command line parameters, the fields to use in the table body are given as a Hash-table in the form + +ColumnName = Average\|Count\|CountNums\|Max\|Min\|Product\|None\|StdDev\|StdDevP\|Sum\|Var\|VarP. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotFilter + +Name\(s\) columns from the spreadsheet which will provide the Filter name\(s\) in a PivotTable created from command line parameters. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotDataToColumn + +If there are multiple datasets in a PivotTable, by default they are shown as separate rows under the given row heading; this switch makes them separate columns. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PivotTableDefinition + +Instead of describing a single PivotTable with multiple command-line parameters; you can use a HashTable in the form PivotTableName = Definition; + +In this table Definition is itself a Hashtable with Sheet, PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values. The New-PivotTableDefinition command will create the definition from a command line. + +```yaml +Type: Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -IncludePivotChart + +Include a chart with the PivotTable - implies -IncludePivotTable. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ChartType + +The type for PivotChart \(one of Excel's defined chart types\). + +```yaml +Type: eChartType +Parameter Sets: (All) +Aliases: +Accepted values: Area, Line, Pie, Bubble, ColumnClustered, ColumnStacked, ColumnStacked100, ColumnClustered3D, ColumnStacked3D, ColumnStacked1003D, BarClustered, BarStacked, BarStacked100, BarClustered3D, BarStacked3D, BarStacked1003D, LineStacked, LineStacked100, LineMarkers, LineMarkersStacked, LineMarkersStacked100, PieOfPie, PieExploded, PieExploded3D, BarOfPie, XYScatterSmooth, XYScatterSmoothNoMarkers, XYScatterLines, XYScatterLinesNoMarkers, AreaStacked, AreaStacked100, AreaStacked3D, AreaStacked1003D, DoughnutExploded, RadarMarkers, RadarFilled, Surface, SurfaceWireframe, SurfaceTopView, SurfaceTopViewWireframe, Bubble3DEffect, StockHLC, StockOHLC, StockVHLC, StockVOHLC, CylinderColClustered, CylinderColStacked, CylinderColStacked100, CylinderBarClustered, CylinderBarStacked, CylinderBarStacked100, CylinderCol, ConeColClustered, ConeColStacked, ConeColStacked100, ConeBarClustered, ConeBarStacked, ConeBarStacked100, ConeCol, PyramidColClustered, PyramidColStacked, PyramidColStacked100, PyramidBarClustered, PyramidBarStacked, PyramidBarStacked100, PyramidCol, XYScatter, Radar, Doughnut, Pie3D, Line3D, Column3D, Area3D + +Required: False +Position: Named +Default value: Pie +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoLegend + +Exclude the legend from the PivotChart. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowCategory + +Add category labels to the PivotChart. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ShowPercent + +Add percentage labels to the PivotChart. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AutoSize + +Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MaxAutoSizeRows + +Autosizing can be time consuming, so this sets a maximum number of rows to look at for the Autosize operation. Default is 1000; If 0 is specified ALL rows will be checked + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 1000 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoClobber + +Not used. Left in to avoid problems with older scripts, it may be removed in future versions. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FreezeTopRow + +Freezes headers etc. in the top row. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FreezeFirstColumn + +Freezes titles etc. in the left column. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FreezeTopRowFirstColumn + +Freezes top row and left column \(equivalent to Freeze pane 2,2 \). + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FreezePane + +Freezes panes at specified coordinates \(in the form RowNumber, ColumnNumber\). + +```yaml +Type: Int32[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AutoFilter + +Enables the Excel filter on the complete header row, so users can easily sort, filter and/or search the data in the selected column. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -BoldTopRow + +Makes the top row boldface. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoHeader + +Specifies that field names should not be put at the top of columns. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RangeName + +Makes the data in the worksheet a named range. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TableName + +Makes the data in the worksheet a table with a name, and applies a style to it. The name must not contain spaces. If the -Tablestyle parameter is specified without Tablename, "table1", "table2" etc. will be used. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: Table + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TableStyle + +Selects the style for the named table - if the Tablename parameter is specified without giving a style, 'Medium6' is used as a default. + +```yaml +Type: TableStyles +Parameter Sets: (All) +Aliases: +Accepted values: None, Custom, Light1, Light2, Light3, Light4, Light5, Light6, Light7, Light8, Light9, Light10, Light11, Light12, Light13, Light14, Light15, Light16, Light17, Light18, Light19, Light20, Light21, Medium1, Medium2, Medium3, Medium4, Medium5, Medium6, Medium7, Medium8, Medium9, Medium10, Medium11, Medium12, Medium13, Medium14, Medium15, Medium16, Medium17, Medium18, Medium19, Medium20, Medium21, Medium22, Medium23, Medium24, Medium25, Medium26, Medium27, Medium28, Dark1, Dark2, Dark3, Dark4, Dark5, Dark6, Dark7, Dark8, Dark9, Dark10, Dark11 + +Required: False +Position: Named +Default value: Medium6 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TableTotalSettings + +A HashTable in the form of either + +- ColumnName = "Average"\|"Count"\|"CountNums"\|"Max"\|"Min"\|"None"\|"StdDev"\|"Sum"\|"Var"|\