人に聞けない痔の悩み、これでスッキリ >>

Public Sub Test(SourceRange As Range, TargetRange As Range)
Dim ResultArray() As Variant
' ここから

' ここまでに該当処理
TargetRange = ResultArray
End Sub

2次元配列について
ReDimで大きな配列を作って1行ずつ代入してからセルに貼り付けるのと、
ReDim Preserveで配列を1行ずつ少しづつ追加してからセルに貼り付けるのと、
5000×5000くらいだとどちらが速いですか?

私のPCだと性能不足で測定困難です。
代わりに試して頂けると助かります。

A 回答 (2件)

VBA(MicrosoftのBasic)でRedimすると、配列を増減するのではなく、新たな場所に新しい大きさのメモリを確保して、配列の参照先を変えます。


今までの配列の本体は参照元が無くなるので、空いた時間に削除されます。
ReDim Preserve は、既存のデータをコピーするので、更に時間がかかります。
なので、頻繁にReDim Preserveすると、メモリの確保とデータのコピーと不要になった配列の掃除のために大忙しになるので、やめた方がいいと思います。
これは文字列の追加でも起こるので、文字列の追加も気を付けた方がいいと思います。

それとVariantはどの型になるか不明なので、1データ16バイトの大きさが必要です。
普通の変数ならあまり気にする必要はありませんが、大きな配列だと、不要にメモリを消費します。
ReDim Preserveも要素数が同じでも他の型の変数と違って、大きなメモリのなるので時間がかかる可能性が高くなります。
例えばIntegerなら2バイトなので、必要なメモリは1/8になり、速度も上がります。

ただし、今のExcelは32ビットで動いているのでLongの場合メモリは1データ4バイト必要ですが、全体の処理は速いかもしれません。

とりあえず、Redimは出来るだけしない方がいいと思います。
ReDim Preserveは更に時間がかかります。
    • good
    • 0
この回答へのお礼

ReDim Preserve って追加だけじゃなくぜんぶコピーしてるんですね。存在意義がよく分からないですね、どう使い分けたら良いのでしょう?

お礼日時:2019/01/02 22:31

こんばんは。



一応、試さないで何かを言うのは失礼だから試してはみたものの、
実際、どんなコードを予想していらっしゃるのかしら?

>ReDimで大きな配列を作って1行ずつ代入してからセルに貼り付けるのと、
セル一つのデータを一つのインデックスに入れました。

>ReDim Preserveで配列を1行ずつ少しづつ追加してからセルに貼り付けるのと、
>5000×5000くらいだとどちらが速いですか?

比べる必要などはないと思うのです。
Redim Preseve とはいっても、1次側を固定しなければならないし、それでも、遅いのに決まっています。何分経ったか、20分は過ぎていますね。いえ、ハングしてしまいました。

>私のPCだと性能不足で測定困難です。
こちらのPCのスペックは悪くありませんよ。PCは、第6世代だったと思います。それに、Excel2013がネックということもないでしょう。


予め Redim xArray(5000,5000)
なら、73.543 s

Redim Preseve xArray(....
計測不能。途中でハング
    • good
    • 0
この回答へのお礼

ありがとうございます。助かりました。

お礼日時:2019/01/02 22:33

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

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

このQ&Aと関連する良く見られている質問

QReDim

下記のコードを詳しく教えて
   
x2 = Range("C3:E5").Value

ReDim ans2(1 To 1, 1 To UBound(x2)) ←この部分の意味

    For i = LBound(x2, 2) To UBound(x2, 2)

      For j = LBound(x2) To UBound(x2)

       この部分の意味 → ans2(1, i) = ans2(1, i) + x2(j, i)

      Next j

    Next i

Aベストアンサー

全体として以下の様な動作をしています。
ans2(1,1) = Range("C3")~Range("C5")の合計を代入
ans2(1,2) = Range("D3")~Range("D5")の合計を代入
ans2(1,3) = Range("E3")~Range("E5")の合計を代入


> x2 = Range("C3:E5").Value

x2は、要素が行方向1~3、列方向1~3の二次元配列になります。
 x2(1,1)がC3セルの値
 x2(1,2)はD3セルの値
 …
 X2(3,3)がE5セルの値



> ReDim ans2(1 To 1, 1 To UBound(x2))

各列の合計を代入するans2は要素が行方向1~1,列方向が1~3の二次元配列の構成が必要となります。
その割り当てを行っています。



そして以下で各列の合計を計算しています。
> For i = LBound(x2, 2) To UBound(x2, 2)   '列方向の要素変化(1~3/C列~E列)
>   For j = LBound(x2) To UBound(x2)    '行方向の要素変化(1~3/3行~5行)
>     ans2(1, i) = ans2(1, i) + x2(j, i) '各列ごとに行の値を足しこむ
>   Next j
> Next i



試しに
 Range("A1:C1").Value = ans2
とすれば対応するセルに計算結果が表示されます。

全体として以下の様な動作をしています。
ans2(1,1) = Range("C3")~Range("C5")の合計を代入
ans2(1,2) = Range("D3")~Range("D5")の合計を代入
ans2(1,3) = Range("E3")~Range("E5")の合計を代入


> x2 = Range("C3:E5").Value

x2は、要素が行方向1~3、列方向1~3の二次元配列になります。
 x2(1,1)がC3セルの値
 x2(1,2)はD3セルの値
 …
 X2(3,3)がE5セルの値



> ReDim ans2(1 To 1, 1 To UBound(x2))

各列の合計を代入するans2は要素が行方向1~1,列方向が1~3の二次元配列の構成が必要となります...続きを読む

QプログラミングVBAについてです。 やり方を教えて下さい。よろしくお願いいたします。

プログラミングVBAについてです。
やり方を教えて下さい。よろしくお願いいたします。

Aベストアンサー

何かの課題のようなので、ヒントのみです。

どこがわからないのかも不明で、単なる丸投げ的な質問になっちゃってますが、大きく分ければ
・設問の意味や考え方がわからない
 (プログラミング言語とは関係なくアルゴリズム等の理解の問題)
・コードを作成できない
 (プログラムのフローを考える力と、言語知識の問題)
のどちらなのでしょうね?(両方なのかも)

ひとまず、このあたりが参考になるかも?
(検索すれば他にもいろいろ見つかると思いますが)
長方形積分と台形積分の説明とコード(C言語)
https://www.vcssl.org/ja-jp/code/archive/0001/3000-integral-rectangular/
https://www.vcssl.org/ja-jp/code/archive/0001/3000-integral-rectangular/

VBAでの例
https://excelmath.atelierkobato.com/trapzoid/

おまけ(シンプソン法の例)
http://shimaphoto03.com/program/simpson-vba/

何かの課題のようなので、ヒントのみです。

どこがわからないのかも不明で、単なる丸投げ的な質問になっちゃってますが、大きく分ければ
・設問の意味や考え方がわからない
 (プログラミング言語とは関係なくアルゴリズム等の理解の問題)
・コードを作成できない
 (プログラムのフローを考える力と、言語知識の問題)
のどちらなのでしょうね?(両方なのかも)

ひとまず、このあたりが参考になるかも?
(検索すれば他にもいろいろ見つかると思いますが)
長方形積分と台形積分の説明とコード(C言語)
ht...続きを読む

Qまちがっているところ

strSQL = " "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード, SUM(東京支店) AS TOKO"
strSQL = strSQL & " FROM"
strSQL = strSQL & " ( "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " *"
strSQL = strSQL & " FROM"
strSQL = strSQL & " [3学期$] "
strSQL = strSQL & " UNION ALL "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " *"
strSQL = strSQL & " FROM"
strSQL = strSQL & " [2学期$] "
strSQL = strSQL & " ) "
strSQL = strSQL & " GROUP BY 商品コード"
まちがっているところおしえてくれませんでしょうか

strSQL = " "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード, SUM(東京支店) AS TOKO"
strSQL = strSQL & " FROM"
strSQL = strSQL & " ( "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " *"
strSQL = strSQL & " FROM"
strSQL = strSQL & " [3学期$] "
strSQL = strSQL & " UNION ALL "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " *"
strSQL = strSQL & " FROM"
strSQL = strSQL & " [2学期$] "
strSQL = strSQL & " ) "
strSQL = strSQL & " GROU...続きを読む

Aベストアンサー

No.3です。

列数が一致しないとなっているならSheet構成がそれぞれで違うのではないですかね?(検証すると確かに列数が違うとエラーになる)

その場合それぞれのSheetでSELECTしたいフィールドを明確にする為に

strSQL = " "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード, SUM(東京支店) AS TOKO"
strSQL = strSQL & " FROM"
strSQL = strSQL & " ( "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード,東京支店" '★
strSQL = strSQL & " FROM"
strSQL = strSQL & " [3学期$] "
strSQL = strSQL & " UNION ALL "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード,東京支店" '★
strSQL = strSQL & " FROM"
strSQL = strSQL & " [2学期$] "
strSQL = strSQL & " ) AS 合計"
strSQL = strSQL & " GROUP BY 商品コード"

とフィールド名を記載したらエラーは消えましたよ。

No.3です。

列数が一致しないとなっているならSheet構成がそれぞれで違うのではないですかね?(検証すると確かに列数が違うとエラーになる)

その場合それぞれのSheetでSELECTしたいフィールドを明確にする為に

strSQL = " "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード, SUM(東京支店) AS TOKO"
strSQL = strSQL & " FROM"
strSQL = strSQL & " ( "
strSQL = strSQL & " SELECT "
strSQL = strSQL & " 商品コード,東京支店" '★
strSQL = strSQL & " FROM"
strSQL = strSQL & " [3学期$] "
...続きを読む

Q時刻文字列を判定する方法について

こんにちは
時刻文字列を比較する方法についておしえてください。

セルに時刻文字列 9:01とか12:34などが記載されていたら「OK」 
そうでない場合は「NG」となるような判定方法についておしえてください。
例)
12:34 MSGBOX ”OK”
1234  MSGBOX ”NG”
宜しくお願いいたします。

Aベストアンサー

どこかのセルに ”OK” または ”NG” と表示させたいなら…
例にある表示が、
 13:56
の書式であること【だけ】を対象としているなら、
 =IF(CELL("format",A1)="D9","GOOD","NG")
でOK。
 12:34:56
の書式なら「D9」の部分を「D8」にすればいい。

CELL関数について調べてみると幸せになれるかもしれません。

・・・
もしも入力時に ”時刻” 以外は弾きたいと言うのであれば「入力規則」で ”時刻” を指定してみましょう。
そして ”時刻” 以外の入力がされた時に返す「エラーメッセージ」を設定すれば良い。

Qデータの抽出について(VBA)

※VBAを勉強中の初心者です。

エクセルのA6以降の行に人物名、B6以降の行にその人物の説明文を表にしたものがあり、説明文中に含まれるワードを入力すると、該当する人物とその説明文が上詰めで表示(該当しないものは非表示)されるようにしたいと考え、それをVBAで書こうとしています。

ワードを、
①E2セルのみに入力したとき、E2のワードを含む説明文とその人物のみを表示。
②E2とE3セルに入力したとき、E2のワードかつE3のワードを含む説明文とその人物のみを表示。
③E2とF2セルに入力したとき、E2のワードまたはF2のワードを含む説明文とその人物のみを表示。

のようにしたくて、以下のように書きました。
しかし、下記プログラム3行目でコンパイルエラーが出ました。

文法が間違っているのか、そもそも、Select Case文を使うこと自体が不適切なのか、調べてもわからないので教えてください。

以下、試しにSelect Case文を使って書いたものですので添削して頂けないでしょうか。
投稿前はプログラムの改行や行前のスペースを空けていますが、投稿後なぜか反映されません、無視してください。

Option Explicit
Sub オートフィルターによる抽出()
Select Case Range("E2").Value, Range("E3").Value, Range("F2").Value
Case Is Range("E2").Value
Range("A6").AutoFilter Field:=1, "*" & Range("E2").Value & "*"
Case Is Range("E2").Value and Range("E3").Value
Range("A6").AutoFilter Field:=1, "*" & Range("E2").Value & "*",Operator:xlAnd "*" & Range("E3").Value & "*"
Case Else Range("E2").Value and Range("F2").Value
Range("A6").AutoFilter Field:=1, "*" & Range("E2").Value & "*",Operator:xlOr "*" & Range("F2").Value & "*"
End Select
End Sub

※VBAを勉強中の初心者です。

エクセルのA6以降の行に人物名、B6以降の行にその人物の説明文を表にしたものがあり、説明文中に含まれるワードを入力すると、該当する人物とその説明文が上詰めで表示(該当しないものは非表示)されるようにしたいと考え、それをVBAで書こうとしています。

ワードを、
①E2セルのみに入力したとき、E2のワードを含む説明文とその人物のみを表示。
②E2とE3セルに入力したとき、E2のワードかつE3のワードを含む説明文とその人物のみを表示。
③E2とF2セルに入力したとき、E2のワ...続きを読む

Aベストアンサー

No3です。
>度々申し訳ございませんが、"国会"ではダメで、"*国会*" としなければならない理由を、もう少し詳しく解説お願いできないでしょうか?

あなたの質問の内容で
Range("A6").AutoFilter Field:=1, "*" & Range("E2").Value & "*",Operator:xlAnd "*" & Range("E3").Value & "*"
となっていますが、
Range("E3").Valueの値が、"国会"なら "*国会*"となりますよね。
それ故、"*国会*" としなければならない理由は、ご存知かと思ったのですが・・・・・・。

あなたの現状の理解の程度が不明なので、基本的なことから説明しますが、(判り切ったことかも知れませんが)
*は、ワイルドカードといって、どのような文字にもマッチすることを示します。(下記参照)(トランプのジョーカーのようなもので何のカードにもなるようなものです)
https://qiita.com/aqril_1132/items/9bf905bbda718372b36a

もし、ワイルドカードを使用しないで、”国会”とすると、
B列の内容が、"国会"と全く同じでないと、マッチしません。(マッチしないと表示対象外となります)
その為、B10の内容が、"熊本県出身の国会議員"となっていると、マッチしません。
これは、望んだ結果ではないでしょう。

"*国会*"になっていると、文字が、「任意の文字+国会+任意の文字」の組みあわせならOKなので、B10の内容にマッチします。
その為に、"*国会*"とします。

余談ですが、
"国会*"とすると、必ず、最初の文字が国会で、以降の文字は何でも良いケースにマッチします。
従って、
国会議事堂・・・・マッチする
国会・・・・・・・マッチする
熊本県出身の国会議員・・・・マッチせず
となります。

同様に、"*国会"となっていると、最後が国会で終わっていれば、マッチします。
通常国会・・・・マッチする
国会・・・・・・・マッチする
熊本県出身の国会議員・・・・マッチせず

結局、"*国会*"は、そのセルの中に、"国会"があればマッチします。
通常国会・・・・マッチする
国会議事堂・・・マッチする
国会・・・・・・・マッチする
熊本県出身の国会議員・・・・マッチする

No3です。
>度々申し訳ございませんが、"国会"ではダメで、"*国会*" としなければならない理由を、もう少し詳しく解説お願いできないでしょうか?

あなたの質問の内容で
Range("A6").AutoFilter Field:=1, "*" & Range("E2").Value & "*",Operator:xlAnd "*" & Range("E3").Value & "*"
となっていますが、
Range("E3").Valueの値が、"国会"なら "*国会*"となりますよね。
それ故、"*国会*" としなければならない理由は、ご存知かと思ったのですが・・・・・・。

あなたの現状の理解の程度が不明なので、基本...続きを読む

QVBAによるデータ処理・加工について

初心者です。
以前、この場で、添付画像のfig1をfig2のように加工するコードを教えていただきました。
加工内容は次のとおりです。
・各idのrecordの平均値を各idの行始めに算出する
・注)各idの行始めはrecordなし
・注)recordには空白セルがある

これを、添付画像のfig3をfig4のように加工するコードに変更したいのです。
加工内容は次のとおりになります。
・各idのrecordの平均値を各idの行始めに算出する
・注)各idの行始めにもrecordあり → 変更点
・注)recordには空白セルがある

ご教授のほどよろしくお願いいたします。
以下に、参考として現在のコードを示しておきます。
Dim id As Long, record As Long
For id = 2 To Cells(Rows.Count, "A").End(xlUp).Row
On Error Resume Next
If Cells(id, "A") <> Cells(id - 1, "A") Then
record = id
Do While Cells(id, "A") = Cells(record, "A")
record = record + 1
Loop
Cells(id, "B") = WorksheetFunction.Sum(Range(Cells(id + 1, "B"), Cells(record - 1, "B"))) / _
WorksheetFunction.Count(Range(Cells(id + 1, "B"), Cells(record - 1, "B")))
Range(Cells(id + 1, "B"), Cells(record - 1, "B")).ClearContents
id = record - 1
End If
Next id

初心者です。
以前、この場で、添付画像のfig1をfig2のように加工するコードを教えていただきました。
加工内容は次のとおりです。
・各idのrecordの平均値を各idの行始めに算出する
・注)各idの行始めはrecordなし
・注)recordには空白セルがある

これを、添付画像のfig3をfig4のように加工するコードに変更したいのです。
加工内容は次のとおりになります。
・各idのrecordの平均値を各idの行始めに算出する
・注)各idの行始めにもrecordあり → 変更点
・注)recordには空白セルがある

ご教...続きを読む

Aベストアンサー

No.1のお礼に対して。

>示させていただいた現在のコードに少し手を加える感じでは無理でしょうか?

正直何をしているのか良くわかりませんので1から作りました。
何せプロパティを省略するとかは考えられませんし。
この方法(No.1)は10年ほど前には良く回答を見かけたやり方でしたし扱いやすかったので。

どうしても質問文のコードを基準に改良したいのであれば、回答者を指名すべきではないかと思います。
・・・知恵袋にはありますけど、ここのサイトはどうなんでしょうね?
質問文の最初に『○○さんへ』とあればわかるのかな?

憶測でよければ。
.Sum(Range(Cells(id + 1, "B"),
.Count(Range(Cells(id + 1, "B")

の2つの id + 1 を id にするとかかな?

QReDim PreserveよりもReDimが遅い

こんにちは、配列がいくつまで取得できるのか計算するマクロを作っている時に変なことに気が付きました。
エクセルでフォームとラベルを1つ用意し、下記のようなプログラムをモジュールに書きます。

実行すると、10万ずつ数字が増えていき、数字が1000~2000万超えたあたりで、メモリ不足ですという
表示がでます。
ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。
ReDim Preserveとしたときは9.5秒ぐらいですが
ReDim の時は 30秒以上かかっています
3台のマシンでテストしましたが、どれも似たような結果になりました
普通に値を保持するredim Preserveの方が遅いと思うのですがなぜこのような結果になるのでしょうか?
ご教授お願いいたします。

Public Sub 配列上限取得計算()
On Error GoTo ErrEnd
Dim i As Long
Const kankaku As Long = 100000

ReDim ans(1 To kankaku) As String
ans(1) = 1
i = 2
UserForm1.Show vbModeless

Do
If i Mod kankaku = 0 Then
DoEvents
UserForm1.Label1 = i
'ここのPreserveをなくすと明らかに遅くなる
ReDim Preserve ans(1 To i + kankaku) As String
End If
ans(i) = i
i = i + 1
Loop
Erase ans
Unload UserForm1
Exit Sub
ErrEnd:
MsgBox "これ以上の配列を設定できません。" & vbCrLf & "上限は" & i & "です。" & vbCrLf & Err.Description
Erase ans
Unload UserForm1
End Sub

こんにちは、配列がいくつまで取得できるのか計算するマクロを作っている時に変なことに気が付きました。
エクセルでフォームとラベルを1つ用意し、下記のようなプログラムをモジュールに書きます。

実行すると、10万ずつ数字が増えていき、数字が1000~2000万超えたあたりで、メモリ不足ですという
表示がでます。
ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。
ReDim Preserveとしたときは9.5秒ぐらいですが
ReDim の時は 30秒以上...続きを読む

Aベストアンサー

こんにちは、

> ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。
> ReDim Preserveとしたときは9.5秒ぐらいですが
> ReDim の時は 30秒以上かかっています

 ReDim は 新築
 ReDim Preserve は 増築
という喩で説明になっているかと思います。

実際には、Eraseして、メモリの再割り当てをしつつ、配列のサイズ(ディメンション)を再定義するのがReDim
既存のメモリを維持しつつ、メモリを拡張、サイズを再定義するのがReDim Preserve
ということになります。
必然的にReDimを繰り返したら遅くなります。

ご提示のコードでPreserve キーワードを抜くと、
kankakuごとに、ReDimしている訳ですから、
せっかく格納したそれまでの値を消去していることになります。
可変長のString型変数の場合は特殊で、割り当てられるメモリサイズが固定ではありませんから
格納したり消去(長さ0の文字列を格納)したりするのに特に時間が掛かります。

ご提示のコードでPreserve キーワードを抜くと、
それまでに格納した文字長に比例したメモリサイズ、は無視されてしまいます。
本来の目的から外れたテストになってしまいます。

可変長の変数なのですから、要素数、だけではなくて、
要素数と文字長、の2点について、色々パラメータを変えながら
テストしてみた方がより有意義なものになるのではないかと思います。

 Dim ans() As String
のように一旦、文字列型として、動的配列変数を予め定義しておいた方が
テストの精度が高まりますし、ReDimに掛かる時間も短くなります。

以上です。

こんにちは、

> ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。
> ReDim Preserveとしたときは9.5秒ぐらいですが
> ReDim の時は 30秒以上かかっています

 ReDim は 新築
 ReDim Preserve は 増築
という喩で説明になっているかと思います。

実際には、Eraseして、メモリの再割り当てをしつつ、配列のサイズ(ディメンション)を再定義するのがReDim
既存のメモリを維持しつつ、メモリを拡張、サイズを再定義するのがReDim Preserve
ということにな...続きを読む

Q続 こっちもするーしちゃったよぉ

こんばんは

先ほどと同様な質問かもしれませんが、

yahooからオークションサイトをクリックするというものですが
そのなかの処理でオークションリンククリック後 While doc.getelementsbytagname("body").Length <= 0でBODYのレングスが1になるまでループさせるというものですが、
ウオッチウインドウには変数なしでendsub 終了しました。

ただし、①の場所に(wait) 
Application.Wait [Now() + "0:00:01.9"]をつけ再度実行すると
正しく処理されるようになりました。(変数なし→値が入っている)

これは、doc.Links(i).Click後処理が早くてdocumnetオブジェクトが作られていないから
なのでしょうか?


Sub ie_test()

Dim objIE As Object 'IEオブジェクト参照用
'
Set objIE = CreateObject("InternetExplorer.application")
objIE.Visible = True
objIE.Navigate "http://www.yahoo.co.jp"

Do While objIE.busy = True Or objIE.ReadyState < READYSTATE_COMPLETE '表示完了待ち

DoEvents

Loop

While objIE.document.ReadyState <> "complete"

Debug.Print objIE.document.ReadyState&; "naka1"

DoEvents

Wend

Dim doc As Object
Set doc = objIE.document

For i = 0 To doc.Links.Length - 1
If doc.Links(i).innertext = "ヤフオク!" Then

doc.Links(i).Click
'Application.Wait [Now() + "0:00:01.9"] '①これをいれるとうまくいく
While doc.getelementsbytagname("body").Length <= 0
Debug.Print objIE.busy
Wend
Exit For
End If
Next

End Sub

こんばんは

先ほどと同様な質問かもしれませんが、

yahooからオークションサイトをクリックするというものですが
そのなかの処理でオークションリンククリック後 While doc.getelementsbytagname("body").Length <= 0でBODYのレングスが1になるまでループさせるというものですが、
ウオッチウインドウには変数なしでendsub 終了しました。

ただし、①の場所に(wait) 
Application.Wait [Now() + "0:00:01.9"]をつけ再度実行すると
正しく処理されるようになりました。(変数なし→値が入ってい...続きを読む

Aベストアンサー

こんばんは。
>これは、doc.Links(i).Click後処理が早くてdocumnetオブジェクトが作られていないからなのでしょうか?

あまり関係ないようです。Clickしたらおそらくステージが変わるのです。
裏技というか、IEイベントにして、変化する場所を監視して、変化した瞬間に次の動作に移る方法もあるのですが、おなじみの
 Do While objIE.Busy Or objIE.ReadyState <> 4: DoEvents: Loop
を一つ入れるだけで劇的に変わるはずです。

具体的には、こんな感じです。実際に動かしていませんから、正確にできるかはこの場では確かめられません。

Dim doc As Object
Set doc = objIE.Document

For i = 0 To doc.Links.Length - 1
 If doc.Links(i).innerText = "ヤフオク!" Then
  doc.Links(i).Click ←リンク先だったら、URLを取って、.Navigate2 URLでもよい

  Do While objIE.Busy Or objIE.ReadyState <> 4: DoEvents: Loop
  '(このように1行にまとめたほうが見やすいです。)
'画面の切り替わりを待ちます。
  'そして、必要に応じて、
  Set doc =objIE.Document を改めて取得しなおします。 <=これを活かすには、ループを抜けるしかありません。
''以下の場合のdoc は、一度しか取っていないので、何回やっても、変わらないです。
'× While doc.getelementsbytagname("body").Length <= 0
  Exit for
  Loop
End If
Next

こんばんは。
>これは、doc.Links(i).Click後処理が早くてdocumnetオブジェクトが作られていないからなのでしょうか?

あまり関係ないようです。Clickしたらおそらくステージが変わるのです。
裏技というか、IEイベントにして、変化する場所を監視して、変化した瞬間に次の動作に移る方法もあるのですが、おなじみの
 Do While objIE.Busy Or objIE.ReadyState <> 4: DoEvents: Loop
を一つ入れるだけで劇的に変わるはずです。

具体的には、こんな感じです。実際に動かしていませんから、正確にできるかはこの...続きを読む

QエクセルのVBA

VBA初心者です

Sub ボタン31_Click()
If Range("B2").Value = True Then
Range("E2:G2").Value = Range("E2:G2").Value
End If
End Sub
VBAのプログラムでセルAにはチェックマークが作ってありB列にはコントロールのセルが設定してあります。チェックは無数にありたとえば100ぐらいあるとして(列B2~B100)チェックを
入れるとB2がTRUEになりE2とF2とG2セルに値が入る(IFを使った関数)のですが値だけを残したいので、ボタン31を作りましたが、上記のままではE2 F2 G2のみの制御なのでE100 F100 G100セルまでもボタン31一つで値だけを残すプログラムはどうすれば良いのでしょうか?教えてください。

Aベストアンサー

あぁ、コピーして値を貼り付ける代わりに、それを選んだんですね。
そしたら下のコードを
Range(cells(i, 5), cells(i, 7)).value = Range(cells(i, 5), cells(i, 7)).value
に書き換えれば動くと思いますよ。

Q特殊な演算

2進数で表記された2つの数字を以下の演算で別の値を出す方法を考えています

その演算は同桁の数字が0と0なら0を
1と0,0と1なら1を
1,1も1
です。

010 と011 なら
1桁目が0、1なので1
2桁目は1,1なので1
3桁目は0,0なので0
となり 011 を返す


同桁の数字が0と0なら0を
1と0,0と1も0を
1,1は1
というバージョンも考えるのですが

エクセルでこのような演算を考えるには
関数であれVBAであれ
まず文字列としてleft() とか right() mid()を使って同桁の数字を取り出し
それを数値に直して計算し、3桁目*4+2桁*2+1桁 をして2進数表記にすればいいでしょうか?

それよりもっと楽なやり方はあるでしょうか?

お願いいたします

Aベストアンサー

使ってるExcelが2013かそれより新しければ、ビット演算関数があるので一発です。それより古いバージョンではVBAを使うか、1桁ごとに分解して演算するしかないですが。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング