Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


294 / 3841 ページ ←次へ | 前へ→

【76553】Re:ユーザフォーム(モーダル)で「数式バ...
発言  独覚  - 15/1/5(月) 13:17 -

引用なし
パスワード
   ▼nossa さん:
ユーザーフォームとは別だけれども。
(後にどうつなげるかという問題もあるけれども)

Application.Dialogs(xlDialogFunctionWizard).Show

で「関数の挿入」ダイアログを表示させるというのは使えないだろうか?
・ツリー全体表示

【76552】Re:ユーザフォーム(モーダル)で「数式バ...
発言  γ  - 15/1/5(月) 12:21 -

引用なし
パスワード
   ▼nossa さん:
> ●数式入力の際に「数式バーと同じように入力できる」ようにしたいです。
補完機能とか、引数のTips表示なども念頭に、
これと同じものとおっしゃっているなら、それは無理です。
数式バーと同機能のコントロールは無いと思うし、
これを自作するのは不可能だと思います。
・ツリー全体表示

【76551】Re:ユーザフォーム(モーダル)で「数式バ...
発言  kanabun  - 15/1/5(月) 11:10 -

引用なし
パスワード
   ▼nossa さん:


> ●ユーザフォームをモーダル表示します。
> ●ユーザフォーム内に数式バー(のようなモノ)をつくり
>  数式を入力できるようにします。

どこまでできていて、
どこでつまづいていますか?

> ●数式入力の際に「数式バーと同じように入力できる」ようにしたいです。

文字列の入力だから、InputBoxなどを使う手もあると思いますが、
UserFormでないとだめなのかな?
・ツリー全体表示

【76550】ユーザフォーム(モーダル)で「数式バー...
質問  nossa  - 15/1/5(月) 10:10 -

引用なし
パスワード
   はじめまして。nossaと申します。
よろしくお願いします。

行いたいことは、以下です(Excel2010です)。
 ●ユーザフォームをモーダル表示します。
 ●ユーザフォーム内に数式バー(のようなモノ)をつくり
  数式を入力できるようにします。
 ●数式入力の際に「数式バーと同じように入力できる」ようにしたいです。
  
ご指導よろしくお願いします。
・ツリー全体表示

【76549】Re:2次元配列の範囲指定について
発言  β  - 14/12/31(水) 21:39 -

引用なし
パスワード
   ▼みかん さん:

ゆっくりと検討し、必要ならまた質問アップしてください。

ところで、現在のコード、EH列までの処理になっていますが、それでいいんですね?
EL列までの処理を想定してるんじゃないんですね?
・ツリー全体表示

【76548】Re:2次元配列の範囲指定について
お礼  みかん  - 14/12/31(水) 14:46 -

引用なし
パスワード
   ▼β さん:

たくさん回答頂きありがとうございます。
明日か明後日になってしまいますが、
じっくり見て、理解を深めたいと思います。

また質問が出ると思いますが、
どうぞよろしくお願いします。
・ツリー全体表示

【76547】Re:2次元配列の範囲指定について
発言  β  - 14/12/30(火) 20:48 -

引用なし
パスワード
   ▼みかん さん:

★いったんアップしたレスを削除し、一部訂正して再度アップします。

そちらのコードをざっと読みました。
私の理解が正しければ、この処理に、配列からの一括転記はかなり無理ですね。

2次元配列の中身をセルに落とし込むときの絶対条件は、セル側が連続している
ということになります。なので、↑で、【連続している一部】を配列から抜き出して
一括転記するコードをアップしたんですが、今回のように4列とびの1列ずつを
別の列に転記するのは、無理ですねぇ。
(1列ずつの配列からの抜出と一括転記はできますが、意味がないですから)

それと、PasteSpecialでxlPasteFormulaとしていますね。
これに意味があるなら(つまりコピー対象領域に、本当に式があるなら)
たとえば元のセルに =A100+B100 といった式があったとして、それを配列に
式として取り込むことはできますが、別のセルに落とし込んでも =A100+B100
となります。PasteSpecialなら、例えば =E100+F100 となるべきところですね。
この意味でも配列に格納ーー>それを落とし込む ということは不可能になります。
もし、たまたま xlPasteFormula としているだけで、実際は値の転記でいいなら
話は別です。

つまり、BC列、BG列、BK列、。。。。のコピー対象行に式がないなら、この処理は
配列にセル領域から取り込み配列内で加工してシートに一挙に書き戻すということは
簡単に(↑でアップしたような INDEX関数処理を使わずとも)可能です。


ところで、もともとのコード自体に、ちょっと難なきにしもあらず。
Ws.Range(Cells(4, Ij(1) + 1), Cells(Maxrows, Ij(1) + 1)).Select
実は、このコードは【間違った書き方】です。
( ) の中の Cells は、実は Ws ではなく ActiveSheet の領域を指します。
その上にWs.Selectがあるので、この間違いが表に出ていませんが
日本語にすると、Wsの中の領域で、その詳細は ActiveSheetのここからここまで
という意味になります。なので、仮に ActiveSheetがWs ではなかったらデバッグ画面
が登場するところです。で、Ws.Selectだからいいだろうといいたいでしょうが、
それなら、 Ws.Range と、Wsで修飾する必要もなく、単に Range( と書けばいいんです。
(あぁ、私は Ws とつけるのは大変いいこと、というか必要なことだと思ってるんですよ)
そのほかにもループの中で毎回シート選択をするのは、いかがなものかとか、
変数Ijを配列にしている意味が全くないとか エトセトラ エトセトラ。
・ツリー全体表示

【76546】Re:2次元配列の範囲指定について
発言  β  - 14/12/30(火) 15:46 -

引用なし
パスワード
   ▼みかん さん:

一応、↑でコメントした Index関数を使った処理案です。
各プロシジャで、最初にテストデータとして、A1:J1000 に値をセットしていますが
ここは、処理効率とは無縁のところですから、割り引いてください。
エクセルのメモリー内での内部処理を利用していますので、効率はいいと思います。

いずれもA1:J1000の内容を配列 v に取り込み、そこから抜出必要部分を
配列 w として生成。この配列 w をM1から始まるセル領域に一括で落とし込みます。

配列 v から配列 w を生成するところは、外だしのFunctionプロシジャにできますし
そうしておけば再利用に便利でしょうね。

(この配列生成方法は、以前に別掲示板で紹介されていたものです)

新規のブックの標準モジュールに以下をコピーして試してみてください。

'配列の指定列の全行を転記
Sub TestbyCol()
  Dim v As Variant
  Dim w As Variant
  
  testdata  'テストデータ生成
  
  'セル領域を配列に格納
  v = Range("A1").CurrentRegion.Value
  '2列目、4列目、6列目、8列目を指定
  w = Application.Index(v, Evaluate("row(1:" & UBound(v, 1) & ")"), Array(2, 4, 6, 8))
  
  Range("M1").Resize(UBound(w, 1), UBound(w, 2)).Value = w
  
End Sub

'配列の指定行の全列を転記
Sub TestbyRow()
  Dim v As Variant
  Dim w As Variant
  
  testdata  'テストデータ生成
  
  'セル領域を配列に格納
  v = Range("A1").CurrentRegion.Value
  '行を抜きだすために、いったん行列入れ替え
  v = WorksheetFunction.Transpose(v)
  '2行目、4行目、5行目を指定
  w = Application.Index(v, Evaluate("row(1:" & UBound(v, 1) & ")"), Array(2, 4, 5))
  '再度反転し元の行列の形式に
  w = WorksheetFunction.Transpose(w)
  
  Range("M1").Resize(UBound(w, 1), UBound(w, 2)).Value = w
  
End Sub

'配列の連続した指定行の指定列を転記
Sub testbyRowCol1()
  Dim v As Variant
  Dim f As Long
  Dim t As Long
  Dim w As Variant
  
  testdata  'テストデータ生成
  
  'セル領域を配列に格納
  v = Range("A1").CurrentRegion.Value
  '抜き出し 開始行 4行目 から 終了行 8行目
  f = 4
  t = 8
  '2列目、4列目、6列目、8列目を指定
  w = Application.Index(v, Evaluate("row(" & f & ":" & t & ")"), Array(2, 4, 6, 8))
  
  Range("M1").Resize(UBound(w, 1), UBound(w, 2)).Value = w

End Sub

'配列内のとびとびの行、列を指定して転記
Sub testbyRowCol2()
  Dim v As Variant
  Dim w As Variant
  
  testdata  'テストデータ生成
  
  'セル領域を配列に格納
  v = Range("A1").CurrentRegion.Value
  v = WorksheetFunction.Transpose(v)
  '2列目、4列目、6列目、8列目を指定
  w = Application.Index(v, Evaluate("row(1:" & UBound(v, 1) & ")"), Array(2, 4, 6, 8))
  '行を抜きだすために、いったん行列入れ替え
  w = WorksheetFunction.Transpose(w)
  '2行目、4行目、5行目を指定
  w = Application.Index(w, Evaluate("row(1:" & UBound(w, 1) & ")"), Array(2, 4, 5))
  
  Range("M1").Resize(UBound(w, 1), UBound(w, 2)).Value = w

End Sub

Sub testdata()
  Dim i As Long, j As Long
  Dim v(1 To 30, 1 To 10) As String
  Cells.Clear
  
  For i = 1 To 1000
    For j = 1 To 10
      Cells(i, j).Value = Cells(i, j).Address
    Next
  Next
  
End Sub
・ツリー全体表示

【76545】Re:2次元配列の範囲指定について
発言  β  - 14/12/30(火) 13:24 -

引用なし
パスワード
   ▼みかん さん:

コードは読んでいませんが、やろうとしておられることは
たとえば 10行5列の配列があったとして、このなかの
5行目から8行目、2列目から4列目の内容を、4行3列のセル範囲に一挙に転記したい。
こういうことでしょうか?

配列の部分を指定して、セルへ書き込むことは正規(?)のコードでは
(おそらく)できないでしょう。

配列のメモリー構造をコード内で把握して、ゴリゴリやればできるかもしれませんが
バージョンアップ時に外部にインターフェースとして公開されているもの以外は
内部構造がころころ変わるのが常ですから、やらないほうがいいですね。

考えられる方法としては、いったん元配列から必要部分を抜き出した配列を作る。
で、その配列から一挙にセルに転記。こういったことでしょうかね。

部分的な配列を作るのは、もちろん、コードを書けばいいんですが、普通に書く方法もありますし
シート関数の INDEX をマクロ内で使って生成する方法もあります。
・ツリー全体表示

【76544】2次元配列の範囲指定について
質問  みかん  - 14/12/30(火) 12:16 -

引用なし
パスワード
   はじめまして。よろしくお願いします。

既存コードのスピードアップのため、配列のコーディングに取組みだしました。
セルからセルへの値の転記のイメージで、配列からセルへの値の転記を
実施しようとしています。

予め、セルの範囲わかっている場合の、配列から一気にセルに転記する例は、
Webでいろいろ検索出来たのですが、配列ないの範囲指定してセルに一気に
転記する例は見つける事が出来ませんでした。

以下のKizonコードを作り直ししていますが、配列の範囲指定が出来るのか、
方法もわからず悩んでいます。
※LOOPでトライしましたが、既存コードの方がスピードが速かったので、
 やはり、一気に転記する方法で実現したいと思っています。

ご指導のほど、お願いいたします。


【既存コード】------------------------------------------------------------
Sub kizon()

Dim Ij(1) as Integer:Dim Maxrows as Long

Maxrows = Ws.Cells(Rows.count, 46).End(xlUp).Row
Ij(1) = 54

Do Until Ij(1) >= 142
  Ws.Select
  Ws.Range(Cells(4, Ij(1) + 1), Cells(Maxrows, Ij(1) + 1)).Select
    Selection.Copy

  Ws.Range(Cells(4, Ij(1)), Cells(Maxrows, Ij(1))).Select
  Selection.PasteSpecial Paste:=xlPasteFormulas,
    Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  Ws.Range(Cells(4, Ij(1) + 1), Cells(Maxrows, Ij(1) + 1)) = 0
 
  Ij(1) = Ij(1) + 4
Loop

End sub


【リメイク中のコード】----------------------------------------------------
Private Function Sheet2Array(BookName As String, SheetName As String) As Variant

 Dim RowNum1 As Double
 Dim ColNum1 As Double

 With Workbooks(BookName).Sheets(SheetName)
   RowNum1 = .UsedRange.Rows.count
   ColNum1 = .UsedRange.Columns.count
   Sheet2Array = .Range(.Cells(1, 1), .Cells(RowNum1, ColNum1))
 End With

End Function
---------------------------------------------------------------------------

Sub ReMake()

Dim Ij(1) as Integer:Dim Maxrows as Long
Dim DataBase() As Variant

Maxrows = Ws.Cells(Rows.count, 46).End(xlUp).Row
Ij(1) = 54

Do Until Ij(1) >= 142
  Ws.Select
  Ws.Range(Cells(4, Ij(1)), Cells(Maxrows, Ij(1))) = 'DataBase・・・ここが不明
  Ws.Range(Cells(4, Ij(1) + 1), Cells(Maxrows, Ij(1) + 1)) = 0
 
  Ij(1) = Ij(1) + 4
Loop

End sub
・ツリー全体表示

【76543】Re:コードを短くしたい
お礼  ゆーあ  - 14/12/30(火) 9:00 -

引用なし
パスワード
   ▼β さん:

おはようございます。
コメントありがとうございます。

「Sheet3をアクティブにして下さい」となる、理由が分かりました!
元ブックの方が、
 Sheet1:フォーム呼出ボタンのみ(sheet表示)
 Sheet2:個人データ登録用シート(非表示)
 Sheet3:(各個人データ)データシート1(非表示)
 Sheet4:(各個人データ)データシート2(非表示)
としており、
フォーム帖の全ての操作の後、
唯一表示しているSheet1をアクティブになるようにしていた為、
Sheet3をアクティブにして下さいと出ておりました。。。

正しい行を選んだか確かに心配です。
少し操作を考えてみます。。。


しかし、お陰様で、
最初より大幅にコードが短くなり、
処理時間も短縮となりました。
望み通りの方向に導いて下さり、本当にありがとうございました。

お教え頂いたことを、もう一度良く読み返し実践し、
自分の力に変えれる様に頑張ります!
ありがとうございました!!
・ツリー全体表示

【76542】Re:コードを短くしたい
発言  β  - 14/12/29(月) 19:41 -

引用なし
パスワード
   ▼ゆーあ さん:

「Sheet3をアクティブにして下さい」
このメッセージは、エクセルやVBAではなく、このマクロで出しています。
決して、プログラムを直してくださいというメッセージではないんです。

マクロ処理を開始する時点でのデータシート(Sheet3) で選ばれているセルの行
のデータを転記先シートに転記しますよね。
ですから、どこが選ばれているかを把握しなきゃいけないんですが、このセル
(ActiveCell) を参照しようとした場合、必ずこのシートがアクティブになっている
必要があります。

想定としては、データシートをゆーあさんがアクティブにして、目的の行を選んで
マクロ実行。
こう考えているんですが、このメッセージがでたということは、実行時には
別のシートがアクティブになっているということになります。

それとも、データシート(Sheet3) がアクティブな状態(前面にでている状態)で
このメッセージがでたあということでしょうか?

もしかして・・・・
ゆーあさんの操作手順として、
・データシート(Sheet3)のコピーすべき行のセルを選ぶ
・それから、別のシートを選んで、なにかする
・で、この状態で(別のシートが表示されている状態で)マクロ実行
・マクロは、前に、データシート上で選択してあったセルの行のデータをコピーする。

もし、こういった流れがいいのなら、SampleA,B,Cともに

  'Just In Case
  If Not ActiveSheet Is dSh Then
    MsgBox dSh.Name & "をアクティブにしてから実行してください"
    Exit Sub
  End If

これを消して

Application.ScreenUpdating = False の下に

dSh.Select

を追加。

これでいけますけど・・・・

でも、自分だったら、ちゃんと、選んだ行を目で確認しながら実行しますけど。
さっき、ちゃんと正しい行を選んでいたかどうか、不安じゃないですか?
・ツリー全体表示

【76541】Re:コードを短くしたい
発言  ゆーあ  - 14/12/29(月) 18:19 -

引用なし
パスワード
   ▼β さん:
 γさん

ご指導頂きありがとうございます。
また勝手なことばかりして、すみません。。。


SampleAを実行すると、
「Sheet3をアクティブにして下さい」
と動作ストップするので、
アクティブにするには?と考えていろいろ試してたのですが、
上手くアクティブにならず、私のなかで唯一アクティブになるコードが、
  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
でしたので、元のコードに戻った次第でした。。。


っで再度SampleAを眺めてみました。
流れは解る(なんとなくですが)のですが、
やはり実行すると何故か「アクティブにして下さい」と言われます。。。
それで、この文を、
  If Not ActiveSheet Is dSh Then
    MsgBox dSh.Name & "をアクティブにしてから実行してください"
    Exit Sub
  End If
消してみました。
すると、ちゃんと動作を行いました。

ここで、元ブックのSheet3をアクティブにしてるから実行するというのは、
なぜ必要なのでしょうか?
・ツリー全体表示

【76540】Re:コードを短くしたい
発言  γ  - 14/12/29(月) 15:18 -

引用なし
パスワード
   >   Dim 氏名 As Range
>   Dim AAA As String
>   Set 氏名 = Worksheets("Sheet2").Cells(ActiveCell.Row, 1)
>   AAA = 氏名.Address(False, False)
>
> 頻繁に、ActiveCellなど使用してますので、
> 現状の管理方法では、とんでもない障害が起こりえるでしょうか??
すべての発言を読んでいるわけではないのですが、
上記のコードをみて ActiveCellの属するシートが心配になったのでした。

ところで、
>   Windows(exiWB).Activate
>   Worksheets("Sheet3").Activate
>   Sheets("Sheet3").Cells(ActiveCell.Row, 1).Resize(, 4).Select
>   Selection.Copy
>   Windows(NewWB).Activate
>   Sheets("データ抽出").Range("B6").Resize(, 4).Select
>   Selection.PasteSpecial Paste:=xlValues
>   
>   Windows(exiWB).Activate
>   Worksheets("Sheet3").Activate
>   Sheets("Sheet3").Cells(ActiveCell.Row, 5).Select
>   Selection.Copy
>   Windows(NewWB).Activate
>   Sheets("データ抽出").Range("H6").Select
>   Selection.PasteSpecial Paste:=xlValues
は、例えば以下のように書けるでしょう。

  Dim sWs As Worksheet
  Dim dWs As Worksheet
  Dim r As Long

  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
  r = ActiveCell.Row

  Set sWs = Workbooks(exiWB).Sheets("Sheet3")
  Set dWs = Workbooks(NewWB).Sheets("データ抽出")

  sWs.Cells(r, 1).Resize(, 4).Copy
  dWs.Range("B6").Resize(, 4).PasteSpecial Paste:=xlValues

  sWs.Cells(r, 5).Copy
  dWs.Range("H6").PasteSpecial Paste:=xlValues
  ・・・以下略 ・・・

こんな感じです。
何度も ActiveCellと連呼せずに、一度定義した r を使い回すと、
逆にそれが変動しているかどうか心配する必要がありません。

これをもっと簡略化したのが、
βさんの ,Valueプロパティに直接書き込む方式です。
すでに、βさんのものがありますから、それを参考にしてください。

# 文章作成後に βさんの投稿があることを知りました。
# たぶん重複しているかと思いますが、あえて追記しておきます。
・ツリー全体表示

【76539】Re:コードを短くしたい
発言  β  - 14/12/29(月) 15:08 -

引用なし
パスワード
   ▼ゆーあ さん:

γさんから、貴重なアドバイスがでています。
紹介されたOfficeTANAKAサイトの記載もよく読んでみてください。

私も、具体的なテーマからちょっと離れて。

「SampleBを使って・・・改良してみました。」
「SampleCを使っての改良もしてみました。」

と書いておられますが、実際に示していただいた「改良コード」は
もともとの、ゆーあさんのコーディングスタイルのままです。
ゆーあさんのコードは値の転記を、Copy-->PasteSpecial(xlValue) で行っていましたね。
それを実現するためにSheetのSelectや、セルのSelectも記述してあったわけです。

で、SampleA は、それを、

転記先セル.Value = 転記元セル.Value

という、ある意味、VBAスタンダードの記述方式に変えたものです。

次に、SampleB は 1項目ごとの転記(つまり転記すべきセル数だけ、転記コードが必要)
から、「連続した領域」を一挙に転記(コードは1行ですみます)するために

転記先セル【群】.Value = 転記元セル【群】.Value

に変更して、コード数を少なくし、コード数が少ないということは、実行回数も少ないので
処理効率のアップも図ったものです。

最後に、SampleC は、短くなったとはいえ、SampleB で、同じような規則性で処理されている
部分を変数を使ったループ処理として記述。コード数を減少させえています。

別のポイントで。

VBAでセルを特定する場合、「このブック」の「このシート」の「このセル」と書きます。
「このブック」が省略されれば、今アクティブなブックというようになります。
「このシート」が省略されれば、今アクティブなシートとみなされます。
(いずれも標準モジュールでの話ですが)
なので、ゆーあさんは「このセル」という表現だけで処理ができるように
処理対象のブックをアクティブにし、処理対象のシートをアクティブにしているわけですね。

でも、私が提示したコードでは、ブックのアクティブもシートのアクティブも行っていない。
だけど、処理はできたはずです。そこのところを、じっくりと考えてみてください。

あるセルの値を、別シートのセルに転記する操作をマクロ記録しますと

Sub Macro1()
  Sheets("Sheet1").Select
  Range("A1").Select
  Selection.Copy
  Sheets("Sheet3").Select
  Range("E9").Select
  Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=False
End Sub

こんなコードが生成されますね。

で、これと同じことをしようと以下のコードを書いたとします。

Sub TestNG1()
  Range("A1").Select
  Selection.Copy
  Range("E9").Select
  Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=False
End Sub

シートのSelectをなくしたものでエス。
でも、これでは最初のA1がどこのシートのA1なのか、ちょっと心細い記述ですね。
何よりも、E9 は、A1と同じシートになってしまいますね。具合悪いですね。

ということで

Sub TestNG2()
  Sheets("Sheet1").Range("A1").Select   '★シートを特定
  Selection.Copy
  Sheets("Sheet3").Range("E9").Select   '★でも、ここでエラー
  Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=False
End Sub

こんなように、セルがどのシートなのかを特定しました。
でも、E9 の Select でエラーになります。
セル.Select は、そのセルがアクティブシートにある場合のみOKで、そうでなければエラー。

なんとかしたいということで

Sub TestOK1() '★シートとセルを特定してコピーペースト
  Sheets("Sheet1").Range("A1").Copy
  Sheets("Sheet3").Range("E9").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=False
End Sub

あぁ、これでうまくいきました。
でも、Copy->PasteSpecialですから22のコードが必要ですね。

Sub TestOK2()
  Sheets("Sheet1").Range("A1").Copy Sheets("Sheet3").Range("E9")
End Sub

あぁ、これで1行でできました。
でも、仮にA1に書式設定があればあそれごとコピーされます。値の転記であれば

Sub TestOK3()
  Sheets("Sheet3").Range("E9").Value = Sheets("Sheet1").Range("A1").Value
End Sub

一般にはこのように書くわけです。

消化不良になるかも?なので、これぐらいでやめます。
ここでコメントしたことを念頭に、もう一度、SampleA,SampleB,SampleC を眺めてください。
・ツリー全体表示

【76538】Re:コードを短くしたい
発言  ゆーあ  - 14/12/29(月) 13:19 -

引用なし
パスワード
   ▼γ さん:

コメントありがとうごいます。
仰っておられるのは、
  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
  Sheets("Sheet3").Cells(ActiveCell.Row, x).Resize(, 4).Select
  Selection.Copy
ですよね?
私も逐一アクティブにしたり、セレクトしたくないので、
短くしようとしたのですが、ことごとく失敗してます。。。

たとえば、
    Worksheets("Sheet3").Activate
を抜いてみたりもしたのですが、抜くと上手く動作しないんです。


申し訳御座いませんが、具体的に
>一度、対応するSheetを確認したうえで、Range変数にセットして、
>その変数を使い回すほうがよいでしょう。
とはどのように記述したら良いのでしょうか?
私もリスクを抱えた書き方では無い方法が良いと思いますので、
お手数お掛け致しますが、お教え頂ければ幸いで御座います。
・ツリー全体表示

【76537】Re:コードを短くしたい
発言  γ  - 14/12/29(月) 12:03 -

引用なし
パスワード
   横から失礼します。# 殆ど同じ指摘かもしれませんが、あえて。

Sheetを逐一アクティブにしたり、Selectを頻繁に行うのは、
速度的な効率が悪い上に、コードの可読性(判りやすさ、簡潔性)を
損ないます。実は後者のほうがより重要かなと考えています。

また、
・Bookがアクティブでなければ、Sheetが選択できない(エラーになる)
・Sheetがアクティブでなければ、セルを選択できない(エラーになる)と
いったことに注意を払わなければならりません。
さらに、単にActiveCellと書くと、別のシートのそれを誤って引用する懼れもあります。
一度、対応するSheetを確認したうえで、Range変数にセットして、
その変数を使い回すほうがよいでしょう。

今は表面上問題化しなくても、リスクを抱えた書き方ではないかと思います。
できるだけこれらに依存しない書き方を採用するのがよいでしょうし、
皆さん、そうされていますよ。(日本人にはこういう言い方が有効らしいです。)


[無駄なSelectをしない]
ht tp://officetanaka.net/excel/vba/speed/s2.htm
などを参考にして下さい。
・ツリー全体表示

【76536】Re:コードを短くしたい
発言  ゆーあ  - 14/12/29(月) 11:30 -

引用なし
パスワード
   ▼β さん:

SampleCを使っての改良もしてみました。
もっと早くなった気がします!!

  j = 6
  For x = 1 To 46 Step 5
  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
  Sheets("Sheet3").Cells(ActiveCell.Row, x).Resize(, 4).Select
  Selection.Copy
  Windows(NewWB).Activate
  Sheets("データ抽出").Range("B" & j).Resize(, 4).Select
  Selection.PasteSpecial Paste:=xlValues
  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
  Sheets("Sheet3").Cells(ActiveCell.Row, x + 4).Select
  Selection.Copy
  Windows(NewWB).Activate
  Sheets("データ抽出").Range("H" & j).Select
  Selection.PasteSpecial Paste:=xlValues
  j = j + 5
  Next
・ツリー全体表示

【76535】Re:コードを短くしたい
発言  ゆーあ  - 14/12/29(月) 11:07 -

引用なし
パスワード
   ▼β さん:

おはようございます。
返信遅くなり、申し訳御座いません。

早速ですが、
まず、
>ActiveCell や Selection や ActiveSheet や ActiveWorkbook を前提にした
>コードは極力避けることが推奨されます。
>ActiveSheetが本来のものとは異なっていたり、そんなことが往々にして発生し、
>とんでもない障害になる可能性があります。
とのことですが、
   Sheets("Sheet3").Cells(ActiveCell.Row, 1).Select
のことを仰ってるでしょうか?
その場合、別件ですがご相談させて頂きたいです。。。

先日、データベースとして使用している元ブックは、
各データを行で一つのグループに分けていると説明したと思いますが、
元ブックのSheet構成として、
 Sheet1:フォーム呼出ボタンのみ(sheet表示)
 Sheet2:個人データ登録用シート(非表示)
 Sheet3:(各個人データ)データシート1(非表示)
 Sheet4:(各個人データ)データシート2(非表示)
としており、
操作(登録/更新/削除)は全て、フォーム(個人データ)上で行っております。
フォーム(個人データ)上に、データシート1&2フォーム呼出のコマンドボタンを
設置しており、
フォーム(個人データ)より別フォームを立ち上げて、データを登録
する様にしております。

Sheet2
  A  B  C   D   ・・・
1 名前 年齢 住所 電話番号 ・・・
2 田中 30 ・・・
3 佐藤 40 ・・・
4 小林 50 ・・・

Sheet3
   A   B  C   D   E   F   G  H  
1 依頼日1 受付1 対応1 内容1 依頼2 受付2 対応2 内容2・・・
2  1/1  山田 ・・・
3  2/1  富樫 ・・・
4  3/1  葉山 ・・・

Sheet4
   A   B    C   D   E   F   G   H  
1 依頼日51 受付51 対応51 内容51 依頼52 受付52 対応52 内容52・・・
2  5/1   富樫 ・・・
3  6/1   葉山 ・・・
4  7/1   山田 ・・・

Sheet3の連番でSheet4に続きます。
どのSheetも2行目は、田中のデータとなり、3行目は、佐藤のデータとなります。

やっと本題ですが、
Sheet2の氏名位置を基に、各シートのデータ管理を行っているのですが、

  Dim 氏名 As Range
  Dim AAA As String
  Set 氏名 = Worksheets("Sheet2").Cells(ActiveCell.Row, 1)
  AAA = 氏名.Address(False, False)

頻繁に、ActiveCellなど使用してますので、
現状の管理方法では、とんでもない障害が起こりえるでしょうか??


次に、ご提示頂いたコードについてですが、
SampleAで動作確認したところ、
"Sheet3をアクティブにしてから実行して下さい"
と言われてしまいました。
アクティブになるように試してみましたが、ダメでした。

よってSampleBでも同様の現象が起こると思ったので、
SampleBを使って、
  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
  Sheets("Sheet3").Cells(ActiveCell.Row, 1).Resize(, 4).Select
  Selection.Copy
  Windows(NewWB).Activate
  Sheets("データ抽出").Range("B6").Resize(, 4).Select
  Selection.PasteSpecial Paste:=xlValues
  
  Windows(exiWB).Activate
  Worksheets("Sheet3").Activate
  Sheets("Sheet3").Cells(ActiveCell.Row, 5).Select
  Selection.Copy
  Windows(NewWB).Activate
  Sheets("データ抽出").Range("H6").Select
  Selection.PasteSpecial Paste:=xlValues

に改良してみました、
C〜E列の記載が無くなった分、早くなった気がしますがどうでしょうか?
宜しくお願い致します。
・ツリー全体表示

【76534】Re:コードを短くしたい
発言  ゆーあ  - 14/12/27(土) 17:57 -

引用なし
パスワード
   ▼β さん:

コメントありがとうございます。
ちょっと(かなり)こんがらがってきました。。。

今バタバタしておりますので、
来週頭に改めて返信させて頂きます。すみません。。。
・ツリー全体表示

294 / 3841 ページ ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free