public/sheets.ps1

using namespace System.Collections.Generic

function New-Smartsheet() {
    [CmdletBinding()]
    Param(
        [Alias('folderId','workspaceId')]
        [Parameter(
            ValueFromPipelineByPropertyName = $true
        )]
        [UInt64]$Id,
        [ValidateSet('home','folder','workspace')]
        [string]$ContainerType = 'home',
        [Parameter(Mandatory = $true)]
        [string]$SheetName,
        [ValidateScript(
            {
                if (-not $_ -and ($templateId)) {
                    throw "Parameter Columns cannot be used with parameter TemplateId."
                } else {
                    $true
                }
            }
        )]        
        [psobject[]]$Columns,
        [ValidateScript(
            {
                if (-not $_ -and ($Columns)) {
                    throw "Parameter TemplateId cannot be used with parameter Columns."
                }
            }
        )]
        [UInt64]$TemplateId,
        [ValidateScript(
            {
                if ($_) {
                    if (
                        $null -ne $IncludeAttachments -or
                        $null -ne $includeCellLinks -or 
                        $null -ne $includeData -or 
                        $null -ne $includeDiscussions -or
                        $null -ne $IncludeFilters -or
                        $null -ne $includeForms -or
                        $null -ne $IncludeRuleReceipts -or
                        $Null -ne $IncludeRules
                    ) {
                        throw "Parameter Include all must not be used with other include parameters."
                    } else {
                        $true
                    }
                } 
            }
        )]
        [switch]$IncludeAll,
        [switch]$IncludeAttachments,
        [switch]$IncludeCellLinks,
        [switch]$IncludeData,
        [switch]$IncludeDiscussions,
        [switch]$IncludeFilters,
        [switch]$IncludeForms,
        [switch]$IncludeRuleReceipts,
        [switch]$IncludeRules 
    )

    switch ($ContainerType) {
        'folder' {
            $Uri = "{0}/folders/{1}/sheets" -f $BaseURI, $id
        }
        'workspace' {
            $Uri = "{0}/workspaces/{1}/sheets" -f $BaseURI, $Id
            if ($IncludeAll) {
                $includes = "attachments", "cellLinks", "data", "discussions", "filters", "forms", "ruleRecipients", "rules"
                $Uri = "{0}?include={1}" -f $Uri, ($includes -join ",")
            } else {
                $includes = [List[string]]::New()
                if ($includeAttachments) {$includes.Add("attachments")}
                if ($includeCellLinks) {$includes.Add("cellLinks")}
                if ($includeData) {$includes.Add("data")}
                if ($includeDiscussions) {$includes.Add("discussions")}
                if ($includeFilters) {$includes.Add("filters")}
                if ($includeForms) {$includes.Add("forms")}
                if ($includeRuleReceipts) {$includes.Add("ruleReciepts")}
                if ($includeRules) {$includes.Add("rules")}

                if ($includes.Count -gt 0) {
                    $Uri = "{0}?include={1}" -f $Uri, ($includes.ToArray() -join ",")
                }
            }
        }
        'home' {
            $Uri = "{0}/sheets" -f $BaseURI
        }
    }
    
    $Headers = Get-Headers

    if ($columns) {
        $payload = [ordered]@{
            name = $sheetName
            columns = $columns
        }
    } elseif ($templateId) {
        $payload = [ordered]@{
            fromId = $templateId
            name = $sheetName
        }
    } else {
        $columns = @()
        $columns += New-SmartsheetColumn -title "NewColumn" -primary
        $payload = [ordered]@{
            name = $sheetName
            columns = $columns
        }
    }
    $body = $payload | ConvertTo-Json -Compress

    try {
        $response = Invoke-RestMethod -Method POST -Uri $Uri -Headers $Headers -Body $body
        if ($response.message -eq 'SUCCESS') {
            return $response.result
        } else {
            throw $response.message
        }
    } catch {
        throw $_
    }
    <#
    .SYNOPSIS
    Create a new Smartsheet
    .DESCRIPTION
    Creates a sheet from scratch or from the specified template.
    .PARAMETER Id
    Folder Id where you can create sheets, sights, reports, templates, and other folders.
    .PARAMETER ContainerType
    Type of container. Either 'home','folder', or'workspace'.
    .PARAMETER SheetName
    Name of the new Sheet
    .PARAMETER
    .PARAMETER Columns
    An array of column objects.
    .PARAMETER TemplateId
    The Id of a sheet to use as a template.
    .PARAMETER IncludeAll
    Include all elements from the template sheet. cannot be used with other Include parameters.
    .PARAMETER IncludeAttachments
    Include attachments
    .PARAMETER IncludeCellLinks
    Include cell links
    .PARAMETER IncludeData
    Include data
    .PARAMETER IncludeDiscussions
    Include discussions
    .PARAMETER IncludeFilters
    Include filters
    .PARAMETER IncludeForms
    Include forms
    .PARAMETER IncludeRuleReceipts
    Include receipts
    .PARAMETER IncludeRules
    Include rules
    .OUTPUTS
    Result object containing a Sheet object for newly created sheet, corresponding to what was specified in the request.
    .NOTES
    Sheet names ARE NOT unique in folders. You can create a sheet with the same name as another sheet.
    This function does not check for name conflicts in the target folder.
    You should check for the existence of a sheet of the same name using the Get-Smartsheets function.
    #>

    
}

function Get-Smartsheets () {
 
    $Uri = "{0}/sheets?includeAll=true" -f $BaseURI
    $Headers = Get-Headers

    $response = Invoke-RestMethod -Method Get -Uri $Uri -Headers $Headers

    return $response.data
    <#
    .SYNOPSIS
    Gets all smartsheet.
    .DESCRIPTION
    Gets an array of Smartsheet object associated the user has access to.
    .OUTPUTS
    AN array of Smartsheet objects.
    #>

} 


function Get-Smartsheet () {    
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = "id"
        )]
        [Alias('SheetId')]
        [UInt64]$id,
        [Parameter(
            Mandatory = $true,
            ParameterSetName = "name"
        )]
        [string]$Name,
        [ValidateSet(0,1,2)]
        [int]$level,
        [switch]$includeAll,
        [switch]$includeAttachments,
        [switch]$includeColumnTypes,
        [switch]$includeCrossSheetReferences,
        [switch]$includeDiscussions,
        [switch]$includeFilters,
        [switch]$includeFilterDefinitions,
        [switch]$includeFormat,
        [switch]$includeGantConfig,
        [switch]$includeObjectValue,
        [switch]$includeOwnerInfo,
        [switch]$includeRowPermalink,
        [switch]$includeSource,
        [switch]$includeWriterInfo,
        [switch]$excludeFilteredOutRows,
        [switch]$excludeLinkInFromCellDetails,
        [switch]$excludeLinkOutToCellDetails,
        [switch]$excludeNonexistentCells,
        [psobject[]]$columnIds,
        [psobject[]]$rowIds
    )
    
    Begin {
        $Header = Get-Headers
        $includes = [List[string]]::New()
        If ($includeAll) {
            "attachments","columnType","crossSheetReferences","discussions","filters","filterDefinitions","format","ganttConfig", `
            "objectValue","ownerInfo","rowPermalink","source","writerInfo" `
            | ForEach-Object { $includes.Add($_)}
        } else {
            if ($includeAttachments) {$includes.Add("attachments")}
            if ($includeColumnTypes) {$includes.Add("columnType")}
            if ($includeCrossSheetReferences) {$includes.Add("crossSheetReferences")}
            if ($includeDiscussions) {$includes.Add("discussions")}
            if ($includeFilters) {$includes.Add("filters")}
            if ($includeFilterDefinitions) {$includes.Add("filterDefinitions")}
            if ($includeFormat) {$includes.Add("format")}
            if ($includeGantConfig) {$includes.Add("ganttConfig")}
            if ($includeObjectValue) {$includes.Add("objectValue")}
            if ($includeOwnerInfo) {$includes.Add("ownerInfo")}
            if ($includeRowPermalink) {$includes.Add("rowPermalink")}
            if ($includeSource) {$includes.Add("source")}
            if ($includeWriterInfo) {$includes.Add("writerInfo")}
        }
        $excludes = [List[string]]::New()
        if ($excludeFilteredOutRows) {$excludes.Add("filteredOutRows")}
        if ($excludeLinkInFromCellDetails) {$excludes.Add("linkInFromCellDetails")}
        if ($excludeLinkOutToCellDetails) {$excludes.Add("linksOutToCellsDetails")}
        if ($excludeNonexistentCells) {$excludes.Add("nonexistentCells")}
    }

    Process {
        # Was a sheet name Provided
        if ($Name) {
            # Get Smartsheet(s) that match the name.
            $sheetInfo = Get-Smartsheets | Where-Object {$_.name -eq $Name}
            if (-not $sheetInfo) {
                $msg = "Sheet {0} not found!" -f $Name
                Throw $msg
            }
            # There may be more than one sheet that matches the name. Prompt the user to select the sheet.
            if ($sheetInfo -is [array]) {
                Write-Host "Select Which Sheet to load:"
                Do {
                    foreach ($Sheet in $sheetInfo) {
                        $Msg = "{0}:{1}:{2}" -f ($sheetInfo.IndexOf($Sheet) +1), $Sheet.Name, $Sheet.modifiedAt 
                        Write-Host $Msg
                    }
                    Write-Host "Q: Quit"
                    $R = Read-Host "Select SmartSheet:"
                    If ($R -eq "q") { exit}
                } while ( $R -notin 1..$SheetInfo.Count)
                $id = $sheetInfo[$R-1].id
            } else {
                $id = $sheetInfo.id
            }
        }

        $Uri = "{0}/sheets/{1}" -f $BaseURI, $id
        if ($level) {
            $Uri = "{0}?level={1}" -f $Uri, $level
        }
        if ($includes.Count -gt 0) {
            [string]$strIncludes = $includes.ToArray() -join ","
            if ($Uri.Contains("?")) {
                $Uri = "{0}&include={1}" -f $Uri, $strIncludes
            } else {
                $Uri = "{0}?include={1}" -f $Uri, $strIncludes
            }
        }
        If ($excludes.Count -gt 0) {
            [string]$strExcludes = $excludes.ToArray() -join ","
            if ($Uri.Contains("?")) {
                $Uri = "{0}&exclude={1}" -f $uri, $strExcludes
            } else {
                $Uri = "{0}?exclude={1}" -f $Uri, $strExcludes
            }
        }
        if ($columnIds) {
            $listOfColIds = [List[string]]::New()
            $columnIds | ForEach-Object {
                $listOfColIdss.Add($_)
            }
            $strColumnIds = $listOfColIds.ToArray() -join ","
            if ($Uri.Contains("?")) {
                $Uri = "{0}&columnIds={1}" -f $Uri, $strColumnIds
            } else {
                $Uri = "{0}?columnIds={1}" -f $Uri, $strColumnIds
            }
        }
        if ($RowIds) {
            $listOfRowIds = [List[string]]::New()
            $rowIds | ForEach-Object {
                $listOfRowIds.Add($_)
            }
            $strRowIds = $listOfRowIds.ToArray() -join ","
            if ($uri.Contains("?")) {
                $Uri = "{0}&rowIds={1}" -f $Uri, $strRowIds
            } else {
                $Uri = "{0}?rowIds={1}" -f $Uri, $strRowIds
            }
        }
        $Sheet = Invoke-RestMethod -Method Get -Uri $Uri -Headers $Header
        $ToArray_Script = {
            param([boolean]$IncludeRowId)
            $psSheet = New-Object System.Collections.Generic.List[psobject]
            foreach ($Row in $this.rows) {                
                $Props = [ordered]@{}
                if ($IncludeRowId) {
                    $Props.Add("rowId", $row.id)
                }
                foreach ($Cell in $row.cells) {
                    $PropName = $this.columns.Where({$_.id -eq $Cell.columnId}).title
                    $Props.Add($PropName, $Cell.value)                    
                }
                $_row = New-Object -TypeName psobject -Property $props
                $psSheet.add($_row)
            }
            return $psSheet.ToArray()
        }
        $Sheet | Add-Member -MemberType ScriptMethod -Name ToArray -Value $ToArray_Script

        return $Sheet
    }
    <#
    .SYNOPSIS
    Retrieve an individual sheet.
    .DESCRIPTION
    Retrieves an individual sheet by either the sheet ID or the Name.
    Note: There can be multiple sheets with the same name. Using the Sheet ID is more accurate!
    The object returned has an additional method ToArray(), this method returns an array of PowerShell objects based on the sheet rows and columns.
    The ToArray method can accept a boolean parameter that instructs the method to include or exclude the RowId in the objects returned.
    True will return the row Id as a property of each object in the array. False will exclude the Row Id. False is the default.
    By using the Row id, you can update the values in a Smartsheet without the need for the primary column to be unique.
    The previous method of updating rows is included for backward compatibility and may eventually be removed.
    .PARAMETER id
    Folder ID, cannot be used with the Name parameter.
    .PARAMETER Name
    Sheet Name, cannot be used with the id parameter.
    .PARAMETER level
    Specifies whether new functionality, such as multi-contact data is returned in a backwards-compatible,
    text format (level=0, default), multi-contact data (level=1), or multi-picklist data (level=2).
    .PARAMETER includeAll
    Include All Sheet objects
    .PARAMETER includeAttachments
    Includes the metadata for sheet-level and row-level attachments.
    To include discussion attachments, both includeAttachments and includeDiscussions must be present.
    .PARAMETER includeColumnTypes
    Includes columnType attribute in the row's cells indicating the type of the column the cell resides in.
    .PARAMETER includeCrossSheetReferences
    Includes the cross-sheet references
    .PARAMETER includeDiscussions
    Includes sheet-level and row-level discussions.
    To include discussion attachments, both includeAttachments and includeDiscussions must be present.
    .PARAMETER includeFilters
    Includes filteredOut attribute indicating if the row should be displayed or hidden according to the sheet's filters.
    .PARAMETER includeFilterDefinitions
    Includes type of filter, operators used, and criteria
    .PARAMETER includeFormat
    Includes column, row, cell, and summary fields formatting.
    .PARAMETER includeGantConfig
    Includes Gantt chart details.
    .PARAMETER includeObjectValue
    When used in combination with a level parameter, includes the email addresses for multi-contact data.
    .PARAMETER includeOwnerInfo
    Includes the workspace and the owner's email address and user Id.
    .PARAMETER includeRowPermalink
    Includes permalink attribute that represents a direct link to the row in the Smartsheet application.
    .PARAMETER includeSource
    Adds the Source object indicating which report, sheet Sight (aka dashboard), or template the sheet was created from, if any.
    .PARAMETER includeWriterInfo
    Includes createdBy and modifiedBy attributes on the row or summary fields, indicating the row or summary field's creator, and last modifier.
    .PARAMETER excludeFilteredOutRows
    Excludes filtered out rows from response payload if a sheet filter is applied; includes total number of filtered rows
    .PARAMETER excludeLinkInFromCellDetails
    Excludes the following attributes from the cell.linkInFromCell object: columnId, rowId, status
    .PARAMETER excludeLinkOutToCellDetails
    Excludes the following attributes from the cell.linksOutToCells array elements: columnId, rowId, status
    .PARAMETER excludeNonexistentCells
    Excludes cells that have never contained any data
    .PARAMETER columnIds
    An array of column ids.
    The response contains only the specified columns in the "columns" array, and individual rows' "cells" array only
    contains cells in the specified columns.
    .PARAMETER rowIds
    A array of row Ids on which to filter the rows included in the result.
    .NOTES
    When retrieving a smartsheet by name there is always the chance that there are multiple sheets with the same name in a folder.
    If more than one sheet have the same name, you will be prompted to select the sheet yu want from a list.
    The list will show Sheet name and modified date.

    .OUTPUTS
    A Smartsheet sheet object.
    There is an added method named ToArray that returns the sheet as an array of PowerShell objects.
    #>

}

function Remove-Smartsheet() {   
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('SheetId')]
        [UInt64]$Id
    )

    $Headers = Get-Headers
    $Uri = "{0}/sheets/{1}" -f $BaseURI, $Id

    $response = Invoke-RestMethod -Method DELETE -Uri $Uri -Headers $Headers
    if ($response.message -eq "SUCCESS") {
        return $true
    } else {
        return $false
    }
     <#
    .SYNOPSIS
    Removes a smartsheet.
    .DESCRIPTION
    Removes a sheet by its SheetID.
    .PARAMETER Id
    Sheet Id, the sheet Id to remove.
    #>

}

function Copy-Smartsheet() {
    [CmdletBinding(DefaultParameterSetName = "props")]
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('SheetId')]
        [UInt64]$Id,
        [string]$newSheetName,
        [Parameter(ParameterSetName="container")]
        [string]$containerId,
        [Parameter(ParameterSetName="container")]
        [ValidateSet(
            "folder",
            "home",
            "workspace"
        )]
        [string]$containerType = "home",
        [switch]$includeAll,
        [switch]$includeAttachments,
        [switch]$includeCellLinks,
        [switch]$includeFormatting,
        [switch]$includeFilters,
        [switch]$includeForms,
        [switch]$includeRuleRecipients,
        [switch]$includeRules,
        [switch]$IncludeShares,
        [switch]$excludeSheetHyperlinks,
        [switch]$passThru

    )

    $Headers = Get-Headers
    $Uri = "{0}/sheets/{1}/copy" -f $BaseURI, $id
    if ($includeAll) {
        $uri = "{0}?include=all" -f $Uri
    } else {
        $includes = @()
        if ($includeAttachments) {
            $includes += "attachments"
        }
        if ($includeCellLinks) {
            $includes += "cellLinks"            
        }
        if ($includeFormatting) {
            $includes += "data"
        }
        if ($includeFilters) {
            $includes += "filters"
        }
        if ($includeForms) {
            $includes += "forms"
        }
        if ($includeRuleRecipients) {
            $includes += "ruleRecipients"
        }
        if ($includeRules) {
            $includes += "rules"
        }
        if ($IncludeShares) {
            $includes += "shares"
        }
        if ($includes.Length -gt 0) {
            $strIncludes = $includes -join ","
            if ($Uri.Contains("?")) {
                $Uri = "{0}&include=" -f $Uri, $strIncludes
            } else {
                $Uri = "{0}?include=" -f $Uri, $strIncludes
            }
        }
    }
    if ($excludeSheetHyperlinks) {
        if ($Uri.Contains("?")) {
            $Uri = "{0}&exclude=" -f $Uri, "sheetHyperlinks"
        } else {
            $Uri = "{0}?exclude=" -f $Uri, "sheetHyperlinks"
        }
    }
    $Payload = [ordered]@{}
    if ($containerId) {         
        $payload.Add("destinationId", $containerId) 
        $payload.Add("destinationType", $containerType)
    } else {
        $payload.Add("destinationType", $containerType)
    }
    $payload.Add("newName", $newSheetName)
    
    $body = $payload | ConvertTo-Json -Compress

    try{
        $response = Invoke-RestMethod -Method POST -Uri $Uri -Headers $Headers -Body $body
        if ($response.message = "SUCCESS") {
            if ($passThru) {
                return Get-Smartsheet -sheetId $id
            }
        } else {
            throw $response.message
        }
    } catch {
        throw $_
    }
    <#
    .SYNOPSIS
    Copy a smartsheet to a new name and/or into a folder.
    .DESCRIPTION
    Copies a smartsheet giving it a new name, or copying it to a folder or copying to a folder with a new name.
    .PARAMETER Id
    The sheet Id of the sheet to be copied.
    .PARAMETER newSheetName
    The name of the new sheet.
    .PARAMETER containerId
    The folder or workspace Id to copy the sheet to.
    .PARAMETER containerType
    One of 'folder', workspace' or 'home' if containerType - 'home' containerId must be omitted.
    'home' is the default value is omitted.
    .PARAMETER includeAll
    Include all elements of the sheet
    .PARAMETER includeAttachments
    Include attachments
    .PARAMETER includeCellLinks
    Include cell links.
    .PARAMETER includeFormatting
    Include formatting
    .PARAMETER includeFilters
    Include filters
    .PARAMETER includeForms
    Include forms
    .PARAMETER includeRuleRecipients
    Include rule recipients
    .PARAMETER includeRules
    Include rules.
    .PARAMETER IncludeShares
    Include Shares
    .PARAMETER excludeSheetHyperlinks
    Exclude sheet hyperlinks.
    .PARAMETER passThru
    Returns the copied Smartsheet object.
    #>

}
function Rename-SmartSheet() {
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('SheetId')]
        [Uint64]$Id,
        [Parameter(Mandatory = $true)]
        [String]$NewSheetName
    )
    Copy-Smartsheet -Id $Id -newSheetName $NewSheetName -includeAll
    Remove-Smartsheet -Id $Id
    <#
    .SYNOPSIS
    Rename a Smartsheet
    .DESCRIPTION
    Renames a smartsheet in the existing container.
    .PARAMETER Id
    Id of the sheet to rename.
    .PARAMETER newSheetname
    New name for the sheet
    .PARAMETER PassThru
    Return the copied smartsheet.
    #>

}

function Move-Smartsheet() {
    [CmdletBinding(DefaultParameterSetName = "props")]
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('SheetId')]
        [UInt64]$Id,
        [Parameter(ParameterSetName = "container")]
        [string]$containerId,
        [Parameter(ParameterSetName = "container")]
        [ValidateSet('folder','home','workspace')]
        [string]$containerType = "home"
    )

    $Headers = Get-Headers
    $Uri = "{0}/sheets/{1}/move" -f $BaseURI, $Id

    $properties = @{}
    $properties.Add("destinationType", $containerType)        
    if ($containerType -ne 'home') {
        $properties.Add("destinationId", $containerId)
    } 
    $objBody = [PSCustomObject]$properties
    $body = $objBody | ConvertTo-Json -Compress

    try{
        $result = Invoke-RestMethod -Method POST -Uri $Uri -Headers $Headers -Body $body
        if ($result.message -ne "SUCCESS") {
            throw $result.message
        }
    } catch {
        throw $_
    }
    <#
    .SYNOPSIS
    Move a Smartsheet
    .DESCRIPTION
    Move a Smartsheet into a different container.
    .PARAMETER Id
    ID of the the Smartsheet to move.
    .PARAMETER containerId
    Id of the container (folder/workspace) to move the Smartsheet to.
    if omitted the container is 'home'
    .PARAMETER containerType
    Can be one of 'folder', 'workspace or 'home'. If 'home' then containerId must be omitted.
    The default for this property is 'home' if omitted.
    #>

}

function Get-SortedSmartsheet() {
    [CmdletBinding()]
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('SheetId')]
        [UInt64]$id,
        [Parameter(
            Mandatory = $true,
            ParameterSetName = "Multi")]
        [psobject[]]$sortCriteria,
        [Parameter(
            Mandatory = $true,
            ParameterSetName = "single"
        )]
        [Uint64]$columnId,
        [Parameter(ParameterSetName = "single")]
        [ValidateSet("ASCENDING","DESCENDING")]
        [string]$direction = "ASCENDING"
    )

    $Headers = Get-Headers
    $Uri = "{0}/sheets/{1}/sort" -f $BaseURI, $id
    $body = $null
    if ($sortCriteria) {
        $body = $sortCriteria | ConvertTo-Json -Compress
    } else {
        $payload = @{
            sortCriteria = @{
                columnId = $columnId
                direction = $direction
            }
        }
        $body = $payload | ConvertTo-Json -Compress
    }
    try {
        return Invoke-RestMethod -Method POST -Uri $Uri -Headers $Headers -Body $body
    } catch {
        throw $_
    }
    <#
    .SYNOPSIS
    Sort rows in a Smartsheet.
    .DESCRIPTION
    Sort the rows in a smartsheet.
    .PARAMETER id
    Id of the sheet to sort rows in.
    .PARAMETER sortCriteria
    An array of sort criteria objects. The objects should have 2 properties, columnId and direction (ASCENDING or DESCENDING)
    .PARAMETER columnId
    Id of the column to sort on for a single column sort.
    .PARAMETER direction
    The direction of the sort.
    .OUTPUTS
    Sheet object with the results of the sort operation.
    .NOTES
    If you are retrieving the Smartsheet to process the data within powershell it may be easier and more efficient to do the sorting within powershell.

    For Example:

    PS> $Sheet = Get-Smartsheet -sheetId 465987456
    PS> $Data = $Sheet.ToArray() | Sort-Object -Property Name, HireDate.

    .EXAMPLE
    How to create a multi-sort sortCriteria object.
    In this example we are going to sort a Smartsheet of employee salary information by Department and Salary in descending order.
    To create the criteria create an array of hash table object.
    PS> $sortCriteria - @(
            @{
                sortCriteria = @{
                    columnId = $Sheet.columns.Where({$_.title -eq "Department"}).ColumnId
                    direction = "ASCENDING"
                },
                @{
                {
                    columnId = $Sheet.Columns.Where({$_.title -eq "Salary"}).ColumnId
                    direction = "DESCENDING"
                }
            }
        )
    Now sort the sheet.
    PS >$SortedSheet = $sheet | Get-SortedSmartSheet -SortCriteria $sortCriteria
    #>

}

function Send-SmartsheetViaEmail() {
    [CmdletBinding()]
    Param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [Alias('SheetId')]
        [UInt64]$Id,
        [ValidateSet('EXCEL','PDF','PDF_GANTT')]
        [string]$format,
        [ValidateSet(
            "LETTER","A4","LEGAL","TABLOID"
        )]
        [string]$paperSize,
        [Parameter(Mandatory = $true)]
        [string[]]$To,
        [Parameter(Mandatory = $true)]
        [string]$Subject,
        [string]$Message,
        [switch]$ccMe
    )
    Begin {
        $Headers = Get-Headers 
        $sendTo = @()
        $To | ForEach-Object {
            $sendTo += @{email = $_}
        }       
        $properties = [ordered]@{
            format = $format
            sendTo = $sendTo
            subject = $Subject
        }
        if ($formatDetails) {
            $properties.Add("formatDetails", @{paperSize = $paperSize})
        }
        if ($Message) {
            $properties.Add("message", $Message)
        } else {
            $properties.Add("message", " ")
        }
        if ($ccMe) {
            $properties.Add("ccMe", "true")
        } else {
            $properties.Add("ccMe", "false")
        }

        $objBody = [PSCustomObject]$properties
        $body = $objBody | ConvertTo-Json
    }

    Process {
        $Uri = "{0}/sheets/{1}/emails" -f $BaseURI, $id
        try {
            $result = Invoke-RestMethod -Method POST -Uri $Uri -Headers $Headers -Body $body
            if ($result.message -eq "SUCCESS") {
                return $true
            } else {
                return $false
            }
        } catch {
            throw $_
        }
    }
    <#
    .SYNOPSIS
    Send a Smartsheet via Email.
    .PARAMETER Id
    Sheet Id if the sheet to send.
    .PARAMETER format
    Attachment format.
    .PARAMETER paperSize
    Set the page size of the attached document.
    .PARAMETER To
    An array of email addresses to send to.
    .PARAMETER Subject
    .Subject of the email.
    .PARAMETER Message
    Body of the email.
    .PARAMETER ccMe
    Send a carbon copy to the sender.
    #>

}