1

I'm getting some odd behavior from Excel's Cells.Find() method:

Variable I'm searching on:

PS > $volumename
vol_01       

PS > $volumename.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                            
-------- -------- ----                                     --------                                                                                                                                            
True     True     String                                   System.Object 

produces no results:

PS > $sheet.Cells.Find($volumename).Row

but if I manually copy and paste the value of that variable:

PS > $volumename = "vol_01"
PS > $volumename.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                            
-------- -------- ----                                     --------                                                                                                                                            
True     True     String                                   System.Object 

Gets the value I am expecting:

PS > $sheet.Cells.Find($volumename).Row
198

They appear to be exactly the same type in every way to me. This doesn't happen for every case. Some volume names passthrough fine while others do not. I did scrub the volume name for this post as it has a customers naming convention. It is the same format as above and the same format as the volume names that work.

4
  • How did you manage opening a powershell terminal within an Excel sheet? Commented Oct 4, 2018 at 13:18
  • I'm not. I'm opening the excel sheet in powershell. Commented Oct 4, 2018 at 13:21
  • Use [int[]] [char[]] 'hello' | % { '0x{0:x} {1}' -f $_, [char] $_ } to inspect the string for hidden control characters. Commented Oct 4, 2018 at 13:25
  • @mklement0, Interesting. I am seeing some extraneous invisible characters at the end of the string with hex code 0xa0. How would I trim that off? string replace? Commented Oct 4, 2018 at 13:31

1 Answer 1

3

The following snippet can be used to inspect a string for hidden control characters:

PS> & { [int[]] [char[]] $Args[0] | 
      % { '0x{0:x} [{1}]' -f $_, [char] $_ } } "vol_01`n"

0x76 [v]
0x6f [o]
0x6c [l]
0x5f [_]
0x30 [0]
0x31 [1]
0xa [
]

The first column is each character's Unicode code point ("ASCII code"), and the second column the character itself, enclosed in [...]

Note that I've added "`n" at the end of the string - a newline character (U+000A) - whose code point expressed as a hex. number is 0xa.

If, as in your case, the only unwanted part of the string is trailing whitespace, you can remove it as follows:

$volumename.TrimEnd() # trim trailing whitespace

In your case, the trailing whitespace is 0xa0, the NO-BREAK SPACE (U+00A0), which .TrimEnd() also removes, as Tom Blodget points out.


Simple function wrapper based on the above, for use with pipeline input:

filter debug-Chars { [int[]] [char[]] $_ | % { '0x{0:x} [{1}]' -f $_, [char] $_ } }

Sample use:

"vol_01`n" | debug-Chars

A more sophisticated function, named Debug-String, is available as an MIT-licensed Gist: It uses PowerShell's own escape-sequence notation to represent control characters in the input string, and also visualizes spaces as · by default; adding -UnicodeEscapes uses escape sequences for all non-ASCII-range characters.

Here's an example that first downloads and defines the function:

# Download and define the Debug-String function.
# NOTE: 
#  I can personally assure you that doing this is safe, but you
#  you should always check the source code first.
irm https://gist.github.com/mklement0/7f2f1e13ac9c2afaf0a0906d08b392d1/raw/Debug-String.ps1 | iex

"A b`nThis is a hyphen: '-', this is an en dash '–'" | Debug-String -SingleLine

Output:

screenshot

Sign up to request clarification or add additional context in comments.

2 Comments

The codepoint in question is U+00A0 NO-BREAK SPACE. .Trim() and TrimEnd() do remove it, too. Also, a PowerShell char is a UTF-16 code unit, not a Unicode codepoint (just like in the rest of .NET and many other environments since VB4 and Java). U+00A0 needs one UTF-16 code unit [char]0x00a0
Thanks for the NO-BREAK SPACE correction, @TomBlodget - I've updated the answer accordingly. As for code point vs. code unit. True, PowerShell chars. are UTF-16 code units, but every code unit is also a Unicode code point. But not every code point by itself is a Unicode character (and thus not every .NET character is necessarily a full Unicode character).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.