xlogI125’s blog

パソコン作業を効率化したい

PowerShell練習 Excelワークシートでの並べ替え用に順序(StrCmpLogicalW)の連番を作成

メモ

範囲C1:C5をコピーする

A B C
1 val11 値0005 =CLEAN(B1)
2 val21 値004 =CLEAN(B2)
3 val31 値02 =CLEAN(B3)
4 val41 値1 =CLEAN(B4)
5 val51 値3 =CLEAN(B5)

使い捨てスクリプトの実行結果を貼り付ける

A B C
1 val11 値0005 5
2 val21 値004 4
3 val31 値02 2
4 val41 値1 1
5 val51 値3 3

貼り付けた番号で並べ替える

A B C
1 val41 値1 1
2 val31 値02 2
3 val51 値3 3
4 val21 値004 4
5 val11 値0005 5

使い捨てスクリプト

# PowerShell 5.1, Windows 11

# [ファイル名]
#  "%USERPROFILE%\Desktop\Sort_Order.ps1"
# [エンコード]
#  UTF-8 (BOM付き)

# [ショートカット(.lnk)]
#  リンク先(T):
#   PowerShell.exe -NoLogo -NoExit -NoProfile -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\Sort_Order.ps1"
#  作業フォルダー(S):
#   ""

using namespace System.Collections.Generic

Set-StrictMode -Version Latest

$a = @(Get-Clipboard -Format Text -TextFormatType UnicodeText)

$null | Set-Clipboard

Write-Verbose @"
`n`$a.Length
$($a.Length)
"@ -Verbose

$b = [List[PSCustomObject]]::new()

# 列方向にセル選択範囲をコピーすると
# クリップボードから取得する配列の要素数が
# 改行の関係でセル選択範囲の個数よりも1つ増える様子。

# 並べ替え前における順番(連番)
for ($i = 0; $i -lt $a.Length - 1; $i++) {
  $b.Add([PSCustomObject]@{
    OrderAfter = -1; 
    OrderBefore = $i + 1; 
    '=CLEAN(string)' = $a[$i]
  })
}

Write-Verbose @"
`n`$b.Count
$($b.Count)
"@ -Verbose

if ($b.Count -eq 0) {
  throw '$b.Count -eq 0'
}

Add-Type -Language CSharp -TypeDefinition @'
namespace Win32Functions {
  using System.Runtime.InteropServices;

  public class Win32StrCmpLogicalW {
    [DllImport(
      "Shlwapi.dll", CharSet = CharSet.Unicode, EntryPoint = "StrCmpLogicalW"
    )]
    public static extern int StrCmpLogicalW(
      [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
      [MarshalAs(UnmanagedType.LPWStr)] string psz2
    );
  }
}

namespace MyNS {
  using System.Collections.Generic;
  using System.Management.Automation;

  public class MyComparer : IComparer<PSObject> {

    private readonly string name = @"=CLEAN(string)";

    public int Compare(PSObject x, PSObject y) {
      string str1 = x.Properties[name].Value.ToString();
      string str2 = y.Properties[name].Value.ToString();
      return Win32Functions.Win32StrCmpLogicalW.StrCmpLogicalW(str1, str2);
    }
  }
}
'@

# 並べ替え
try {
  $b.Sort([MyNS.MyComparer]::new())
}
catch {
  throw $_
}

# 並べ替え後における順番(連番)
for ($i = 0; $i -lt $b.Count; $i++) {
  $b[$i].OrderAfter = $i + 1
}

# 並べ替え前の順番でソート
$c = $b | Sort-Object -Property OrderBefore

Write-Verbose @"
`n`$c
$(Out-String -InputObject $c)
"@ -Verbose

# 並べ替え前における並べ替え後の順番(連番)をクリップボードにコピー
$c.OrderAfter | Set-Clipboard

Write-Verbose @"
`nクリップボードからの貼り付けが上手く出来ない場合は再度コピー
`$c.OrderAfter | Set-Clipboard
"@ -Verbose