みなさんこんにちは!ヒロポンです!
Excelマクロ(VBA)で、業務のちょっとした集計や一括処理を回してきた。そういう業務SE、めっちゃ多いですよね。俺もそうでした。
で、それを PowerShell に移そうとすると、最初の壁が配列とハッシュテーブル。Dim arr() As String のノリで書くと、まず動かない。あれ、なんで動かへん??ってなるやつ。powershell 配列 ハッシュテーブル で検索してつまずくのは、だいたいここの構造差なんですよね。
先に結論を言っときます。@()(配列)と @{}(ハッシュテーブル)の2つさえ覚えれば、業務スクリプトはだいたい動く。これだけ。
この記事は、前に書いたVBA → C# 翻訳チートシートの PowerShell 版です。VBA で知ってる書き方を、PowerShell に翻訳していく。コードは Docker 上の PowerShell で実機確認済み。Windows PowerShell 5.1 でも 7 でも同じ挙動でした。
忙しい人向けに最初にまとめ
- 配列は
@()— VBA のDim arr(2) As Stringのような固定長宣言は不要。可変長で、追加は$arr += x。インデックスは VBA と同じ 0 始まり。 - 連想配列は
@{}— VBA のScripting.Dictionary相当。参照設定なしで@{ "key" = value }と書くだけ。 - ループは
ForEach-Objectかforeach— VBA のFor Each相当。PowerShell はパイプライン(|)で流す発想が加わる。
この記事の位置づけ
VBA → C# 翻訳チートシートでは、VBA を C# に移す話を書きました。今回はその別方向。VBA を PowerShell に移す話です。
C# は「がっつりアプリを作る」方向。PowerShell は「Excelマクロでやってた自動化を、もっと手軽に回す」方向です。VBA 勢からすると、実は PowerShell のほうが移りやすかったりする。変わるのは、配列・連想配列・ループの3つの書き方だけなんですよね。
対応マップ — VBA ↔ PowerShell
まず全体像から。VBA でやってたことが PowerShell でどう書けるか、対応表にしました。

右側の @() と @{} と ForEach-Object。この3つさえ押さえれば、VBA の自動化はだいたい移せます。順番に見ていきましょう。
構造差1: 配列 — Dim arr() As から @() へ
VBA の配列は、型と大きさを宣言してから使うのが基本でした。
' VBA: 固定長で宣言してから使う。大きさを変えるなら ReDim
Dim arr(2) As String ' 0〜2 の3要素
arr(0) = "りんご"
ReDim Preserve arr(3) ' 大きさを変えるのに ReDim が要る
PowerShell は、この宣言がいりません。ん?型も大きさも書かんでええの?って最初は不安になるけど、@() で囲むだけ。しかも最初から可変長です。
# 配列は @() で作る。可変長・0始まり・宣言不要
$arr = @("りんご", "みかん", "ぶどう")
$arr += "もも" # 追加は += だけ(ReDim 不要)
Write-Output $arr[0] # りんご(0始まりは VBA と同じ)
Write-Output $arr.Count # 4
ReDim Preserve のあの煩わしさから解放されます。インデックスが 0 始まりなのは VBA と一緒なので、ここは戸惑わない。.Count で件数が取れるのも、いい感じに素直です。
構造差2: 連想配列 — Scripting.Dictionary から @{} へ
VBA で連想配列(キーと値のペア)を使うには、Scripting.Dictionary が定番でした。でもこれ、参照設定(Microsoft Scripting Runtime)を追加しないと使えないのが地味に面倒だった。連想配列1個使うのに参照設定??って、毎回思ってましたよね。
' VBA: 参照設定を追加してから Scripting.Dictionary
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
d("りんご") = 100
PowerShell は、これが最初から @{} として組み込まれてます。参照設定はいりません。
# ハッシュテーブルは @{} で作る(Scripting.Dictionary 相当・参照設定不要)
$ht = @{ "りんご" = 100; "みかん" = 80 }
$ht["ぶどう"] = 300 # 追加もこれだけ
Write-Output $ht["りんご"] # 100
Write-Output $ht.Keys.Count # 3
CreateObject も参照設定もなしで、いきなり連想配列が書ける。VBA で Dictionary の参照設定を忘れてエラー、をやらかした人ほど、この手軽さが効きます。
構造差3: ループ — For Each から ForEach-Object へ
VBA のループは For Each でした。PowerShell でも foreach はそのまま使えるので、ここは移行コストほぼゼロ。
# VBA の For Each 相当。foreach 文はほぼそのまま
foreach ($item in $arr) {
Write-Output $item
}
ただ、PowerShell にはもう一つの発想がある。パイプラインです。配列を | で次の処理に流して、ForEach-Object で1件ずつ捌く。
# パイプラインで流す。$_ が「今の1件」
@("りんご", "みかん", "ぶどう") | ForEach-Object { Write-Output "果物: $_" }
$_ が「今処理してる1件」を指します。最初は戸惑う。でもこれに慣れると、CSV を読んで→絞り込んで→出力、みたいな処理が1行でつながる。Excelマクロで何十行も書いてたのが、パイプ1本で済んだりするんですよね。こんな感じでスッキリ書けるのが、PowerShell の気持ちいいところ。
ミニマム検証 — VBA脳のまま動く最小スクリプト
理屈だけだと不安ですよね。@() と @{} だけで書いた、コピペで動く最小形を置いときます。
# 単価表(ハッシュ)と買い物リスト(配列)で合計を出す
$price = @{ "りんご" = 100; "みかん" = 80; "ぶどう" = 300 }
$cart = @("りんご", "りんご", "ぶどう")
$total = 0
foreach ($item in $cart) {
$total += $price[$item]
}
Write-Output "合計: $total 円" # 合計: 500 円
配列でリストを持って、ハッシュで単価を引いて、foreach で合計する。Excelマクロでやってた集計が、ほぼそのままの発想で書ける。いい感じに VBA の発想が乗るんですよね。@() と @{} の2つ、と言った意味がこれです。
俺も最初は VBA の Dim と ReDim の癖が抜けなくて、無駄にエラー出してました。でも @() と @{} の2つに割り切ってから、Excelマクロ1本を PowerShell に移すのが一気に早くなった。結局、構文の慣れの問題だったんですよね。
ハマりポイント — VBAの癖のまま書くと詰まる所
俺が実際にやらかした順に3つ。
Dimで宣言しようとする: PowerShell にDimはありません。$arr = @()で即作る。VBA の宣言癖が抜けないと、最初ここで止まる。- 要素1個の配列が配列にならない:
$x = @("りんご")は配列だけど、$x = "りんご"だと文字列。1件でも@()で囲むのがコツ。 - ハッシュの順番を期待する:
@{}は基本、入れた順番を保証しません。順番が要るなら[ordered]@{}を使う。VBA の Dictionary 感覚だと、ここでハマる。
まとめ
VBA から PowerShell へ。配列とハッシュの構造差は、突き詰めるとこの3つだけです。
- 配列は
@()— 宣言不要・可変長・0始まり。ReDimから解放される - 連想配列は
@{}— 参照設定不要。Scripting.Dictionaryの手軽版 - ループは
foreachか パイプラインForEach-Object— VBA の発想 + パイプの新発想
逆に言えば、この @() と @{} の2つを覚えるだけで、Excelマクロでやってた自動化は PowerShell にどんどん移せる。別世界じゃないんです。VBA でやってきた経験は、ちゃんと地続きで活きます!!
よくある質問
Q1. VBA の ReDim Preserve は PowerShell でどう書きますか?
書く必要がありません。PowerShell の配列は可変長なので、$arr += "新しい値" で追加できます。ただし += は内部で配列を作り直すので、何万件もループで足すなら [System.Collections.ArrayList] や List を使うほうが速いです。
Q2. @{} の中身を順番どおりに取り出したいです。
通常のハッシュテーブル @{} はキーの順番を保証しません。順番を保ちたいときは [ordered]@{} と書くと、入れた順番が維持されます。CSV を順番どおり出力したい時などに使います。
Q3. PowerShell で Excel ファイルを直接操作できますか?
できます。ImportExcel モジュールを入れると、Excel を開かずに読み書きできます。VBA のように Excel 上でマクロを動かすのではなく、PowerShell スクリプトから Excel ファイルを処理する形になります。まずは CSV での受け渡しから始めると移行が楽です。
Q4. VBA の経験は PowerShell で無駄になりますか?
なりません。配列・連想配列・ループでデータを捌くという発想は、そのまま使えます。変わるのは構文の書き方だけ。むしろ参照設定や ReDim の煩わしさが減って、VBA でやりたかったことがより素直に書けるようになります。
次に読むべき記事
- VBA → C# 翻訳チートシート — この記事の出発点。VBA を C# に移す方向。PowerShell と合わせて移行の地図が揃う
- PowerShell で CSV から AD ユーザーを一括作成する —
@{}と配列を実務で使う応用編。VBA 集計の次のステップ - PowerShell の ErrorAction で踏む3つの落とし穴 — スクリプトが動き出したら次はエラー処理。PowerShell の作法
- C# のコレクション選び — 配列 / List / IEnumerable の使い分け — 配列・ハッシュの考え方を C# 側でも。型の世界の話
- 「客先常駐しかない」と感じてる業務SEへ — VBA だけでなく自動化を1つ持つと、現場での立ち位置が変わる話
VBA から PowerShell に移ろうとしてる同業がいたら、この記事ぶん投げてやってください。どんどんシェア待ってるぜ!!
以上!
執筆者
バイブス父さん — 業務 SE 7 年 (SIer 正社員 2 / フリーランス 5)。現職は SEO 直轄部の AI アドバイザー兼 PL、副業で中小 SIer の CTO。SIer の正社員からフリーランスに転じ、複数のエージェント経由で案件を回してきた経験ベースで「業務 SE 視点」の技術 + キャリア記事を書いています。
🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る


コメント