エクセル2003です。VBAは初心者です。

ある列(Aとして)にデータがあって、A列をキーに昇順に並べ替えます。(1行目が見出し。)

その後、2行目の値を基準値として、
ループで3行目から4行目、5行目…と順に値を見ていき基準値と比較して、
値が異なったら基準値でフィルタをかけて印刷し、
現在の値を新たな基準値として次のループを行う、
という処理を行っていました。

上記の時は数字4文字(0001、0100等)という前提だった為、空白や4文字の数字以外は
事前にチェックしてエラーメッセージを出していたのですが、
新たに「01」や「00001」も「0001」と同じ値として扱うことにしました。

この場合オートフィルタで「01」や「00001」と「0001」を同時に抽出する事は可能でしょうか?

また無理な場合、どのような処理にすればよろしいでしょうか?


今の所、2つの値の文字数を取得(Len関数)し、
RIGHT関数で1文字取得。

1文字を比較して異なれば別とみなし印刷、
同じなら次はRIGHTで2文字取得して2文字を比較…
これを少ない方の文字数分行う。

その後、文字数が多い方の文字列からLEFT関数で差分の文字数分取得し、
オールゼロなら同じとみなし、オールゼロでなければ別とみなす…。

という様な処理を作っている途中なのですが、

まずCOBOLのように、不特定な文字数の文字列に対して「ALLZERO」かどうかを見る
方法はあるでしょうか?

また、処理が長引いているような気もするのですが、
これ以外に有効な方法はあるでしょうか?

教えていただけると助かります。
よろしくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

文章で表現することも必要だが、実例を挙げて説明すべきだ。


何のことか判りにくい。無駄な記述も多いので焦点がぼやけているのでは。
>2行目の値を基準値として、ループで3行目から4行目、5行目…と順に値を見ていき基準値と比較して、値が異なったら基準値でフィルタをかけて印刷し、現在の値を新たな基準値として次のループを行う、という処理を行っていました。
など本質問に、書く必要があるのか。過去にやっていたというだけで本質問に直接関係がない場合は、質問の中に書かないこと。
ーーー
>VBAで「1」、「01」等を同じ数字とみなすには
これをしたいなら、「セルの値」として、別の(同行別列)セルに統一したデータをつくるべきなだけ。
Format関数などで文字列に統一するか、VALで数値に統一すれば仕舞いではないか。なぜ質問が出るのか
ーー
上記で「別のセルに」といった理由は、
それとエクセルを使うものとして、根本的なことがわかっていない。VBAの初心者だとしても、エクセルも良くわかってない。
エクセルは、「セルの値」の「学」(まなび)である場合が多いのだ。「セルの値」に対比するものは「表示形式適用後の見た目」だ。
ソートやフィルタは、セルに「実現している値」を元に処理するようになっているのだ。
VBAで言えば、Rangeオブジェクトに対するメソッドになっているのがそれを意味する。
セルなどを前提にしないVBプログラムでは、プログラムの中で修正キーをつくり、その値に基づいてソートなどの処理をするのは自由だ。
それでもソートについては、一旦配列などに修正キーを「全」レコード分作らねばならない場合が多い。
またレコード処理で出来る課題で、1レコード内で修正した値を変数に作成し、其れで処理できる場合はあろう。(前後関係・全体関係を問題にしないで良い場合)
しかしソートなどは、プログラムの中の変数に、修正データを作るだけでなく、セルの「値」として実現せ(作ら)ねばならない(表示形式の見た目の結果ではダメということも意味する)。ソートなどの場合はそれも各行セルに対応して、全行のデータがセル範囲(普通同一列データ)に作成されて居ないとダメ。
フィルタの場合もFilterメソッドを使うなら、前もってセルの「値」として実現せ(作ら)ねばならないのだ。
ルール(例「1」、「01」等を同じ数字とみなすには)適用後のデータがシートに必要ということ。
1レコードづつ  該当かどうか判別していくなら、変数にプログラムで修正データを作って、そちらで考えればしまい。
ーー
すなわちエクセルでは
プログラムで、1レコード分の変数に修正値を作る+エクセルのRangeオブジェクトのメソッドなどに頼って、修正後変数値を使って処理はできない。
これらは「単独」レコード(行)を処理するのでなく、セル範囲で考えざるを得ないもの(ソート)や、セル範囲のデータ全部に
一遍に、同じルールを適用する(フィルタ)ものが多い。
これがあるお蔭でVBAコード1行でソートが済んでしまうのでありがたいわけ。フィルタも同じ。
例外に見えるソートのオプション特にユーザー指定(例日・月・火・・順)の並べ替えなどがあると、いうかもしれないが、それらはマイクロソフトが別途、問題を引き取って、作業列などを作り、処理しているわけで、我々ユーザーには、舞台裏側は見せてないだけ。
===
総括すると
基本的にはエクセルでは空き列に、修正データを作って、そのシートデータにの新設列のデータに対して処理することを基本と心得ること。
本質問では修正データを作るコードは簡単なものだ。それをメインテーマに質問をしてないだけ。
それでは無駄をかんじて、もっと無駄を省けないか、などは、相当エクセルも習熟し、VBAに熟達してからゆっくり考えること。
多分無いと思うが。
    • good
    • 0
この回答へのお礼

確かにまだエクセルを理解できていないですね。
勉強します。

ありがとうございます。

お礼日時:2011/04/17 22:27

やりたいことが、よくわからないのですが、


>新たに「01」や「00001」も「0001」と同じ値として扱うことにしました。
これは、先頭の0は無視するという意味ですか?
コンピュータの問題を解くとき、このように例をあげて考えてはいけません。
どういうルールなのか、一般規則を見つけることが、問題解決の第1歩です。

前に書いたとおり、先頭の0を無視するのでよいなら、
・数字しか出てこないのなら、Val関数で、数値化してから比較する。
・数字以外の文字もありえるなら、Mid関数で左から順に1文字ずつ調べ、0以外の文字が出たところで、それより右の文字だけ取り出して(Mid関数は取り出す文字数を十分大きくしておくと、それより右の文字を取り出すことができる) 比較する。
のどちらかとすればよいでしょう。
    • good
    • 0
この回答へのお礼

すいません説明不足でした。

現在は数字以外の文字も含み、表示形式も標準以外を考慮しなければならない
状態で作成しています。

一般規則を見つけることですね…
ありがとうございます。

お礼日時:2011/04/17 22:25

>不特定な文字数の文字列に対して「ALLZERO」かどうか



そういう手順を組んでしまうなり,関数を作成してしまえばどうとでもなります。
例:
dim buf as string
buf = "0000"
if application.substitute(buf, "0", "") = "" then
msgbox "buf is all zero"
end if


>他の手

val関数で数値化してしまう手もあります。
例:
dim buf as string
buf = "0010"
msgbox val(buf)

ワークシート上で数式によって数字の文字列を数値化してしまい,そちらでフィルタをかける手もあります。
例:
A列にそういった文字列が記入されている
D列でそれらを数値化する
range("D2:D" & range("A65536").end(xlup).row).formula = "=A2+0"
range("D:D").autofilter field:=1, criteria1:="=1"

オートフィルタの代わりにadvancedfilterを使ってみる手もあります。マクロ以前に「フィルタオプションの設定」のエクセルの機能について習熟しておく必要があります。
    • good
    • 0
この回答へのお礼

勉強不足でした。

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

お礼日時:2011/04/17 22:22

このQ&Aに関連する人気のQ&A

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

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

このQ&Aを見た人が検索しているワード

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

Qエクセルマクロで「1」を「01」に変換したい

エクセルマクロで、セルに入力された数値を、
変換するマクロを以下のように作成したのですが、
もっと簡単な方法はないのでしょうか。

やりたいことは、
「1」で入力された値を「01」に変換することです。
よろしくお願いします。

c = Sheets("Sheet1").Cells(1, 1).Value
If c = 1 Then
c = "01"
ElseIf c = 2 Then
c = "02"
ElseIf b = 3 Then
c = "03"
ElseIf c = 4 Then
c = "04"
ElseIf c = 5 Then
c = "05"
ElseIf c = 6 Then
c = "06"
ElseIf c = 7 Then
c = "07"
ElseIf c = 8 Then
c = "08"
ElseIf c = 9 Then
c = "09"
End If

エクセルマクロで、セルに入力された数値を、
変換するマクロを以下のように作成したのですが、
もっと簡単な方法はないのでしょうか。

やりたいことは、
「1」で入力された値を「01」に変換することです。
よろしくお願いします。

c = Sheets("Sheet1").Cells(1, 1).Value
If c = 1 Then
c = "01"
ElseIf c = 2 Then
c = "02"
ElseIf b = 3 Then
c = "03"
ElseIf c = 4 Then
c = "04"
ElseIf c = 5 Then
c = "05"
ElseIf c...続きを読む

Aベストアンサー

Format関数を使えばどうでしょうか。

With ActiveCell
If .Value >= 1 And .Value <= 9 Then
MsgBox Format(.Value, "00")
End If
End With

QEXCEL VBAマクロ作成で、他のEXCELからデータを取り込みたい

メインプログラム(EXCEL VBA)より、
他のフォルダーにあるEXCELの項目の内容を取り込みたいです。
たとえば他のフォルダーのEXCELのRange("A2:A3").ValueをメインプログラムのRange("C2:C3").Valueにセットしたい時です。

・コマンドボタン押したら、どこのEXCELから取り込むかのポップアップ(?)は、表示はできてます。
・作業者が選んだパスとブックもMsgBoxで表示できてるので、もらう相手の場所も取得できてます。

・となると次はOPEN,INPUTですか?
テキストデータの取り込みですと、Inputでそのバッファを定義してるのですが、なんか違うような。。。

よろしくお願いします!

Aベストアンサー

私がやる方法です。

Dim writeSheet As Worksheet ' 自分自身の書き出し先シート
Set writeSheet = ThisWorkbook.Worksheets(1) ' Sheet1 を参照

Dim readBook As Workbook ' 相手ブック
Set readBook = Workbooks.Open(filename) ' 相手ブックを開いて参照
Dim readSheet As WorkSheet ' 相手シート
Set readSheet = readBook.Worksheets("sheetName") ' 相手シートを参照
' または Set readSheet = readBook.Worksheets(sheetIndex)

' 例えば
writeSheet.Cells(1, 1).Value = readSheet.Cells(2, 2).Value ' 相手シートの B2 の値を自分自身の A1 に書き込む

readBook.Close False ' 相手ブックを閉じる
Set readSheet = Nothing
Set readBook = Nothing

私がやる方法です。

Dim writeSheet As Worksheet ' 自分自身の書き出し先シート
Set writeSheet = ThisWorkbook.Worksheets(1) ' Sheet1 を参照

Dim readBook As Workbook ' 相手ブック
Set readBook = Workbooks.Open(filename) ' 相手ブックを開いて参照
Dim readSheet As WorkSheet ' 相手シート
Set readSheet = readBook.Worksheets("sheetName") ' 相手シートを参照
' または Set readSheet = readBook.Worksheets(sheetIndex)

' 例えば
writeSheet.Cells(1, 1).Value = readSheet.Ce...続きを読む

QExcelの終了時に「クリップボードに…」を出なくする方法

Aファイル上でBファイルを開いて、BファイルのデータをAファイルにコピーして、Bファイルを閉じるマクロ(VBA)を作っています。
しかし、Bファイルを閉じるとき「クリップボードにデータがあり、他のアプリケーションで使用する場合は…」とかいうメッセージが出ます。
他のアプリケーションで使う予定はないので、このメッセージを出さずにBファイルを閉じたいのですが、どなたかおわかりの方、教えてください。
ちなみに、マクロの最後の部分は次のようになっています。

Application.Goto Reference:=strName
Selection.Copy
Windows(strMasterName).Activate
Application.Goto Reference:=strName & strNo
Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=False
Windows(strFileName).Activate
Sheets(strBase).Select
ActiveWindow.Close
Windows(strMasterName).Activate

Application.ScreenUpdating = True
MsgBox "コピーが終了しました"

Aファイル上でBファイルを開いて、BファイルのデータをAファイルにコピーして、Bファイルを閉じるマクロ(VBA)を作っています。
しかし、Bファイルを閉じるとき「クリップボードにデータがあり、他のアプリケーションで使用する場合は…」とかいうメッセージが出ます。
他のアプリケーションで使う予定はないので、このメッセージを出さずにBファイルを閉じたいのですが、どなたかおわかりの方、教えてください。
ちなみに、マクロの最後の部分は次のようになっています。

Application.Goto Reference:=...続きを読む

Aベストアンサー

マクロの最後に
Application.CutCopyMode = False
を追加してみて下さい。
切り取りモードまたはコピー モードを解除し、点滅している枠線を取り除きます。

QExcel VBA で日付を4ケタの数値に変換させるには?

ある日付データを 『月』と『日付』のみの4ケタの"文字列"にさせて表示処理させたいのですが、困っております。

現在、VBAを使用しないで処理させると…こんな感じで困っています。

1.日付を yyyy/mm/dd 表示
2.編集~ 『/』のみを全て『0』に変換
3.RIGHT関数で4ケタ(または5ケタ)抜き取る

*データ*
日付    yyyy/mm/dd  変換      RIGHT(4ケタ)
1月5日  2005/1/5     20050105   0105
1月10日  2005/1/10    200501010   0110
 ・    ・
 ・    ・

▲不具合状況
1."1月10日" のように日付が2ケタになる日は "1010" のように表示がずれる。RIGHT(○,5) で対処する方法もあるが…効率があまり良くない。

2."yyyy/mm/dd" のデータを直で "RIGHT( )" で処理させると思ったとおりの値が戻ってこない。

yyyy/mm/dd      RIGHT()
2005/1/5    →   8537 …変な値が戻ってくる?

VBAで一気にやる方法ありますでしょうか?
お知恵を拝借ください!

ある日付データを 『月』と『日付』のみの4ケタの"文字列"にさせて表示処理させたいのですが、困っております。

現在、VBAを使用しないで処理させると…こんな感じで困っています。

1.日付を yyyy/mm/dd 表示
2.編集~ 『/』のみを全て『0』に変換
3.RIGHT関数で4ケタ(または5ケタ)抜き取る

*データ*
日付    yyyy/mm/dd  変換      RIGHT(4ケタ)
1月5日  2005/1/5     20050105   0105
1月10日  2005/1/10    200501010   0110
 ・    ・
 ・    ...続きを読む

Aベストアンサー

こんばんは。

VBAでなくてもいいんですよね?

"2005/1/10" と表示されているセルをA2として、
↓でどうでしょうか?
------------------
=TEXT(A2,"mmdd")
------------------

QEXCEL VBAで計算値を四捨五入、切り上げ、切捨てする方法

ネットで探してみたのですが、計算結果を四捨五入して特定のセルを
返すにはどうしたらいいのでしょうか?

Sub hokangosa()

Dim ZPS As Double
Dim ZPOS As Double
Dim DMN As Double
MsgBox (" >>> 補間誤差自動計算 <<< ")
MsgBox (" >>> 初期値入力します <<< ")
ZPS = InputBox(">>> ステップを入力してください<<<")
ZPOS = Sheet1.Cells(22, 4).Value
DMN = ZPOS / ZPS
Sheet1.Cells(23, 6).Value = DMN
End Sub

ここでDMNの値を四捨五入したいです。

またこれとは別に切上げ、切捨ても教えていただけるとありがたいです。

Aベストアンサー

DMN = Application.WorksheetFunction.Round(ZPOS / ZPS, 0)
で、四捨五入
DMN = Application.RoundDown(ZPOS / ZPS, 0)
で切り捨て
DMN = Application.RoundUp(ZPOS / ZPS, 0)
で切り上げです。

引数で、対象桁を変更できます。

QExcelVBAを使って、値がある場合は作業を繰り返し実行するプログラムを作成したい。

以下のようなプログラムをVBAで作成したいと考えています。

A1のセルに値があれば、その値をB1に返す。
次にA2のセルに値があれば、その値をB2に返す。
A行に値がある一番下のセルまで同じようなことをさせたいと考えています。

VBAは初心者です。
どなかた宜しくお願い致します。

Aベストアンサー

#2さんと似たものですが・・・・参考にしてください。

Sub test001()
Dim i As Long
i = 1
Do While Cells(i, 1) <> ""
Cells(i, 2) = Cells(i, 1)
i = i + 1
Loop
End Sub

Qエクセル VBA セルの個数を所得する

いつも皆様には大変お世話になっております。

早速の質問ですが、

    A    B     C     D     E
1
2       123
3       123
4       123
5       123
6
7       123
とエクセルのセルがなっている場合の
上のB2から下のB7までのセルの個数を所得したいのです
B8以降にも数字が入る場合があるのと間に空白が入る場合があるので
困っています。
B2のセルは固定となっているのでB2からの判別で問題ない状況です。
どうぞ皆様お知恵をお借りしたく思っておりますのでよろしくお願いいたします。

Aベストアンサー

質問が非常に不明確なのですが・・・

所得?取得ですよね?

単にB2:B7のセルの個数をVBAで取得するなら
MsgBox Range("B2:B7").Count

B2:B7の空白でないセルの個数なら
MsgBox Application.CountA(Range("B2:B7"))

B7まででなくB2からB列のデータがある最後までのセル個数なら
MsgBox Range("B2:B" & Cells(Rows.Count, "B").End(xlUp).Row).Count

B2からB列のデータがある最後までの空白でないセル個数なら
MsgBox Application.CountA(Range("B2:B" & Cells(Rows.Count, "B").End(xlUp).Row))

QExcelVBAでセルをクリックしてユーザーフォームを表示するには

OfficeExcel2003を使用しています。
ユーザーフォームのテキストボックスやコンボボックスに文字や数値を入力し、OKボタンを押せばエクセルのセルに記入できるようにしようと思ってます。
フォームはなんとか(形だけですが..)作成できたのですが、そのフォームを呼び出す方法として、入力したい行のA列のセルをクリックすればユーザーフォームが表示されるようにしたいのです。
ネット上でいろいろ検索してみましたがなかなか見つけることができませんでした。
初歩的な質問かもわかりませんが、教えて頂けないでしょうか。
宜しくお願い致します。

Aベストアンサー

シートモジュールに下記を入れる。
A列をダブルクリックするとユーザーフォームが起動
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Column <> 1 Then Exit Sub
UserForm1.Show
End Sub

QVBAでワークブックの名前を変数にして開かせる?

最近VBAを勉強し始めたばかりです。 面白いですね…。

さて、恐らく基礎なんでしょうけれど、行き詰まっているので是非アドバイスをお願いします。
とりあえず、テキスト見ながら作ったマクロですがダメでした。
目的は対話型?で入力した名前のワークブックの名前を開かせるというものです。
Sub Macro1()
Dim mywbname As String
Dim mymsg As String, mytitle As String

myMgs = "開いて欲しいファイル名を入力してください"
mytitle = "ファイルを選択"
mywbname = Application.InputBox(Prompt:=myMgs, Title:=mytitle)

If mywbname <> "False" Then

Workbooks.Open Filename:="C:\Documents and Settings\○○○\デスクトップ\mywbname.xls"

End If

End Sub
なんてなものを作ったのですが、mywbnameを変数として受け取ってくれません。なのでそんなファイルはない…なんてことになっています。

構文自体の見直しも含めてアドバイスお願いします。
蛇足かもしれませんが、○○○のところは個人名が入ります。
C:\Documents and Settings\○○○\デスクトップ\mywbname.xls"
の箇所のmywbnameを既存のファイル名にしてみるとMgsBoXに適当な文字さえ入れれば、そのファイルは開いたので問題なのはmywbnameを入力した名前に置き換えてくれない部分だと思うのですが、よろしくおねがいします。

最近VBAを勉強し始めたばかりです。 面白いですね…。

さて、恐らく基礎なんでしょうけれど、行き詰まっているので是非アドバイスをお願いします。
とりあえず、テキスト見ながら作ったマクロですがダメでした。
目的は対話型?で入力した名前のワークブックの名前を開かせるというものです。
Sub Macro1()
Dim mywbname As String
Dim mymsg As String, mytitle As String

myMgs = "開いて欲しいファイル名を入力してください"
mytitle = "ファイルを選択"
mywbname = Applicatio...続きを読む

Aベストアンサー

>問題なのはmywbnameを入力した名前に置き換えてくれない部分だと思うのですが
その通りです、変数と文字列の連結方法が間違っています
>Workbooks.Open Filename:="C:\Documents and Settings\○○○\デスクトップ\mywbname.xls"
Workbooks.Open Filename:="C:\Documents and Settings\○○○\デスクトップ\" & mywbname & ".xls"
とします
したのマクロを実行してみてください

Sub test()
Dim 変数 As String
変数 = "変数を""""でくくっていない"
MsgBox "こちらは変数を""""でくくった例です"
MsgBox "こちらは" & 変数 & "例です"
End Sub

違い分かりますか


修正したものを載せておきます

Sub Macro1()
Dim mywbname As String
Dim mymsg As String, mytitle As String

mymgs = "開いて欲しいファイル名を入力してください"
mytitle = "ファイルを選択"
mywbname = Application.InputBox(Prompt:=mymgs, Title:=mytitle)

If mywbname <> "" Then

Workbooks.Open Filename:="C:\Documents and Settings\○○○\デスクトップ\" & mywbname & ".xls"

End If

あと、InputBoxの未入力の戻り値は "False" では無く "" です
>If mywbname <> "False" Then
If mywbname <> "" Then

こんな所でしょうか

>問題なのはmywbnameを入力した名前に置き換えてくれない部分だと思うのですが
その通りです、変数と文字列の連結方法が間違っています
>Workbooks.Open Filename:="C:\Documents and Settings\○○○\デスクトップ\mywbname.xls"
Workbooks.Open Filename:="C:\Documents and Settings\○○○\デスクトップ\" & mywbname & ".xls"
とします
したのマクロを実行してみてください

Sub test()
Dim 変数 As String
変数 = "変数を""""でくくっていない"
MsgBox "こちらは変数を""""でくくった例です"
Msg...続きを読む

QVBAで Set wb = Sheets(1).Copyができないわけ?

つい先ほどの質問 4150169 は掲示したコードが抜けておりましたので無視して、こちらにご回答ください。
ほんと抜けた話です。すみません。

以下のマクロtest01はエラーになります。

Sub test01()
Dim wb As Workbook
Set wb = Sheets(1).Copy 'エラー「オブジェクトが必要です」
End Sub

もちろん
Dim wb As Workbook
Sheets(1).Copy
Set wb = ActiveWorkbook
と修正すればエラーにならないことは存じていますが、ふと疑問がわきました。
Sheets(1).Copyの段階であたらしいWorkbookが誕生していますよね。
ならば、そのWorkbookはオブジェクトではないのでしょうか?

Workbooks.Add で誕生したWorkbookは
Set wb = Workbooks.Add
と変数wbにSetできるのに
Set wb = Sheets(1).Copy
ができないのが不思議です。

Set wb = ActiveWorkbook
としないでもSheets(1).CopyをwbにSetする書き方はないのでしょうか?

つい先ほどの質問 4150169 は掲示したコードが抜けておりましたので無視して、こちらにご回答ください。
ほんと抜けた話です。すみません。

以下のマクロtest01はエラーになります。

Sub test01()
Dim wb As Workbook
Set wb = Sheets(1).Copy 'エラー「オブジェクトが必要です」
End Sub

もちろん
Dim wb As Workbook
Sheets(1).Copy
Set wb = ActiveWorkbook
と修正すればエラーにならないことは存じていますが、ふと疑問がわきました。
Sheets(1).Copyの段階であたらしいWorkbookが誕生し...続きを読む

Aベストアンサー

こんばんは。

少し、全体的に考えさせてもらいました。ご質問の最終的な終着点がどういうところにあるのかはあまりはっきりしませんし、私が書いたところで、この手の話は、あまり分かってもらえるという自信はありません。merlionXXさん、ご自身のVBAのコーディングの問題であって、個々の問題ではないからでもあります。

今回の質問は、merlionXX さん自身が、解答した中で考えたことでしょうし、まさか、サブルーチンや特殊なコードで解決をしようと思ったわけではないと思います。

実際のコードとして、

 Set wb = Sheets(1).Copy

というのは出来ないのはご存知なわけですが、なぜ「そうしたいと思った」か、ということがポイントではないでしょうか。出来ないのは、VBAの製作者の恣意的な設計だったのか、それとも、他の要因があったのかと思います。それを、私たちユーザーレベルでは分かりません。

あえて理由を言えば、もともと、Copy メソッドには、戻り値にオブジェクトではない、ということです。

実際に、
ret = Sheets(1).Copy

で返るのは、True です。失敗すれば、実行時エラーが起こります。

質問は、前回のコード( http://oshiete1.goo.ne.jp/qa4138541.html ) から、思いついた事だとは思っていますが、Sheets(1).Copy の時点で、Application側の暗黙的な Workbookのインスタンスの生成を与えてしまっているわけで、そこで、ActiveWorkbook で、オブジェクトを取得することに、なにかしら不自然さを感じていたとしたら、その感覚は正しいのではないかと思います。私も同じように思います。

しかし、その方法で、ブックオブジェクトを取得する方法は、ActiveWorkbook をオブジェクトとして取る方法以外には、新たに Copy メソッド自体から手を加えるぐらいしか、実現する方法はないような気がします。そうすると、その親オブジェクトのSheet のClass 設定から、手を入れなくてはなりません。それは、遥か上級の話だろうし、VBAレベルで可能かどうかさえ分かりません。それに、そんなに難しいコードが、この種のもので必要だと思えません。また、一行、二行の問題で、特別なワザもなく、わざわざFunction プロシージャで取り出すというのは、理屈ではあっても、実務的にはまず考えられません。

VBAは、合理的に出来ているようでいて、はっきりとしないものがいくつもあり、「やって見なければ分からない」としかいいようがありません。本当に単純なコードでも、VBに出来て、VBAには出来ないものがあります。自分は、プロだと豪語している人に限って、こういうところでね凡ミスをするのが常です。VBAのコーディングは、よほど初歩的なこと以外は、戻り値を想定するというような「推測」で済まされるようなことはできません。

ただ、私は全体を通してみて、もし、もう一度、考える余裕があるなら、個々のメソッドやそれに関わるワザよりも、全体のプロセス自体に手を付けたほうがよいのではないか、と思います。

前のコードを、私自身で考えてみました。これは、定番のコードではあるので、私のアレンジあるものの、それ自体がオリジナルというわけではありません。シートモジュールにあるマクロコードをコピーしたいという特例の場合は、以下のコードを少し変更して可能です。これは一例ですが、こういうものは自力で編み出したわけではなく、VBAの入門時に、教わっているものです。6年経っても、そのとき覚えたものは忘れていません。

http://oshiete1.goo.ne.jp/qa4148672.html

----------------------------------------
Sub 保存3()
  Dim orgShCnt As Integer
'  Dim shName As String
  Dim fn As Variant
  'ブックのシートの規定数
  orgShCnt = Application.SheetsInNewWorkbook
  Application.SheetsInNewWorkbook = 1
  With Worksheets("Sheet1")
'    shName = .Name
    .Cells.Copy
  End With
  With Workbooks.Add  '※
    .ActiveSheet.Paste
    Range("A1").Select
    Application.CutCopyMode = False
    '規定数を戻す
    Application.SheetsInNewWorkbook = orgShCnt
    'shName → は、"" になっている
    fn = Application.GetSaveAsFilename("", "Excelブック(*.xls),*.xls", 1, "保存")
    If VarType(fn) = vbBoolean Then
      .Close False
      MsgBox "キャンセルしました。", 48
      Exit Sub
    End If
    .SaveAs fn
    .Close False
  End With
  MsgBox "終了しました。", 64
End Sub


----------------------------------------
※ Workbooks.Add というメソッドで、明示的なブックを生成していればこそ、そのオブジェクトは確実に取得できるわけです。Application の NewBook イベントで、ブックオブジェクトは取得は出来ますが、それは、ひとつのプロセスの中にはありません。

はたして、本当に、Sheets(1).Copy でオブジェクトを捕らえることが必要なのか、と思います。私は、今まで、VBAのコードを2~3千件書いていますが、ほとんど、その方法は、記録マクロを写した程度にしか、そのような方法は出てこないように思います。

失礼な言い方があったら、お許しください。

こんばんは。

少し、全体的に考えさせてもらいました。ご質問の最終的な終着点がどういうところにあるのかはあまりはっきりしませんし、私が書いたところで、この手の話は、あまり分かってもらえるという自信はありません。merlionXXさん、ご自身のVBAのコーディングの問題であって、個々の問題ではないからでもあります。

今回の質問は、merlionXX さん自身が、解答した中で考えたことでしょうし、まさか、サブルーチンや特殊なコードで解決をしようと思ったわけではないと思います。

実際のコードとし...続きを読む


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

人気Q&Aランキング