アプリ版:「スタンプのみでお礼する」機能のリリースについて

同じような現象がなかったので、初心者ではありますが
質問させていただきます

http://okwave.jp/qa447885.html
こちらの質問にあった
ryuu001さん回答の

 ◎テーブル名 = テーブル1
 ◎連番のフィールド名 = ID とし
 ◎連番は後から入力した数値が
  先に入力した数値より
  小さくなることは無い。
  (dmaxを使用しているので大丈夫かと思いますが)

Sub test()
Dim Db As Database
Dim Rs As DAO.Recordset
Dim Temp As String
Dim I As Integer

Set Db = CurrentDb()
Set Rs = Db.OpenRecordset("テーブル1")

Rs.MoveFirst
I = 1
Temp = ""
Do Until Rs.EOF = True
Do While I < Rs!ID
Temp = Temp & " " & I
I = I + 1   *1
Loop
Rs.MoveNext
I = I + 1
Loop
Rs.Close
Set Rs = Nothing
Db.Close
Set Db = Nothing
MsgBox "次の数字が抜けています。" & vblf & Temp
End Sub

VBAを利用させていただきました。
ですが「オーバーフローしました」とエラーが出てしまい
デバッグすると*1の場所で止まっているようでした
これはやはりLoopしているのが原因なんでしょうか

ずっと+1を繰り返している・・・?

A 回答 (9件)

こんにちは


#8です。 的確なアドヴァイスが出来なくてごめんなさい。

>>MsgBox "比較処理中 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
>このメッセージボックス部分で「型が一致しません」と出てしまうようです。宣言など>が必要なんでしょうか?
>Str関数?がうまく機能してないのでしょうか・・・

質問者さんがにらんだ通り、当たりです(^^;
STR$()関数は、引数が数値でなくてはならないのですが、「Rs!ID」は
数値ではないため、エラーになりました。

>MsgBox "比較処理中 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
>MsgBox "Loop通過 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)

従って、上記はどちらでも処理が通過するときエラーになります。
片方しかエラーが見つからないのは、たまたまデータが片方を通過
するパターンしかなかったということと理解しています。
ホントにすみませんでした m(__;m

さて、下記のようにしていただく案と..

MsgBox "比較処理中 I=" & Str$(I) & ", Rs!ID=" & Rs!ID
MsgBox "Loop通過 I=" & Str$(I) & ", Rs!ID=" & Rs!ID

Str$(Rs!ID) を Str$(J)にする案があります。

MsgBox "比較処理中 I=" & Str$(I) & ", J=" & Str$(J)
MsgBox "Loop通過 I=" & Str$(I) & ", J=" & Str$(J)

どちらでもいいです。プログラムが思ったように動いているかを変数
の値から把握するのが目的ですから。

飛び番がないときは、Loop通過 I=..しか表示されません。
飛び番があったら、比較処理中 I=.. が飛び番の数だけ表示されてか
ら Loop通過 I=.. に移るはずですね。

この回答への補足

夜遅くに回答ありがとうございます。
週末は見ることが出来ずに申し訳ありません・・・
おかげさまで検索開始することができ、状況も把握できるようになりました。
ですが、疑問が・・・

検索開始してOKをずっと押していると
 比較処理中 I=6131, Rs!riyou_id=ZZZZ8939
等の結果がでるようになりました。
これは6131から8939までは空き番号と判断してしまっていいんでしょうか

理想としては最後にフォームが開き空き番号を参照できるようにしたいのですが、このVBAの最後は空き番号の最小値が出るだけだと思うのですが
実際空き番号の検索をしてみると総当りで見ているので検索が非常に長かったです。
毎回検索して空き番号を探しそこに登録!
という流れだと時間的に厳しいかなと思いました。
何かいい案はありますでしょうか?
コレばかりは仕方ないですかね・・・

補足日時:2009/03/30 11:32
    • good
    • 0
この回答へのお礼

何度かテスト見てみたところI=9920ぐらいで勝手に終了してしまうようです
データ多いためでしょうか・・・

お礼日時:2009/03/30 16:38

こんにちは


#7です。横入りでごめんなさい。
積極的に変数の内容が意図したように変わっているか見てみましょう。VBAエディタを使いこなせるとステップ実行やウォッチ機能でできるのですが、コードに埋め込む手もあります。

Sub test()
'◆前提条件
'・レコードセットは、ID昇順で得られる。
'・同じ数値のIDはない。
'・IDの最小値は 1 である。
'・IDの最大値は Integerで扱える。
'・フィールド ID は、数値型
'

 Dim Db As Database
 Dim Rs As DAO.Recordset
 Dim Temp As String '抜け番号レポート用文字列バッファ
 Dim I As Integer 'レコード番号カウンタ(1~対象IDすべて)(32767以内)
 Dim J As Integer 'ID番号(数字部分を整数に変換して格納される)

 '●DBからIDのZZZZnnnn 抽出し、IDをキーに昇順ソート
 Set Db = CurrentDb()
 Set Rs = Db.OpenRecordset("SELECT ID FROM テーブル1 WHERE ID LIKE 'ZZZZ*' ORDER BY ID")

 Rs.MoveFirst

 Let I = 1 '1番目のIDからスタートするため、カウンタも1に初期化
 Let Temp = "" 'レポート用バッファは空に初期化

 '■レコードセットの終わりが来るまで Loop
 Do Until Rs.EOF = True
   '●IDの ZZZZnnnnの数字部分を切り取る
   Let J = CInt(Right(Rs!ID, 4))
   '■レコード番号カウンタがID番号よりも小さい(=抜けがある)間Loop
   Do While I < J
     Let Temp = Temp & " " & I '●抜けているレコード番号を記録
     Let I = I + 1 '●次のID番号と比較する準備
     MsgBox "比較処理中 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
   '■
   Loop
   MsgBox "Loop通過 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
   Rs.MoveNext
   Let I = I + 1 '●次のID番号と比較する準備
 '■
 Loop
 MsgBox "Loop終了(レコードセットの終端に達した)"

 Rs.Close
 Set Rs = Nothing
 Db.Close
 Set Db = Nothing
 MsgBox "次の数字が抜けています。" & vbLf & Temp

End Sub

この回答への補足

A88No8さん、度々回答ありがとうございます。非常に参考になります。
補足が遅くなって申し訳ありません。

今回教えていただいた箇所を変更してみましたが、

>MsgBox "比較処理中 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
このメッセージボックス部分で「型が一致しません」と出てしまうようです。宣言などが必要なんでしょうか?
Str関数?がうまく機能してないのでしょうか・・・

ちなみにこのメッセージボックスの1行前にメッセージボックスを作ってみましたが表示がされました。

”や’の位置を変えてみたりしましたが、コンパイルエラーが帰ってきます・・・自分で解決できなくて申し訳ありません。
お暇な時にでも助言をお願いします。

補足日時:2009/03/27 10:34
    • good
    • 0
この回答へのお礼

あ、すみません。ちょっと記載ミスが・・・

>MsgBox "比較処理中 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
ではなくて
>MsgBox "Loop通過 I=" & Str$(I) & ", Rs!ID=" & Str$(Rs!ID)
こちらでした・・・。
お礼欄使ってしまって申し訳ないです

お礼日時:2009/03/27 14:21

横入りでごめんなさい。


#6のアドヴァイスでトライされたのはよいのですが、古いDOコードが残ったままです(DOは、LOOPとセットで、DO~LOOP文です)。
とりあえず、下記の←印の行を削除して試してみましょう。

Do Until Rs.EOF = True
   J = CInt(Right(Rs!ID,4))
   Do While I < J
Do While I < Rs!ID   ←前の2行で置換えるべきステートメントなので削除しないと
Temp = Temp & " " & I
I = I + 1   
Loop
   msgBox "Loop通過"
Rs.MoveNext
I = I + 1
Loop

この回答への補足

回答ありがとうございます!
あ・・・これは写しミスでしたごめんなさい・・・
この行じたいは'コメントアウトしてありますうっかりしてて申し訳ない・・・
ご指摘ありがとうございます!

補足日時:2009/03/26 13:11
    • good
    • 0

#4 での前提条件に(基本的な条件として)1つ抜けがありました。



・フィールド ID は、数値型


> たとえば個人データならABCD0001。未特定データならZZZZ0001~9999のようになります。

数字部分を分離する必要があります。


未特定データでの修正案1)
IDの右4文字を数値として INUM 名で抽出しておく

・レコードセットを得るSQLを以下

SELECT CInt(Right([ID],4)) AS INUM FROM テーブル1 WHERE ID LIKE 'ZZZZ*' ORDER BY ID;

・Do While I < Rs!ID → Do While I < Rs!INUM



未特定データでの修正案2)

・レコードセットを得るSQLを以下

SELECT ID FROM テーブル1 WHERE ID LIKE 'ZZZZ*' ORDER BY ID;

・VBA 記述追加/変更

 Dim J As Integer 宣言追加

 Do Until Rs.EOF = True
   Do While I < Rs!ID


 Do Until Rs.EOF = True
   J = CInt(Right(Rs!ID,4))
   Do While I < J

※ ID の右4文字を数値とする方法は上記のとおりで、5文字目以降という意味合いなら
  CInt(Mid(○○,5))

※ 個人データであれば、'ZZZZ*' → 'ABCD*'


※ メモ

 Dim I As Integer

 I = 1
 Do While I < AAA '----- (1)
  I = I + 1
 Loop

上記状態で、(1)の AAA をいろいろ変えた時の動き
・Do While I < 3
  I が 3 になるまでループ
・Do While I < "3"
  I が 3 になるまでループ
・Do While I < "A3"
  型が一致しないエラー
・Do While I < Rs!ID   IDはテキスト型で、中身 "A3"
  I のオーバーフロー

この回答への補足

ご回答ありがとうございます。2つも案も出して頂きありがとうございます!メモとっても参考になります;;もしかするとZZZZの文字が邪魔してオーバーフローだったのかもしれないのですかね・・・

修正案をさっそくトライしてみました。

Sub test()
Dim Db As Database
Dim Rs As DAO.Recordset
Dim Temp As String
   Dim I As Variant
   Dim J As Integer

Set Db = CurrentDb()
   Set Rs = Db.OpenRecordset("SELECT ID FROM テーブル1 WHERE ID LIKE 'ZZZZ*' ORDER BY ID")

Rs.MoveFirst
I = 1
Temp = ""
Do Until Rs.EOF = True
   J = CInt(Right(Rs!ID,4))
   Do While I < J
Do While I < Rs!ID
Temp = Temp & " " & I
I = I + 1   
Loop
   msgBox "Loop通過"
Rs.MoveNext
I = I + 1
Loop
   msgBox "Loop終了"
Rs.Close
Set Rs = Nothing
Db.Close
Set Db = Nothing
MsgBox "次の数字が抜けています。" & vblf & Temp
End Sub

加えた場所は段差をつけて見ました
オーバーフローは解消 I を Variantにしたため解消できたようです
ですがやっぱりLoopの場所でずっと繰り返しているだけでした。エラーもでなかったので繰り返しているだけ?
気になってLoopの場所にメッセージボックスを置いてみたのですがやはり
Loop通過を繰り返すだけでした。
こればかりは結果でるまで待つしかないのでしょうか・・・それともLoopしてるだけで進んでいないのか・・・
申し訳ないのですが、助言いただけると幸いです。

補足日時:2009/03/26 11:34
    • good
    • 0

こんにちは


#1、#3です。
#4さんの適切なご指摘で#1、3は外していることが明確になりましたので#1、#3は無視して下さい。
ごめんなさい。
ただ、「Rs!ID」の正体が気になり始めました。

この回答への補足

何度も回答ありがとうございます。助かります
>#4さんの適切なご指摘
本当に力不足で申し訳ないです。理解できるように勉強します。
Rs!IDは個人データ(IDが固有のもの)未特定データ(IDをとりあえず割り振ったもの)になるんですが、
たとえば個人データならABCD0001。未特定データならZZZZ0001~9999のようになります。
そういうことではなかったですか・・・?

補足日時:2009/03/25 16:15
    • good
    • 0

なぜオーバーフローしたか分かりませんが、



このコードの前提条件は、以下と思われます。

・レコードセットは、ID昇順で得られる。
・同じ数値のIDはない。
・IDの最小値は =1 である。
・IDの最大値は Integer で扱える。


> データ数は数字上限でいうと9999です。
> 個人データと未特定データを合わせても2万弱になります。

一度確認されてみてはいかがでしょう。


  Rs.MoveNext
  I = I + 1 ← 次に得られるであろうID値を事前に設定している

この回答への補足

みなさん返答おくれまして申し訳ありません
もしかすると#3のA88No8さんの仰っていたIntegerの限界かもしれないです
フィールドが7つありレコードが2万弱・・・

前提条件に関しましてはまったくその通りです。
最後の行がとってもヒントにみえるのですがはっきりしません・・・
理解できるように勉強します。

補足日時:2009/03/25 16:03
    • good
    • 0

こんにちは


#1です。勘違いされているようなので..
>Let I = I + 1 に両方とも変更してみたのですが
>同じくオーバーフローしてしまいました。データ数2万弱ですがこのVBAだと無理なんでしょうか・・・

 いいたかったのは「Let I = I + 1」が変じゃない?ってことなんです。
 外側のDOでレコード(行)をトレースし、内側のDOでフィールド(列)をトレースしているように見える。 Iの目的がデータすべての順序番号なら外側と内側の間にあるLet I=I+1は、不要。
 Iの目的がフィールド順序番号を繰返す目的なら Let I=1 でフィールド(列)を一巡する内側のDOを抜けた時点で、Iを初期化すべきではないでしょうか?
 あと、Iの目的がデータすべての順序番号なら、多分 integer だと16ビットのような気がするので 65536 の半分(3万ぐらい)までしかカウントできません。
 フィールド×レコードの値が3万以内に入っていますか?

この回答への補足

回答ありがとうございます。とても参考になります!
>フィールド×レコードの値が3万以内に入っていますか?
これは・・・
テーブル1にはフィールドが7個ありました・・・それでいてレコードも2万弱ということは完全にあふれてしまっていますね・・・
integerでは扱いきれなかったのですね。納得です。

>フィールド(列)を一巡する内側のDOを抜けた時点で、Iを初期化すべきではないでしょうか?
申し訳ありません。Iを初期化する。とはどういうことでしょうか・・・無知で申し訳ないです。

Variant形式にして内側と外側の間にあるI = I + 1を削除してみたところ
オーバーフローはでなくなりましたがずっと検索を行っているようで終わりそうにありませんでした。重いのかもしれません・・・

補足日時:2009/03/25 14:57
    • good
    • 0

回答ではないですが。



リンク先の回答のコードを使ってみたらオーバーフローしました。
と言ってもその質問者と同じ環境なのかどうかもわかりません。

あとIntegerの範囲を超えたデータ量と言うわけでもないですよね。
⇒Excelでたまに使ってしまい範囲を超えてオーバーフローさせる事もありましたもので。

この回答への補足

書き込みありがとうございます。
やはり分かりにくい現象なんでしょうか。。。
データ数は数字上限でいうと9999です。
個人が特定できているものを削除し、個人データに書き換えた時に空き番がでるのですが。。。
個人データと未特定データを合わせても2万弱になります。

補足日時:2009/03/25 08:34
    • good
    • 0

こんにちは


 Do Until Rs.EOF = True
  Do While I < Rs!ID
   Temp = Temp & " " & I
   Let I = I + 1
  Loop
  Rs.MoveNext
  Let I = I + 1 ←外側のループにあるこれが無意味のような(Let I=1 なら納得)。
 Loop

この回答への補足

回答ありがとうございます。
I = I + 1

Let I = I + 1
に両方とも変更してみたのですが
同じくオーバーフローしてしまいました。
データ数2万弱ですがこのVBAだと無理なんでしょうか・・・

補足日時:2009/03/25 08:51
    • good
    • 0

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