Private/Convert-VellumPdfSlotText.ps1
|
function Convert-VellumPdfSlotText { <# .SYNOPSIS Turns the values of table cells or list items into the text to draw: number detection, format and culture. .DESCRIPTION Each slot is an object with Value (the raw value), Format ($null or a .NET format string), Parse (whether a string value may be read as a number), Group (a key: strings of one group are evidence for each other, a table column or the whole list) and What (a name for error messages, for example "column 2"). The function sets Text on every slot: * A string that consists only of a number is read as [decimal] (ConvertFrom-VellumPdfNumberText; with -InputCulture strictly by that culture, else detected, with the decimal mark of the group's other values resolving ambiguous ones such as '1,234') and then formatted like any other number. * Everything else is formatted by ConvertTo-VellumPdfText: strings unchanged, IFormattable values with the slot's format and the culture. Ambiguous strings that stay unchanged are named in ONE warning for the whole call. #> [CmdletBinding()] param( [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]]$Slot, [Parameter(Mandatory)] [cultureinfo]$Culture, [AllowNull()] [cultureinfo]$InputCulture, [switch]$NoNumberParsing, [Parameter(Mandatory)] [string]$CommandName ) # Cheap pre-filter so ordinary text never reaches the number functions. $numeric = [regex]::new('^\s*\S?[0-9]') $candidates = [System.Collections.Generic.List[object]]::new() if (-not $NoNumberParsing) { foreach ($slotItem in $Slot) { if ($slotItem.Parse -and $slotItem.Value -is [string] -and $numeric.IsMatch($slotItem.Value)) { $candidates.Add($slotItem) } } } $ambiguous = [System.Collections.Generic.List[string]]::new() foreach ($group in ($candidates | Group-Object { [string]$_.Group })) { $arguments = @{} if ($InputCulture) { $arguments['InputCulture'] = $InputCulture } else { $hint = Get-VellumPdfNumberHint -Text @($group.Group | ForEach-Object { $_.Value }) if ($hint) { $arguments['Hint'] = $hint } } foreach ($candidate in $group.Group) { $number = ConvertFrom-VellumPdfNumberText -Text $candidate.Value @arguments if ($null -ne $number) { $candidate.Parsed = $number } elseif (-not $InputCulture -and (Get-VellumPdfNumberShape -Text $candidate.Value).Kind -eq 'Ambiguous') { if ($candidate.Value -notin $ambiguous) { $ambiguous.Add($candidate.Value) } } } } foreach ($slotItem in $Slot) { $source = if ($null -ne $slotItem.Parsed) { $slotItem.Parsed } else { $slotItem.Value } if ($source -is [string]) { $slotItem.Text = $source; continue } $slotItem.Text = ConvertTo-VellumPdfText -Value $source -Culture $Culture -Format $slotItem.Format -CommandName $CommandName -What $slotItem.What } if ($ambiguous.Count -gt 0) { Write-Warning ("${CommandName}: $($ambiguous.Count) number text(s) are ambiguous and were left unchanged: " + (($ambiguous | ForEach-Object { "'$_'" }) -join ', ') + '. A single separator followed by exactly three digits could be a decimal mark or ' + 'thousands grouping, and no other value in the same column or list shows which. Pass -InputCulture, write the number unambiguously, ' + 'or use -NoNumberParsing to draw text as given.') } } |