dポイントプレゼントキャンペーン実施中!

セルA7から下へ向かってデータが入っています。その数をセルA1に入れたいと思い、

  「 Cells(1, 1) = Range("a7", Range("a7").End(xlDown)).Rows.Count 」

こんなマクロを書きました。出展は
 「 http://park7.wakwak.com/~efc21/cgi-bin/exqaloung … 」です。


ここで、下記のようなデータを入れて試してみました。()内が期待する値で、[]内が実際の値です。


       <テスト1> <テスト2> <テスト3> <テスト4> <テスト5>
セルA7           あああ    あああ           あああ 
セルA8                  いいい    いいい    いいい 
セルA9                         ううう        
セルA10                                   
セルA11                               おおお
-----------------------------------------
期待する値     0      1      2      0      2
実際の値  65530  65530      2      2      2


と、このように期待する値が得られません。何が間違っているのでしょうか。
丸1日考えているのですが原因が分かりません。よろしくお願いします。
(文字幅がおかしくて見にくいと思いますがよろしくお願いします)

A 回答 (4件)

こんにちは。



正しいとか間違っているというよりも、「期待する値」に、特別な法則を持っている、と思います。

Cells(1, 1) = Range("a7", Range("a7").End(xlDown)).Rows.Count
End プロパティは、値のあるセルを下に向かって探せ、ということです。だから、A7 から、その下を最後まで探して、その行数を出せ、ということでは、意味が違いますね。

質問者さんの直感なのでしょうか、「期待する値」の求め方は、関数タイプですね。「最初の空白行を探せ」ということですね。

関数なら、こうなります。

=MATCH(TRUE,INDEX(ISBLANK(A7:A100),,),0)-1

7行目より手前か、引数の範囲の外に数式を置いてください。循環参照になります。
もちろん、この数式をマクロに代入しても構いませんが、少し工夫が必要です。

以下のマクロと比較すると、上記の数式に軍配が上がりそうですね。Excelのワークシートはマクロよりも難しいですね。

'------------------------------------

Sub Test1()
  Dim i As Integer
  Dim ret As Long
  Const col As Integer = 5
  '書き出す行...15 行目
  Cells(15, col).Resize(, 5).ClearContents
  For i = 1 To col
    ret = spBlankRow(Cells(7, i)) '7行目から
    Cells(15, i).Value = ret - 7
  Next
End Sub
Function spBlankRow(rng As Range) As Long
Dim r As Range
  On Error Resume Next
  Set r = Range(rng, Cells(Rows.Count, rng.Column)).SpecialCells(xlCellTypeBlanks)
  On Error GoTo 0
  spBlankRow = r.Cells.Cells(1).Row
End Function


ちょっと言い訳:
最初、ユーザー定義関数だけで作ろうと思いましたが、SpecialCells で範囲を認識させるには、コマンドに命令を与える信号が必要ですが、ユーザー定義だけでは、そのコマンドに命令が与えられないので、プロシージャ型になっています。
    • good
    • 1

#3の回答者です。



「#1 のお礼」に対するレス

Range("A7").End(xlDown) というのは、

A7にカーソルを置いて、Ctrl + ↓ という結果と変わらないということです。
次の下のセルから、値の入っているセルを探しているわけです。

バグではないのですが、VBAをいつも使っている者からすると、ワークシートの仕様を映しているだけだとしか言いようがありません。VBA全体を体系的に、Office, Excel, VBAという三つに分かれます。その中で、Excel の仕様だけ、とって付けたような感じがしますし、その分、難しい問題が表れてきます。

しかし、そっくり同じだとは言えない部分も持っています。例えば、JIS関数やCODE関数が、VBAでは、そのまま使えません。

他にもいくつかありますが、今回の #3 の
範囲.SpecialCells(xlCellTypeBlanks)

も、この範囲を、同じ列の最後の行まで指定しても、
範囲.SpecialCells(xlCellTypeBlanks).Select

Select される範囲は、認識できる最後の行までなので、数行しかないことが分かるはずです。
    • good
    • 0
この回答へのお礼

解説ありがとうございます。

「Ctrl + ↓ という結果と変わらない」と言うことで、いろいろやってみました。

「値のあるセルを下に向かって探せ」というより、「値のないセルから値のあるセルに変わるセルを下に向かって探せ」という感じですね。電気回路で言うところの立ち上がりエッジを探すようなイメージですね。

解説を読んで意味がわかってきました。

私がバグではないかと思ったのは、いろいろ方法を探す中で、
「指定行から空白セルまでの行数を数えるには?」という質問に対する回答が「Range("A7", Range("A7").End(xlDown)).Rows.Count」だったり、
「xldownで探すと空白行で止まってしまうから、一番下からxlupで上に向かって探せ」
などの説明を読んでそれなりに納得していたからでした。


おかげさまですっきりしました。
また、「=MATCH(TRUE,INDEX(ISBLANK(A7:A100),,),0)-1」もすばらしいです。似たような所まで行ったのですができませんでした。

お礼日時:2008/12/31 16:57

Sub test()


Dim i, ii As Integer
i = 0
Do While Cells(i + 7, "a").Value <> ""
i = i + 1
Loop
Cells(1, "a").Value = i
End Sub

do ~ loop を使用しました
    • good
    • 0
この回答へのお礼

マクロまで書いて頂いてありがとうございます。
でも、下の方でも書きましたが、一番知りたいのは原因なんです。
マクロを書けば簡単なんですが、できれば関数だけで何とかなりませんでしょうか。

お礼日時:2008/12/31 10:57

とりあえずベタに



Sub Macro2()
Dim idx As Long
 For idx = 7 To 65536
  If Cells(idx, "A").Value = "" Then
   Cells(1, 1).Value = idx - 7
   Exit For
  End If
 Next idx
End Sub

Range("A7").End(xlDown)では
 7行目 ああああ
 8行目 (空白)
 9行目 いいいい
のときは9行目を示しますから使いにくいのではないでしょうか
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>のときは9行目を示しますから使いにくいのではないでしょうか
これですが、

 7行目 ああああ
 8行目 (空白)
 9行目 いいいい

のときは「3」になります。この場合はご指摘の通り「Range("A7").End(xlDown)」が9行目を示しているのかもしれません。しかし、

 7行目 ああああ
 8行目 (空白)
 9行目 いいいい
 10行目 うううう

の時は10行目を示し、値は4になるような気がしますが、実際には値は3です。
さらに不思議なのは、

 7行目 ああああ
 8行目 いいいい
 9行目 (空白)
 10行目 うううう

とすると、値は2になります。

エクセルのバグのような気がしますがどうでしょう。
もしかするとエクセル2000だけの現象でしょうか。

お礼日時:2008/12/31 10:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています