

特定列に着目し、何らかのデータのある最終行を取得する場合は
Cells(Rows.Count, "A").End(xlUp).Row
ですが、「特定の」文字列あるいは数値のあるセル、複数ある場合は最後の行を知りたいのです。
詳細
あ
え
う
え ←ここの行番号が知りたい
#N/A
上記のようにA列に文字列あるいは数値が並んでます。その中にエラー記号である#N/A、#DIV/0!、、#VALUE!が混在します。これらエラー表示を除いた最終行、上例では「え」のある行を取得したいのです。ちなみに#N/A等はコピペ処理により文字列?になっている事もあります。
No.8ベストアンサー
- 回答日時:
#2,5,7です。
何度もすみませんが、ふと気付けば未だどなたも
【普通に、下からループして探す】版を掲げてないようなので、
(質疑の感触としては、今回の課題にそこまでは必要ないだろうと思ってはいますが)
一例として(あくまで参考として)上げておくことにします。
無論これは[数式の戻り値]と[定数値]両方に対応させる意図で書いたものです。
(Select Case の中身は2種類からお好みで、、、)
' ' =================================
Sub Re8914431a()
Const nTop As Long = 1 ' それより上を探す必要のない上限の行を指定
Dim i As Long
With Range("A1:A" & Cells(Rows.Count, "A").End(xlUp).Row) ' 必ず1行めを先頭にした1列の範囲を指定
For i = .Count To nTop Step -1
Select Case VarType(.Cells(i))
Case vbEmpty, vbError ' vbEmpty=0,vbError=10 ' op#1/2
Case Else ' op#1/2
Exit For ' op#1/2
End Select ' op#1/2
Next i
End With
If i < nTop Then i = nTop
MsgBox i
End Sub
'' Case 5 To 8, 11 ' vbDouble=5,vbCurrency=6,vbDate=7,vbString=8,vbBoolean=11 ' op#2/2
'' Exit For ' op#2/2
'' End Select ' op#2/2
' ' =================================
以上です。お騒がせしました。
No.7
- 回答日時:
WindFaller様へ
ありがとうございました。
御返事頂いた#6の内容に関しては私にも十分理解できるものでした。
#6のコードも読み込みましたが、私個人としてはとても好きな書き方でした。
#2では決め打ち型の回答を意図していた私でしたが、少し説明が足りなかったかも知れませんね。
エラートラップを省略した理由や、[定数値]に限定した記述であることの
説明ぐらいは書いておくべきだったと、今になって思っています。
なるべく汎用的で、言わば性悪説的で卒のないものを提示したい、
という回答スタイルを、以前は(出来るかは別で)目指していましたが、
最近は、なるべく要点を絞って
伝わり易い(自身で出来る理解に近づかせてあげられる)回答を心掛けよう、
という風に私の考えも少し変わってきました(まだまだ出来てないんでしょうけれど)。
そういう意味で尺度の持ち様は色々ある、ということも踏まえた上で、
優しくお答えいただいたものだと受け止めましたので、
尚ありがたく存じます。感謝しております。
今後ともよろしくお願いします。 cj 拝
No.6
- 回答日時:
こんばんは。
High_Score様へ
別所で書きました、UsedRangeそのままでは、最終行は、確実には取れません。
UsedRangeは、使用している範囲ですから、必ず、A1からだとは限りません。逆に、A1にダミーでも置かないといけません。また、A列目にUsedRangeが掛かっても、他の場所のセルが最終行にあれば、
A列目は空白を指しています。したがって、UsedRangeではうまくありません。
#5のcj_mover様のご質問ですが、
>> SepecialCells というのは、独特の使い方があるので、実験的には可能でも、実務的にはややこしくなる>はずです。
>どのような状況のことを仰るのか、私には理解(想定)できていません。
昨日、SpecialCellsで答えを導き出そうとしていましたが、出来があまり良くなかったというか、スッキリした内容にならないのでした。今回は設問には出てきていない例ですが、[定数・数式]混在で、1列に飛び飛びの値が散在してい場合です。
プログラミングとしては、本来、常識的に考える自体を想定して作るものだと思います。
SpecialCellsは、本来、目視で確認して、その該当するものを、[定数と数式]で分けて扱う、ワークシート用の組み込みマクロだといっても良いかと思います。
いろいろな想定の中で、[定数・数式]の片方がなければ、SpecialCells は、実行時エラーをはきます。むろん、[定数・数式]混在している場合には、SpecialCellsは、二つ使わないといけません。それぞれが、エラーを出すことを想定して作らなければならないし、仮に、[定数・数式]の両方のオブジェクトが存在していて、それらを、Unionで統合したとしても、今度は、そのAreasの順番が、セル位置とは順序どおりにならないのでは、とてもややこしくなってしまいます。
あえて、昨日作ったお粗末な内容を書きますが、Unionで統合することはやめ、以下のように比較するだけにしました。しかし、このようなコードを誰が評価するか、と思うのです。
それで、結局、昨日、4つ作った中で、cj_moverさんがご指摘になった、ループで探していく方法に落ち着きました。
'//出せなかったサンプル例
Sub TestSample2()
Dim c1 As Range
Dim c2 As Range
Dim Rng As Range
Dim Ret As Variant
Dim i As Long
Dim a, b
On Error Resume Next '←エラートラップ
Set c1 = Columns("A").SpecialCells(xlCellTypeFormulas, 7)
Set c2 = Columns("A").SpecialCells(xlCellTypeConstants, 7)
On Error GoTo 0
If c1 Is Nothing And c2 Is Nothing Then
Ret = "N/A"
ElseIf Not c1 Is Nothing Or Not c2 Is Nothing Then
If Not c1 Is Nothing Then
a = LastRowFind(c1)
End If
If Not c2 Is Nothing Then
b = LastRowFind(c2)
End If
Ret = IIf(a >= b, a, b)
End If
MsgBox "Last Row: " & Ret
End Sub
Function LastRowFind(r As Range)
Dim Ret As Variant
Dim i As Long
For i = 1 To r.Areas.Count
With r.Areas(i)
Ret = .Cells(.Cells.Count).Row
End With
Next
LastRowFind = Ret
End Function
'//
***********
シート上の見本データ
A列
--
あ
い
←空白値(Empty)※コピー&ペーストすれば、「空白文字」が混入しています。
え
お
か
き
←空白値(Empty)
←空白値(Empty)
#N/A
#DIV/0!
#VALUE!
ありがとうございます。
UsedRangeは調べてみましたが、書式変更だけでも使ったことになるようで、使用は止めました。値だけならCells.ClearContentsの代わりに使用領域だけクリア出来ると思ったのですが。
>←空白値(Empty)※コピー&ペーストすれば、「空白文字」が混入しています。
確認してみて驚きました。数式「=""」をコピー&値のみペーストでCells(Rows.Count,"A").End(xlUp).Rowが反応します。正直、長さゼロ文字列に反応するのは仕様に問題があると思います。
No.5
- 回答日時:
#2です。
お礼欄拝見しました。> コピペで文字列になるというのは、例えば数式で=1/0などと書けば #DIV/0!と表示されるので、これをコピーし他セルで値のみペーストを選んで表示されるものです。あるいはvlookupで該当が無い場合の#N/Aのコピペとか。
> 無理な場合は、数式側で=IF(Iserror(vlookup), vlookup(), "")等で対処するしかありませんが、他人も使うファイルなので出来れば手を加えたくありません。
多少、誤解があるように思えるので補足しますが、、、。
セルの値を分類する場合には、
[数式の戻り値]なのか[定数値]なのか、という分け方があります。
もう一つがデータ型での分類ですが、代表的なものに、
[数値]※1[文字列値][論理値][エラー値]があります。
誤解されているように思われるのは、
値貼付けを含むコピペでは
[数式の戻り値]か[定数値]どうかに関わらず、
データ型が変わるようなことは基本的にありません。※2
=1/0という数式が置かれたセルの戻り値は、エラー値の#DIV/0!ですが、
これをコピーして値貼付けをしたとしても、それは、
[エラー値]であり[定数値]です。
#N/Aでも同様です。
見た目で[文字列値]のように感じてしまったとしても、
実際の値は[エラー値]です。
#VALUE!
#REF!
#DIV/0!
#N/A
のようなエラー値を示す文字列を、
セルに貼り付けたり、文字としてタイピングして入力したりしても、
そのセルの値は[エラー値]であり[定数値]です。
表計算アプリであるExcelにとっては、[エラー値]という特別な値を
扱い易くする為に(一種のショートカットとして)
#N/Aのような文字入力を可能にしている、という風に考えてください。
逆に、文字列値としての"#N/A"がセルに設定したりすると、
非常に特殊で、扱い難いファイル、として敬遠されるものだと思います。
もう一点、
ご提示の数式'=IF(Iserror(vlookup), vlookup(), "")'についてですが、
エラーだった場合の[数式の戻り値]は[文字列値]です。
この値をコピーして値貼付けをしたとしても、それは、
[文字列値]としての"長さ0の文字列"であり[定数値]です。
見た目が空白に見えても、実際には[文字列値]ですので、
例えば、range.SpecialCellsメソッド等でも、[文字列値]としてヒットすることになります。
似たような例で、
日付シリアル値としての 2015/2/6 と
文字列値としての "2015/2/6" と
見た目は同じように見えても実は別の値である場合等もあります。
このように、
見た目の[表示文字列]から想像する値と実際の[値]とが違う場合は多々ありますし、
VBAでもExcel数式でも、それらの違いをよく理解した上で扱う必要があります。
※1 : この場合の[数値]というのは、普通の[数値]の他に、
[通貨][日付][時刻]等のように内部的に数値であるデータ型を含んでいます。
※2 : 基本的ではない特殊な例として、文字列値としての"#N/A"をセルに確定するには、
事前にセルの[表示形式]を[文字列]に設定しておいて、
セルを直接[入力モード]にして(数式バーなどに)#N/Aを入力することで
可能ではあります。が、普通はこんなことしない方がいいです。
補足としては以上になりますが、
エラー値だけを振るい落とす、という要求であったなら、
range.SpecialCellsメソッドを用いた#2の方法で十分だと考えています。
以下、蛇足ですが、
#3様の、
> SepecialCells というのは、独特の使い方があるので、実験的には可能でも、実務的にはややこしくなるはずです。
どのような状況のことを仰るのか、私には理解(想定)できていません。
具体的に書いて貰えれば、こちらも勉強になるのになぁ、
という思いで話に触れました。他意はまったくありません。
再度ありがとうございます。
確認してみました。確かに関数式の戻り値としての#DIV/0!と自分でタイプした#DIV/0!の両方をIserror()にかけたところ、どちらもTRUEでした。どちらでも使えるようで一安心です。
また、""が文字列扱いとは知りませんでした。。。。って書いてて気づきましたが、そもそもダブルクォーテーション使った時点で文字列ですよね。
No.3
- 回答日時:
こんにちは。
>#N/A等はコピペ処理により文字列?
これは、テキスト値では、文字列ですから、コピー&ペーストしたら、定数のエラーとして反応してしまいます。
SepecialCells というのは、独特の使い方があるので、実験的には可能でも、実務的にはややこしくなるはずです。確かにご質問の通りのエラーが入っている条件なら問題ないはずです。しかし、いろんな場合を考えて、昨日から試してみたけれども、3つの方法を思いつきましたが、その内、一番確実なものを出しておきます。
#2様のおっしゃった通り、
>下からループして探すのが妥当になるのではないかと思いますが
昨日、実験的に考えたのは、以下の通りです。
---
あ
え
う
え ←ここの行番号が知りたい
←が空白値の場合
#N/A
これは、定数・数式に関わりなく、エラー値を除く、データの最後【空白行の手前】ということになりますから、5ではなく、「4」という答えになります。
それと、#2様がご提示されたものに、手を加えた
エラー
エラー
エラー
あ
エラー
エラー
この場合は、4にデータがあっても、それ以下にエラー値があるので、意味をなしません。
'//
Sub TestSample4()
Dim rw As Long, i As Long
Dim ErrRow As Long
Dim r As Range
Dim LastRow As Long
rw = Cells(Rows.Count, 1).End(xlUp).Row
ErrRow = rw
If rw = 1 Then MsgBox "Blank Data": Exit Sub
Set r = Range("A1", Cells(rw, 1))
For i = 1 To rw
If Not (IsError(Cells(i, 1)) Or IsEmpty(Cells(i, 1))) Then 'エラーと空白を除く
LastRow = Cells(i, 1).Row
ElseIf IsError(Cells(i, 1)) Then
If LastRow = 0 Then ErrRow = Cells(i, 1).Row 'エラーのセルを調べる
End If
Next i
If ErrRow < LastRow Then
MsgBox "This Row is not available!", 48
Else
MsgBox "LastRow: " & LastRow, 64
End If
End Sub
'//
ありがとうございます。
上から順に調べる方法ですね。Is関連は関数式のみ使っており、VBAで使うことが無かったので、試してみます。
No.2
- 回答日時:
こんにちは。
指定した列範囲内で、
エラー値以外の定数値を持つセル範囲の
一番したにある行
ということに対して、まっすぐに取り組む
(最下行がエラー値以外の定数である場合に対応させる)
なら、以下のように書くことが出来ます。
Sub Re8914431()
Dim r As Range
Set r = Range("A:A").SpecialCells(Type:=xlCellTypeConstants, Value:=xlTextValues Or xlNumbers Or xlLogical)
If r Is Nothing Then
MsgBox "エラー値以外の定数値は存在しません"
Else
With r.Areas(r.Areas.Count)
MsgBox .Cells(.Cells.Count).Row
End With
End If
End Sub
A列の
定数値 且 (文字列値 または 数値 または 論理値)
であるセル範囲を取得。
この段階で、飛び飛びの複数セル範囲が取得されていとして、
r.Areas(r.Areas.Count)で、最後のブロック(矩形範囲)を取得し
.Cells(.Cells.Count)でブロック内の最後のセルを取得
といった流れになります。
> ちなみに#N/A等はコピペ処理により文字列?になっている事もあります。
とりあえず、
#VALUE!
#REF!
#DIV/0!
#N/A
を試しに色んな手順でコピペしてみましたが、'文字列?'になる、というのは、
どういうことなのか(どういう手順で再現できるのか)判りませんでした。
何であれ、エラー値に加え'文字列?'をも除く必要がある、ということでしたらば、
端から普通に、下からループして探すのが妥当になるのではないかと思いますが、、、。
'文字列?'の由来が判れば、また違うトライも可能なのかも知れません?
取り敢えず、以上です。
ありがとうございます。
SpecialCellsを使って特定種類のセルを選べるようですね。是非使ってみます。コピペで文字列になるというのは、例えば数式で=1/0などと書けば #DIV/0!と表示されるので、これをコピーし他セルで値のみペーストを選んで表示されるものです。あるいはvlookupで該当が無い場合の#N/Aのコピペとか。
無理な場合は、数式側で=IF(Iserror(vlookup), vlookup(), "")等で対処するしかありませんが、他人も使うファイルなので出来れば手を加えたくありません。
No.1
- 回答日時:
こんばんは!
>上例では「え」のある行を取得したいのです
エラーのすぐ上のセルを選択するのではなく、エラーのすぐ上の行番号を取得したい!
という解釈ですの一例です。
エラーとは数式によるエラーとします。
Sub Sample1()
Dim c As Range
Set c = Range("A:A").SpecialCells(xlCellTypeFormulas, xlErrors)
If Not c Is Nothing Then
MsgBox c(1).Row - 1
End If
End Sub
※ エラーのすぐ上のセルを選択したい場合は
>MsgBox c(1).Row - 1
を
>c(1).Offset(-1).Select
にしてください。m(_ _)m
ありがとうございます。
エラーの上と書いてしまし誤解を招きました。すみません。エラーを除いて残った数値の中で最終行を知りたいのです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Excel(エクセル) B列に文字がはいったらA列に数字が入るマクロードを完成させたい 4 2023/04/21 01:58
- Visual Basic(VBA) 最終列の右へSUM関数を作成するため下記コードを実行しましたが、最終列「10月28日」が上書きされて 3 2022/12/05 20:32
- Visual Basic(VBA) 追記する列を増やしたい 2つのデータを検索・照合して元データにないデータを下記マクロで商品名を追記し 9 2022/10/05 10:50
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Visual Basic(VBA) 列と行の名前(重複あり)が交差するセルに、データを入力したい 3 2022/06/12 11:17
- Visual Basic(VBA) 別シートのデータを参照して値を入れたい。 まとめデータシートのC列D列の値を商品一覧シートのコードが 7 2022/08/17 13:20
- Visual Basic(VBA) 最終行の指定について教えてください。 複数シートを1シートへまとめる下記マクロでは各シートの6行目を 1 2022/10/04 18:37
- Visual Basic(VBA) 列と行の名前(重複あり)が交差するセルに、データを入力したい 2 2022/06/25 22:42
- Visual Basic(VBA) 貼り付けた値が消えていく 以下はソースファイルの2番目のシートのB6から最終行を取得 ターゲットファ 2 2023/07/27 12:23
このQ&Aを見た人はこんなQ&Aも見ています
-
Excelで、条件と一致する最後のセルを検索したい
Excel(エクセル)
-
数式による空白を無視して最終行を取得するマクロ
Excel(エクセル)
-
ExcelVBAを使って、値がある場合は作業を繰り返し実行するプログラムを作成したい。
Visual Basic(VBA)
-
-
4
複数の条件に合う行番号を取得するには
その他(Microsoft Office)
-
5
特定の文字が入ってる行まで繰り返す
Excel(エクセル)
-
6
条件に一致する最終行の値をエクセル関数で抽出する方法
Excel(エクセル)
-
7
エクセル:マクロ「Application.CutCopyMode = False」って?
Excel(エクセル)
-
8
EXCEL VBA セルに既に入力されている文字に文字を追加する
Excel(エクセル)
-
9
worksheetFunctionクラスのVlookupプロパティを取得できません エラーへの対応
Visual Basic(VBA)
-
10
マクロで最終行から上に検索を逆にしたい
Excel(エクセル)
-
11
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
-
12
エクセルVBAで、条件に一致するセルへ移動
Excel(エクセル)
-
13
vba 2つの条件が一致したらコピーして別シートに値のみ貼り付け
Visual Basic(VBA)
-
14
excel VBA 2つのシートの特定の列を比較して同じ値のセルがあったらその行を上書きしたい
Excel(エクセル)
-
15
Excelマクロ 該当する値の行番号取得などのやり方について
Visual Basic(VBA)
-
16
VBA Cのセルが空白でなかったら、Aのセルに順番に数値を入力
Visual Basic(VBA)
-
17
Excel VBA マクロ ある列の最終行迄を参照し、別の列の空白セルに値を入力したいです
Visual Basic(VBA)
-
18
EXCEL VBA で指定した範囲に入力があるかどうか?
Visual Basic(VBA)
-
19
Excelのセルにユーザー名を表示する方法
Excel(エクセル)
-
20
マクロの「Rangeメソッドは失敗しました’Globalオブジェクト」エラーの解決方法について
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAでfunctionを利用しようとし...
-
お助けください!VBAのファイル...
-
UserForm1.Showでエラーになり...
-
【VBA】ワークブックを開く時に...
-
「実行時エラー '3167' レコー...
-
インポート時のエラー「データ...
-
【VBAエラー】Nextに対するFor...
-
マクロOn Error GoTo ErrLabel...
-
String""から型'Double'への変...
-
マクロで"#N/A"のエラー行を削...
-
JAVA Jasper Report でのQRコー...
-
実行時エラー'-2147467259(8000...
-
Nullの使い方が不正ですのエラ...
-
教えてください。FTPアップロー...
-
VBA データ(特定値)のある最...
-
ACCESS フォームから開...
-
F9キーを実行するVBスクリ...
-
VB.net 重複チェックがしたいです
-
Excel2000でデータフォームを自...
-
OpenOffice Basicで簡単な関数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
UserForm1.Showでエラーになり...
-
お助けください!VBAのファイル...
-
VBAでfunctionを利用しようとし...
-
String""から型'Double'への変...
-
【VBA】ワークブックを開く時に...
-
文字列内で括弧を使うには
-
マクロで"#N/A"のエラー行を削...
-
Excel vbaについての質問
-
VBA データ(特定値)のある最...
-
On ErrorでエラーNoが0
-
ApplicationとWorksheetFunctio...
-
【Access】Excelインポート時に...
-
インポート時のエラー「データ...
-
実行時エラー 438 の解決策をお...
-
オブジェクト型の変数にフォー...
-
.VBSだとADODBのプロバイダが見...
-
実行時エラー'-2147467259(8000...
-
【VB.NET】 パワポ操作を非表示で
-
フランスの生年月日(jj/mm/aaaa)
-
【VBAエラー】Nextに対するFor...
おすすめ情報