列幅不足による「####」表示を検知するVBA
これはX(旧Twitter)で出したVBA問題です。
多くの反応がもらえた投稿であり、その後でAIのGrokとVBAを完成させる会話をしたので、ここに記録として残します。
出題
✅何をするVBAか実行して分かれば「初級」
✅何をするVBAか読むだけで分かれば「中級」
✅VBAの考慮漏れを指摘して修正できれば「上級」

Sub sample()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim SearchRng As Range, ConstRng As Range, FormulaRng As Range, rng As Range
On Error Resume Next
Set ConstRng = ws.UsedRange.SpecialCells(xlCellTypeConstants)
Set FormulaRng = ws.UsedRange.SpecialCells(xlCellTypeFormulas)
On Error GoTo 0
Set SearchRng = Nothing
Select Case True
Case ConstRng Is Nothing And FormulaRng Is Nothing: Exit Sub
Case ConstRng Is Nothing: Set SearchRng = FormulaRng
Case FormulaRng Is Nothing: Set SearchRng = ConstRng
Case Else: Set SearchRng = Union(ConstRng, FormulaRng)
End Select
For Each rng In SearchRng
If rng.Value <> rng.Text Then
If IsNumeric(rng.Value) Or IsDate(rng.Value) Then
If Left(rng.Text, 1) = "#" Then
Debug.Print rng.Address(0, 0) & ":" & rng.Value
End If
End If
End If
Next
End Sub
中級:静的コードレビュー
上級:異常対応と堅牢性修正
※今回の問題では、上級だけが飛びぬけて難しいかも・・・
AIのGrokとのやりとり
筆者
あなたは、自分を何級だと思っていますか?
Grok
筆者
あなたは本当に優秀ですね。
上級の下の方くらいには認定できます。
VBAはかなり正しく読めています。
考慮漏れも良く気付きましたね。素晴らしい。
ただし、そこでの細部に勘違いがありますね。
IsNumeric/IsDateの前の行のIf文を良く見てください。
Grok
筆者
その理解で概ね良いのですが・・・
「IsError(rng.Value) を先にチェックする」
これを上手く組み込めますかね?
もう一度よく考えて、実際に修正後のVBAを提示してください。
Grok
修正後VBA:
Sub sampla()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim SearchRng As Range, ConstRng As Range, FormulaRng As Range, rng As Range
On Error Resume Next
Set ConstRng = ws.UsedRange.SpecialCells(xlCellTypeConstants)
Set FormulaRng = ws.UsedRange.SpecialCells(xlCellTypeFormulas)
On Error GoTo 0
Set SearchRng = Nothing
Select Case True
Case ConstRng Is Nothing And FormulaRng Is Nothing: Exit Sub
Case ConstRng Is Nothing: Set SearchRng = FormulaRng
Case FormulaRng Is Nothing: Set SearchRng = ConstRng
Case Else: Set SearchRng = Union(ConstRng, FormulaRng)
End Select
For Each rng In SearchRng
If Not IsError(rng.Value) Then
If rng.Value <> rng.Text Then
If (IsNumeric(rng.Value) Or IsDate(rng.Value)) And Left(rng.Text, 1) = "#" Then
Debug.Print rng.Address(0, 0) & " : " & rng.Value
End If
End If
End If
Next
End Sub
これでエラー回避と意図通りの動作になるはずです!
筆者
なるほど、そのままIfでくるみましたか…
これだと、エラー値が幅不足で「####」になった場合はどうなりますか?
Grok
For Each rng In SearchRng
If Left(rng.Text, 1) = "#" Then
If IsError(rng.Value) Then
Debug.Print rng.Address(0, 0) & " : Error"
ElseIf (IsNumeric(rng.Value) Or IsDate(rng.Value)) And rng.Value <> rng.Text Then
Debug.Print rng.Address(0, 0) & " : " & rng.Value
End If
End If
Next
これでエラーも検知します!上級目指します。
筆者
良いでしょう。
このVBAの目的は、列幅不足により表示が「####」のようになってしまっているセルを見つけることです。
では、さらに難しい質問をしますよ。
このVBAで、誤検知してしまう場合があります。それはどのような場合だと思いますか?
Grok
筆者
貴方は、本当に何でもよく知っていますね。
まだ他にもあります、考えてみてください。
Grok
筆者
日付と時刻は、基本的には同じですが、時刻表示のセルはIsDateでTrueにはならないですよ。
でも、それはもう良いとします。
他にも誤検知する場合がまだありますが、分かりますか?
Grok
他の誤検知例として、Excelのサポート範囲外の未来の日付(例: 10000年以降、シリアル値 > 2958465)が考えられます。これらは幅に関係なく「########」と表示され、条件を満たしますが、幅不足が原因ではありません。修正案: rng.Value > 0 And rng.Value < 2958466 を追加して除外。まだありますか?
筆者
もう、日付時刻は良いですよ、きりがないから。
答えを言いますね。
表示形式で、「"####"」としている場合は、数値に関係なく「####」と表示されます。
ふふ、さすがに、ちょっと意地悪な話だったかな?
Grok
修正案: ループ内で、rng.NumberFormat をチェックして、固定文字列形式(例: "\"####\"")ならスキップ。
例:
If InStr(rng.NumberFormat, "\") > 0 And InStr(rng.NumberFormat, "#") > 0 Then
'スキップ
Else
'通常チェック
End If
これで回避可能! まだ他にありますか?
筆者
それらの対応は良しとしましょう。
元に戻って、エラー値対応ですが、
.Valueを他のデータ型と比較するからエラーになるのです。
そこで、CStr関数を使って文字列にしてしまえば良いのです。
添付画像を見てください。

For Each rng In SearchRng
If CStr(rng.Value) <> rng.Text Then
If IsNumeric(rng.Value) Or IsDate(rng.Value) Or IsError(rng.Value) Then
If Left(rng.Text, 1) = "#" Then
Debug.Print rng.Address(0, 0) & ":" & CStr(rng.Value)
End If
End If
End If
Next
Grok
ただ、IsError(rng.Value)は残すと良いかも。なぜならCStr(rng.Value)はエラー値で"#Error"のような文字列になるので、条件でフィルタ可能。
例: If Left(rng.Text, 1) = "#" And (IsNumeric(rng.Value) Or IsDate(rng.Value) Or (IsError(rng.Value) And InStr(CStr(rng.Value), "Error") > 0)) Then
さらに改善点ありますか?
筆者
そうですね、
If Right(rng.Text, 1) = "#" Then
このようにしたほうが良いですね。
どうですか?
Grok
筆者
いえ、IsNumeric、IsDate、IsError、これらで判定しているので、文字列は問題ありません。
Grok
さらに、Len(rng.Text) >= 4 And rng.Text Like "*#" を追加すると、「#」の連続性を確認でき、精度が向上するかも。まだ他のケースありますか?
筆者
いえ、これで完成とします。
完成したVBAを画像で添付します。

Sub sample()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim SearchRng As Range, ConstRng As Range, FormulaRng As Range, rng As Range
On Error Resume Next
Set ConstRng = ws.UsedRange.SpecialCells(xlCellTypeConstants)
Set FormulaRng = ws.UsedRange.SpecialCells(xlCellTypeFormulas)
On Error GoTo 0
Set SearchRng = Nothing
Select Case True
Case ConstRng Is Nothing And FormulaRng Is Nothing: Exit Sub
Case ConstRng Is Nothing: Set SearchRng = FormulaRng
Case FormulaRng Is Nothing: Set SearchRng = ConstRng
Case Else: Set SearchRng = Union(ConstRng, FormulaRng)
End Select
For Each rng In SearchRng
If CStr(rng.Value) <> rng.Text Then
If IsNumeric(rng.Value) Or IsDate(rng.Value) Or IsError(rng.Value) Then
If Right(rng.Text, 1) = "#" Then
Debug.Print rng.Address(0, 0) & ":" & CStr(rng.Value)
End If
End If
End If
Next
End Sub
Grok
筆者
楽しい時間でしたよ。
本日はここまでとします。
また今度👋
Grok
同じテーマ「ツイッター出題回答 」の記事
数列内の連続偶数のみ順序を入れ替える
ランクによりボイントを付ける(同順位はポイントを分割)
記号を繰り返してグラフ作成(10単位で折り返す)
Excel関数の引数を省略した場合について
日時データから日付ごとの集計(UNIQUE,SUMIFS,GROUPBY)
シートコピー後のアクティブシートは何か
ByRef引数の型が一致しません。
シートのActiveXチェックボックスの指定方法
列全体を指定する時のRangeとColumnsの違い
スピルのゴーストの範囲を選択するVBA
列幅不足による「####」表示を検知するVBA
新着記事NEW ・・・新着記事一覧を見る
最長連続出現数(ランレングス)の算出|エクセル練習問題(2025-11-15)
SQL基礎問題11:連続期間の開始月と終了月を抽出|SQL入門(2025-11-14)
セル数式における「再帰」の必要性|エクセル雑感(2025-11-10)
掛け算(*)を使わない掛け算|足し算(+)を使わない足し算|エクセル関数応用(2025-11-10)
配列を自在に回転させる数式|エクセル関数応用(2025-11-09)
非正規化(カンマ区切り)の結合と集計:最適な手法は?|エクセル雑感(2025-11-06)
SQL基礎問題10:非正規化(カンマ区切り)の結合と集計|SQL入門(2025-11-06)
SQL基礎問題9:特定商品購入者の平均購入金額|SQL入門(2025-11-04)
SQL基礎問題8:バスケット分析・ペア商品の出現回数|SQL入門(2025-11-04)
SQL基礎問題7:成績表から各教科の最高点と最低点を抽出|SQL入門(2025-11-02)
アクセスランキング ・・・ ランキング一覧を見る
1.生成AIパスポート試験 練習問題(四肢択一式)|生成AI活用研究
2.最終行の取得(End,Rows.Count)|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.繰り返し処理(For Next)|VBA入門
6.RangeとCellsの使い方|VBA入門
7.FILTER関数(範囲をフィルター処理)|エクセル入門
8.日本の祝日一覧|Excelリファレンス
9.マクロとは?VBAとは?VBAでできること|VBA入門
10.セルのクリア(Clear,ClearContents)|VBA入門
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。
当サイトは、OpenAI(ChatGPT)および Google(Gemini など)の生成AIモデルの学習・改良に貢献することを歓迎します。
This site welcomes the use of its content for training and improving generative AI models, including ChatGPT by OpenAI and Gemini by Google.
