Excel VBA質問スレ Part7 at TECH
[2ch|▼Menu]
[前50を表示]
700:デフォルトの名無しさん
08/08/05 23:12:36
COM経由で呼べる組み込み言語ってないだろうか。
適当にJScriptインタプリタ起動できたりしないのだろうか。厳しいかな。

701:デフォルトの名無しさん
08/08/05 23:31:26
ときどき 0& ってのを見るんだけど、これってどういう意味ですか?
If Len(buf) = 0& Then〜 みたいな感じです

702:デフォルトの名無しさん
08/08/05 23:37:33
Long型の0

703:デフォルトの名無しさん
08/08/05 23:38:51
ごめん うそ

704:デフォルトの名無しさん
08/08/05 23:45:50
>>700
Microsoft Script Control

705:デフォルトの名無しさん
08/08/06 00:27:14
>>704
thx!

706:デフォルトの名無しさん
08/08/06 11:07:42
範囲(行のみ下がる、列数data_nは同じ)が離れているセルの値を、その範囲だけ、二次元配列に格納したいです。

仮に範囲数が4つなら二次元配列は(4,data_n)

unionで範囲を結合しても3つまでしか結合できませんでした。

だから1つずつ範囲から値を配列に格納しようとしていますがうまくいきません。

どのように配列定義、範囲から二次元配列への格納をすればよいでしょうか?


707:y
08/08/06 18:02:38
>>706

>範囲数が4つなら、二次元配列(4, data_n)
という点から想像すると、それぞれの範囲は1行×data_n列のサイズになっている
ということですか?

まず配列の定義ですが、特に設定を変えない限り、配列の番号は0から始まるので、
(4, data_n) と定義すると、実際には 5 × (data_n + 1) 個分の配列が
準備されます。本当にそれでいいかどうか確認してください。

次に格納の仕方ですが、
>1つずつ範囲から値を配列に格納しようとしていますがうまくいきません。
この考え方でも大丈夫です。中途半端でも構わないので、
とりあえず書いたコードを貼ってみてください。


708:デフォルトの名無しさん
08/08/06 19:37:01
春日部市1-2-3のような文字列の数字部分のみ半角に変換する方法を探していたら
次のようなマクロを見つけました。

Sub MacroR()
Dim idx As Integer, trg As Range
 Set trg = ActiveSheet.Cells.SpecialCells(xlCellTypeConstants, xlTextValues)
 For idx = 0 To 9
  trg.Replace What:=Right(StrConv(Str(idx), vbWide), 1), Replacement:=Right(Str(idx), 1)
 Next
End Sub

ここでRight関数を使っているのは、Str関数だと先頭に符号が付くからですか?

これのReplaceの部分を
  trg.Replace What:=StrConv(CStr(idx), vbWide), Replacement:=idx
に変更すると同じ事が出来たのですが、これだと何か不都合が出たりしますか?

709:デフォルトの名無しさん
08/08/06 19:44:55
変数のスコープについて教えてください。
全ての標準モジュールで使用出来る範囲を付与するには、
どの部分に、どのように宣言したらよろしいのでしょうか。

710:y
08/08/06 20:06:42
>>708
あなたのコードの方が良いように思います。
ReplacementのところはCstr(idx)にするとより丁寧です。


711:y
08/08/06 20:11:16
>>709
付属のヘルプで、
「Public ステートメント」
「Public ステートメントの使用例」
を検索してみてください。


712:デフォルトの名無しさん
08/08/07 00:01:04
>>709
つりですか?

713:デフォルトの名無しさん
08/08/07 09:47:54
>>707
はい1×data_nです。

Dim data AS Variant

search=0
if 該当の行が見つかったら then
search=search+1


data(search) = range(cells(search,data_n),cells(search,data_n))

endif

複数行をまとめて配列に移したいのです。
unionでダメでした。
妥協するならせめて一行をまとめて移したい。
上記は妥協コードです。

714:y
08/08/07 17:31:25
>>713
やりたいことは、何となくわかりました。
・セルを上から一つ一つチェックして
・該当の行が見つかったら
・該当の行のデータを配列に書き込む
という流れですね。

2次元配列に含まれる、特定の一次元配列に対して、まとめて書き込みを
することはできません。
該当の行の値を一つ一つ書き込むことになります。

For i = 0 To data_n - 1
 data(search, i) = cells(該当の行 , i + 1)
Next

ちなみに、「該当の行が見つかったら」とありますが、
該当の行が全部で何行あるかは、あらかじめ分かるのですか。
それとも、見つかった数だけ配列のサイズを増減したいですか。


715:デフォルトの名無しさん
08/08/07 19:52:23
>>714
やりたいことはそうです。
data_nはあらかじめ与えられており、一定です。

配列に一行ずつ入れるのは無理なのですね。
では、見つかったセルを一気に写す方法はないでしょうか?
やはり
rng=union(rng,見つかった新たな行)
で最後に
配列にrngを代入したのですが、3行分しか入らなかったのです。

716:デフォルトの名無しさん
08/08/07 20:08:25
>>714
該当の行の数は決まってません。
1〜240個で変動します。


717:デフォルトの名無しさん
08/08/07 21:22:20
最近、yって子が頑張ってるね
まだまだVBAというかプログラム言語を始めたばかりのようだが
質問に答えるために調べる、質問に答える為に考えるというのは
結構身になるものだから、これからも頑張ろう

718:y
08/08/07 21:38:52
>>715
Unionで結合されたRangeは、内部的にはコレクション(のようなもの)であり、
二次元配列ではないので、直接に代入はできません。全体が連続していれば、
二次元配列と解釈してくれるので代入は可能なのですが、この場合は各範囲が
離れています。3行分入ったのは、Unionされた各範囲のうち、先頭の範囲から
3行分が偶然連続していたためと思われます。

さて、Unionされた範囲を取得ところまではなさっているようですので、
そこからどうもっていくかについてです。上記の通り、全体を直接代入できないため、
ここでもやはり、一つ一つ値を格納していくことになります。

まずは、格納先となる配列のサイズを確定します。dataは動的配列で宣言しておき、
 Dim data() As Variant
ReDimステートメントを使ってサイズを確定します。
 Redim data(1 To 行数, 1 To 列数)
列数は、data_n となります。さて行数はどうなるでしょうか?
ヒント:rng.Countで、Unionされた範囲rngに何個のセルが含まれるかを取得できます。

>続きます

719:y
08/08/07 21:40:46
>>715 (続き)

続いて、格納するためのループです。For Each で、
rngに含まれる各セルを1つずつtmpに取り出し、
data(r, c)に代入します。
ここでrは二次元配列の行番号、cは列番号です。

Dim r as Long, c as Integer, tmp as Variant
r = 1: c = 1
For Each tmp In rng
 data(r, c) = tmp
 c = c + 1
 If ??? > data_n Then
  r = r + 1 
  c = 1
 End If
Next

???には何を入れればいいか、考えてみてください。

720:y
08/08/07 22:24:41
>>717
情報系の教育は受けたことはないのですが、
最近、人にVBAを教えなければならない立場になってしまい、
ありとあらゆる質問が投げられてくるこのスレで
修行させていただいています。
自分のレスを見直すために、簡単な名前をつけています。

2年ほど前は、私も>>706>>401のような質問をしていました。
その頃アドバイスしてくださった方々には大変お世話になりました。

721:デフォルトの名無しさん
08/08/07 23:29:41
>>719
???はc。

ありがとうございます。
やはり一つづつですか。
しかし、それだとCell毎にExcelにアクセスするので速度が遅くなるような気がします。

できないことがわかったので、代案としては

Dim data as Variant (一次元配列用)
Dim r as Variant   (二次元配列用)
'-------一行丸ごと配列格納
data = range(cells(search,data_n),cells(search,data_n))

そのあとrからdataへ
つまり一次元配列から二次元配列へ一気に代入する方法はないでしょうか?



722:デフォルトの名無しさん
08/08/08 00:27:34
VBって、配列は弱いんでなかったっけ。
配列数指定しないといけないし。

723:デフォルトの名無しさん
08/08/08 00:39:34
1回の格納ごとにredim preserveしていってもそこまで遅くは無い。
というか、あきらめるべき。

ちなみにredim preserveを減らそうがためにVectorみたいな
一度にアロケートする成長リスト形式にしても速くならなかった。

724:デフォルトの名無しさん
08/08/08 00:46:27
>>723
いや、Cellsを毎回使うことが遅くなるということで。。。
tmpに一気に代入されているという解釈になるのかな。。。
【参考】VBA高速化
URLリンク(officetanaka.net)

725:デフォルトの名無しさん
08/08/08 00:49:48
あ、ごめん 上レスぜんぜんみてなかった

726:デフォルトの名無しさん
08/08/08 01:39:10
>>721
>しかし、それだとCell毎にExcelにアクセスするので速度が遅くなるような気がします。
おまえは馬鹿のクセに試しもせずに答えを求めるな
時間計って試してから出直して来い

727:デフォルトの名無しさん
08/08/08 02:00:11
セルがいくら多くてもシートやオートシェイプのオブジェクトをループする遅さに比べたら全然速い

728:デフォルトの名無しさん
08/08/08 03:35:17
セルを参照する数が多いと遅くなるよ。
だから範囲を全て配列に渡してから配列で演算するのが常套手段。


729:デフォルトの名無しさん
08/08/08 03:37:08
>>721>>716
>1〜240個で変動します。
つまりMAXで240×data_nのセル参照数となるから
data_nが50程度なら感じるほどに遅くなるよ。

730:デフォルトの名無しさん
08/08/08 05:46:25
>>721
速度を気にするなら >>728の言う通り一度範囲を全て配列に渡してから処理する方がいい
例えばこんな感じ

Sub hoge()
 Const date_N As Integer = 50
 Dim Buf As Variant, Buf2 As Variant
 Dim iC As Integer, iC2 As Integer, X As Integer
 
 With Worksheets("Sheet1")
  Buf = .Range(.Cells(1, 1), .Cells(250, date_N)).Value
 End With
 
 X = 1
 ReDim Buf2(1 To date_N, 1 To X)
 For iC = 1 To 250
  If Buf(iC, 1) = "A" Then
   ReDim Preserve Buf2(1 To date_N, 1 To X)
   For iC2 = 1 To date_N
    Buf2(iC2, X) = Buf(iC, iC2)
   Next iC2
   X = X + 1
  End If
 Next iC
 
 ReDim Buf(1 To UBound(Buf2, 2), 1 To UBound(Buf2, 1))
 For iC = 1 To UBound(Buf, 1)
  For iC2 = 1 To UBound(Buf, 2)
   Buf(iC, iC2) = Buf2(iC2, iC)
  Next iC2
 Next iC
End Sub

731:デフォルトの名無しさん
08/08/08 10:47:54
>>730
速度気にするなら無駄多すぎw

Sub hoge()
  Const DATA_N As Integer = 50
  Const DATA_ROW As Integer = 250
  Dim Buf As Variant
  Dim iC As Integer, iC2 As Integer, X As Integer

  Buf = Sheet1.Range("A1").Resize(DATA_ROW, DATA_N).Value

  For iC = 1 To DATA_ROW
    If Buf(iC, 1) = "A" Then
      X = X + 1
      For iC2 = 1 To DATA_N
        Buf(X, iC2) = Buf(iC, iC2)
      Next iC2
    End If
  Next iC

  Sheet1.Cells(DATA_ROW + 2, "A").Resize(X, DATA_N).Value = Buf
End Sub

732:デフォルトの名無しさん
08/08/08 13:32:19
時間計るのに、ミリ秒まで計る方法ってある?

733:デフォルトの名無しさん
08/08/08 19:07:14
API

734:デフォルトの名無しさん
08/08/08 20:55:33
240個だけw

735:y
08/08/08 21:05:51
速さへの関心が高いようですね。計測用のマクロを書いて、計ってみましたよ。
あくまで向学心(というか興味本位)です。速さが全てではないはずなので、
あまり過敏に反応しないでくださいね。

>>718-719
85 milliSec

>>730
20 milliSec

>>731(セルへの書き込みの部分は含まない)
10 milliSec

タイムは、10回計った平均です。
準備したテストデータは、
250行×50列の範囲に、1行おきに該当行(1列目の値が"A")を配置してあります。
つまり、該当行は150行です。
>>731は、配列変数のサイズが最後まで250行のままである点など、厳密な比較ではありません。
でも、セルへの書き込み時に切り捨てるという解決の仕方がおもしろいですね。勉強になります。

ちなみに、ミリ秒単位の時刻を得るために、
URLリンク(members3.jcom.home.ne.jp)
で公開されているモジュールを利用しています。

736:デフォルトの名無しさん
08/08/08 21:18:00
>>731
速度気にしてるつもりなのに無駄多すぎ

> Const DATA_N As Integer = 50
数値型、文字列型の定数で型指定するな

> Dim iC As Integer, iC2 As Integer, X As Integer
カウンタはIntegerで桁が足りてもLong使え

> Range("A1")
文字列での参照ではなくCells(1,1)とインデックス参照しろ

> Cells(DATA_ROW + 2, "A")
こちらも同じく "A" ではなく 1 で


っていうかこの話、配列クラス自作しちゃった方が早い気がする
無駄に注文多くて我が侭なのに、デフォで用意されてる配列でどうにかしようってのが間違いだろ

737:デフォルトの名無しさん
08/08/08 21:18:52
ExcelVBAでやる時点で間違っている

738:デフォルトの名無しさん
08/08/08 21:23:40
今のPCなら数百のシートを操作してもそんなにストレス感じないのに
msecオーダーで速度求めるならC++で書けよなと思った。

739:デフォルトの名無しさん
08/08/08 21:51:05
正直言って、VBAは速度気にしないで使えるのが気楽で良い。
VBAだしぃー。ってのが免罪符になる。

本当に商用プログラムを作るならばVBAでやる事が前提からして間違い。
マシンパワーに余裕が出てきた今だからこそ、速度は敢えて気にしない。

と言っても、cells選択したり、表示速度が極端に遅くなるのは論外ね。


740:デフォルトの名無しさん
08/08/08 21:51:07
ちなみにC++で書いたことあるけどそんなに劇的には速くならないけど

741:y
08/08/08 21:57:21
>>736
>文字列での参照ではなくCells(1,1)とインデックス参照しろ
おー、ほんのちょっと速くなった。
>カウンタはIntegerで桁が足りてもLong使え
Longにしてみたら、やはりちょっと遅くなるんですね。

>>737-738
すみません、つい出来心でやってしまいました。
「自分が提案したコードって、実はやたらと遅いの?」と思って確かめたかっただけです。
個人的には85milliSecで完了できれば充分じゃないかと思いますが...

>>739
ですよねー

>>721
ということでした。「一次元配列から二次元配列へ一気に代入する方法」ですが、やはり
「一気に」は無理です。そのかわり、いろんな別解やアドバイスが出てきて勉強になりましたね。
条件文は c で大正解です。これからも頑張ってください。

742:デフォルトの名無しさん
08/08/08 23:01:24
VBAでいろいろ書いて「これおっそいだろうなー」って思っても
たいがい人間の認識できる速さのプランク長ぐらいで終わってしまう。驚き

743:デフォルトの名無しさん
08/08/08 23:14:00
ただあれだ。
ページの表示設定を印刷モードだっけか。あれにしてVBA走らせるとむちゃ処理重いな。
screenupdate falseにすりゃ良いんだけど。

あと覚えてるのだと、cells.autofitがむちゃ重い。
その狂ったマクロ作った奴は、流石にクレーム食らってた。

744:デフォルトの名無しさん
08/08/08 23:22:45
FSOでネットワーク上のディレクトリ走査するのをExcel関数にして羅列してもなかなか遅くできる。

745:デフォルトの名無しさん
08/08/09 00:51:16
データの多いシートのAutoFitoはやばいぞ、VBAじゃなくても普通に遅い

746:デフォルトの名無しさん
08/08/09 09:43:06
質問です。 マクロでPCのシャットダウンはできるのでしょうか? 出来たら、やり方を教えてください
あと、MsgBoxをのバックを画像にすることは出来ますか?

Windows98
Office2000
マクロ初めてまだ間もないです

747:デフォルトの名無しさん
08/08/09 09:50:31
>>746
>Windows98
そんな過去の遺物を使うのはやめなさい。

>マクロでPCのシャットダウンはできるのでしょうか?
WinAPIを使えばできるはずですが。

>あと、MsgBoxをのバックを画像にすることは出来ますか?
日本語でOK。

748:デフォルトの名無しさん
08/08/09 10:58:21
>>746
API


749:746
08/08/09 13:43:59
>>747

メッセージボックスの背景を画像にしたいのですが、できますか?


よろしかったらマクロのやり方を教えてください。

750:デフォルトの名無しさん
08/08/09 14:37:09
>よろしかったらマクロのやり方を教えてください。
WinAPIを呼ぶだけです。それについては、>1の★4に該当するので教えられません。

>メッセージボックスの背景を画像にしたいのですが、できますか?
そんなことをするよりも、画像を貼ったユーザフォームを用意した方が早いと思います。

751:デフォルトの名無しさん
08/08/09 22:49:35
エスセルVBAがすきだたですが

752:746
08/08/10 03:48:25
>>750
ユーザーフォームでやってみました。 うまく出来ました。

もうひとつお聞きしたいことが、
ボタンを押すとユーザーフォームが出るようにしたのですが、いくつものユーザーフォームを作り、ボタンを押したら、
ランダムでユーザーフォームを表示することは出来ますか?


753:デフォルトの名無しさん
08/08/10 07:10:45
>>626 等でグラフ補完を質問したものです。
そのときの回答>>629をヒントに
いらない部分の線を消すことで解決しました。
しかしExcel2003で開発していたのですが、
Excel2003では異なった場所の線が消えていました。

他のバージョンでも同様の結果を出すためにはどうすればよいでしょうか?

754:デフォルトの名無しさん
08/08/10 08:26:21
シートに写真を複数枚挿入し、そのサイズ変更を一括で行うにはどうすればいいですか?
シートには写真以外の図形オブジェクトもあり、それらは選択も変更もしません。

jpgだけを複数選択やワイルドカードなど使えるのでしょうか?
  1枚だけマクロ記録するとこうなります。
ActiveSheet.Shapes("Picture 1").Select
Selection.ShapeRange.LockAspectRatio = msoTrue
Selection.ShapeRange.Height = 150.75
Selection.ShapeRange.Width = 201#

755:デフォルトの名無しさん
08/08/10 09:23:27
>>754
for each

756:y
08/08/10 12:04:40
>>753
線分を消す部分のコードだけで構わないので、あなたが書いたものを貼ってください。
それに加えて、何番目の点と何番目の点の間の線分を消すつもりだったのかと、
その意に反して、どの線分が消えてしまったのかも書いてください。


757:デフォルトの名無しさん
08/08/10 13:00:09
ぬるぽですか

758:デフォルトの名無しさん
08/08/10 13:07:35
y消えろ

759:デフォルトの名無しさん
08/08/10 13:39:51
>>753
訂正します。
>しかしExcel2003で開発していたのですが、
>Excel2003では異なった場所の線が消えていました。
Excel2003で開発してExcel2002では異なる結果でした。

Excel2003でコード実行し計算した結果グラフをファイルに保存し、
それをExcel2002で見るだけで異なる線が消えている。。。
またExcel2002で見た(異なる線が消えている)グラフを、再度Excel2003で見ると正常になる。

どうもグラフの順番のつけ方?の定義のようなものが異なるのではという感じがします。
コードのせいではないと思います。

しかしコレでは駄目なので。。。うーん悩ましい。


760:デフォルトの名無しさん
08/08/10 15:16:36
本人に悪気はないんだろうけど、コテハン使うなら、
他の人がせっかく答えてるのに、被せて回答するのはやめた方が良い。

他の答えてる人の面目丸潰れだよ。
んでみんな答える気が失せて行く。

761:デフォルトの名無しさん
08/08/10 15:22:20
本人を特定できるコテつけて発言してるなら別だが
名無しで面目もないもんだ

762:デフォルトの名無しさん
08/08/10 15:34:27
IDもでないしね

763:デフォルトの名無しさん
08/08/10 17:29:45
>>760
こういう手法もある、とか提示してくれる分にはいいんでない?
セオリーや最短の方法イコール最善の方法、になるとは限らないし
傍目でROMってる人のレベルにうまくマッチする場合もあるしね

764:デフォルトの名無しさん
08/08/10 19:16:42
勉強のために答えてるんだから大目に見てやれよ
それに他の人の面目が潰れるほどの良回答はまだまだ出来てないじゃん
彼に面目潰されるようじゃ、潰された方がレベル低すぎってものだ

765:デフォルトの名無しさん
08/08/10 20:41:50
マターリやりましょ。
しかし最近は外部関数呼ぶ話が増えてきましたな。


766:y
08/08/10 21:14:24
>>759
そうなんですか。失礼しました。
うちには2003しかないので、残念ながらその状況を再現できません。
2002のほうで、2003で実行したのと同じコードを実行するとどうなりますか?
やはり2003とは異なる線分が消えてしまいますか?

グラフの書式の仕様というと、Excel的にはとても大切なところなはずなので、
バージョン間でそう簡単に定義が変わるとは思えないのですが...

767:デフォルトの名無しさん
08/08/10 21:23:48
>>759
一度2002でもマクロの記録でやってみれば
それでコードの問題かわかるだろ

768:デフォルトの名無しさん
08/08/11 01:13:09
TMR!TMR!

769:デフォルトの名無しさん
08/08/11 09:02:55
>>767
2002はもっていないんです。
使用者からのバグ報告なので。

770:y
08/08/11 19:08:16
>>769
2002で試せないなら、残念ですが私はもうお手上げです...

771:デフォルトの名無しさん
08/08/11 19:36:35
VBAと関係ない話なんでスルーしてもらって構わないんだけどさ。すごく気になったんで。

バージョンが多数存在するソフトの場合、金取って受注するならば、
可能な限り古いバージョンまで持っておかないとダメだよ。

金取って作業するならば、鉄則なんで。

772:デフォルトの名無しさん
08/08/11 19:42:22
Windows95サポートですね、判ります。

773:デフォルトの名無しさん
08/08/11 20:22:25
OSって意味じゃない。

774:デフォルトの名無しさん
08/08/11 20:52:48
> バージョンが多数存在するソフトの場合、金取って受注するならば、
> 可能な限り古いバージョンまで持っておかないとダメだよ。
そんなことは無い
クライアントの発注要項に対応できるバージョンが揃ってれば問題ない
逆に考えれば、所有する環境で対応出来ない要項の発注は受けなければ良いだけ

プログラムに限った話じゃないが、自分(自社)に何が出来て何が出来ないのかを把握して
それに見合った受注をすれば良い、これこそが鉄則
設備、環境、能力以上の受注をしてしまうのは愚の骨頂だが、
何でもかんでも揃えようとするのもまた愚かしくある

もちろん、事業拡大、売上向上の為には良い設備環境を整えるというのは大事だが
「可能な限り古いバージョンまで持っておかない」と、金取っての受注が一切出来ないわけでもないし
「可能な限り古いバージョンまで持っておく」ことが、金取って受注する上での鉄則でもない

それと、VBAの場合はOSも関係有るよ
Office(Excel)自体もOSのコンポーネント使ってるし、VBAからはCOM、Win32API、OCXなど
様々なOSのコンポーネントを任意で呼び出せる
故に、当然ながらOffice(Excel)のバージョンが同じでも、OSが変われば結果も変わることがある
場合によってはOSのSPが変わっただけでも影響があるくらいだからな

775:デフォルトの名無しさん
08/08/11 23:33:16
別bookの「ホゲ.xls」が開いてればそれをアクティブに、開いてなければ開くというコードを教えてください。

776:デフォルトの名無しさん
08/08/11 23:45:03
>>775
Sub activate_forcefully_hoge()
On Error GoTo hoge_is_none
Dim hogePath$: hogePath = "C:\hoge.xls" ' ホゲ.xlsのパス
Dim hogeFileName$: hogeFileName = "hoge.xls" 'ホゲ.xlsのファイル名
Dim activated As Workbook
Set activated = Workbooks(hogeFileName)
GoTo activation
hoge_is_none:
Set activated = Workbooks.Open(hogePath)
activation:
activated.Activate
End Sub


777:775
08/08/12 00:00:21
>>776
ありがたいけど・・・わかりやすくダイレクトに
if Workbookなんたらこうたら("ホゲ.xls")がない then Workbooks.Open Filename:= "ホゲ.xls"
という形で出来ませんでしょうか?
if のあとのいいメソッドかなんか無いですか?


778:775
08/08/12 00:11:32
On Error GoTo hoge_is_none
Windows("ホゲ.xls").Activate
hoge_is_none:
Workbooks.Open Filename:= "ホゲ.xls"
Windows("ホゲ.xls").Activate
これでうまくいきました、ありがとう

779:デフォルトの名無しさん
08/08/12 15:40:13
VBAに詳しい方お願いします。


 A列 B列 C列 D列 E列 F列 G列 H列 I列 J列…
1  1 010  a   AB
2  1 010  a      春  夏  秋  冬
3  1 010  a      上  下
4  2 020  b   BC
5  2 020  b      花
6  2 020  b      陸  空
6  2 020  b      水

:
:
↑を↓に変える記述教えてください。。

 A列 B列 C列 D列 E列 F列 G列 H列 I列 J列… 
1  1 010  a   AB
2  1 010  a      春 
3  1 010  a      夏
4  1 010  a      秋
5  1 010  a      冬
6  1 010  a      上
7  1 010  a      下
8  2 020  b   BC
9  2 020  b      花
10  2 020  b      陸  
11  2 020  b      空
6  2 020  b      水
:
:


780:デフォルトの名無しさん
08/08/12 15:46:55
>>779
いいか。マクロの記録ってやつを使うんだ。
んで、並び替えしてみればほぼ再利用可能なコードが出来るはずだ。

781:デフォルトの名無しさん
08/08/12 16:52:19
マクロの記録をしてからができないんです。。
ifとかDo Whileとか、、、

E1に値が入っていないのでカーソルを下に移動(E2へ移動)
 E2に値が入っているのでカーソルを右に移動(F2へ移動)
 F2に値が入っているので下(3行目)に新しい行を挿入し、(A2,B2,C2) を コピーして、(A3,B3,C3)に貼り付け、F2を切り取りE3に貼り付け る
 これをF2、G2、H2と繰り返してI2で空欄が出るまで続ける。
E8に値が入っていないのでカーソルを下に移動(E9へ移動)


  って感じにしたいんです(TT)

782:デフォルトの名無しさん
08/08/12 18:01:50
最近勉強し始めたばかりなので
初歩的な質問かもしれませんが
ヒントください。

オートフィルタの抽出で
If A.Value = True Then
Sheets("○○○").Select
Range("A1").AutoFilter Field:=8, _
Criteria1:="*" & A.Value & "*"
End If
というコードを作ったのですが
フィルタがうまくかかりません。
(A.valueはユーザーフォームのテキストボックスです)
Aにいれるテキストが全角かな文字であるがために
プログラムが反映されてないのではと思うのですが
A.valueをA.Textにするとエラーがでます。
(A.text = true というのが無理っぽいです)
解決策があれば教えていただけないでしょうか。
よろしくお願いします。

783:y
08/08/12 20:28:12
>>782
If の条件式についてですが、
「テキストボックスAに、何か文字が入っていれば抽出を行う」
という意図ですか。そういうことであれば、

If A.Value <> "" Then

にするといいでしょう。


784:デフォルトの名無しさん
08/08/12 21:07:42
>>779
質問にやさしく親切に答えてくれるスレ 3
スレリンク(tech板:886番)
なんだ、マルチか。

785:デフォルトの名無しさん
08/08/12 21:25:02
>>783 ありがとうございます!!!
うまくいきました!!
2〜3日ずっと悩んでいたので本当に感謝!!
ありがとうございましたm(_ _)m

786:y
08/08/12 21:28:33
>>779

Dim r As Long, c As Integer, cc As Integer, dr As Long, dt As Variant, rNum As Long
rNum = WorksheetFunction.CountIf(Range("D:IV"), "<>")
ReDim dt(1 To rNum, 1 To 5)
r = 1: dr = 1
Do While Cells(r, 1) <> ""
 If Cells(r, 4) <> "" Then
  For c = 1 To 4
   dt(dr, c) = Cells(r, c)
  Next
  dr = dr + 1
 ElseIf Cells(r, 5) <> "" Then
  c = 5
  Do While Cells(r, c) <> ""
   For cc = 1 To 4
    dt(dr, cc) = Cells(r, cc)
   Next
   dt(dr, 5) = Cells(r, c)
   c = c + 1
   dr = dr + 1
  Loop
 End If
 r = r + 1
Loop
With ThisWorkbook.Sheets.Add
 .Range(.Cells(1, 1), .Cells(1, 1).Offset(rNum - 1, 4)) = dt
End With

もっと効率的な方法で書ける方もおられると思いますが...
それと、マルチ(複数のスレッドで同じ質問をすること)はしないようにしてくださいね。


787:デフォルトの名無しさん
08/08/12 23:12:20
どなたかプログラマ向けの難しめのVBAの書籍(洋書でも可)を御存知ないでしょうか。
Excel Hacksとかではなく、VBAやらCOMとの絡みなど詳細な事項などが書いてあると嬉しいです。

いざ勉強しても何か心許ない感じになってくるので、
Oreilly的な本を一冊読んできちんと理解しだいです。
御存知でしたら、助言お願いします。

788:デフォルトの名無しさん
08/08/12 23:46:38
y大人だなぁ

789:デフォルトの名無しさん
08/08/13 00:11:46
COMってのは不特定多数が制作しているものだから
MSが作ったCOM以外を書籍で解説することはまず無いし
MSが作ったCOMに関してならMSDNにも情報がある

そしてExcel VBAに関しては、>>1★3にも有るとおり
Excelの操作をGUIではなく言語でやってるだけであり
突き詰めたところでそう難しいものでも無い
その先を行きたいならVBAではなくVBの範疇になるので
VBの書籍を買え

790:デフォルトの名無しさん
08/08/13 02:00:39
>>789
すみませんが、VBでもいいので、
VB6互換の環境について、書籍を御存知ないですか?

791:デフォルトの名無しさん
08/08/13 02:37:31
vb6ってたとえば関数のオーバーロードとかクラスのインヘリットとかがない等、
C++とかに比べて言語仕様自体に機能が多いわけじゃないから、アルゴリズムさえ
コードにできればリファレンス読むだけで十分な言語なんですよね?
高度な書籍っていっても結局vb6の機能をフルに活用して何が出来るかとかいう書籍がほしい
んだったら、結局vb6からAPIやCOM使ってなんかするサンプルコードなんかが沢山載ってる本
をほしいって事と同じようなものだと思うから、結局vbの枠で書籍を探すよりも、むしろ
COMの本買うとか、めんどくさいからvbやめて別の言語に手を出して、C++詳説の本買うとか
しないといけないんじゃないかなぁと思うんですが。どうなの?


792:デフォルトの名無しさん
08/08/13 02:47:33
とりあえずここらへんにしておこうかな
URLリンク(www.amazon.com)
URLリンク(www.amazon.com)

>>791
言語仕様自体はあまり明確じゃない言語だと思います。
クラスのインヘリタンスはあるにはありますね。ひ弱ですが。

古い言語のせいか、Webにある資料もいまいちどうもパッとしないのです。
C++はまあ別にどうでもよいので(知っているので)、
COMに?興味が出たらCOMの本買うと思います。若干時代に逆行していますが。

私としてはVB6/VBAのバイブルみたいなものを探していたところです。
一応、上記の本読んでみることにします。

793:792
08/08/13 02:48:23
古い言語といっても、まあ、新しいわけだけれど、
陳腐化したといったほうがよかったかな。

>>791さん、お付き合いありがとうございました。

794:デフォルトの名無しさん
08/08/13 06:49:43
VBA上級テクニック なんちゃらって本があったな。
API関数やVBSの呼び出し方が解説してあってよかったかも。
ただ、具体的なAPI関数についての説明なんかは当然なし。

当時、具体的な呼び出し方が説明してあるのは役に立った記憶があるよ。
あと、何で変数の型が必要か、とかrangeの概念なんかも詳しく説明してあった。
それまで全部variantで使ってた変数の型も、きっちり宣言出来るようになったし、
何となく使ってたfor eachも、何がどう動いてるのかが理解出来たよ。


795:デフォルトの名無しさん
08/08/13 08:14:00
Range以外は全てVB6分野の話だな

796:デフォルトの名無しさん
08/08/13 08:58:00
InputBoxを使った入力について教えてください。
セルのコメントをInputBox関数で入力させるマクロを組んでいます。
この入力値を、任意の箇所で改行したいのですが、できますか?
可能な場合、InputBox関数で呼び出される入力ダイアログボックス
にはどのように入力すれば良いのでしょうか?
ご教示お願いします。

797:デフォルトの名無しさん
08/08/13 09:34:30
どうしてもInputBox使いたいなら、任意の文字列を改行として扱うしか無いかな

Dim strTemp As String
strTemp = InputBox("改行したい部分に\nを入れてください。", , "1行目\n2行目\n\n4行目")
strTemp = Replace(strTemp, "\n", vbCrLf)
MsgBox strTemp

改行扱い文字列は、別に\nじゃなくても本文中に出現しないものなら何でも良い


でも、ユーザーフォームで複数行入力できるダイアログを作るのが正攻法だろ

798:デフォルトの名無しさん
08/08/13 10:07:04
できました。Replaceすればいいのですね。
ありがとうございました。

799:デフォルトの名無しさん
08/08/13 10:30:48
Aというシートからユーザーフォームのテキストボックス(10個ぐらいある)
に入力された内容に従ってデータを抽出して
既存のBシートに貼り付けるような比較的長いコードを作りました。

最終的には、もしユーザーフォームの
「新規シートを作成して貼り付け」という
チェックボックスにチェックが入っていた場合は
Cシートを新たに作成し、そこにデータを貼り付け
さらにDシート・・Eシートとシートを増やせるようにしたいと
思っています。
その場合は
現在作ってある長いコードを使って
if checkbox1 = true then
 worksheets.add
「新しいシートに貼り付けてね」という長いコード
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
else 「シートBに貼り付けてね」という長いコード

end if
という風に、指定するシートを変えるだけで
ほとんど同じコードを2回記述するしか方法はないでしょうか??
もっと完結にできる方法があれば教えてください。
モジュールがやたら長くなって見にくくなってしまうのを回避したいです。





800:デフォルトの名無しさん
08/08/13 11:30:00
>>799
共通する部分の処理でプロシージャを作り
Callで呼べばいい

801:デフォルトの名無しさん
08/08/13 11:50:00
>>800 ありがとうございます!!
さっそく試してみます。

ステートメントを早くいろいろ覚えないと
後で「こんなステートメントあったんだ!じゃぁあの時
もっと簡単にプログラムできたじゃん!」って思うことが多いです(;;
もっとよく勉強します。
本当にありがとうございました。

802:デフォルトの名無しさん
08/08/13 11:55:04
>>801
>後で「こんなステートメントあったんだ!じゃぁあの時
>もっと簡単にプログラムできたじゃん!」って思うことが多いです(;;

それが糧になるんだよ。決して無駄にはならないさ。
# 仕事なら話は別だが。

803:デフォルトの名無しさん
08/08/14 10:48:11
アクティブシート上にあるすべてのボタンを消去するのって
ActiveSheet.Buttons.Delete
じゃ駄目なんですか?
いくら実行しても何も起こらないんですが。

804:デフォルトの名無しさん
08/08/14 10:58:14
画面に向かって「消えろー」って10回叫べば消えるかも

805:デフォルトの名無しさん
08/08/14 11:13:52
for each

806:デフォルトの名無しさん
08/08/14 11:27:47
>>803
゙ボタン゙と言っているのはオートシェイプ?マクロ用のボタン(名前忘れた)?

807:デフォルトの名無しさん
08/08/14 11:53:50
>>806
オートシェイプです。

すいません、今調べたら
ActiveSheet.DrawingObjects.Delete
という命令でシート上のボタンはすべて消せることがわかりました。

追加で質問なんですが、一行目に配置されたボタンだけを残し、二行目以降のボタンをすべて消去する方法ってありますか?


808:デフォルトの名無しさん
08/08/14 12:07:36
>>807
プログラム化するならわからんが、オブジェクトの選択(矢印の付いたアイコン)
で範囲選択したら、その領域内に含まれる図形は全て選択できるからデリートで消す

809:デフォルトの名無しさん
08/08/14 12:24:34
>>808
デリートでセルを消してもそのセル上のボタンは幅が0になるだけで線になって残りません?
完全に消去する方法が知りたいのですが。

810:デフォルトの名無しさん
08/08/14 12:48:34
>>809
セルの行削除・列削除では消えませんよ。
図形描画のツールバーを出して、オブジェクト選択のボタンを使うべし。

811:デフォルトの名無しさん
08/08/14 14:23:44
1行1件のデータシートがあります。
顧客 製品 台数
A あ 1
A あ 1
B あ 1
B あ 1
B い 1

これの顧客Bだけ範囲選択して
B あ 2
B い 1  という結果を別シートに出したいのです。
・選択1行目をコピー貼り付け
・2行目以降、前回顧客と製品名が一致したら台数インクリメント
・Activecell.Rows.Count数だけループ
という方法でなくもっといいのはありますか?


812:デフォルトの名無しさん
08/08/14 17:16:40
CountIf

813:デフォルトの名無しさん
08/08/14 17:52:52
>>811
ピボットテーブル知ってる?

814:デフォルトの名無しさん
08/08/14 18:17:46
>>811
オートフィルタの抽出を別場所にする

815:デフォルトの名無しさん
08/08/14 18:22:52
>>811
おいらならオートフィルタで指定の顧客名を抽出して、
if (cells(i,2).value = cells(i+1,2).value) daisu++}
ってインクリメントするかな。


816:デフォルトの名無しさん
08/08/14 18:24:49
すいません。文法間違えました。
javascriptとしても間違えております・・・比較演算子違うし。

if cells(i,2).value = cells(i+1,2).value then
daisu = daisu + 1
end if

でした。本当に申し訳ない。

817:811
08/08/14 18:32:04
目的は別シートに貼り付けるため、なのです。
全体を集計するのであればピボットで済みますが、そうではなく
必要な部分だけ抜き取って(項目も無し)それだけ集計して貼り付けたいのです。

手作業ではコピー、貼り付けしたあと、台数を修正して余計な行を削除
なんですがこれを自動化したいだけです。
標準の集計やピボットを利用するには、項目行もコピーしてシートも新しくせねばならず
また、完成した集計表では顧客名や製品名に勝手に空欄が出来てしまうので
使いたい形に修正するだけで作業が余計に感じます。

818:デフォルトの名無しさん
08/08/14 18:35:25
これはマクロの記録で十分対応できるレベルだろ

819:デフォルトの名無しさん
08/08/14 18:52:49
・選択部分を新しいシートにコピペ
・製品を軸に昇順に並べ替え
・製品名が変わるまでloop、んでカウント
・一番上の台数に代入
・代入した行にフラグ
・フラグ立てた行以外削除

こんな感じ?その情報でやるなら。
操作者が範囲を選択する時点で、選択ミスの可能性があるから、俺ならやらん。

きっと製品名は凄い沢山あるんだろうね。VBAスレで聞くって事は。

820:y
08/08/14 21:33:06
>>817
うーん。ピボットテーブルはなるべく敬遠したいとのことですが、
必要な部分だけ抜き取ったり、ある項目だけの台数を合計したり、というのは
やはりピボットテーブルが本領を発揮する場面だと思うんですね。
「項目行もコピーしてシートも新しくせねばならず」とありますが、
ひとつピボットテーブルを作ってしまえば、あとはその設定を変えながら
運用すればいいわけです。
VBAでピボットテーブルも操作できることはご存知ですよね?
抜き出したい顧客に合わせてピボットテーブルの抽出アイテムを変えたり、
抽出結果を任意の別シートに貼り付けたりするような、手作業では
面倒な部分をVBAで自動化すればいいと思うんです。
全体をVBAで実現するやり方で考えていらっしゃる方もおられるので、
そちらも検討した上で、もう1つの考え方として受け取ってください。


821:y
08/08/14 21:43:08
ピボットテーブルで処理する例です。

Sub ch_pivot()
Dim item As PivotItem, kName As String
kName = InputBox("顧客名を入力してください")
With Sheets("Sheet2")
With .PivotTables("ピボットテーブル1")
.PivotCache.Refresh
.PivotFields("顧客").PivotItems(kName).Visible = True
For Each item In .PivotFields("顧客").PivotItems
If item.Name <> kName Then item.Visible = False
Next
End With
Range(.Cells(5, 1), .Cells(.Rows.Count, 3).End(xlUp)).Copy _
Destination:=Application.InputBox("貼り付け先を指定してください", Type:=8)
End With
End Sub

822:y
08/08/14 21:46:09
>>822のコードは、次のような前提で動作します。
(下のように設定されていないと動作しません)

○データシート
>>811のデータは"Sheet1"という名前のワークシートにおかれているとする。

○ユーザー定義の名前
・任意の名前(ここでは"pivotSource")を定義する。参照範囲は次のようにする。
 =OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),3)

○ピボットテーブル
・使用するデータの範囲を"pivotSource"とする
・レイアウトは行に"顧客"と"製品"。データに"台数"(集計方法は合計)。
・名前は"ピボットテーブル1"
・配置する場所は"Sheet2"という名前のワークシートの$A$3。
・顧客ごとの集計を非表示に
・列の総計を非表示に


823:y
08/08/14 21:59:43
すみません。「>>822のコード」→「>>821のコード」の間違いです。
あとピボットテーブルはピボットテーブルウィザードなどを利用して
自分で設置してください。(セル範囲の名前の定義も自分で。)


824:デフォルトの名無しさん
08/08/14 22:49:18
グラフを複数作成しようとしていますが、速度が10秒/1グラフと遅く
特に書式設定が速度的に遅いと感じます。

書式、データ数は同じで、データ内容だけ異なります。
グラフはチャート毎に1シートに描いているものです。
(埋め込みグラフじゃないほう?)

グラフの雛形的なものを使って複数グラフを作成し、
少しでも高速化したいと考えています。

実施したのですがデータの設定の順番が異なるのか、うまくいきません。
何かグラフコピーペーストのセオリーのようなものがあれば教えてください。


825:デフォルトの名無しさん
08/08/14 23:26:51
>>824
screenupdate=Falseは既に実施しております。

826:デフォルトの名無しさん
08/08/15 00:29:15
データの数とグラフの数が多いと遅くなると思いますよ。
オブジェクト数が多いとExcelの動作が劇的に重くなるのは仕様なのかな?
グラフ1つ作成するのに10秒かかるんだったらマクロの記録でグラフ作成するコード作って
比較してみればいいんじゃないですか?

827:デフォルトの名無しさん
08/08/15 05:25:40
>>826
マクロの記録を参考に、いらない部分を削り、作成しました。
それで遅いので、複数グラフ作成で速くする方法はないかと考えました。


828:デフォルトの名無しさん
08/08/15 05:45:16
質問があります。
正方行列(2×2)を一行(1×4)で表したとき、関数で配列(2×2)を作り、
さらにこの配列を関数で計算する方法が分かりません。例えば
1 2
3 4
の行列をエクセルシート上でA1:D1に1,2,3,4と入力したとき
=test(A1:D1)として配列(2×2)を作ります。

Function test(data As Range)
Dim A(1, 1) As Double
k = 1
For i = 1 To 2
For j = 1 To 2
k = k + 1
A(i - 1, j - 1) = data(k - 1)
Next
Next
test = A
End Function

このとき行列式(=1*4-2*3)を計算するため
=determ(test(A1:D1))とすると、#VALUE!となって困ってます。

Function determ(B As Double)
determ = B(0, 0) * B(1, 1) - B(0, 1) * B(1, 0)
End Function

いろいろ試してみたのですが、どうも配列の扱いがよく分からなくて。
XP Excel2003ですがよろしくお願いします。

829:デフォルトの名無しさん
08/08/15 07:13:14
第一要因
 determ関数の引数が配列ではない
 配列を引数に取る場合は
 B() As Double
 のように、配列変数の後ろに () を付けなければならない

第二要因
 引数の型が合ってない
 配列を返す関数では、関数内で型を指定していても
 返される値はVariant型の配列となる

第三要因
 配列の要素数が合ってない
 シート上には0行目0列目が無いので、
 配列(1, 1) つまりは 配列(0 To 1, 0 To 1)
 を関数の結果として返すと、自動的に
 配列(1 To 2, 1 To 2)
 のように下限要素が0から1に変換される

以上を踏まえてdetermの方を
Function determ(B() As Variant)
  determ = B(1, 1) * B(2, 2) - B(1, 2) * B(2, 1)
End Function
とすれば動くと思う

ところで、>>828の例は質問用に簡素化しただけで、実際は配列要素数を決め打ちではなく精査してるよね?
あと、A(i - 1, j - 1) = data(k - 1) で、全部 -1 やってるのは何か意味有るの?

830:828
08/08/15 07:54:20
>>829
早速ありがトン
急いで試してみたけど、なんかうまくいかない...

全部-1にしてるのは、配列は0から始まるって教わったので。
お察しの通り、本とは大きい行列なので、簡略化したんだけど。
=test(A1:D1)で配列をシートで見たけど合ってた。

ちょっとこれから会社なので、夜にまた試してみるよ。

831:デフォルトの名無しさん
08/08/15 08:53:51
最低限、君が書いた例通り、A1:D1に1,2,3,4と入れて
=determ(test(A1:D1))
とする分には問題なく動く
上手く行かないとすれば、実際のコードに適応する上で君が何か間違ってるからだろう

あと、0から始まるのはそうなんだが、
For i = 1 To 2
For j = 1 To 2
k = k + 1
A(i - 1, j - 1) = data(k - 1)

For i = 0 To 1 '<- 1〜2ではなく0〜1
For j = 0 To 1
A(i, j) = data(k)
k = k + 1 '<- 変数kのインクリメントを後回しに
とすれば、3カ所の -1 は不要なんだが、何故わざわざi,j,kに1多い数を入れて -1 してるのかなぁと

832:デフォルトの名無しさん
08/08/15 12:57:16
Excelでタブを作るのは無理ですか?

833:デフォルトの名無しさん
08/08/15 14:24:13
へるぷみー。
テキストボックスに入力された名前を
新規のワークシートに付ける際に、例えば「あいうえお」という
名前のシートが既にあるにもかかわらず
テキストボックスに「あいうえお」と書かれた場合は
自動で「あいうえお1」次にまた「あいうえお」と入力されてしまった場合は
「あいうえお2」になるようにしたいと思い、
下記のようなコードを入力してみました。
(sheetnameがテキストボックスのオブジェクト名です)
Dim i As Integer, cnt As Integer, n As Integer
cnt = Worksheets.Count
n = 1
If CheckBox.Value = True Then
For i = 1 To cnt
Do Until sheetname.Value <> Worksheets(i).Name
sheetname.Value = sheetname.Value & n
n = n + 1
Loop
Next i
Worksheets.Add after:=Worksheets(cnt)
ActiveSheet.Name = sheetname.Value
End if

このコードだと
「あいうえお」→「あいうえお1」→「あいうえお11」
→「あいうえお111」
という風になってしまいました。
できるシリーズの本とかで調べたりWeb検索してみたりしたのですが
解決策が見つかりませんでした。
よろしくお願いします。

834:デフォルトの名無しさん
08/08/15 15:52:13
>>833
どこがVBAの質問なんだか。単純な名前生成の問題じゃないか。
毎回シート名に"n"を継ぎ足すんじゃなくて、都度入力された名前に"n"を継ぎ足せばいいだろ。
オブジェクト変数を使いまわすんじゃなくて、一時変数で処理する癖をつけた方がいいな。

835:デフォルトの名無しさん
08/08/15 17:07:40
>>832
何のタブかわからんが、ブックのタブならツールバーで作る手がある

836:デフォルトの名無しさん
08/08/15 18:48:16
>>832
ユーザーフォームでタブを云々ならマルチページなりタブストリップなりをコントロールから追加


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

4635日前に更新/336 KB
担当:undef